From 8a25708f6f07a009bddce2772092079459e0039b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 20 Apr 2018 12:57:05 +1000 Subject: [PATCH] Fix a bunch of stuff --- src/Client/Chat.c | 24 ++++++++++++ src/Client/Chat.h | 1 + src/Client/Formats.c | 24 ++++++++---- src/Client/Game.c | 10 +++++ src/Client/Game.h | 8 ++-- src/Client/InputHandler.c | 3 +- src/Client/Platform.h | 4 ++ src/Client/Screens.c | 15 +++++--- src/Client/Screens.h | 8 ++-- src/Client/ServerConnection.c | 10 ++++- src/Client/Stream.c | 70 ++++++++++++++++++----------------- src/Client/Stream.h | 2 + src/Client/String.c | 26 ++++++------- src/Client/String.h | 1 + src/Client/WinPlatform.c | 20 ++++++++++ 15 files changed, 154 insertions(+), 72 deletions(-) diff --git a/src/Client/Chat.c b/src/Client/Chat.c index 9abc70d08..f53ea4ea1 100644 --- a/src/Client/Chat.c +++ b/src/Client/Chat.c @@ -13,6 +13,28 @@ #include "Funcs.h" #include "Block.h" +#define CHAT_LOGTIMES_DEF_ELEMS 256 +#define CHAT_LOGTIMES_EXPAND_ELEMS 512 +Int64 Chat_DefaultLogTimes[CHAT_LOGTIMES_DEF_ELEMS]; +Int64* Chat_LogTimes = &Chat_DefaultLogTimes; +UInt32 Chat_LogTimesCount = CHAT_LOGTIMES_DEF_ELEMS, Chat_LogTimesUsed; + +void Chat_GetLogTime(UInt32 index, Int64* timeMs) { + if (index >= Chat_LogTimesUsed) ErrorHandler_Fail("Tries to get time past LogTime end"); + *timeMs = Chat_LogTimes[index]; +} + +void Chat_AppendLogTime(void) { + DateTime now = Platform_CurrentUTCTime(); + UInt32 count = Chat_LogTimesUsed; + + if (count == Chat_LogTimesCount) { + StringsBuffer_Resize(&Chat_LogTimes, &Chat_LogTimesCount, sizeof(Int64), + CHAT_LOGTIMES_DEF_ELEMS, CHAT_LOGTIMES_EXPAND_ELEMS); + } + Chat_LogTimes[Chat_LogTimesUsed++] = DateTime_TotalMs(&now); +} + void ChatLine_Make(ChatLine* line, STRING_TRANSIENT String* text) { String dst = String_InitAndClearArray(line->Buffer); String_AppendString(&dst, text); @@ -113,6 +135,7 @@ void Chat_AddOf(STRING_PURE String* text, Int32 msgType) { if (msgType == MSG_TYPE_NORMAL) { StringsBuffer_Add(&Chat_Log, text); Chat_AppendLog(text); + Chat_AppendLogTime(); } else if (msgType >= MSG_TYPE_STATUS_1 && msgType <= MSG_TYPE_STATUS_3) { ChatLine_Make(&Chat_Status[msgType - MSG_TYPE_STATUS_1], text); } else if (msgType >= MSG_TYPE_BOTTOMRIGHT_1 && msgType <= MSG_TYPE_BOTTOMRIGHT_3) { @@ -511,6 +534,7 @@ void Chat_Reset(void) { void Chat_Free(void) { commands_count = 0; + if (Chat_LogTimes != Chat_DefaultLogTimes) Platform_MemFree(Chat_LogTimes); StringsBuffer_Free(&Chat_Log); StringsBuffer_Free(&Chat_InputLog); diff --git a/src/Client/Chat.h b/src/Client/Chat.h index 0d029caa8..4e1700506 100644 --- a/src/Client/Chat.h +++ b/src/Client/Chat.h @@ -22,6 +22,7 @@ typedef struct ChatLine_ { UInt8 Buffer[String_BufferSize(STRING_SIZE)]; DateTime Received; } ChatLine; ChatLine Chat_Status[3], Chat_BottomRight[3], Chat_ClientStatus[3], Chat_Announcement; StringsBuffer Chat_Log, Chat_InputLog; +void Chat_GetLogTime(UInt32 index, Int64* timeMS); IGameComponent Chat_MakeGameComponent(void); void Chat_SetLogName(STRING_PURE String* name); diff --git a/src/Client/Formats.c b/src/Client/Formats.c index 9f992f201..2c9d0ffd9 100644 --- a/src/Client/Formats.c +++ b/src/Client/Formats.c @@ -184,8 +184,7 @@ void Fcm_Load(Stream* stream) { #define NBT_TAG_COMPOUND 10 #define NBT_TAG_INT32_ARRAY 11 -/* supported utf8 codepoint can be up to 3 bytes big */ -#define NBT_SMALL_SIZE (STRING_SIZE * 3) +#define NBT_SMALL_SIZE STRING_SIZE struct NbtTag_; typedef struct NbtTag_ { struct NbtTag_* Parent; @@ -244,14 +243,23 @@ UInt8 NbtTag_U8_At(NbtTag* tag, Int32 i) { return tag->DataBig[i]; } -UInt32 Nbt_ReadString(Stream* stream, UInt8* buffer) { +UInt32 Nbt_ReadString(Stream* stream, UInt8* strBuffer) { UInt16 nameLen = Stream_ReadUInt16_BE(stream); - if (nameLen > NBT_SMALL_SIZE) ErrorHandler_Fail("NBT String too long"); + if (nameLen > NBT_SMALL_SIZE * 4) ErrorHandler_Fail("NBT String too long"); + UInt8 nameBuffer[NBT_SMALL_SIZE * 4]; + Stream_Read(stream, nameBuffer, nameLen); - /* TODO: this is wrong, we need to UTF8 decode here*/ - encoding.utf8.decode(buffer, nameLen); - Stream_Read(stream, buffer, nameLen); - return nameLen; + /* TODO: Check how slow reading strings this way is */ + Stream memStream; + Stream_ReadonlyMemory(&memStream, nameBuffer, nameLen, &stream->Name); + UInt16 codepoint; + + UInt32 i; + for (i = 0; i < NBT_SMALL_SIZE; i++) { + if (!Stream_ReadUtf8Char(&memStream, &codepoint)) break; + strBuffer[i] = Convert_UnicodeToCP437(codepoint); + } + return i; } void Nbt_ReadTag(UInt8 typeId, bool readTagName, Stream* stream, NbtTag* parent) { diff --git a/src/Client/Game.c b/src/Client/Game.c index dfbffb8a0..16d7312cb 100644 --- a/src/Client/Game.c +++ b/src/Client/Game.c @@ -18,6 +18,16 @@ #include "Chat.h" #include "Platform.h" +UInt8 Game_UsernameBuffer[String_BufferSize(STRING_SIZE)]; +extern String Game_Username = String_FromEmptyArray(Game_UsernameBuffer); +UInt8 Game_MppassBuffer[String_BufferSize(STRING_SIZE)]; +extern String Game_Mppass = String_FromEmptyArray(Game_MppassBuffer); + +UInt8 Game_IPAddressBuffer[String_BufferSize(STRING_SIZE)]; +extern String Game_IPAddress = String_FromEmptyArray(Game_IPAddressBuffer); +UInt8 Game_FontNameBuffer[String_BufferSize(STRING_SIZE)]; +extern String Game_FontName = String_FromEmptyArray(Game_FontNameBuffer); + Int32 Game_GetWindowScale(void) { Real32 windowScale = min(Game_Width / 640.0f, Game_Height / 480.0f); return 1 + (Int32)windowScale; diff --git a/src/Client/Game.h b/src/Client/Game.h index 9cf65d3db..52c6658c7 100644 --- a/src/Client/Game.h +++ b/src/Client/Game.h @@ -20,9 +20,9 @@ PickedPos Game_CameraClipPos; GfxResourceID Game_DefaultIb; bool Game_UseCPEBlocks; -String Game_Username; -String Game_Mppass; -String Game_IPAddress; +extern String Game_Username; +extern String Game_Mppass; +extern String Game_IPAddress; Int32 Game_Port; Int32 Game_ViewDistance; Int32 Game_MaxViewDistance; @@ -51,7 +51,7 @@ bool Game_SmoothLighting; bool Game_ChatLogging; bool Game_AutoRotate; bool Game_SmoothCamera; -String Game_FontName; +extern String Game_FontName; Int32 Game_ChatLines; bool Game_ClickableChat; bool Game_HideGui; diff --git a/src/Client/InputHandler.c b/src/Client/InputHandler.c index 58f947db5..82e2d5871 100644 --- a/src/Client/InputHandler.c +++ b/src/Client/InputHandler.c @@ -332,7 +332,8 @@ void InputHandler_MouseWheel(void* obj, Real32 delta) { if (!hotbar && Camera_Active->Zoom(delta)) return; if (InputHandler_DoFovZoom(delta) || !Inventory_CanChangeHeldBlock) return; - Gui.hudScreen.hotbar.HandlesMouseScroll(delta); + Widget* hotbarW = HUDScreen_GetHotbar(Gui_HUD); + Elem_HandlesMouseScroll(hotbarW, delta); } void InputHandler_MouseMove(void* obj, Int32 xDelta, Int32 yDelta) { diff --git a/src/Client/Platform.h b/src/Client/Platform.h index 2873c4d3b..fdbdc8586 100644 --- a/src/Client/Platform.h +++ b/src/Client/Platform.h @@ -43,6 +43,10 @@ UInt32 Platform_FilePosition(void* file); UInt32 Platform_FileLength(void* file); void Platform_ThreadSleep(UInt32 milliseconds); +typedef void Platform_ThreadFunc(void); +void* Platform_ThreadStart(Platform_ThreadFunc* func); +/* Frees handle to thread - NOT THE THREAD ITSELF */ +void Platform_ThreadFreeHandle(void* handle); void Platform_MakeFont(FontDesc* desc, STRING_PURE String* fontName, UInt16 size, UInt16 style); void Platform_FreeFont(FontDesc* desc); diff --git a/src/Client/Screens.c b/src/Client/Screens.c index 3b611f17c..22c18d51f 100644 --- a/src/Client/Screens.c +++ b/src/Client/Screens.c @@ -1093,16 +1093,16 @@ void ChatScreen_Render(GuiElement* elem, Real64 delta) { if (screen->HandlesAllInput) { Elem_Render(&screen->Chat, delta); } else { + Int64 nowMS = DateTime_TotalMs(&now); + /* Only render recent chat */ for (i = 0; i < screen->Chat.LinesCount; i++) { Texture tex = screen->Chat.Textures[i]; Int32 logIdx = screen->ChatIndex + i; if (tex.ID == NULL) continue; if (logIdx < 0 || logIdx >= Chat_Log.Count) continue; - DateTime received = game.Chat.Log[logIdx].Received; - if (DateTime_MsBetween(&received, &now) <= 10000) { - Texture_Render(&tex); - } + Int64 received; Chat_GetLogTime(logIdx, &received); + if ((nowMS - received) <= 10 * 1000) Texture_Render(&tex); } } @@ -1114,7 +1114,7 @@ void ChatScreen_Render(GuiElement* elem, Real64 delta) { } } - if (screen->Announcement.Texture.ID != NULL && DateTime_MsBetween(&Chat_Announcement.Received, &now) > 5000) { + if (screen->Announcement.Texture.ID != NULL && DateTime_MsBetween(&Chat_Announcement.Received, &now) > 5 * 1000) { Elem_Free(&screen->Announcement); } } @@ -1376,6 +1376,11 @@ void HUDScreen_AppendInput(Screen* hud, STRING_PURE String* text) { InputWidget_AppendString(&widget->Base, text); } +Widget* HUDScreen_GetHotbar(Screen* hud) { + HUDScreen* screen = (HUDScreen*)hud; + return &screen->Hotbar; +} + /*########################################################################################################################* *----------------------------------------------------DisconnectScreen-----------------------------------------------------* diff --git a/src/Client/Screens.h b/src/Client/Screens.h index 5286f31f6..b36ed0d72 100644 --- a/src/Client/Screens.h +++ b/src/Client/Screens.h @@ -13,13 +13,11 @@ Screen* LoadingScreen_MakeInstance(STRING_PURE String* title, STRING_PURE String Screen* GeneratingScreen_MakeInstance(void); Screen* HUDScreen_MakeInstance(void); IGameComponent HUDScreen_MakeComponent(void); -void HUDScreen_OpenInput(Screen* hud, STRING_PURE String* text); -void HUDScreen_AppendInput(Screen* hud, STRING_PURE String* text); Screen* DisconnectScreen_MakeInstance(STRING_PURE String* title, STRING_PURE String* message); -Screen* OptionsGroupScreen_MakeInstance(void); -Screen* PauseScreen_MakeInstance(void); - /* Raw pointer to inventory screen. DO NOT USE THIS. Use InventoryScreen_MakeInstance() */ extern Screen* InventoryScreen_UNSAFE_RawPointer; +void HUDScreen_OpenInput(Screen* hud, STRING_PURE String* text); +void HUDScreen_AppendInput(Screen* hud, STRING_PURE String* text); +Widget* HUDScreen_GetHotbar(Screen* hud); #endif \ No newline at end of file diff --git a/src/Client/ServerConnection.c b/src/Client/ServerConnection.c index 185d82242..29670c327 100644 --- a/src/Client/ServerConnection.c +++ b/src/Client/ServerConnection.c @@ -52,7 +52,15 @@ void ServerConnection_BeginGeneration(Int32 width, Int32 height, Int32 length, I Gui_SetNewScreen(GeneratingScreen_MakeInstance()); Gen_Width = width; Gen_Height = height; Gen_Length = length; Gen_Seed = seed; - gen.GenerateAsync(); + + void* threadHandle; + if (vanilla) { + threadHandle = Platform_ThreadStart(&NotchyGen_Generate); + } else { + threadHandle = Platform_ThreadStart(&FlatgrassGen_Generate); + } + /* don't leak thread handle here */ + Platform_ThreadFreeHandle(threadHandle); } void ServerConnection_EndGeneration(void) { diff --git a/src/Client/Stream.c b/src/Client/Stream.c index 32b76b1a0..ff71895ff 100644 --- a/src/Client/Stream.c +++ b/src/Client/Stream.c @@ -236,45 +236,47 @@ void Stream_WriteUInt32_BE(Stream* stream, UInt32 value) { /*########################################################################################################################* *--------------------------------------------------Read/Write strings-----------------------------------------------------* *#########################################################################################################################*/ +bool Stream_ReadUtf8Char(Stream* stream, UInt16* codepoint) { + UInt32 read = 0; + UInt8 header; + ReturnCode code = stream->Read(stream, &header, 1, &read); + + if (read == 0) return false; /* end of stream */ + if (!ErrorHandler_Check(code)) { Stream_Fail(stream, code, "reading utf8 from"); } + /* Header byte is just the raw codepoint (common case) */ + if (header <= 0x7F) { *codepoint = header; return true; } + + /* Header byte encodes variable number of following bytes */ + /* The remaining bits of the header form first part of the character */ + Int32 byteCount = 0, i; + for (i = 7; i >= 0; i--) { + if ((header & (1 << i)) != 0) { + byteCount++; + header &= (UInt8)~(1 << i); + } else { + break; + } + } + + *codepoint = header; + for (i = 0; i < byteCount - 1; i++) { + *codepoint <<= 6; + /* Top two bits of each are always 10 */ + *codepoint |= (UInt16)(Stream_ReadUInt8(stream) & 0x3F); + } + return true; +} + bool Stream_ReadLine(Stream* stream, STRING_TRANSIENT String* text) { String_Clear(text); for (;;) { - UInt32 byteCount = 0, read = 0; - UInt8 header; - - ReturnCode code = stream->Read(stream, &header, 1, &read); - if (read == 0) return false; /* end of stream */ - if (!ErrorHandler_Check(code)) { Stream_Fail(stream, code, "reading line from"); } - - /* Header byte encodes variable number of following bytes */ - /* The remaining bits of the header form first part of the character */ - Int32 bit; - for (bit = 7; bit >= 0; bit--) { - if ((header & (1 << bit)) != 0) { - byteCount++; - header &= (UInt8)~(1 << bit); - } else { - break; - } - } - - UInt16 codeword; - if (byteCount == 0) { - codeword = (UInt8)header; - } else { - codeword = header; - Int32 i; - for (i = 0; i < byteCount - 1; i++) { - codeword <<= 6; - /* Top two bits of each are always 10 */ - codeword |= (UInt16)(Stream_ReadUInt8(stream) & 0x3F); - } - } + UInt16 codepoint; + if (!Stream_ReadUtf8Char(stream, &codepoint)) return false; /* Handle \r\n or \n line endings */ - if (codeword == '\r') continue; - if (codeword == '\n') return true; - String_Append(text, Convert_UnicodeToCP437(codeword)); + if (codepoint == '\r') continue; + if (codepoint == '\n') return true; + String_Append(text, Convert_UnicodeToCP437(codepoint)); } } diff --git a/src/Client/Stream.h b/src/Client/Stream.h index 434eaa88d..4ae2e0cdb 100644 --- a/src/Client/Stream.h +++ b/src/Client/Stream.h @@ -57,6 +57,8 @@ void Stream_WriteUInt32_LE(Stream* stream, UInt32 value); void Stream_WriteUInt32_BE(Stream* stream, UInt32 value); #define Stream_WriteInt32_BE(stream, value) Stream_WriteUInt32_BE(stream, (UInt32)(value)) +/* Reads a UTF8 encoded character from the given stream. Returns false if end of stream. */ +bool Stream_ReadUtf8Char(Stream* stream, UInt16* codepoint); /* Reads a line of UTF8 encoding text from the given stream. Returns false if end of stream. */ bool Stream_ReadLine(Stream* stream, STRING_TRANSIENT String* text); /* Writes a line of UTF8 encoded text to the given stream. */ diff --git a/src/Client/String.c b/src/Client/String.c index 2031a4654..4d8821f88 100644 --- a/src/Client/String.c +++ b/src/Client/String.c @@ -574,10 +574,10 @@ void StringsBuffer_Init(StringsBuffer* buffer) { } void StringsBuffer_Free(StringsBuffer* buffer) { - if (buffer->TextBufferElems > STRINGSBUFFER_BUFFER_DEF_SIZE) { + if (buffer->TextBuffer != buffer->DefaultBuffer) { Platform_MemFree(buffer->TextBuffer); } - if (buffer->FlagsBufferElems > STRINGSBUFFER_FLAGS_DEF_ELEMS) { + if (buffer->FlagsBuffer != buffer->DefaultFlags) { Platform_MemFree(buffer->FlagsBuffer); } StringsBuffer_UNSAFE_Reset(buffer); @@ -603,20 +603,23 @@ String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, UInt32 index) { return String_Init(&buffer->TextBuffer[offset], (UInt16)len, (UInt16)len); } -void StringsBuffer_ResizeArray(void** buffer, UInt32 curSize, UInt32 newSize, bool reallocing) { +void StringsBuffer_Resize(void** buffer, UInt32* elems, UInt32 elemSize, UInt32 defElems, UInt32 expandElems) { /* We use a statically allocated buffer initally, so can't realloc first time */ void* dst; void* cur = *buffer; - if (!reallocing) { + UInt32 curElems = *elems, newSize = (curElems + expandElems) * elemSize; + if (curElems <= defElems) { dst = Platform_MemAlloc(newSize); if (dst == NULL) ErrorHandler_Fail("Failed allocating memory for StringsBuffer"); - Platform_MemCpy(dst, cur, curSize); + Platform_MemCpy(dst, cur, curElems * elemSize); } else { dst = Platform_MemRealloc(cur, newSize); if (dst == NULL) ErrorHandler_Fail("Failed allocating memory for resizing StringsBuffer"); } + *buffer = dst; + *elems = curElems + expandElems; } void StringsBuffer_Add(StringsBuffer* buffer, STRING_PURE String* text) { @@ -625,11 +628,8 @@ void StringsBuffer_Add(StringsBuffer* buffer, STRING_PURE String* text) { if (buffer->FlagsBufferElems == 0) { ErrorHandler_Fail("StringsBuffer not properly initalised"); } - - UInt32 curElemSize = buffer->FlagsBufferElems * sizeof(UInt32); - UInt32 newElemsSize = (buffer->FlagsBufferElems + STRINGSBUFFER_FLAGS_EXPAND_ELEMS) * sizeof(UInt32); - bool reallocingElems = buffer->FlagsBufferElems > STRINGSBUFFER_FLAGS_DEF_ELEMS; - StringsBuffer_ResizeArray(&buffer->FlagsBuffer, curElemSize, newElemsSize, reallocingElems); + StringsBuffer_Resize(&buffer->FlagsBuffer, &buffer->FlagsBufferElems, sizeof(UInt32), + STRINGSBUFFER_FLAGS_DEF_ELEMS, STRINGSBUFFER_FLAGS_EXPAND_ELEMS); } if (text->length > STRINGSBUFFER_LEN_MASK) { @@ -638,10 +638,8 @@ void StringsBuffer_Add(StringsBuffer* buffer, STRING_PURE String* text) { UInt32 textOffset = buffer->UsedElems; if (textOffset + text->length >= buffer->TextBufferElems) { - UInt32 curTextSize = buffer->TextBufferElems; - UInt32 newTextSize = buffer->TextBufferElems + STRINGSBUFFER_BUFFER_EXPAND_SIZE; - bool reallocingText = buffer->TextBufferElems > STRINGSBUFFER_BUFFER_DEF_SIZE; - StringsBuffer_ResizeArray(&buffer->FlagsBuffer, curTextSize, newTextSize, reallocingText); + StringsBuffer_Resize(&buffer->TextBuffer, &buffer->TextBufferElems, sizeof(UInt8), + STRINGSBUFFER_BUFFER_DEF_SIZE, STRINGSBUFFER_BUFFER_EXPAND_SIZE); } if (text->length > 0) { diff --git a/src/Client/String.h b/src/Client/String.h index 73718f316..d5797261e 100644 --- a/src/Client/String.h +++ b/src/Client/String.h @@ -114,6 +114,7 @@ void StringsBuffer_Free(StringsBuffer* buffer); void StringsBuffer_UNSAFE_Reset(StringsBuffer* buffer); void StringsBuffer_Get(StringsBuffer* buffer, UInt32 index, STRING_TRANSIENT String* text); STRING_REF String StringsBuffer_UNSAFE_Get(StringsBuffer* buffer, UInt32 index); +void StringsBuffer_Resize(void** buffer, UInt32* elems, UInt32 elemSize, UInt32 defElems, UInt32 expandElems); void StringsBuffer_Add(StringsBuffer* buffer, STRING_PURE String* text); void StringsBuffer_Remove(StringsBuffer* buffer, UInt32 index); Int32 StringsBuffer_Compare(StringsBuffer* buffer, UInt32 idxA, UInt32 idxB); diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index 3c2d94dfd..9c38d038a 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -228,6 +228,26 @@ void Platform_ThreadSleep(UInt32 milliseconds) { Sleep(milliseconds); } +DWORD WINAPI Platform_ThreadStartCallback(LPVOID lpParam) { + Platform_ThreadFunc* func = (Platform_ThreadFunc*)lpParam; + (*func)(); + return 0; +} + +void* Platform_ThreadStart(Platform_ThreadFunc* func) { + void* handle = CreateThread(NULL, 0, Platform_ThreadStartCallback, func, 0, NULL); + if (handle == NULL) { + ErrorHandler_FailWithCode(GetLastError(), "Creating thread"); + } + return handle; +} + +void Platform_ThreadFreeHandle(void* handle) { + if (!CloseHandle((HANDLE)handle)) { + ErrorHandler_FailWithCode(GetLastError(), "Freeing thread handle"); + } +} + void Platform_MakeFont(FontDesc* desc, STRING_PURE String* fontName, UInt16 size, UInt16 style) { desc->Size = size;