diff --git a/README.md b/README.md index 49ebd555..70d3b5f7 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,14 @@
Language License -Latest release +Version Downloads Total downloads Issues Pull requests
-[![](https://raw.githubusercontent.com/PQCraft/PQCraft/master/Screenshot_20220918_210819.png)](#?) +[![](https://raw.githubusercontent.com/PQCraft/PQCraft/master/Screenshot_20221128_010856.png)](#?) --- ### Contributing @@ -36,7 +36,7 @@ OpenGL 3.3 or OpenGLES 3.0 support. - To build for debugging, add `DEBUG=[level]` after `make` (eg. `make DEBUG=0 -j run`). This will build the executable with debug symbols, disable symbol stripping, and define the internal `DEBUG` macro with the level specified.
- To compile with using SDL2 instead of GLFW, add `USESDL2=y` after `make`.
- To compile using OpenGL ES instead of OpenGL, add `USEGLES=y` after `make`.
-- To change the target to the standalone server, add `SERVER=y` after `make`. This variable will change the object directory.
+- To change the target to the standalone server, add `MODULE=server` after `make`. This variable will change the object directory.
- To cross compile to Windows on a non-Windows OS, add `WINCROSS=y` after `make`. This variable will change the object directory and binary name.
- To compile a 32-bit binary on a 64-bit machine, add `M32=y` after `make`. This variable will change the object directory.
@@ -49,4 +49,4 @@ When using MSYS2, the MINGW64 environment is recommended and always use `MSYS2=y --- ### Notes Packaging status
-- CaveCube can be installed on Arch Linux using the [cavecube](https://aur.archlinux.org/packages/cavecube) or [cavecube-bin](https://aur.archlinux.org/packages/cavecube-bin) package.
+- CaveCube can be installed on Arch Linux using the [cavecube](https://aur.archlinux.org/packages/cavecube), [cavecube-bin](https://aur.archlinux.org/packages/cavecube-bin), [cavecube-sdl2](https://aur.archlinux.org/packages/cavecube-sdl2), or [cavecube-sdl2-bin](https://aur.archlinux.org/packages/cavecube-sdl2-bin) AUR package.
diff --git a/TODO.md b/TODO.md index f60dd2dd..bd0860a5 100644 --- a/TODO.md +++ b/TODO.md @@ -3,6 +3,7 @@ - More UI elements (buttons, text boxes, etc) - UI interaction (elem states, tooltips, etc) - Add `fit_width_to_text` and `fit_height_to_text` attrib + - Add `text_fmt` attrib - Add items to hotbar - Redo almost everything to do with chunks/blocks - Add physics in `src/physics/` @@ -43,4 +44,8 @@ ### IN-PROGRESS: ### DONE: -- Removed some left-over debugging code +- Made internal messages more linear +- Fixed memory issues +- Updated README.md +- Changed default loopDelay value from 5ms to 1ms +- DEBUG=1+ is now required to print out detailed server start/stop info diff --git a/extras/docs/world saves.txt b/extras/docs/world saves.txt new file mode 100644 index 00000000..1c0da542 --- /dev/null +++ b/extras/docs/world saves.txt @@ -0,0 +1,25 @@ +/ + server/ + players/ + [Player ID in 16 network order hex chars] + + ... + config.cfg + + world/ + entities/ + [Entity ID in 16 hex chars] + + ... + chunks/ + / + [] + + ... + state + + dynamic.inf + + static.inf + + diff --git a/src/common/config.c b/src/common/config.c index 4883892c..7ef1899b 100644 --- a/src/common/config.c +++ b/src/common/config.c @@ -274,6 +274,7 @@ struct config* openConfig(char* path) { } free(sect); cfg->changed = false; + freeFile(fdata); return cfg; } diff --git a/src/game/game.c b/src/game/game.c index 57d02119..b5af17b4 100644 --- a/src/game/game.c +++ b/src/game/game.c @@ -299,7 +299,7 @@ bool doGame(char* addr, int port) { tmpbuf[i] = malloc(4096); } declareConfigKey(config, "Game", "viewDist", "8", false); - declareConfigKey(config, "Game", "loopDelay", "5000", false); + declareConfigKey(config, "Game", "loopDelay", "1000", false); declareConfigKey(config, "Player", "name", "Player", false); declareConfigKey(config, "Player", "skin", "", false); chunks = allocChunks(atoi(getConfigKey(config, "Game", "viewDist"))); diff --git a/src/input/input.c b/src/input/input.c index 2643ea35..4f3dd03c 100644 --- a/src/input/input.c +++ b/src/input/input.c @@ -69,6 +69,8 @@ char* input_sa_names[] = { "single.rotBlockX", "single.rotBlockY", "single.rotBlockZ", + "single.chat", + "single.command", "single.fullscreen", "single.debug", //"single.leftClick", @@ -138,6 +140,8 @@ input_keys input_sa[INPUT_ACTION_SINGLE__MAX] = { KEY('k', 'b', SDL_SCANCODE_R, 0, 0, 0), KEY('k', 'b', SDL_SCANCODE_F, 0, 0, 0), KEY('k', 'b', SDL_SCANCODE_C, 0, 0, 0), + KEY('k', 'b', SDL_SCANCODE_T, 0, 0, 0), + KEY('k', 'b', SDL_SCANCODE_SLASH, 0, 0, 0), KEY('k', 'b', SDL_SCANCODE_F11, 0, 0, 0), KEY('k', 'b', SDL_SCANCODE_F3, 0, 0, 0), //KEY('m', 'b', SDL_BUTTON(1), 0, 0, 0), @@ -162,6 +166,8 @@ input_keys input_sa[INPUT_ACTION_SINGLE__MAX] = { KEY('k', 'b', GLFW_KEY_R, 0, 0, 0), KEY('k', 'b', GLFW_KEY_F, 0, 0, 0), KEY('k', 'b', GLFW_KEY_C, 0, 0, 0), + KEY('k', 'b', GLFW_KEY_T, 0, 0, 0), + KEY('k', 'b', GLFW_KEY_SLASH, 0, 0, 0), KEY('k', 'b', GLFW_KEY_F11, 0, 0, 0), KEY('k', 'b', GLFW_KEY_F3, 0, 0, 0), //KEY('m', 'b', GLFW_MOUSE_BUTTON_LEFT, 0, 0, 0), diff --git a/src/input/input.h b/src/input/input.h index 22128214..78fda38c 100644 --- a/src/input/input.h +++ b/src/input/input.h @@ -47,6 +47,8 @@ enum { /*INPUT_ACTION_SINGLE_ROT_X*/ INPUT_ACTION_SINGLE_VARIANT_NEXT, /*INPUT_ACTION_SINGLE_ROT_Y*/ INPUT_ACTION_SINGLE_VARIANT_PREV, INPUT_ACTION_SINGLE_ROT_Z, + INPUT_ACTION_SINGLE_CHAT, + INPUT_ACTION_SINGLE_COMMAND, INPUT_ACTION_SINGLE_FULLSCR, INPUT_ACTION_SINGLE_DEBUG, //INPUT_ACTION_SINGLE_LCLICK, // move to INPUT_ACTION_UI diff --git a/src/main/version.h b/src/main/version.h index 5d6ff87d..4e93c875 100644 --- a/src/main/version.h +++ b/src/main/version.h @@ -3,7 +3,7 @@ #define VER_MAJOR 0 #define VER_MINOR 5 -#define VER_PATCH 2 +#define VER_PATCH 3 #define _STR(x) #x #define STR(x) _STR(x) diff --git a/src/renderer/renderer.c b/src/renderer/renderer.c index 4bb230ca..c85a4dcf 100644 --- a/src/renderer/renderer.c +++ b/src/renderer/renderer.c @@ -440,16 +440,18 @@ struct msgdata_msg { }; struct msgdata { - bool valid; int size; + int rptr; + int wptr; struct msgdata_msg* msg; - pthread_mutex_t lock; uint64_t id; + pthread_mutex_t lock; }; static force_inline void initMsgData(struct msgdata* mdata) { - mdata->valid = true; mdata->size = 0; + mdata->rptr = -1; + mdata->wptr = -1; mdata->msg = malloc(0); pthread_mutex_init(&mdata->lock, NULL); } @@ -466,30 +468,19 @@ static void deinitMsgData(struct msgdata* mdata) { static force_inline void addMsg(struct msgdata* mdata, int64_t x, int64_t z, uint64_t id, bool dep, int lvl) { pthread_mutex_lock(&mdata->lock); - if (mdata->valid) { - int index = -1; - for (int i = 0; i < mdata->size; ++i) { - /*if (mdata->msg[i].valid && mdata->msg[i].x == x && mdata->msg[i].z == z) { - printf("dup: [%"PRId64", %"PRId64"] with [%d]\n", x, z, i); - goto skip; - } else*/ if (!mdata->msg[i].valid && index == -1) { - index = i; - break; - } - } - if (index == -1) { - index = mdata->size++; - mdata->msg = realloc(mdata->msg, mdata->size * sizeof(*mdata->msg)); - } - //printf("adding [%d]/[%d]\n", index + 1, mdata->size); - mdata->msg[index].valid = true; - mdata->msg[index].dep = dep; - mdata->msg[index].lvl = lvl; - mdata->msg[index].x = x; - mdata->msg[index].z = z; - mdata->msg[index].id = (dep) ? id : mdata->id++; - //skip:; + if (mdata->wptr < 0 || mdata->rptr >= mdata->size) { + mdata->rptr = 0; + mdata->size = 0; } + mdata->wptr = mdata->size++; + //printf("[%lu]: wptr: [%d] size: [%d]\n", (uintptr_t)mdata, mdata->wptr, mdata->size); + mdata->msg = realloc(mdata->msg, mdata->size * sizeof(*mdata->msg)); + mdata->msg[mdata->wptr].valid = true; + mdata->msg[mdata->wptr].dep = dep; + mdata->msg[mdata->wptr].lvl = lvl; + mdata->msg[mdata->wptr].x = x; + mdata->msg[mdata->wptr].z = z; + mdata->msg[mdata->wptr].id = (dep) ? id : mdata->id++; pthread_mutex_unlock(&mdata->lock); } @@ -506,8 +497,8 @@ void setMeshChunkOff(int64_t x, int64_t z) { static force_inline bool getNextMsg(struct msgdata* mdata, struct msgdata_msg* msg) { pthread_mutex_lock(&mdata->lock); - if (mdata->valid) { - for (int i = 0; i < mdata->size; ++i) { + if (mdata->rptr >= 0) { + for (int i = mdata->rptr; i < mdata->size; ++i) { if (mdata->msg[i].valid) { msg->valid = mdata->msg[i].valid; msg->dep = mdata->msg[i].dep; @@ -516,6 +507,8 @@ static force_inline bool getNextMsg(struct msgdata* mdata, struct msgdata_msg* m msg->z = mdata->msg[i].z; msg->id = mdata->msg[i].id; mdata->msg[i].valid = false; + mdata->rptr = i + 1; + //printf("[%lu]: rptr: [%d] size: [%d]\n", (uintptr_t)mdata, mdata->rptr, mdata->size); pthread_mutex_unlock(&mdata->lock); //printf("returning [%d]/[%d]\n", i + 1, mdata->size); return true; @@ -1035,6 +1028,7 @@ static force_inline void meshUIElem(struct meshdata* md, struct ui_data* elemdat y += tch * s; } } + free(tdata); p->x -= mx; p->width += mx * 2; p->y -= my; diff --git a/src/renderer/ui.c b/src/renderer/ui.c index ea6ecf53..5b3501a5 100644 --- a/src/renderer/ui.c +++ b/src/renderer/ui.c @@ -356,6 +356,7 @@ bool calcUIProperties(struct ui_data* elemdata) { void freeUI(struct ui_data* elemdata) { clearUIElems(elemdata); glDeleteBuffers(1, &elemdata->renddata.VBO); + free(elemdata->data); free(elemdata); } diff --git a/src/server/server.c b/src/server/server.c index 0d7b3495..c5900717 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -24,22 +24,23 @@ struct msgdata_msg { }; struct msgdata { - bool valid; int size; + int rptr; + int wptr; struct msgdata_msg* msg; pthread_mutex_t lock; }; static force_inline void initMsgData(struct msgdata* mdata) { - mdata->valid = true; mdata->size = 0; + mdata->rptr = -1; + mdata->wptr = -1; mdata->msg = malloc(0); pthread_mutex_init(&mdata->lock, NULL); } static force_inline void deinitMsgData(struct msgdata* mdata) { pthread_mutex_lock(&mdata->lock); - mdata->valid = false; free(mdata->msg); pthread_mutex_unlock(&mdata->lock); pthread_mutex_destroy(&mdata->lock); @@ -47,36 +48,32 @@ static force_inline void deinitMsgData(struct msgdata* mdata) { static force_inline void addMsg(struct msgdata* mdata, int id, void* data, uint64_t uuid, int uind) { pthread_mutex_lock(&mdata->lock); - if (mdata->valid) { - int index = -1; - for (int i = 0; i < mdata->size; ++i) { - if (mdata->msg[i].id < 0) { - index = i; - break; - } - } - if (index == -1) { - index = mdata->size++; - mdata->msg = realloc(mdata->msg, mdata->size * sizeof(*mdata->msg)); - } - mdata->msg[index].id = id; - mdata->msg[index].data = data; - mdata->msg[index].uuid = uuid; - mdata->msg[index].uind = uind; + if (mdata->wptr < 0 || mdata->rptr >= mdata->size) { + mdata->rptr = 0; + mdata->size = 0; } + mdata->wptr = mdata->size++; + //printf("[%lu]: wptr: [%d] size: [%d]\n", (uintptr_t)mdata, mdata->wptr, mdata->size); + mdata->msg = realloc(mdata->msg, mdata->size * sizeof(*mdata->msg)); + mdata->msg[mdata->wptr].id = id; + mdata->msg[mdata->wptr].data = data; + mdata->msg[mdata->wptr].uuid = uuid; + mdata->msg[mdata->wptr].uind = uind; pthread_mutex_unlock(&mdata->lock); } static force_inline bool getNextMsg(struct msgdata* mdata, struct msgdata_msg* msg) { pthread_mutex_lock(&mdata->lock); - if (mdata->valid) { - for (int i = 0; i < mdata->size; ++i) { + if (mdata->rptr >= 0) { + for (int i = mdata->rptr; i < mdata->size; ++i) { if (mdata->msg[i].id >= 0) { msg->id = mdata->msg[i].id; msg->data = mdata->msg[i].data; msg->uuid = mdata->msg[i].uuid; msg->uind = mdata->msg[i].uind; mdata->msg[i].id = -1; + mdata->rptr = i + 1; + //printf("[%lu]: rptr: [%d] size: [%d]\n", (uintptr_t)mdata, mdata->rptr, mdata->size); pthread_mutex_unlock(&mdata->lock); return true; } @@ -88,14 +85,16 @@ static force_inline bool getNextMsg(struct msgdata* mdata, struct msgdata_msg* m static force_inline bool getNextMsgForUUID(struct msgdata* mdata, struct msgdata_msg* msg, uint64_t uuid) { pthread_mutex_lock(&mdata->lock); - if (mdata->valid) { - for (int i = 0; i < mdata->size; ++i) { + if (mdata->rptr >= 0) { + for (int i = mdata->rptr; i < mdata->size; ++i) { if (mdata->msg[i].id >= 0 && mdata->msg[i].uuid == uuid) { msg->id = mdata->msg[i].id; msg->data = mdata->msg[i].data; msg->uuid = mdata->msg[i].uuid; msg->uind = mdata->msg[i].uind; mdata->msg[i].id = -1; + mdata->rptr = i + 1; + //printf("[%lu]: rptr: [%d] size: [%d]\n", (uintptr_t)mdata, mdata->rptr, mdata->size); pthread_mutex_unlock(&mdata->lock); return true; } @@ -120,6 +119,7 @@ struct timerdata_timer { int priority; uint64_t interval; uint64_t intertime; + bool ack; }; struct timerdata { @@ -218,6 +218,7 @@ static void* servtimerthread(void* vargs) { enum { _SERVER_TIMER1 = 512, _SERVER_TIMER2, + _SERVER_TICK, }; static struct timerdata servtimer; @@ -352,7 +353,7 @@ static void* servthread(void* args) { } case _SERVER_USERCONNECT:; { struct server_data_setskycolor* tmpdata = malloc(sizeof(*tmpdata)); - *tmpdata = (struct server_data_setskycolor){0x8A, 0xC9, 0xFF}; + *tmpdata = (struct server_data_setskycolor){0xA0, 0xC8, 0xFF}; addMsg(&servmsgout[MSG_PRIO_HIGH], SERVER_SETSKYCOLOR, tmpdata, msg.uuid, msg.uind); break; } @@ -579,7 +580,9 @@ int startServer(char* addr, int port, int mcli, char* world) { return -1; } serveralive = true; + #if DBGLVL(1) puts(" Initializing connection..."); + #endif port = servcxn->info.port; setCxnBufSize(servcxn, SERVER_SNDBUF_SIZE, CLIENT_SNDBUF_SIZE); pdata = calloc(maxclients, sizeof(*pdata)); @@ -589,28 +592,37 @@ int startServer(char* addr, int port, int mcli, char* world) { for (int i = 0; i < MSG_PRIO__MAX; ++i) { initMsgData(&servmsgout[i]); } + #if DBGLVL(1) puts(" Initializing noise..."); + #endif setRandSeed(0, 32464); initNoiseTable(0); initWorldgen(); + #if DBGLVL(1) puts(" Initializing timer and events..."); + #endif initTimerData(&servtimer); addTimer(&servtimer, _SERVER_TIMER1, MSG_PRIO_LOW, 2000000); addTimer(&servtimer, _SERVER_TIMER2, MSG_PRIO_LOW, 1200000); + addTimer(&servtimer, _SERVER_TICK, MSG_PRIO_HIGH, 50000); #ifdef NAME_THREADS char name[256]; char name2[256]; name[0] = 0; name2[0] = 0; #endif + #if DBGLVL(1) puts(" Starting server network thread..."); + #endif pthread_create(&servnetthreadh, NULL, &servnetthread, NULL); #ifdef NAME_THREADS pthread_getname_np(servnetthreadh, name2, 256); sprintf(name, "%s:snet", name2); pthread_setname_np(servnetthreadh, name); #endif + #if DBGLVL(1) puts(" Starting server timer thread..."); + #endif pthread_create(&servtimerh, NULL, &servtimerthread, &servtimer); #ifdef NAME_THREADS pthread_getname_np(servtimerh, name2, 256); @@ -622,7 +634,9 @@ int startServer(char* addr, int port, int mcli, char* world) { name[0] = 0; name2[0] = 0; #endif + #if DBGLVL(1) printf(" Starting server thread [%d]...\n", i); + #endif pthread_create(&servpthreads[i], NULL, &servthread, (void*)(intptr_t)i); #ifdef NAME_THREADS pthread_getname_np(servpthreads[i], name2, 256); @@ -644,18 +658,26 @@ void stopServer() { printf(" Waiting for server thread [%d]...\n", i); pthread_join(servpthreads[i], NULL); } + #if DBGLVL(1) puts(" Waiting for server network thread..."); + #endif pthread_join(servnetthreadh, NULL); + #if DBGLVL(1) puts(" Waiting for server timer thread..."); + #endif pthread_join(servtimerh, NULL); + #if DBGLVL(1) puts(" Closing connections..."); + #endif for (int i = 0; i < maxclients; ++i) { if (pdata[i].valid) { closeCxn(pdata[i].cxn); } } closeCxn(servcxn); + #if DBGLVL(1) puts(" Cleaning up..."); + #endif free(pdata); deinitTimerData(&servtimer); for (int i = 0; i < MSG_PRIO__MAX; ++i) {