Testing out networking. Skins get loaded, but not for every player.
Build / build (push) Has been cancelled

This commit is contained in:
milkwx3
2026-06-24 00:44:45 +03:00
parent 6a9dd15020
commit cfc693785d
12 changed files with 360 additions and 355 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
rm raylib -r rm raylib -r
rm yaml-cpp -r rm yaml-cpp -r
wget https://github.com/zpl-c/enet/archive/refs/heads/master.zip wget https://github.com/lsalzman/enet/archive/refs/heads/master.zip
unzip master.zip unzip master.zip
mv enet-master enet mv enet-master enet
rm master.zip rm master.zip
Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 628 B

After

Width:  |  Height:  |  Size: 2.9 KiB

+3 -28
View File
@@ -427,12 +427,12 @@ void TickBlock(Chunk world[], int wx, int wy, int wz) {
if(tile == BLOCK_SAND) { if(tile == BLOCK_SAND) {
if(GetBlock(world, wx, wy-1, wz) == 0) { if(GetBlock(world, wx, wy-1, wz) == 0) {
SetBlockNetwork(world, wx, wy, wz, 0); SetBlockNetwork(world, wx, wy, wz, 0);
Entity temp = NewEntity(); Entity temp = NewEntity(0);
temp.type = 4; temp.type = 4;
temp.position = (Vector3){wx, wy, wz}; temp.position = (Vector3){wx, wy, wz};
temp.velocity = {0, 0, 0}; temp.velocity = {0, 0, 0};
temp.data[1] = BLOCK_SAND; temp.data[1] = BLOCK_SAND;
AddEntity(temp); //AddEntity(temp);
} }
} }
} }
@@ -442,32 +442,7 @@ void TickChunk(Chunk *chunk, Chunk *world, int wx, int wz) {
{ {
for (int z = 0; z < CHUNK_SIZE; z++) for (int z = 0; z < CHUNK_SIZE; z++)
{ {
int tile = fetch_block_ptr(chunk, x, y, z); TickBlock(world, x, y, z);
if(tile == BLOCK_SAND) {
if(fetch_block_ptr(chunk, x, y-1, z) == 0) {
SetBlockChunk(chunk, x, y, z, 0);
Entity temp = NewEntity();
temp.type = 4;
temp.position = (Vector3){((int)wx * CHUNK_SIZE + x), y, ((int)wz * CHUNK_SIZE + z)};
temp.velocity = {0, 0, 0};
temp.data[1] = BLOCK_SAND;
AddEntity(temp);
chunk->isDirty = true;
}
}
if(false) { // tile == BLOCK_WATERS
int rx = GetRandomValue(-1, 1);
int rz = GetRandomValue(-1, 1);
for (int _y = 0; _y >= -1; _y--)
{
if(GetBlock(world, wx+x+rx, y+_y, wz+z+rz) == 0) {
SetBlockChunk(chunk, x, y+_y, z, 0);
SetBlock(world, wx+x+rx, y+_y, wz+z+rz, BLOCK_WATERS);
chunk->isDirty = true;
continue;
}
}
}
} }
} }
} }
+26 -27
View File
@@ -62,12 +62,16 @@
#define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS #define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS
#define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw #define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw
#define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max) #define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max)
#define NET_ARG_ENTITYSPAWN 0x0A // uint16_t entityWorldID, uint8_t entityTypeID, uint16_t x, uint16_t y, uint16_t z, uint8_t data[8]
#define NET_ARG_ENTITYMOVE 0x0B // uint16_t entityWorldID, uint16_t x, uint16_t y, uint16_t z
#define NET_ARG_PLRSKIN 0x0C // Byte 1 - ID, bytes 2-3 - size, rest is skin
#define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw #define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw
#define NET_ARG_BLOCKDELTA 0x81 // Block X, block Y, block Z, block type #define NET_ARG_BLOCKDELTA 0x81 // Block X, block Y, block Z, block type
#define NET_ARG_REQWORLD 0x82 // No additional data #define NET_ARG_REQWORLD 0x82 // No additional data
#define NET_ARG_REQPLAYERS 0x83 // No additional data #define NET_ARG_REQPLAYERS 0x83 // No additional data
#define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw #define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw
#define NET_ARG_MESSAGEC 0x85 // All is message (64b max) #define NET_ARG_MESSAGEC 0x85 // All is message (64b max)
#define NET_ARG_PLRSKINSET 0x86 // Byte 1 - ID, bytes 2-3 - size, rest is skin
#define NET_ERROR_DSCN 0x00 #define NET_ERROR_DSCN 0x00
#define NET_ERROR_NOTFOUND 0x01 #define NET_ERROR_NOTFOUND 0x01
#define NET_ERROR_FAILED 0x02 #define NET_ERROR_FAILED 0x02
@@ -79,6 +83,7 @@
#define TPS_DIV 1.0 / TPS #define TPS_DIV 1.0 / TPS
#define RENDER_DISTANCE 16 #define RENDER_DISTANCE 16
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE #define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
#define PIXUNIT 1.0f / 16.0f
#define MAX_HP 100 #define MAX_HP 100
#define PATH_APPEND "resources/" #define PATH_APPEND "resources/"
#define PATH_APPEND_USER "user/" #define PATH_APPEND_USER "user/"
@@ -201,17 +206,18 @@ struct Vector3I {
}; };
typedef struct Entity Entity; typedef struct Entity Entity;
struct Entity { struct Entity {
uint16_t id;
uint8_t type; uint8_t type;
uint8_t id;
uint8_t damage_flash; uint8_t damage_flash;
uint8_t data[16]; uint8_t data[4];
uint8_t data_sv[8];
bool free;
float smoothing; float smoothing;
float health; float health;
float lifetime; float lifetime;
Vector3 position; Vector3 position;
Vector3 velocity; Vector3 velocity;
unsigned short yaw; unsigned short yaw;
bool free;
}; };
typedef struct NetPlayer NetPlayer; typedef struct NetPlayer NetPlayer;
struct NetPlayer { struct NetPlayer {
@@ -223,6 +229,9 @@ struct NetPlayer {
float x; float x;
float y; float y;
float z; float z;
std::string nickname;
Texture2D texture;
std::vector<uint8_t> skin;
}; };
typedef struct MemInfo MemInfo; typedef struct MemInfo MemInfo;
struct MemInfo { struct MemInfo {
@@ -321,49 +330,34 @@ bool Debug_GetProcessMemory(MemInfo&out);
#if !defined(WIN32) #if !defined(WIN32)
bool Debug_GetProcessMemory(MemInfo&out); bool Debug_GetProcessMemory(MemInfo&out);
#endif #endif
#if !defined(SERVER)
extern Camera camera; extern Camera camera;
#endif
extern Camera3D camera; extern Camera3D camera;
#if !defined(SERVER) #if !defined(SERVER)
extern Camera camera; extern Camera camera;
extern Font fnt;
extern Font fnt;
extern Texture2D terrain;
#endif #endif
extern Font fnt;
#if !defined(SERVER)
extern Font fnt;
#endif
extern Texture2D terrain;
extern Texture2D terrain; extern Texture2D terrain;
#if !defined(SERVER) #if !defined(SERVER)
extern Texture2D terrain; extern Texture2D terrain;
extern Texture2D terrain; extern Texture2D terrain;
extern Texture2D playerTex; #endif
extern Texture2D playerTex; extern Texture2D nekitTex;
extern Texture2D bomb; extern Texture2D bomb;
extern Sound nekit_idle; extern Sound nekit_idle;
void EntitiesInit(); void EntitiesInit();
extern bool online; extern bool online;
#if !defined(SERVER)
extern bool online; extern bool online;
#endif #endif
#if !(!defined(SERVER))
extern bool online;
#endif
#if !defined(SERVER)
extern Vector3 player_position;
#endif
extern Vector3 player_position;
#if !defined(SERVER)
extern Vector3 player_velocity;
#endif
extern Vector3 player_velocity;
#if !defined(SERVER)
void TakeDamage(float amount); void TakeDamage(float amount);
void SetBlockNetwork(Chunk world[],int bx,int by,int bz,int t); void SetBlockNetwork(Chunk world[],int bx,int by,int bz,int t);
#endif Entity NewEntity(int id);
Entity NewEntity();
void AddEntity(Entity ent);
void UpdateEntities(Chunk world[],float dt);
extern float globalCounter; extern float globalCounter;
#if !defined(SERVER) #if !defined(SERVER)
void DrawEntities(float dt);
extern bool swap_mouse; extern bool swap_mouse;
bool InputGetLMB(); bool InputGetLMB();
bool InputGetLMBDown(); bool InputGetLMBDown();
@@ -378,6 +372,7 @@ extern int currentlySelected;
extern GameState state; extern GameState state;
extern Texture2D cubemap; extern Texture2D cubemap;
int TryConnect(const char *hostname); int TryConnect(const char *hostname);
void InitSingleplayer();
void GameModeCleanup(); void GameModeCleanup();
void DrawBackground(); void DrawBackground();
void InitMenu(); void InitMenu();
@@ -395,6 +390,7 @@ void DrawMainMenu();
void _LoadWorld(const char *path); void _LoadWorld(const char *path);
void DrawWorldSelect(); void DrawWorldSelect();
void DrawMultiplayer(); void DrawMultiplayer();
void ExitSingleplayer();
void DrawPauseMenu(); void DrawPauseMenu();
extern char bufferChat[MAX_MESSAGE_LENGTH]; extern char bufferChat[MAX_MESSAGE_LENGTH];
char *DrawChat(); char *DrawChat();
@@ -586,6 +582,7 @@ extern InventoryItem inventory[INVENTORY_SIZE];
#endif #endif
extern InventoryItem inventory[INVENTORY_SIZE]; extern InventoryItem inventory[INVENTORY_SIZE];
#if !defined(SERVER) #if !defined(SERVER)
extern Texture2D playerTex;
extern bool inventoryOpen; extern bool inventoryOpen;
extern InventoryItem *movingItem; extern InventoryItem *movingItem;
void DrawItem(InventoryItem item,int x,int y); void DrawItem(InventoryItem item,int x,int y);
@@ -612,6 +609,8 @@ extern float player_health;
extern float player_attack_time; extern float player_attack_time;
extern float player_place_time; extern float player_place_time;
extern float player_break_parts_time; extern float player_break_parts_time;
extern Vector3 player_position;
extern Vector3 player_velocity;
void SavePlayerData(); void SavePlayerData();
bool LoadPlayerData(); bool LoadPlayerData();
void MS_PlaySound(Sound src,float pitch,float volume,Vector3 position); void MS_PlaySound(Sound src,float pitch,float volume,Vector3 position);
+9 -145
View File
@@ -9,42 +9,32 @@
#include <vector> #include <vector>
#include <algorithm> #include <algorithm>
#define PIXUNIT 1.0f / 16.0f
#ifndef SERVER
extern Camera camera; extern Camera camera;
extern Font fnt; extern Font fnt;
extern Texture2D terrain; extern Texture2D terrain;
Texture2D playerTex; Texture2D nekitTex;
Texture2D bomb; Texture2D bomb;
Sound nekit_idle; Sound nekit_idle;
void EntitiesInit() { void EntitiesInit() {
playerTex = LoadTexture(Pathify("player.png")); nekitTex = LoadTexture(Pathify("nekit.png"));
bomb = LoadTexture(Pathify("bomb.png")); bomb = LoadTexture(Pathify("bomb.png"));
nekit_idle = LoadSound(Pathify("sound/nekit/idle.ogg")); nekit_idle = LoadSound(Pathify("sound/nekit/idle.ogg"));
} }
extern bool online; extern bool online;
extern Vector3 player_position;
extern Vector3 player_velocity;
void TakeDamage(float amount); void TakeDamage(float amount);
void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t); void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t);
#else
bool online = true;
#endif
std::list<Entity> entities; Entity NewEntity(int id) {
Entity NewEntity() {
Entity ent; Entity ent;
ent.id = entities.size(); ent.id = id;
ent.type = 0; ent.type = 0;
ent.yaw = 0; ent.yaw = 0;
ent.free = false; ent.free = false;
return ent; return ent;
} }
void AddEntity(Entity ent) { void AddEntity(std::list<Entity> entities, Entity ent) {
entities.push_back(ent); entities.push_back(ent);
} }
@@ -67,7 +57,7 @@ static void UpdateEntityPhysics(Chunk world[], Entity& ent, float dt) {
ent.velocity = velocityTgt; ent.velocity = velocityTgt;
ent.position = final; ent.position = final;
} }
void UpdateEntities(Chunk world[], float dt) { void UpdateEntities(std::list<Entity> entities, Chunk world[], float dt) {
if(entities.size() > 0) { if(entities.size() > 0) {
int idx = 0; int idx = 0;
for(Entity& ent : entities) { for(Entity& ent : entities) {
@@ -93,9 +83,6 @@ void UpdateEntities(Chunk world[], float dt) {
Vector3 direction = Vector3Normalize(Vector3Subtract(target, ent.position)); Vector3 direction = Vector3Normalize(Vector3Subtract(target, ent.position));
float degYaw = -atan2f(direction.z, direction.x) * RAD2DEG + 90; float degYaw = -atan2f(direction.z, direction.x) * RAD2DEG + 90;
if(GetRandomValue(0, 2000) == 0) {
MS_PlaySound(nekit_idle, GetRandomValue(75,125)/100.0f, 1.0f, ent.position);
}
ent.velocity = Vector3Add(ent.velocity, (Vector3){direction.x * 20.0f, 0, direction.z * 20.0f}*dt); ent.velocity = Vector3Add(ent.velocity, (Vector3){direction.x * 20.0f, 0, direction.z * 20.0f}*dt);
if(GetBlock(world, (int)ent.position.x, (int)ent.position.y-1, (int)ent.position.z) && GetRandomValue(0, 100) == 0) { if(GetBlock(world, (int)ent.position.x, (int)ent.position.y-1, (int)ent.position.z) && GetRandomValue(0, 100) == 0) {
ent.velocity.y += 10.0f; ent.velocity.y += 10.0f;
@@ -110,54 +97,8 @@ void UpdateEntities(Chunk world[], float dt) {
if(ent.health < 0.1f) { if(ent.health < 0.1f) {
ent.free = true; ent.free = true;
} }
if(ent.data[2] < 90)
ent.data[2]++;
ent.yaw = (unsigned short)(degYaw/360.0f*65535); ent.yaw = (unsigned short)(degYaw/360.0f*65535);
} }
/*if(ent.type == 3) {
Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f});
Vector3 tgt = Vector3Add(ent.position, Vector3Scale(velocityTgt, dt));
Vector3 final = ent.position;
if(!GetBlock(world, (int)tgt.x, (int)final.y, (int)final.z)) {
final.x = tgt.x;
}
if(!GetBlock(world, (int)final.x, (int)tgt.y, (int)final.z)) {
final.y = tgt.y;
}
else {
velocityTgt.y = -velocityTgt.y / 2.0f;
velocityTgt = Vector3Scale(velocityTgt, 0.9f);
}
if(!GetBlock(world, (int)final.x, (int)final.y, (int)tgt.z)) {
final.z = tgt.z;
}
Entity* entp = &ent;
entp->yaw = 0;
entp->position = final;
entp->velocity = velocityTgt;
if(ent.lifetime > 5.0f) {
int radius = 3;
for (int x = -radius; x < radius; x++)
{
for (int y = -radius; y < radius; y++)
{
for (int z = -radius; z < radius; z++)
{
if(Vector3Distance({final.x + x, final.y + y, final.z + z}, final) <= radius) {
if(!CheckOOBWorld(final.x + x, final.y + y, final.z + z)) {
#ifndef SERVER
SetBlockNetwork(world, final.x + x, final.y + y, final.z + z, 0);
#endif
}
}
}
}
}
entp->free = true;
}
idx++;
}*/
if(ent.type == 4) { if(ent.type == 4) {
Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f}); Vector3 velocityTgt = Vector3Clamp(Vector3Add(ent.velocity, {0, -dt * 20.0f, 0}), {-30.0f, -30.0f, -30.0f}, {30.0f, 30.0f, 30.0f});
@@ -184,7 +125,7 @@ void UpdateEntities(Chunk world[], float dt) {
} }
Entity* entp = &ent; Entity* entp = &ent;
if(hit) { if(hit) {
SetBlockNetwork(world, (int)ent.position.x, (int)ent.position.y, (int)ent.position.z, ent.data[1]); SetBlockNetwork(world, (int)ent.position.x, (int)ent.position.y, (int)ent.position.z, ent.data_sv[1]);
entp->free = true; entp->free = true;
} }
entp->yaw = 0; entp->yaw = 0;
@@ -203,8 +144,8 @@ void UpdateEntities(Chunk world[], float dt) {
} }
} }
float globalCounter = 0; float globalCounter = 0;
#ifndef SERVER
void DrawEntities(float dt) { void DrawEntities(std::list<Entity> entities, float dt) {
globalCounter += dt; globalCounter += dt;
for(Entity& ent : entities) { for(Entity& ent : entities) {
ent.smoothing += dt; ent.smoothing += dt;
@@ -281,83 +222,7 @@ void DrawEntities(float dt) {
rlPopMatrix(); rlPopMatrix();
} }
if(ent.type == 1) { if(ent.type == 1) {
Color color = WHITE;
Vector3 posLerp = Vector3Add(ent.position, {-0.5f, -0.1f, -0.5f});
float time = ent.lifetime * 4.0f;
float armWave0 = sinf(time * PI);
float armWave1 = -abs(cosf(time * PI));
float headWave = cosf(time * PI);
posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0});
Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0});
float yaw = -ent.yaw / 65535.0f * 360.0f - 90;
rlPushMatrix();
rlTranslatef(posLerp.x, posLerp.y, posLerp.z);
rlRotatef(yaw, 0, 1, 0);
rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z);
//
rlPushMatrix();
rlTranslatef(headPivot.x, headPivot.y, headPivot.z);
rlRotatef(25.0f * armWave0, 1, 0, 0);
rlRotatef(25.0f * headWave, 0, 0, 1);
// Head
DrawCubeTexture(playerTex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8);
rlPopMatrix();
Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
rlRotatef(45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
rlRotatef(-45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(playerTex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(body.x, body.y, body.z);
DrawCubeTexture(playerTex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4);
rlPopMatrix();
leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(playerTex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPopMatrix();
Vector3 dir = Vector3Subtract(camera.position, ent.position);
rlPushMatrix();
rlTranslatef(ent.position.x, ent.position.y + 1.5f, ent.position.z);
rlRotatef(atan2f(dir.x, dir.z) * RAD2DEG, 0.0f, 1.0f, 0.0f);
rlRotatef(90.0f, 1.0f, 0.0f, 0.0f);
char name[12];
sprintf(name, "Player %d", (int)ent.data[0]);
DrawText3D(fnt, name, {-MeasureTextEx(fnt, name, PIXUNIT * 4, 0).x * 1.5f, 0, 0}, PIXUNIT * 4, PIXUNIT, 1, true, WHITE);
rlPopMatrix();
} }
if(ent.type == 3) { if(ent.type == 3) {
DrawCube(pos_lerped, 1, 1, 1, RED); DrawCube(pos_lerped, 1, 1, 1, RED);
@@ -367,4 +232,3 @@ void DrawEntities(float dt) {
} }
} }
} }
#endif
+1 -1
View File
@@ -6,7 +6,7 @@
#include <iostream> #include <iostream>
#include <map> #include <map>
#include <rlgl.h> #include <rlgl.h>
#define PIXUNIT 1.0f / 16.0f
InventoryItem hotbar[ITEMS]; InventoryItem hotbar[ITEMS];
InventoryItem inventory[INVENTORY_SIZE]; InventoryItem inventory[INVENTORY_SIZE];
static uint8_t selected = 0; static uint8_t selected = 0;
+4 -4
View File
@@ -29,7 +29,7 @@ static int MakeUIPOI(int x, int y) {
std::unordered_set<uint32_t> ui_pois; std::unordered_set<uint32_t> ui_pois;
int TryConnect(const char* hostname); int TryConnect(const char* hostname);
//void InitSingleplayer(); void InitSingleplayer();
void GameModeCleanup(); void GameModeCleanup();
static int mouseX = -1; static int mouseX = -1;
@@ -503,7 +503,7 @@ void DrawWorldSelect() {
} }
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48, 128, 0)) { if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48, 128, 0)) {
UIResetMousePos(); UIResetMousePos();
//InitSingleplayer(); InitSingleplayer();
return; return;
} }
if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48-48, 128, 0)) { if (Button(LocaleGet("create_world").c_str(), GetScreenWidth()/2+196-128, GetScreenHeight()-48-48, 128, 0)) {
@@ -550,12 +550,12 @@ void DrawMultiplayer() {
EndDrawing(); EndDrawing();
UIHandleControls(); UIHandleControls();
} }
void ExitSingleplayer();
void DrawPauseMenu() { void DrawPauseMenu() {
UIBegin(); UIBegin();
DrawRectangle(0,0,GetScreenWidth(),GetScreenHeight(),Fade(GRAY,0.5f)); DrawRectangle(0,0,GetScreenWidth(),GetScreenHeight(),Fade(GRAY,0.5f));
if (Button(LocaleGet("exit").c_str(), GetScreenWidth()/2-64, 48, 128, 0)) { if (Button(LocaleGet("exit").c_str(), GetScreenWidth()/2-64, 48, 128, 0)) {
GameModeCleanup(); ExitSingleplayer();
UIResetMousePos(); UIResetMousePos();
return; return;
} }
+3 -3
View File
@@ -87,17 +87,17 @@ void BroadcastPacketR(ENetHost* server, void* data, int len)
void SerializeFloat2Data(float v, void *target, int offset) { void SerializeFloat2Data(float v, void *target, int offset) {
uint8_t *buf = (uint8_t*)target + offset; uint8_t *buf = (uint8_t*)target + offset;
if (!isfinite(v)) { // handle NaN/Inf as zero (choose policy) if (!isfinite(v)) {
buf[0] = 0; buf[0] = 0;
buf[1] = 0; buf[1] = 0;
return; return;
} }
if (v < 0.0f) v = 0.0f; if (v < 0.0f) v = 0.0f;
if (v > 255.0f) v = 255.0f; // clamp to representable range if (v > 255.0f) v = 255.0f;
int intpart = (int)floorf(v); int intpart = (int)floorf(v);
float frac = v - (float)intpart; float frac = v - (float)intpart;
int frac_byte = (int)floorf(frac * 255.0f + 0.5f); // round to nearest int frac_byte = (int)floorf(frac * 255.0f + 0.5f);
if (frac_byte < 0) frac_byte = 0; if (frac_byte < 0) frac_byte = 0;
if (frac_byte > 255) frac_byte = 255; if (frac_byte > 255) frac_byte = 255;
buf[0] = (uint8_t)intpart; buf[0] = (uint8_t)intpart;
+61 -3
View File
@@ -11,6 +11,7 @@
#include <atomic> #include <atomic>
static std::list<NetPlayer> players; static std::list<NetPlayer> players;
static std::list<Entity> entities;
static Chunk world[MAX_WORLD_AREA]; static Chunk world[MAX_WORLD_AREA];
static ENetHost* server; static ENetHost* server;
@@ -167,6 +168,15 @@ static int PeerToPlayerID(ENetPeer* peer) {
static bool CompareAddress(NetPlayer plr, ENetPeer* peer) { static bool CompareAddress(NetPlayer plr, ENetPeer* peer) {
return plr.addr == peer->address.host && plr.port == (int)(peer->address.port); return plr.addr == peer->address.host && plr.port == (int)(peer->address.port);
} }
static void SendPlayerSkin(ENetPeer* peer, NetPlayer plr) {
unsigned char responseD[plr.skin.size()+4];
responseD[0] = NET_ARG_PLRSKIN;
responseD[1] = (plr.skin.size() & 0xFF00) << 8;
responseD[2] = plr.skin.size() & 0xFF;
memcpy(responseD+4, plr.skin.data(), plr.skin.size());
SendPacketR(peer, responseD, plr.skin.size()+4);
}
static void ParseData(ENetPacket* packet, ENetPeer* peer) { static void ParseData(ENetPacket* packet, ENetPeer* peer) {
int len = packet->dataLength; int len = packet->dataLength;
unsigned char data[len]; unsigned char data[len];
@@ -237,8 +247,25 @@ static void ParseData(ENetPacket* packet, ENetPeer* peer) {
responseP[1] = plr.id; responseP[1] = plr.id;
responseP[8] = plr.yaw; responseP[8] = plr.yaw;
SendPacketR(peer, responseP, 9); SendPacketR(peer, responseP, 9);
SendPlayerSkin(peer, plr);
} }
} }
for (Entity &ent : entities)
{
unsigned char responseP[10+8];
responseP[0] = NET_ARG_ENTITYSPAWN;
responseP[1] = ent.id & 0xFF00 >> 8;
responseP[2] = ent.id & 0xFF;
responseP[3] = ent.type;
SerializeFloat2Data(ent.position.x, responseP, 4);
SerializeFloat2Data(ent.position.y, responseP, 6);
SerializeFloat2Data(ent.position.z, responseP, 8);
for (int i = 0; i < 8; i++)
{
responseP[i+10] = ent.data_sv[i];
}
SendPacketR(peer, responseP, 18);
}
break; break;
case NET_ARG_BLOCKDELTA: case NET_ARG_BLOCKDELTA:
response[0] = NET_ARG_BLOCK; response[0] = NET_ARG_BLOCK;
@@ -257,6 +284,30 @@ static void ParseData(ENetPacket* packet, ENetPeer* peer) {
} }
} }
break; break;
case NET_ARG_PLRSKINSET:
{
NetPlayer tmp;
for (NetPlayer &plr : players)
{
if(plr.id == data[1]) {
int size = (data[2] << 8) | data[3];
std::cout << size << std::endl;
for (int i = 0; i < size; i++)
{
plr.skin.push_back(data[4+i]);
}
tmp = plr;
break;
}
}
for (NetPlayer &plr : players)
{
if(!CompareAddress(plr, peer)) {
SendPlayerSkin(peer, tmp);
}
}
break;
}
default: default:
break; break;
} }
@@ -290,11 +341,18 @@ void StartInternalServer(std::atomic_bool& started) {
std::cout << "Serving on port: " << PORT << std::endl; std::cout << "Serving on port: " << PORT << std::endl;
serverStarted = true; serverStarted = true;
started = true; started = true;
Entity test = NewEntity(0);
test.type = 2;
test.position = {0, 64, 0};
entities.push_back(test);
} }
void UpdateEntities(std::list<Entity> entities, Chunk world[], float dt);
void ServerNetworkUpdate() { void ServerNetworkUpdate() {
if(serverStarted) { if(serverStarted) {
UpdateEntities(entities, world, TPS_DIV);
ENetEvent event; ENetEvent event;
while(enet_host_service (server, &event, 0) > 0) while(enet_host_service (server, &event, 1000 / TPS) > 0)
{ {
switch (event.type) switch (event.type)
{ {
@@ -308,6 +366,7 @@ void ServerNetworkUpdate() {
id = FirstFreeID(players); id = FirstFreeID(players);
response[1] = id; response[1] = id;
SendPacketR(event.peer, response, sizeof(response)); SendPacketR(event.peer, response, sizeof(response));
{ {
NetPlayer netPlayer; NetPlayer netPlayer;
netPlayer.id = id; netPlayer.id = id;
@@ -315,11 +374,11 @@ void ServerNetworkUpdate() {
netPlayer.port = (int)(event.peer->address.port); netPlayer.port = (int)(event.peer->address.port);
netPlayer.peer = event.peer; netPlayer.peer = event.peer;
players.push_back(netPlayer); players.push_back(netPlayer);
response[0] = NET_ARG_PLRCON; response[0] = NET_ARG_PLRCON;
response[1] = netPlayer.id; response[1] = netPlayer.id;
BroadcastPacketR(server, response, sizeof(response)); BroadcastPacketR(server, response, sizeof(response));
} }
CallPluginOnConnect(id); CallPluginOnConnect(id);
break; break;
@@ -346,7 +405,6 @@ void ServerNetworkUpdate() {
break; break;
} }
} }
break; break;
} }
} }
+13 -3
View File
@@ -79,6 +79,10 @@
#define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS #define NET_ARG_PLRREG 0x07 // Same as ECHOMOVE, used as an answer to REQPLAYERS
#define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw #define NET_ARG_ECHOYAW 0x08 // Byte 1 - ID, byte 2 - yaw
#define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max) #define NET_ARG_MESSAGEE 0x09 // Byte 1 - sender ID, byte 2 - length, rest is message (128b max)
#define NET_ARG_ENTITYSPAWN 0x0A // uint16_t entityWorldID, uint8_t entityTypeID, uint16_t x, uint16_t y, uint16_t z, uint8_t data[8]
#define NET_ARG_ENTITYMOVE 0x0B // uint16_t entityWorldID, uint16_t x, uint16_t y, uint16_t z
#define NET_ARG_PLRSKIN 0x0C // Byte 1 - ID, bytes 2-3 - size, rest is skin
//Client->Server //Client->Server
// Byte 0 // Byte 0
#define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw #define NET_ARG_PLAYERMOVE 0x80 // Byte 1-2 - player X, byte 3-4 - player Y, byte 5-6 - player Z, byte 7 - player yaw
@@ -87,6 +91,7 @@
#define NET_ARG_REQPLAYERS 0x83 // No additional data #define NET_ARG_REQPLAYERS 0x83 // No additional data
#define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw #define NET_ARG_PLAYERYAW 0x84 // Byte 1 - yaw
#define NET_ARG_MESSAGEC 0x85 // All is message (64b max) #define NET_ARG_MESSAGEC 0x85 // All is message (64b max)
#define NET_ARG_PLRSKINSET 0x86 // Byte 1 - ID, bytes 2-3 - size, rest is skin
// //
//Errors //Errors
#define NET_ERROR_DSCN 0x00 #define NET_ERROR_DSCN 0x00
@@ -103,6 +108,7 @@
//Rendering //Rendering
#define RENDER_DISTANCE 16 #define RENDER_DISTANCE 16
#define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE #define RENDER_DISTANCE_SQUARED RENDER_DISTANCE*RENDER_DISTANCE
#define PIXUNIT 1.0f / 16.0f
//Game stuff //Game stuff
#define MAX_HP 100 #define MAX_HP 100
@@ -225,17 +231,18 @@ struct Vector3I {
int z; int z;
}; };
struct Entity { struct Entity {
uint16_t id;
uint8_t type; uint8_t type;
uint8_t id;
uint8_t damage_flash; uint8_t damage_flash;
uint8_t data[16]; uint8_t data[4];
uint8_t data_sv[8];
bool free;
float smoothing; float smoothing;
float health; float health;
float lifetime; float lifetime;
Vector3 position; Vector3 position;
Vector3 velocity; Vector3 velocity;
unsigned short yaw; unsigned short yaw;
bool free;
}; };
struct NetPlayer struct NetPlayer
@@ -248,6 +255,9 @@ struct NetPlayer
float x; float x;
float y; float y;
float z; float z;
std::string nickname;
Texture2D texture;
std::vector<uint8_t> skin;
}; };
struct MemInfo { struct MemInfo {
+220 -121
View File
@@ -15,8 +15,11 @@
#include <list> #include <list>
#include <climits> #include <climits>
#include <queue> #include <queue>
#include <thread>
#include <atomic> #include <atomic>
#include <thread>
#include <set>
#include <map>
#include <fstream>
#define MAX_RAY_DISTANCE 8.0f #define MAX_RAY_DISTANCE 8.0f
struct MessageData { struct MessageData {
std::string message; std::string message;
@@ -32,11 +35,14 @@ Vector2 cameraMovementSmooth;
static float camYaw = 0.0f; static float camYaw = 0.0f;
static float camPitch = -45.0f; static float camPitch = -45.0f;
static const float acceleration = 48.0f; static const float acceleration = 48.0f;
static const float drag = 6.0f; // tuned for feel static const float drag = 6.0f;
static bool singleplayerServer;
Camera camera; Camera camera;
Texture2D playerTex;
bool online = false; bool online = false;
bool flying = false; bool flying = false;
void DrawEntities(std::list<Entity> entities, float dt);
unsigned long long worldTime; unsigned long long worldTime;
static float entUpdateCounter; static float entUpdateCounter;
@@ -53,7 +59,6 @@ Font fnt;
Texture2D terrain; Texture2D terrain;
Texture2D water; Texture2D water;
Texture2D white_pixel; Texture2D white_pixel;
Entity* ent;
const bool ROTATE_PLAYER_WITH_CAMERA = true; const bool ROTATE_PLAYER_WITH_CAMERA = true;
static Sound wood_place; static Sound wood_place;
static Sound stone_place; static Sound stone_place;
@@ -63,9 +68,10 @@ bool tick_entities;
const std::string LocaleGet(std::string loc); const std::string LocaleGet(std::string loc);
bool InputGetKeyDown(const std::string name); bool InputGetKeyDown(const std::string name);
bool InputGetKeyPressed(const std::string name); bool InputGetKeyPressed(const std::string name);
extern std::list<Entity> entities;
std::bitset<WORLD_SIZE_BLOCKS*WORLD_SIZE_BLOCKS/8/8> clouds; std::bitset<WORLD_SIZE_BLOCKS*WORLD_SIZE_BLOCKS/8/8> clouds;
std::queue<Vector3I> tickedBlocks; std::queue<Vector3I> tickedBlocks;
static std::list<Entity> entities;
static std::map<int, NetPlayer> players;
struct MeshUnit { struct MeshUnit {
Model model; Model model;
int vertices; int vertices;
@@ -91,6 +97,96 @@ static Vector3 CameraForwardFromYawPitch(float yaw, float pitch)
f.z = cosf(pitch) * sinf(yaw); f.z = cosf(pitch) * sinf(yaw);
return Vector3Normalize(f); return Vector3Normalize(f);
} }
static const char* GetPlayerTexturePath() {
if(FileExists(PathifyUser("player.png"))) {
return PathifyUser("player.png");
}
else {
return Pathify("nekit.png");
}
}
static void DrawPlayer(Texture2D texture, NetPlayer netPlayer) {
Color color = WHITE;
float x = netPlayer.x;
float y = netPlayer.y;
float z = netPlayer.z;
int _yaw = netPlayer.yaw;
Vector3 posLerp = Vector3Add((Vector3){x, y, z}, {-0.5f, -0.1f, -0.5f});
float time = GetTime() * 4.0f;
float armWave0 = sinf(time * PI);
float armWave1 = -abs(cosf(time * PI));
float headWave = cosf(time * PI);
posLerp = Vector3Add(posLerp, {0, abs(sinf(time * PI)) * 0.1f, 0});
Vector3 headPivot = Vector3Add(posLerp, (Vector3){0, 16*PIXUNIT, 0});
float yaw = -yaw / 65535.0f * 360.0f - 90;
Texture2D tex = netPlayer.texture;
rlPushMatrix();
rlTranslatef(posLerp.x, posLerp.y, posLerp.z);
rlRotatef(yaw, 0, 1, 0);
rlTranslatef(-posLerp.x, -posLerp.y, -posLerp.z);
//
rlPushMatrix();
rlTranslatef(headPivot.x, headPivot.y, headPivot.z);
rlRotatef(25.0f * armWave0, 1, 0, 0);
rlRotatef(25.0f * headWave, 0, 0, 1);
// Head
DrawCubeTexture(tex, {0, 4*PIXUNIT, 0}, 8*PIXUNIT, 8*PIXUNIT, 8*PIXUNIT, WHITE, 8, 8, 8, 8);
rlPopMatrix();
Vector3 leftPivot = Vector3Add(posLerp, (Vector3){-6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
Vector3 rightPivot = Vector3Add(posLerp, (Vector3){6*PIXUNIT, 1.25f - 5*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
rlRotatef(45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(tex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
rlRotatef(-45.0f * armWave1, 0, 0, 1);
DrawCubeTexture(tex, (Vector3){0, -6*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 44,20,4,4);
rlPopMatrix();
Vector3 body = Vector3Add(posLerp, {0, 1.25f - 10*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(body.x, body.y, body.z);
DrawCubeTexture(tex, Vector3Zero(), 8*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 20, 20, 8, 4);
rlPopMatrix();
leftPivot = Vector3Add(posLerp, (Vector3){-2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rightPivot = Vector3Add(posLerp, (Vector3){2*PIXUNIT, 1.25f - 14*PIXUNIT, 0});
rlPushMatrix();
rlTranslatef(leftPivot.x, leftPivot.y, leftPivot.z);
rlRotatef(-45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(tex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPushMatrix();
rlTranslatef(rightPivot.x, rightPivot.y, rightPivot.z);
rlRotatef(45.0f * armWave0, 1, 0, 0);
DrawCubeTexture(tex, {0*PIXUNIT, -8*PIXUNIT, 0}, 4*PIXUNIT, 12*PIXUNIT, 4*PIXUNIT, WHITE, 4, 20, 4, 4);
rlPopMatrix();
rlPopMatrix();
Vector3 dir = Vector3Subtract(camera.position, (Vector3){x, y, z});
rlPushMatrix();
rlTranslatef(x, y + 1.5f, z);
rlRotatef(atan2f(dir.x, dir.z) * RAD2DEG, 0.0f, 1.0f, 0.0f);
rlRotatef(90.0f, 1.0f, 0.0f, 0.0f);
const char* name = netPlayer.nickname.c_str();
DrawText3D(fnt, name, {-MeasureTextEx(fnt, name, PIXUNIT * 4, 0).x * 1.5f, 0, 0}, PIXUNIT * 4, PIXUNIT, 1, true, WHITE);
rlPopMatrix();
}
Chunk world[MAX_WORLD_AREA]; Chunk world[MAX_WORLD_AREA];
static MeshUnit rendering[MAX_WORLD_AREA]; static MeshUnit rendering[MAX_WORLD_AREA];
static MeshUnit renderingT[MAX_WORLD_AREA]; static MeshUnit renderingT[MAX_WORLD_AREA];
@@ -234,17 +330,14 @@ static void ResolveCollisions(float dt)
if (ix > 0 && iy > 0 && iz > 0) if (ix > 0 && iy > 0 && iz > 0)
{ {
// find smallest penetration axis and push out along it
if (ix < iy && ix < iz) if (ix < iy && ix < iz)
{ {
// push on X
if (player_position.x < bx0) player_position.x -= ix; if (player_position.x < bx0) player_position.x -= ix;
else player_position.x += ix; else player_position.x += ix;
player_velocity.x = 0; player_velocity.x = 0;
} }
else if (iy < ix && iy < iz) else if (iy < ix && iy < iz)
{ {
// push on Y
if (player_position.y < by0) player_position.y -= iy; if (player_position.y < by0) player_position.y -= iy;
else player_position.y += iy; else player_position.y += iy;
if (player_velocity.y > 0) player_velocity.y = 0; if (player_velocity.y > 0) player_velocity.y = 0;
@@ -252,7 +345,6 @@ static void ResolveCollisions(float dt)
} }
else else
{ {
// push on Z
if (player_position.z < bz0) player_position.z -= iz; if (player_position.z < bz0) player_position.z -= iz;
else player_position.z += iz; else player_position.z += iz;
player_velocity.z = 0; player_velocity.z = 0;
@@ -357,21 +449,12 @@ static inline void RemeshChunkForBlock(int bx, int by, int bz)
if (cx >= 0 && cx < MAX_WORLD_SIZE && cz >= 0 && cz < MAX_WORLD_SIZE) RemeshChunk(cx, cz); if (cx >= 0 && cx < MAX_WORLD_SIZE && cz >= 0 && cz < MAX_WORLD_SIZE) RemeshChunk(cx, cz);
} }
static void AddNekit() {
Entity temp = NewEntity();
temp.type = 2;
temp.health = 50;
temp.velocity = {0, 0, 0};
temp.position = player_position + (Vector3){0, 10, 0};
AddEntity(temp);
}
ENetPeer *peer; ENetPeer *peer;
ENetHost* client; ENetHost* client;
static std::stack<std::vector<uint8_t>> worldPacketStack; static std::stack<std::vector<uint8_t>> worldPacketStack;
static int fetchedChunks; static int fetchedChunks;
int plrId = -1; int plrId = 0;
static bool pauseMenuActive; static bool pauseMenuActive;
void _LoadWorld(const char* path) { void _LoadWorld(const char* path) {
@@ -451,7 +534,7 @@ void SetBlockNetwork(Chunk world[], int bx, int by, int bz, int t) {
data[2] = (uint8_t)by; data[2] = (uint8_t)by;
data[3] = (uint8_t)bz; data[3] = (uint8_t)bz;
data[4] = (uint8_t)t; data[4] = (uint8_t)t;
SendPacketR(peer, data, sizeof(data)); SendPacketR(peer, data, 5);
} }
else { else {
SetBlock(world, bx, by, bz, t); SetBlock(world, bx, by, bz, t);
@@ -507,14 +590,16 @@ int TryConnect(const char* hostname) {
"No available peers for initiating an ENet connection.\n"); "No available peers for initiating an ENet connection.\n");
return NET_ERROR_NOTFOUND; return NET_ERROR_NOTFOUND;
} }
printf("Found a host\n");
if (enet_host_service (client, & event, 5000) > 0 && while (!serverStarted)
event.type == ENET_EVENT_TYPE_CONNECT)
{ {
if(!online) serverStarted = true;
}
if (enet_host_service (client, & event, 10000) && event.type == ENET_EVENT_TYPE_CONNECT){
puts ("Connection succeeded."); puts ("Connection succeeded.");
char data[1]; char data[1];
data[0] = NET_ARG_REQWORLD; data[0] = NET_ARG_REQWORLD;
SendPacketR(peer, data, 1); SendPacketR(peer, data, 1); // Tell the server to send all chunks
online = true; online = true;
state = GAME_STATE_LOADING; state = GAME_STATE_LOADING;
return 0; return 0;
@@ -528,26 +613,37 @@ int TryConnect(const char* hostname) {
return -1; return -1;
} }
//std::thread serverThread;
std::thread serverThread;
std::atomic_bool stop_server = false; std::atomic_bool stop_server = false;
void StartInternalServer(std::atomic_bool& started); void StartInternalServer(std::atomic_bool& started);
/*void ServerThread(std::atomic_bool& started) { void ServerThread(std::atomic_bool& started) {
StartInternalServer(started); StartInternalServer(started);
stop_server = false; stop_server = false;
while(true) { while(true) {
if (stop_server) if (stop_server) {
serverStarted = false;
StopInternalServer();
return; return;
}
ServerNetworkUpdate(); ServerNetworkUpdate();
} }
}*/ }
/*void InitSingleplayer() { void InitSingleplayer() {
online = true; online = true;
serverThread = std::thread(ServerThread, std::ref(serverStarted)); serverThread = std::thread(ServerThread, std::ref(serverStarted));
int result = TryConnect("localhost"); int result = TryConnect("localhost");
if(result == NET_ERROR_FAILED) { if(result == NET_ERROR_FAILED) {
state = GAME_STATE_MAINMENU; state = GAME_STATE_MAINMENU;
return;
}
singleplayerServer = true;
}
void ExitSingleplayer() {
GameModeCleanup();
} }
}*/
std::vector<MessageData> messages; std::vector<MessageData> messages;
bool survival = false; bool survival = false;
bool chatOpen = false; bool chatOpen = false;
@@ -695,19 +791,6 @@ static void GameUpdate(Camera camera, float &time) {
Vector3 rayOrigin = (Vector3){ player_position.x, player_position.y + 1.7f, player_position.z};; Vector3 rayOrigin = (Vector3){ player_position.x, player_position.y + 1.7f, player_position.z};;
Vector3 hitBlock, prevBlock; Vector3 hitBlock, prevBlock;
if(IsKeyDown(KEY_N) && !online) {
AddNekit();
}
if(IsKeyPressed(KEY_F10)) {
tick_entities = !tick_entities;
}
if(IsKeyPressed(KEY_B) && !online) {
Entity temp = NewEntity();
temp.type = 3;
temp.position = camera.position;
temp.velocity = (camera.target - camera.position) * 4.0f;
AddEntity(temp);
}
if (RaycastBlock(rayOrigin, Vector3Normalize(camForward), 5, &hitBlock, &prevBlock)) if (RaycastBlock(rayOrigin, Vector3Normalize(camForward), 5, &hitBlock, &prevBlock))
{ {
if((int)hitBlock.x != (int)highlightBlock.x || (int)hitBlock.y != (int)highlightBlock.y || (int)hitBlock.z != (int)highlightBlock.z) if((int)hitBlock.x != (int)highlightBlock.x || (int)hitBlock.y != (int)highlightBlock.y || (int)hitBlock.z != (int)highlightBlock.z)
@@ -895,22 +978,6 @@ static void GameUpdate(Camera camera, float &time) {
} }
AddProfilerPart("rebuild", GetTime()-PROFCOUNT, BLUE); AddProfilerPart("rebuild", GetTime()-PROFCOUNT, BLUE);
PROFCOUNT = GetTime();
if(tick_entities) {
entUpdateCounter += dt;
if(entUpdateCounter > TPS_DIV) {
while (entUpdateCounter > 0)
{
UpdateEntities(world, TPS_DIV / 2.0f);
entUpdateCounter-= TPS_DIV;
}
TickAvailableBlocks();
entUpdateCounter = 0.0f;
}
}
AddProfilerPart("entities", GetTime()-PROFCOUNT, MAGENTA);
PROFCOUNT = GetTime(); PROFCOUNT = GetTime();
ParticlesUpdate(dt, world); ParticlesUpdate(dt, world);
AddProfilerPart("particles", GetTime()-PROFCOUNT, ORANGE); AddProfilerPart("particles", GetTime()-PROFCOUNT, ORANGE);
@@ -932,7 +999,7 @@ static void GameUpdate(Camera camera, float &time) {
Frustum frustum = ExtractFrustumPlanes(camera, (float)GetScreenWidth() / (float)GetScreenHeight()); Frustum frustum = ExtractFrustumPlanes(camera, (float)GetScreenWidth() / (float)GetScreenHeight());
BeginDrawing(); BeginDrawing();
ClearBackground(RAYWHITE); ClearBackground(RAYWHITE);
DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), BLUE); DrawRectangle(0, 0, GetScreenWidth(), GetScreenHeight(), {120, 167, 255});
BeginMode3D(camera); BeginMode3D(camera);
@@ -952,7 +1019,10 @@ static void GameUpdate(Camera camera, float &time) {
} }
AddProfilerPart("chunk render opq", GetTime()-PROFCOUNT, MAROON); AddProfilerPart("chunk render opq", GetTime()-PROFCOUNT, MAROON);
DrawEntities(dt); DrawEntities(entities, 0);
for (const auto& [id, netplayer] : players) {
DrawPlayer(terrain, netplayer);
}
ParticlesDraw(); ParticlesDraw();
//Transparent shit //Transparent shit
rlDisableDepthMask(); rlDisableDepthMask();
@@ -1126,13 +1196,6 @@ static void GameUpdate(Camera camera, float &time) {
DrawTriangle({x3, y3}, {x2, y2}, {x1, y1}, p.color); DrawTriangle({x3, y3}, {x2, y2}, {x1, y1}, p.color);
angleA = angleB; angleA = angleB;
} }
/*float mid = (startAngle + endAngle) * 0.5f;
float lx = cx + cosf(mid) * (radius * 0.6f);
float ly = cy + sinf(mid) * (radius * 0.6f);
char label[128];
sprintf(label, "%s (%.1f ms)", p.id.c_str(), p.time * 1000.0f);
DrawText(label, lx - 20, ly - 6, 10, WHITE);*/
startAngle = endAngle; startAngle = endAngle;
} }
int T = 0; int T = 0;
@@ -1157,10 +1220,12 @@ static void GameUpdate(Camera camera, float &time) {
if(msg != nullptr) { if(msg != nullptr) {
chatOpen = false; chatOpen = false;
DisableCursor(); DisableCursor();
if(online) {
char data[1+MAX_MESSAGE_LENGTH]; char data[1+MAX_MESSAGE_LENGTH];
data[0] = NET_ARG_MESSAGEC; data[0] = NET_ARG_MESSAGEC;
memcpy(data+1, msg, MAX_MESSAGE_LENGTH); memcpy(data+1, msg, MAX_MESSAGE_LENGTH);
SendPacketR(peer, data, 1+MAX_MESSAGE_LENGTH); SendPacketR(peer, data, 1+MAX_MESSAGE_LENGTH);
}
memset(msg, 0, MAX_MESSAGE_LENGTH); memset(msg, 0, MAX_MESSAGE_LENGTH);
} }
} }
@@ -1187,10 +1252,31 @@ static void GameStart() {
} }
LoadPlayerData(); LoadPlayerData();
//PlayRandomMusic(); //PlayRandomMusic();
if(online) {
char data[1]; char data[1];
data[0] = NET_ARG_REQPLAYERS; data[0] = NET_ARG_REQPLAYERS;
SendPacketR(peer, data, 1); SendPacketR(peer, data, 1);
int memory_size = 65535;
char* dynamic_buffer = new char[memory_size];
std::ifstream file;
file.open(GetPlayerTexturePath(), std::ios_base::in | std::ios_base::binary );
file.read(dynamic_buffer, memory_size);
int bytes_read = (int)(file.gcount());
std::cout << bytes_read << std::endl;
file.close();
uint8_t skin_packet[4+bytes_read];
skin_packet[0] = NET_ARG_PLRSKINSET;
skin_packet[1] = plrId;
skin_packet[2] = (bytes_read & 0xFF00) >> 8;
skin_packet[3] = bytes_read & 0xFF;
memcpy(skin_packet+4, dynamic_buffer, bytes_read);
SendPacketR(peer, skin_packet, sizeof(skin_packet)*sizeof(uint8_t));
//free(skin_packet);
//free(dynamic_buffer);
}
camera = { 0 }; camera = { 0 };
camera.position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 12.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE}; camera.position = (Vector3){ MAX_WORLD_SIZE / 2 * CHUNK_SIZE, 12.0f, MAX_WORLD_SIZE / 2 * CHUNK_SIZE};
camera.target = (Vector3){camera.position.x, camera.position.y, camera.position.z + 1}; camera.target = (Vector3){camera.position.x, camera.position.y, camera.position.z + 1};
@@ -1213,22 +1299,8 @@ static void GameStart() {
grass_place = LoadSound(Pathify("sound/block_grass.wav")); grass_place = LoadSound(Pathify("sound/block_grass.wav"));
} }
static void CreateNetPlayer(int id) {
Entity temp = NewEntity();
temp.type = 1;
temp.position = player_position;
temp.data[0] = id;
temp.data[1] = 0;
AddEntity(temp);
}
static void RemovePlayerEntity(int id) { static void RemovePlayerEntity(int id) {
auto match = [&](const Entity ent){ players.erase(id);
return ent.data[0] == id && ent.type == 1;
};
auto it = std::find_if(entities.begin(), entities.end(), match);
if (it != entities.end()) {
entities.erase(it);
}
} }
static void ParseMessagePacket(std::vector<unsigned char> &a_data) { static void ParseMessagePacket(std::vector<unsigned char> &a_data) {
std::string output; std::string output;
@@ -1243,6 +1315,14 @@ static void ParseMessagePacket(std::vector<unsigned char> &a_data) {
msg.message = output; msg.message = output;
messages.push_back(msg); messages.push_back(msg);
} }
static void CreatePlayer(int id) {
if(id != plrId) {
NetPlayer temp = {0};
temp.id = id;
temp.nickname = "testificate";
players[id] = temp;
}
}
static void ParseData(ENetPacket* packet) { static void ParseData(ENetPacket* packet) {
int len = packet->dataLength; int len = packet->dataLength;
std::vector<unsigned char> a_data; std::vector<unsigned char> a_data;
@@ -1251,6 +1331,7 @@ static void ParseData(ENetPacket* packet) {
{ {
a_data.push_back(packet->data[i]); a_data.push_back(packet->data[i]);
} }
switch (a_data[0]) switch (a_data[0])
{ {
case NET_ARG_CHUNKF: case NET_ARG_CHUNKF:
@@ -1263,9 +1344,7 @@ static void ParseData(ENetPacket* packet) {
break; break;
case NET_ARG_PLRCON: case NET_ARG_PLRCON:
puts("Player connected"); puts("Player connected");
if(a_data[1] != plrId) { CreatePlayer(a_data[1]);
CreateNetPlayer(a_data[1]);
}
break; break;
case NET_ARG_PLRDCN: case NET_ARG_PLRDCN:
puts("Player disconnected"); puts("Player disconnected");
@@ -1281,49 +1360,37 @@ static void ParseData(ENetPacket* packet) {
player_position.y = y; player_position.y = y;
player_position.z = z; player_position.z = z;
} }
for (Entity &plr : entities) else {
{ NetPlayer &plr = players[a_data[1]];
std::cout << (int)(plr.data[0]) << " " << (int)(plr.type) << std::endl; players[plrId].yaw = a_data[2];
if(plr.data[0] == a_data[1] && plr.type == 1) {
float x = DeserializeFloat(a_data[2],a_data[3]); float x = DeserializeFloat(a_data[2],a_data[3]);
float y = DeserializeFloat(a_data[4],a_data[5]); float y = DeserializeFloat(a_data[4],a_data[5]);
float z = DeserializeFloat(a_data[6],a_data[7]); float z = DeserializeFloat(a_data[6],a_data[7]);
plr.position.x = x; plr.x = x;
plr.position.y = y; plr.y = y;
plr.position.z = z; plr.z = z;
//plr.yaw = (short)floorf(a_data[8] / 255.0f* 65536);
plr.data[1] = 255;
std::cout << x << " " << y << " " << z << " " << (float)(plr.yaw) << std::endl;
}
} }
break; break;
case NET_ARG_ECHOYAW: case NET_ARG_ECHOYAW:
std::cout << "Server requested to sync yaw " << (int)(a_data[1]) << std::endl; std::cout << "Server requested to sync yaw " << (int)(a_data[1]) << std::endl;
for (Entity &plr : entities) if(a_data[1] != plrId) {
{ NetPlayer &plr = players[a_data[1]];
if(plr.data[0] == a_data[1] && plr.type == 1) { players[plrId].yaw = a_data[2];
plr.yaw = (short)floorf(a_data[2] / 255.0f * 65536);
}
} }
break; break;
case NET_ARG_PLRREG: case NET_ARG_PLRREG:
puts("Got a connected player"); puts("Got a connected player");
if(a_data[1] != plrId) { if(a_data[1] != plrId) {
CreateNetPlayer(a_data[1]); CreatePlayer(a_data[1]);
} NetPlayer &plr = players[a_data[1]];
for (Entity &plr : entities)
{
if(plr.data[0] == a_data[1] && plr.type == 1) {
float x = DeserializeFloat(a_data[2],a_data[3]); float x = DeserializeFloat(a_data[2],a_data[3]);
float y = DeserializeFloat(a_data[4],a_data[5]); float y = DeserializeFloat(a_data[4],a_data[5]);
float z = DeserializeFloat(a_data[6],a_data[7]); float z = DeserializeFloat(a_data[6],a_data[7]);
plr.position.x = x; plr.x = x;
plr.position.y = y; plr.y = y;
plr.position.z = z; plr.z = z;
plr.yaw = (short)floorf(a_data[8] / 255.0f * 65536); plr.yaw = (short)floorf(a_data[8] / 255.0f * 65536);
} }
}
break;
case NET_ARG_BLOCK: case NET_ARG_BLOCK:
SetBlock(world, a_data[2], a_data[3], a_data[4], a_data[5]); SetBlock(world, a_data[2], a_data[3], a_data[4], a_data[5]);
dirtyChunks[GetIndexWorld(a_data[2] / 16, a_data[4] / 16)] = true; dirtyChunks[GetIndexWorld(a_data[2] / 16, a_data[4] / 16)] = true;
@@ -1343,6 +1410,32 @@ static void ParseData(ENetPacket* packet) {
case NET_ARG_MESSAGEE: case NET_ARG_MESSAGEE:
ParseMessagePacket(a_data); ParseMessagePacket(a_data);
break; break;
case NET_ARG_ENTITYSPAWN:
{
Entity ent = {0};
ent.id = a_data[1] << 8 | a_data[2];
ent.type = a_data[3];
float x = DeserializeFloat(a_data[4],a_data[5]);
float y = DeserializeFloat(a_data[6],a_data[7]);
float z = DeserializeFloat(a_data[8],a_data[9]);
memcpy(ent.data_sv, a_data.data()+10, 8);
entities.push_back(ent);
}
break;
case NET_ARG_PLRSKIN:
{
NetPlayer &plr = players[a_data[1]];
int texsize = (a_data[2] << 8) | a_data[3];
uint8_t img[texsize];
std::cout << texsize << std::endl;
memcpy(img, a_data.data()+4, texsize);
Image temp = LoadImageFromMemory(".png", img, texsize);
plr.texture = LoadTextureFromImage(temp);
std::cout << plr.id << std::endl;
UnloadImage(temp);
//free(img);
}
break;
default: default:
puts("Malformed data?"); puts("Malformed data?");
break; break;
@@ -1403,14 +1496,10 @@ void NetworkUpdate() {
void GameModeCleanupFull() { void GameModeCleanupFull() {
if(online) { if(online) {
enet_host_destroy(client); enet_host_destroy(client);
online = false; online = false;
} }
stop_server = true;
//serverThread.join();
for (int idx = 0; idx < MAX_WORLD_AREA; idx++) for (int idx = 0; idx < MAX_WORLD_AREA; idx++)
{ {
if(loadedChunks[idx]) { if(loadedChunks[idx]) {
@@ -1418,6 +1507,7 @@ void GameModeCleanupFull() {
//UnloadModel(rendering[idx]); //UnloadModel(rendering[idx]);
} }
} }
stop_server = true;
memset(loadedChunks, 0, sizeof(loadedChunks)); memset(loadedChunks, 0, sizeof(loadedChunks));
memset(dirtyChunks, 0, sizeof(dirtyChunks)); memset(dirtyChunks, 0, sizeof(dirtyChunks));
entities.clear(); entities.clear();
@@ -1430,7 +1520,6 @@ void GameModeCleanup() {
pauseMenuActive = false; pauseMenuActive = false;
EnableCursor(); EnableCursor();
GameModeCleanupFull(); GameModeCleanupFull();
state = GAME_STATE_MAINMENU;
worldCreationProgress = 0; worldCreationProgress = 0;
worldCreationStep = 0; worldCreationStep = 0;
} }
@@ -1439,7 +1528,6 @@ extern void InitMenu();
int main(void) int main(void)
{ {
SetTraceLogLevel(LOG_WARNING); SetTraceLogLevel(LOG_WARNING);
NetworkingStart();
SetConfigFlags(FLAG_WINDOW_RESIZABLE); SetConfigFlags(FLAG_WINDOW_RESIZABLE);
InitWindow(WIDTH, HEIGHT, GAME_NAME); InitWindow(WIDTH, HEIGHT, GAME_NAME);
InitWorldgen(0); InitWorldgen(0);
@@ -1450,6 +1538,8 @@ int main(void)
LocaleUpdate(); LocaleUpdate();
LoadRecipes(); LoadRecipes();
playerTex = LoadTexture(GetPlayerTexturePath());
camera = { 0 }; camera = { 0 };
camera.position = (Vector3){0, 0, 0}; camera.position = (Vector3){0, 0, 0};
camera.target = (Vector3){camera.position.x, camera.position.y, camera.position.z + 1}; camera.target = (Vector3){camera.position.x, camera.position.y, camera.position.z + 1};
@@ -1496,7 +1586,6 @@ int main(void)
GetXZFromIndex(idx, &x, &z); GetXZFromIndex(idx, &x, &z);
c.x = (uint8_t)x; c.x = (uint8_t)x;
c.z = (uint8_t)z; c.z = (uint8_t)z;
std::cout << data.size() << std::endl;
for (int i = 2; i < CHUNK_DATA_SIZE+2; i++) for (int i = 2; i < CHUNK_DATA_SIZE+2; i++)
{ {
c.blocks[i-2] = data[i]; c.blocks[i-2] = data[i];
@@ -1564,12 +1653,14 @@ int main(void)
} }
if (worldCreationStep == 2) if (worldCreationStep == 2)
{ {
//RebuildOpaqueMask(&world[idx]); RebuildOpaqueMask(&world[idx]);
} }
if (worldCreationStep == 3) { if (worldCreationStep == 3) {
dirtyChunks[idx] = true; dirtyChunks[idx] = true;
} }
if(online) if(!(worldCreationStep == 0 && online))
worldCreationProgress++;
else
worldCreationProgress = fetchedChunks+1; worldCreationProgress = fetchedChunks+1;
} }
} }
@@ -1595,7 +1686,15 @@ int main(void)
DrawMultiplayer(); DrawMultiplayer();
break; break;
case GAME_STATE_TRANSITION: case GAME_STATE_TRANSITION:
DrawBackground();
DrawLogoCenter(); DrawLogoCenter();
if(!singleplayerServer || !serverStarted) {
state = GAME_STATE_MAINMENU;
}
if (serverThread.joinable()) {
serverThread.join();
singleplayerServer = false;
}
break; break;
case GAME_STATE_OPTIONS: case GAME_STATE_OPTIONS:
DrawControls(); DrawControls();
@@ -1603,7 +1702,7 @@ int main(void)
} }
} }
enet_deinitialize();
GameModeCleanupFull(); GameModeCleanupFull();
UnloadTexture(terrain); UnloadTexture(terrain);