diff --git a/ClassicalSharp/2D/Screens/Menu/ListScreen.cs b/ClassicalSharp/2D/Screens/Menu/ListScreen.cs index 17cbc9639..6b4bfe86b 100644 --- a/ClassicalSharp/2D/Screens/Menu/ListScreen.cs +++ b/ClassicalSharp/2D/Screens/Menu/ListScreen.cs @@ -68,8 +68,10 @@ namespace ClassicalSharp.Gui.Screens { ButtonWidget MakeText(int i) { string text = Get(currentIndex + i); - return ButtonWidget.Create(game, 300, text, font, TextButtonClick) + ButtonWidget btn = ButtonWidget.Create(game, 300, "", font, TextButtonClick) .SetLocation(Anchor.Centre, Anchor.Centre, 0, (i - 2) * 50); + UpdateText(btn, text); + return btn; } ButtonWidget Make(int x, string text, ClickHandler onClick) { @@ -89,11 +91,15 @@ namespace ClassicalSharp.Gui.Screens { currentIndex = index; for (int i = 0; i < items; i++) { - ((ButtonWidget)widgets[i]).SetText(Get(currentIndex + i)); + UpdateText((ButtonWidget)widgets[i], Get(currentIndex + i)); } UpdateArrows(); } + protected virtual void UpdateText(ButtonWidget widget, string text) { + widget.SetText(text); + } + void UpdateArrows() { widgets[5].Disabled = false; widgets[6].Disabled = false; diff --git a/ClassicalSharp/ClassicalSharp.csproj b/ClassicalSharp/ClassicalSharp.csproj index 0dc44be2c..d2b4397c8 100644 --- a/ClassicalSharp/ClassicalSharp.csproj +++ b/ClassicalSharp/ClassicalSharp.csproj @@ -257,7 +257,6 @@ - diff --git a/ClassicalSharp/Platform/Font.cs b/ClassicalSharp/Platform/Font.cs deleted file mode 100644 index 57b9d1c09..000000000 --- a/ClassicalSharp/Platform/Font.cs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 -#if ANDROID -using System; - -namespace ClassicalSharp { - - // TODO: Actually apply this to the text - public class Font : IDisposable { - - public int Size; - - public FontStyle Style; - - public Font(string name, int size, FontStyle style) { - Size = size; - Style = style; - } - - public Font(Font font, FontStyle style) { - Size = font.Size; - Style = style; - } - - public Font(string name, int size) { - Size = size; - Style = FontStyle.Regular; - } - - void IDisposable.Dispose() { - } - } - - public enum FontStyle { - Regular, - Italic, - Bold, - Underline, - } -} -#endif \ No newline at end of file diff --git a/src/Client/AsyncDownloader.c b/src/Client/AsyncDownloader.c index 439e80e37..f4e9fdef5 100644 --- a/src/Client/AsyncDownloader.c +++ b/src/Client/AsyncDownloader.c @@ -96,10 +96,10 @@ static void AsyncDownloader_Add(String* url, bool priority, String* id, UInt8 ty Platform_Log2("Adding %s (type %b)", &reqUrl, &type); - if (lastModified != NULL) { + if (lastModified) { req.LastModified = *lastModified; } - if (etag != NULL) { + if (etag) { String reqEtag = String_FromEmptyArray(req.Etag); String_Set(&reqEtag, etag); } //request.Data = data; TODO: Implement this. do we need to copy or expect caller to malloc it? @@ -206,7 +206,7 @@ bool AsyncDownloader_GetCurrent(struct AsyncRequest* request, Int32* progress) { *progress = async_curProgress; } Platform_MutexUnlock(async_curRequestMutex); - return request->ID[0] != NULL; + return request->ID[0]; } static void AsyncDownloader_ProcessRequest(struct AsyncRequest* request) { diff --git a/src/Client/BlockPhysics.c b/src/Client/BlockPhysics.c index e4fe93faf..4fc9131f6 100644 --- a/src/Client/BlockPhysics.c +++ b/src/Client/BlockPhysics.c @@ -8,7 +8,7 @@ #include "Block.h" #include "Lighting.h" #include "Options.h" -#include "TreeGen.h" +#include "MapGenerator.h" #include "Platform.h" #include "Game.h" #include "ErrorHandler.h" @@ -121,7 +121,7 @@ void Physics_SetEnabled(bool enabled) { static void Physics_Activate(Int32 index) { BlockID block = World_Blocks[index]; PhysicsHandler activate = Physics_OnActivate[block]; - if (activate != NULL) activate(index, block); + if (activate) activate(index, block); } static void Physics_ActivateNeighbours(Int32 x, Int32 y, Int32 z, Int32 index) { @@ -153,10 +153,10 @@ static void Physics_BlockChanged(void* obj, Vector3I p, BlockID oldBlock, BlockI if (block == BLOCK_AIR) { PhysicsHandler deleteHandler = Physics_OnDelete[oldBlock]; - if (deleteHandler != NULL) deleteHandler(index, oldBlock); + if (deleteHandler) deleteHandler(index, oldBlock); } else { PhysicsHandler placeHandler = Physics_OnPlace[block]; - if (placeHandler != NULL) placeHandler(index, block); + if (placeHandler) placeHandler(index, block); } Physics_ActivateNeighbours(p.X, p.Y, p.Z, index); } @@ -176,17 +176,17 @@ static void Physics_TickRandomBlocks(void) { Int32 index = Random_Range(&physics_rnd, lo, hi); BlockID block = World_Blocks[index]; PhysicsHandler tick = Physics_OnRandomTick[block]; - if (tick != NULL) tick(index, block); + if (tick) tick(index, block); index = Random_Range(&physics_rnd, lo, hi); block = World_Blocks[index]; tick = Physics_OnRandomTick[block]; - if (tick != NULL) tick(index, block); + if (tick) tick(index, block); index = Random_Range(&physics_rnd, lo, hi); block = World_Blocks[index]; tick = Physics_OnRandomTick[block]; - if (tick != NULL) tick(index, block); + if (tick) tick(index, block); } } } diff --git a/src/Client/Chat.c b/src/Client/Chat.c index 8af1c66ff..c27f92ad2 100644 --- a/src/Client/Chat.c +++ b/src/Client/Chat.c @@ -201,7 +201,7 @@ static struct ChatCommand* Commands_GetMatch(STRING_PURE String* cmdName) { String name = String_FromReadonly(cmd->Name); if (!String_CaselessStarts(&name, cmdName)) continue; - if (match != NULL) { + if (match) { Commands_Log("&e/client: Multiple commands found that start with: \"&f%s&e\".", cmdName); return NULL; } diff --git a/src/Client/ChunkUpdater.c b/src/Client/ChunkUpdater.c index e499c33d0..32a358e18 100644 --- a/src/Client/ChunkUpdater.c +++ b/src/Client/ChunkUpdater.c @@ -122,7 +122,7 @@ static void ChunkUpdater_PerformAllocations(void) { void ChunkUpdater_Refresh(void) { ChunkUpdater_ChunkPos = Vector3I_MaxValue(); - if (MapRenderer_Chunks != NULL && World_Blocks != NULL) { + if (MapRenderer_Chunks && World_Blocks) { ChunkUpdater_ClearChunkCache(); ChunkUpdater_ResetChunkCache(); @@ -355,7 +355,7 @@ void ChunkUpdater_DeleteChunk(struct ChunkInfo* info) { #endif Int32 i; - if (info->NormalParts != NULL) { + if (info->NormalParts) { struct ChunkPartInfo* ptr = info->NormalParts; for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) { if (ptr->Offset < 0) continue; @@ -367,7 +367,7 @@ void ChunkUpdater_DeleteChunk(struct ChunkInfo* info) { info->NormalParts = NULL; } - if (info->TranslucentParts != NULL) { + if (info->TranslucentParts) { struct ChunkPartInfo* ptr = info->TranslucentParts; for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) { if (ptr->Offset < 0) continue; @@ -392,14 +392,14 @@ void ChunkUpdater_BuildChunk(struct ChunkInfo* info, Int32* chunkUpdates) { } Int32 i; - if (info->NormalParts != NULL) { + if (info->NormalParts) { struct ChunkPartInfo* ptr = info->NormalParts; for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) { if (ptr->Offset >= 0) { MapRenderer_NormalPartsCount[i]++; } } } - if (info->TranslucentParts != NULL) { + if (info->TranslucentParts) { struct ChunkPartInfo* ptr = info->TranslucentParts; for (i = 0; i < MapRenderer_1DUsedCount; i++, ptr += MapRenderer_ChunksCount) { if (ptr->Offset >= 0) { MapRenderer_TranslucentPartsCount[i]++; } diff --git a/src/Client/Client.vcxproj b/src/Client/Client.vcxproj index d18b37157..796b8041e 100644 --- a/src/Client/Client.vcxproj +++ b/src/Client/Client.vcxproj @@ -232,7 +232,6 @@ - @@ -241,7 +240,6 @@ - @@ -296,12 +294,11 @@ - - + @@ -314,7 +311,6 @@ - diff --git a/src/Client/Client.vcxproj.filters b/src/Client/Client.vcxproj.filters index 32ba46929..8711eee04 100644 --- a/src/Client/Client.vcxproj.filters +++ b/src/Client/Client.vcxproj.filters @@ -144,9 +144,6 @@ - - Header Files\Generator - Header Files\Defines @@ -258,9 +255,6 @@ Header Files\SelectionBox - - Header Files\Generator - Header Files\2D @@ -365,9 +359,6 @@ - - Source Files\Generator - Source Files\Platform @@ -440,9 +431,6 @@ Source Files\SelectionBox - - Source Files\Generator - Source Files\2D @@ -572,10 +560,10 @@ Source Files\Platform - + Source Files\Platform - + Source Files\Platform diff --git a/src/Client/Entity.c b/src/Client/Entity.c index ed6db1dd6..33ef0c1d5 100644 --- a/src/Client/Entity.c +++ b/src/Client/Entity.c @@ -344,7 +344,7 @@ void Entities_Free(void) { Event_UnregisterVoid(&GfxEvents_ContextRecreated, NULL, Entities_ContextRecreated); Event_UnregisterVoid(&ChatEvents_FontChanged, NULL, Entities_ChatFontChanged); - if (ShadowComponent_ShadowTex != NULL) { + if (ShadowComponent_ShadowTex) { Gfx_DeleteTexture(&ShadowComponent_ShadowTex); } } diff --git a/src/Client/Formats.c b/src/Client/Formats.c index aaf3f30fe..536976ba9 100644 --- a/src/Client/Formats.c +++ b/src/Client/Formats.c @@ -267,17 +267,9 @@ static UInt32 Nbt_ReadString(struct Stream* stream, UChar* strBuffer) { UChar nameBuffer[NBT_SMALL_SIZE * 4]; Stream_Read(stream, nameBuffer, nameLen); - /* TODO: Check how slow reading strings this way is */ - struct 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; + String str = String_Init(strBuffer, 0, NBT_SMALL_SIZE); + String_DecodeUtf8(&str, nameBuffer, nameLen); + return str.length; } typedef bool (*Nbt_Callback)(struct NbtTag* tag); @@ -573,7 +565,7 @@ static bool Cw_Callback_5(struct NbtTag* tag) { static bool Cw_Callback(struct NbtTag* tag) { UInt32 depth = 0; struct NbtTag* tmp = tag->Parent; - while (tmp != NULL) { depth++; tmp = tmp->Parent; } + while (tmp) { depth++; tmp = tmp->Parent; } switch (depth) { case 1: return Cw_Callback_1(tag); diff --git a/src/Client/Game.c b/src/Client/Game.c index 043b7bfd7..adecf197c 100644 --- a/src/Client/Game.c +++ b/src/Client/Game.c @@ -202,7 +202,7 @@ void Game_UpdateBlock(Int32 x, Int32 y, Int32 z, BlockID block) { BlockID oldBlock = World_GetBlock(x, y, z); World_SetBlock(x, y, z, block); - if (Weather_Heightmap != NULL) { + if (Weather_Heightmap) { WeatherRenderer_OnBlockChanged(x, y, z, oldBlock, block); } Lighting_OnBlockChanged(x, y, z, oldBlock, block); @@ -231,7 +231,7 @@ void Game_SetDefaultSkinType(struct Bitmap* bmp) { Int32 i; for (i = 0; i < ENTITIES_MAX_COUNT; i++) { struct Entity* entity = Entities_List[i]; - if (entity == NULL || entity->TextureId != NULL) continue; + if (entity == NULL || entity->TextureId) continue; entity->SkinType = Game_DefaultPlayerSkinType; } } diff --git a/src/Client/Gui.c b/src/Client/Gui.c index 58a636e25..7e6122bbe 100644 --- a/src/Client/Gui.c +++ b/src/Client/Gui.c @@ -116,7 +116,7 @@ static void Gui_Free(void) { Gui_ReplaceActive(NULL); Elem_TryFree(Gui_Status); - if (Gui_Active != NULL) { Elem_TryFree(Gui_Active); } + if (Gui_Active) { Elem_TryFree(Gui_Active); } Gfx_DeleteTexture(&Gui_GuiTex); Gfx_DeleteTexture(&Gui_GuiClassicTex); Gfx_DeleteTexture(&Gui_IconsTex); @@ -142,7 +142,7 @@ void Gui_ReplaceActive(struct Screen* screen) { Gui_SetActive(screen); } void Gui_FreeActive(void) { - if (Gui_Active != NULL) { Elem_TryFree(Gui_Active); } + if (Gui_Active) { Elem_TryFree(Gui_Active); } } void Gui_SetActive(struct Screen* screen) { @@ -155,7 +155,7 @@ void Gui_SetActive(struct Screen* screen) { Game_SetCursorVisible(true); } - if (screen != NULL) { Elem_Init(screen); } + if (screen) { Elem_Init(screen); } Gui_Active = screen; } void Gui_RefreshHud(void) { Elem_Recreate(Gui_HUD); } @@ -216,10 +216,10 @@ void Gui_RenderGui(Real64 delta) { if (Gui_Active == NULL || !Gui_Active->HidesHUD && !Gui_Active->RenderHUDOver) { Elem_Render(Gui_HUD, delta); } - if (Gui_Active != NULL) { + if (Gui_Active) { Elem_Render(Gui_Active, delta); } - if (Gui_Active != NULL && !Gui_Active->HidesHUD && Gui_Active->RenderHUDOver) { + if (Gui_Active && !Gui_Active->HidesHUD && Gui_Active->RenderHUDOver) { Elem_Render(Gui_HUD, delta); } @@ -230,7 +230,7 @@ void Gui_RenderGui(Real64 delta) { } void Gui_OnResize(void) { - if (Gui_Active != NULL) { + if (Gui_Active) { Gui_Active->OnResize((struct GuiElem*)Gui_Active); } Gui_HUD->OnResize((struct GuiElem*)Gui_HUD); diff --git a/src/Client/Gui.h b/src/Client/Gui.h index a224ebade..9d1f69001 100644 --- a/src/Client/Gui.h +++ b/src/Client/Gui.h @@ -116,5 +116,5 @@ void TextAtlas_AddInt(struct TextAtlas* atlas, Int32 value, VertexP3fT2fC4b** ve #define Elem_HandlesMouseScroll(elem, delta) (elem)->VTABLE->HandlesMouseScroll((struct GuiElem*)(elem), delta) #define Widget_Reposition(widget) (widget)->Reposition((struct GuiElem*)(widget)); -#define Elem_TryFree(elem) if ((elem)->VTABLE != NULL) { Elem_Free(elem); } +#define Elem_TryFree(elem) if ((elem)->VTABLE) { Elem_Free(elem); } #endif diff --git a/src/Client/InputHandler.c b/src/Client/InputHandler.c index ee3cbfbb5..e535f2e3d 100644 --- a/src/Client/InputHandler.c +++ b/src/Client/InputHandler.c @@ -58,7 +58,7 @@ static void InputHandler_ButtonStateChanged(MouseButton button, bool pressed) { } void InputHandler_ScreenChanged(struct Screen* oldScreen, struct Screen* newScreen) { - if (oldScreen != NULL && oldScreen->HandlesAllInput) { + if (oldScreen && oldScreen->HandlesAllInput) { Platform_CurrentUTCTime(&input_lastClick); } diff --git a/src/Client/MapGenerator.c b/src/Client/MapGenerator.c index 2b95be0ae..24f31e019 100644 --- a/src/Client/MapGenerator.c +++ b/src/Client/MapGenerator.c @@ -3,13 +3,11 @@ #include "ErrorHandler.h" #include "ExtMath.h" #include "Funcs.h" -#include "Noise.h" #include "Platform.h" -#include "Random.h" -#include "TreeGen.h" -#include "Vectors.h" Int32 Gen_MaxX, Gen_MaxY, Gen_MaxZ, Gen_Volume; +#define Gen_Pack(x, y, z) (((y) * Gen_Length + (z)) * Gen_Width + (x)) + static void Gen_Init(void) { Gen_MaxX = Gen_Width - 1; Gen_MaxY = Gen_Height - 1; Gen_MaxZ = Gen_Length - 1; Gen_Volume = Gen_Width * Gen_Length * Gen_Height; @@ -24,6 +22,10 @@ static void Gen_Init(void) { Gen_Done = false; } + +/*########################################################################################################################* +*-----------------------------------------------------Flatgrass gen-------------------------------------------------------* +*#########################################################################################################################*/ static void FlatgrassGen_MapSet(Int32 yStart, Int32 yEnd, BlockID block) { yStart = max(yStart, 0); yEnd = max(yEnd, 0); Int32 y, yHeight = (yEnd - yStart) + 1; @@ -53,6 +55,9 @@ void FlatgrassGen_Generate(void) { } +/*########################################################################################################################* +*----------------------------------------------------Notchy map gen-------------------------------------------------------* +*#########################################################################################################################*/ Int32 waterLevel, oneY, minHeight; Int16* Heightmap; Random rnd; @@ -494,3 +499,171 @@ void NotchyGen_Generate(void) { Platform_MemFree(&Heightmap); Gen_Done = true; } + + +/*########################################################################################################################* +*---------------------------------------------------Noise generation------------------------------------------------------* +*#########################################################################################################################*/ +void ImprovedNoise_Init(UInt8* p, Random* rnd) { + /* shuffle randomly using fisher-yates */ + Int32 i; + for (i = 0; i < 256; i++) { p[i] = i; } + + for (i = 0; i < 256; i++) { + Int32 j = Random_Range(rnd, i, 256); + UInt8 temp = p[i]; p[i] = p[j]; p[j] = temp; + } + + for (i = 0; i < 256; i++) { + p[i + 256] = p[i]; + } +} + +Real32 ImprovedNoise_Calc(UInt8* p, Real32 x, Real32 y) { + Int32 xFloor = x >= 0 ? (Int32)x : (Int32)x - 1; + Int32 yFloor = y >= 0 ? (Int32)y : (Int32)y - 1; + Int32 X = xFloor & 0xFF, Y = yFloor & 0xFF; + x -= xFloor; y -= yFloor; + + Real32 u = x * x * x * (x * (x * 6 - 15) + 10); /* Fade(x) */ + Real32 v = y * y * y * (y * (y * 6 - 15) + 10); /* Fade(y) */ + Int32 A = p[X] + Y, B = p[X + 1] + Y; + + /* Normally, calculating Grad involves a function call. However, we can directly pack this table + (since each value indicates either -1, 0 1) into a set of bit flags. This way we avoid needing + to call another function that performs branching */ +#define xFlags 0x46552222 +#define yFlags 0x2222550A + + Int32 hash = (p[p[A]] & 0xF) << 1; + Real32 g22 = (((xFlags >> hash) & 3) - 1) * x + (((yFlags >> hash) & 3) - 1) * y; /* Grad(p[p[A], x, y) */ + hash = (p[p[B]] & 0xF) << 1; + Real32 g12 = (((xFlags >> hash) & 3) - 1) * (x - 1) + (((yFlags >> hash) & 3) - 1) * y; /* Grad(p[p[B], x - 1, y) */ + Real32 c1 = g22 + u * (g12 - g22); + + hash = (p[p[A + 1]] & 0xF) << 1; + Real32 g21 = (((xFlags >> hash) & 3) - 1) * x + (((yFlags >> hash) & 3) - 1) * (y - 1); /* Grad(p[p[A + 1], x, y - 1) */ + hash = (p[p[B + 1]] & 0xF) << 1; + Real32 g11 = (((xFlags >> hash) & 3) - 1) * (x - 1) + (((yFlags >> hash) & 3) - 1) * (y - 1); /* Grad(p[p[B + 1], x - 1, y - 1) */ + Real32 c2 = g21 + u * (g11 - g21); + + return c1 + v * (c2 - c1); +} + + +void OctaveNoise_Init(struct OctaveNoise* n, Random* rnd, Int32 octaves) { + n->octaves = octaves; + Int32 i; + for (i = 0; i < octaves; i++) { + ImprovedNoise_Init(n->p[i], rnd); + } +} + +Real32 OctaveNoise_Calc(struct OctaveNoise* n, Real32 x, Real32 y) { + Real32 amplitude = 1, freq = 1; + Real32 sum = 0; + Int32 i; + + for (i = 0; i < n->octaves; i++) { + sum += ImprovedNoise_Calc(n->p[i], x * freq, y * freq) * amplitude; + amplitude *= 2.0f; + freq *= 0.5f; + } + return sum; +} + + +void CombinedNoise_Init(struct CombinedNoise* n, Random* rnd, Int32 octaves1, Int32 octaves2) { + OctaveNoise_Init(&n->noise1, rnd, octaves1); + OctaveNoise_Init(&n->noise2, rnd, octaves2); +} + +Real32 CombinedNoise_Calc(struct CombinedNoise* n, Real32 x, Real32 y) { + Real32 offset = OctaveNoise_Calc(&n->noise2, x, y); + return OctaveNoise_Calc(&n->noise1, x + offset, y); +} + + +/*########################################################################################################################* +*--------------------------------------------------Tree generation----------------------------------------------------* +*#########################################################################################################################*/ +#define Tree_Pack(x, y, z) (((y) * Tree_Length + (z)) * Tree_Width + (x)) + +bool TreeGen_CanGrow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 treeHeight) { + /* check tree base */ + Int32 baseHeight = treeHeight - 4; + Int32 x, y, z; + + for (y = treeY; y < treeY + baseHeight; y++) { + for (z = treeZ - 1; z <= treeZ + 1; z++) { + for (x = treeX - 1; x <= treeX + 1; x++) { + if (x < 0 || y < 0 || z < 0 || x >= Tree_Width || y >= Tree_Height || z >= Tree_Length) + return false; + Int32 index = Tree_Pack(x, y, z); + if (Tree_Blocks[index] != BLOCK_AIR) return false; + } + } + } + + /* and also check canopy */ + for (y = treeY + baseHeight; y < treeY + treeHeight; y++) { + for (z = treeZ - 2; z <= treeZ + 2; z++) { + for (x = treeX - 2; x <= treeX + 2; x++) { + if (x < 0 || y < 0 || z < 0 || x >= Tree_Width || y >= Tree_Height || z >= Tree_Length) + return false; + Int32 index = Tree_Pack(x, y, z); + if (Tree_Blocks[index] != BLOCK_AIR) return false; + } + } + } + return true; +} + +#define TreeGen_Place(x, y, z, block)\ +coords[count].X = (x); coords[count].Y = (y); coords[count].Z = (z);\ +blocks[count] = block; count++; + +Int32 TreeGen_Grow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 height, Vector3I* coords, BlockID* blocks) { + Int32 baseHeight = height - 4; + Int32 count = 0; + Int32 xx, y, zz; + + /* leaves bottom layer */ + for (y = treeY + baseHeight; y < treeY + baseHeight + 2; y++) { + for (zz = -2; zz <= 2; zz++) { + for (xx = -2; xx <= 2; xx++) { + Int32 x = treeX + xx, z = treeZ + zz; + + if (Math_AbsI(xx) == 2 && Math_AbsI(zz) == 2) { + if (Random_Float(Tree_Rnd) >= 0.5f) { + TreeGen_Place(x, y, z, BLOCK_LEAVES); + } + } else { + TreeGen_Place(x, y, z, BLOCK_LEAVES); + } + } + } + } + + /* leaves top layer */ + Int32 bottomY = treeY + baseHeight + 2; + for (y = treeY + baseHeight + 2; y < treeY + height; y++) { + for (zz = -1; zz <= 1; zz++) { + for (xx = -1; xx <= 1; xx++) { + Int32 x = xx + treeX, z = zz + treeZ; + + if (xx == 0 || zz == 0) { + TreeGen_Place(x, y, z, BLOCK_LEAVES); + } else if (y == bottomY && Random_Float(Tree_Rnd) >= 0.5f) { + TreeGen_Place(x, y, z, BLOCK_LEAVES); + } + } + } + } + + /* then place trunk */ + for (y = 0; y < height - 1; y++) { + TreeGen_Place(treeX, treeY + y, treeZ, BLOCK_LOG); + } + return count; +} diff --git a/src/Client/MapGenerator.h b/src/Client/MapGenerator.h index 577f6d9ec..23ba4dce3 100644 --- a/src/Client/MapGenerator.h +++ b/src/Client/MapGenerator.h @@ -1,7 +1,9 @@ #ifndef CC_MAP_GEN_H #define CC_MAP_GEN_H #include "String.h" -/* Implements flatgrass map generator, and original classic vanilla map generation. +#include "Random.h" +#include "Vectors.h" +/* Implements flatgrass map generator, and original classic vanilla map generation (with perlin noise) Based on: https://github.com/UnknownShadow200/ClassicalSharp/wiki/Minecraft-Classic-map-generation-algorithm Thanks to Jerralish for originally reverse engineering classic's algorithm, then preparing a high level overview of the algorithm. Copyright 2014 - 2017 ClassicalSharp | Licensed under BSD-3 @@ -10,13 +12,33 @@ volatile Real32 Gen_CurrentProgress; volatile const UChar* Gen_CurrentState; volatile bool Gen_Done; -Int32 Gen_Width, Gen_Height, Gen_Length; -Int32 Gen_Seed; +Int32 Gen_Width, Gen_Height, Gen_Length, Gen_Seed; bool Gen_Vanilla; BlockID* Gen_Blocks; -#define Get_SetDimensions(x, y, z) Gen_Width = x; Gen_Height = y; Gen_Length = z; -#define Gen_Pack(x, y, z) (((y) * Gen_Length + (z)) * Gen_Width + (x)) +#define Gen_SetDimensions(x, y, z) Gen_Width = x; Gen_Height = y; Gen_Length = z; void FlatgrassGen_Generate(void); void NotchyGen_Generate(void); + +#define NOISE_TABLE_SIZE 512 +void ImprovedNoise_Init(UInt8* p, Random* rnd); +Real32 ImprovedNoise_Calc(UInt8* p, Real32 x, Real32 y); + +struct OctaveNoise { UInt8 p[8][NOISE_TABLE_SIZE]; Int32 octaves; }; +void OctaveNoise_Init(struct OctaveNoise* n, Random* rnd, Int32 octaves); +Real32 OctaveNoise_Calc(struct OctaveNoise* n, Real32 x, Real32 y); + +struct CombinedNoise { struct OctaveNoise noise1, noise2; }; +void CombinedNoise_Init(struct CombinedNoise* n, Random* rnd, Int32 octaves1, Int32 octaves2); +Real32 CombinedNoise_Calc(struct CombinedNoise* n, Real32 x, Real32 y); + + +Int32 Tree_Width, Tree_Height, Tree_Length; +BlockID* Tree_Blocks; +Random* Tree_Rnd; +/* Appropriate buffer size to hold positions and blocks generated by the tree generator. */ +#define Tree_BufferCount 96 + +bool TreeGen_CanGrow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 treeHeight); +Int32 TreeGen_Grow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 height, Vector3I* coords, BlockID* blocks); #endif diff --git a/src/Client/Menus.c b/src/Client/Menus.c index 3bb943d10..05e849e86 100644 --- a/src/Client/Menus.c +++ b/src/Client/Menus.c @@ -226,7 +226,7 @@ static Int32 Menu_HandleMouseDown(struct GuiElem* screen, struct Widget** widget if (widget == NULL || !Widget_Contains(widget, x, y)) continue; if (widget->Disabled) return i; - if (widget->MenuClick != NULL && btn == MouseButton_Left) { + if (widget->MenuClick && btn == MouseButton_Left) { widget->MenuClick(screen, (struct GuiElem*)widget); } else { Elem_HandlesMouseDown(widget, x, y, btn); @@ -240,7 +240,7 @@ static Int32 Menu_HandleMouseMove(struct Widget** widgets, Int32 count, Int32 x, Int32 i; for (i = 0; i < count; i++) { struct Widget* widget = widgets[i]; - if (widget != NULL) widget->Active = false; + if (widget) widget->Active = false; } for (i = count - 1; i >= 0; i--) { @@ -494,7 +494,7 @@ static Int32 MenuScreen_Index(struct MenuScreen* screen, struct Widget* w) { static void MenuScreen_Remove(struct MenuScreen* screen, Int32 i) { struct Widget** widgets = screen->Widgets; - if (widgets[i] != NULL) { Elem_TryFree(widgets[i]); } + if (widgets[i]) { Elem_TryFree(widgets[i]); } widgets[i] = NULL; } @@ -556,10 +556,10 @@ static void MenuScreen_Free(struct GuiElem* elem) { struct MenuScreen* screen = (struct MenuScreen*)elem; screen->ContextLost(screen); - if (screen->TitleFont.Handle != NULL) { + if (screen->TitleFont.Handle) { Platform_FontFree(&screen->TitleFont); } - if (screen->TextFont.Handle != NULL) { + if (screen->TextFont.Handle) { Platform_FontFree(&screen->TextFont); } @@ -1103,7 +1103,7 @@ static void GenLevelScreen_Gen(struct GenLevelScreen* screen, bool vanilla) { String msg = String_FromConst("&cOne of the map dimensions is invalid."); Chat_Add(&msg); } else { - Get_SetDimensions(width, height, length); + Gen_SetDimensions(width, height, length); Gen_Vanilla = vanilla; Gen_Seed = seed; Gui_ReplaceActive(GeneratingScreen_MakeInstance()); } @@ -1121,7 +1121,7 @@ static void GenLevelScreen_Notchy(struct GuiElem* elem, struct GuiElem* widget) static void GenLevelScreen_InputClick(struct GuiElem* elem, struct GuiElem* widget) { struct GenLevelScreen* screen = (struct GenLevelScreen*)elem; - if (screen->Selected != NULL) screen->Selected->Base.ShowCaret = false; + if (screen->Selected) screen->Selected->Base.ShowCaret = false; screen->Selected = (struct MenuInputWidget*)widget; Elem_HandlesMouseDown(&screen->Selected->Base, Mouse_X, Mouse_Y, MouseButton_Left); @@ -1167,7 +1167,7 @@ static void GenLevelScreen_Free(struct GuiElem* elem) { static bool GenLevelScreen_HandlesKeyDown(struct GuiElem* elem, Key key) { struct GenLevelScreen* screen = (struct GenLevelScreen*)elem; - if (screen->Selected != NULL && Elem_HandlesKeyDown(&screen->Selected->Base, key)) return true; + if (screen->Selected && Elem_HandlesKeyDown(&screen->Selected->Base, key)) return true; return MenuScreen_HandlesKeyDown(elem, key); } @@ -1242,7 +1242,7 @@ struct GuiElementVTABLE ClassicGenScreen_VTABLE; struct ClassicGenScreen ClassicGenScreen_Instance; static void ClassicGenScreen_Gen(Int32 size) { Random rnd; Random_InitFromCurrentTime(&rnd); - Get_SetDimensions(size, 64, size); Gen_Vanilla = true; + Gen_SetDimensions(size, 64, size); Gen_Vanilla = true; Gen_Seed = Random_Next(&rnd, Int32_MaxValue); Gui_ReplaceActive(GeneratingScreen_MakeInstance()); } @@ -1309,7 +1309,7 @@ static void SaveLevelScreen_RemoveOverwrites(struct SaveLevelScreen* screen) { } static void SaveLevelScreen_MakeDesc(struct SaveLevelScreen* screen, STRING_PURE String* text) { - if (screen->Widgets[5] != NULL) { Elem_TryFree(screen->Widgets[5]); } + if (screen->Widgets[5]) { Elem_TryFree(screen->Widgets[5]); } TextWidget_Create(&screen->Desc, text, &screen->TextFont); Widget_SetLocation((struct Widget*)(&screen->Desc), ANCHOR_CENTRE, ANCHOR_CENTRE, 0, 65); diff --git a/src/Client/ModelCache.c b/src/Client/ModelCache.c index 758c7ae1b..3bb39129f 100644 --- a/src/Client/ModelCache.c +++ b/src/Client/ModelCache.c @@ -54,7 +54,7 @@ void ModelCache_Register(STRING_REF const UChar* name, STRING_PURE const UChar* model.Instance = instance; ModelCache_Models[ModelCache_modelCount++] = model; - if (defaultTexName != NULL) { + if (defaultTexName) { String defaultTex = String_FromReadonly(defaultTexName); instance->defaultTexIndex = ModelCache_GetTextureIndex(&defaultTex); } diff --git a/src/Client/Noise.c b/src/Client/Noise.c deleted file mode 100644 index c964f76e7..000000000 --- a/src/Client/Noise.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "Noise.h" - -void ImprovedNoise_Init(UInt8* p, Random* rnd) { - /* shuffle randomly using fisher-yates */ - Int32 i; - for (i = 0; i < 256; i++) { p[i] = i; } - - for (i = 0; i < 256; i++) { - Int32 j = Random_Range(rnd, i, 256); - UInt8 temp = p[i]; p[i] = p[j]; p[j] = temp; - } - - for (i = 0; i < 256; i++) { - p[i + 256] = p[i]; - } -} - -Real32 ImprovedNoise_Calc(UInt8* p, Real32 x, Real32 y) { - Int32 xFloor = x >= 0 ? (Int32)x : (Int32)x - 1; - Int32 yFloor = y >= 0 ? (Int32)y : (Int32)y - 1; - Int32 X = xFloor & 0xFF, Y = yFloor & 0xFF; - x -= xFloor; y -= yFloor; - - Real32 u = x * x * x * (x * (x * 6 - 15) + 10); /* Fade(x) */ - Real32 v = y * y * y * (y * (y * 6 - 15) + 10); /* Fade(y) */ - Int32 A = p[X] + Y, B = p[X + 1] + Y; - - /* Normally, calculating Grad involves a function call. However, we can directly pack this table - (since each value indicates either -1, 0 1) into a set of bit flags. This way we avoid needing - to call another function that performs branching */ - #define xFlags 0x46552222 - #define yFlags 0x2222550A - - Int32 hash = (p[p[A]] & 0xF) << 1; - Real32 g22 = (((xFlags >> hash) & 3) - 1) * x + (((yFlags >> hash) & 3) - 1) * y; /* Grad(p[p[A], x, y) */ - hash = (p[p[B]] & 0xF) << 1; - Real32 g12 = (((xFlags >> hash) & 3) - 1) * (x - 1) + (((yFlags >> hash) & 3) - 1) * y; /* Grad(p[p[B], x - 1, y) */ - Real32 c1 = g22 + u * (g12 - g22); - - hash = (p[p[A + 1]] & 0xF) << 1; - Real32 g21 = (((xFlags >> hash) & 3) - 1) * x + (((yFlags >> hash) & 3) - 1) * (y - 1); /* Grad(p[p[A + 1], x, y - 1) */ - hash = (p[p[B + 1]] & 0xF) << 1; - Real32 g11 = (((xFlags >> hash) & 3) - 1) * (x - 1) + (((yFlags >> hash) & 3) - 1) * (y - 1); /* Grad(p[p[B + 1], x - 1, y - 1) */ - Real32 c2 = g21 + u * (g11 - g21); - - return c1 + v * (c2 - c1); -} - - -void OctaveNoise_Init(struct OctaveNoise* n, Random* rnd, Int32 octaves) { - n->octaves = octaves; - Int32 i; - for (i = 0; i < octaves; i++) { - ImprovedNoise_Init(n->p[i], rnd); - } -} - -Real32 OctaveNoise_Calc(struct OctaveNoise* n, Real32 x, Real32 y) { - Real32 amplitude = 1, freq = 1; - Real32 sum = 0; - Int32 i; - - for (i = 0; i < n->octaves; i++) { - sum += ImprovedNoise_Calc(n->p[i], x * freq, y * freq) * amplitude; - amplitude *= 2.0f; - freq *= 0.5f; - } - return sum; -} - - -void CombinedNoise_Init(struct CombinedNoise* n, Random* rnd, Int32 octaves1, Int32 octaves2) { - OctaveNoise_Init(&n->noise1, rnd, octaves1); - OctaveNoise_Init(&n->noise2, rnd, octaves2); -} - -Real32 CombinedNoise_Calc(struct CombinedNoise* n, Real32 x, Real32 y) { - Real32 offset = OctaveNoise_Calc(&n->noise2, x, y); - return OctaveNoise_Calc(&n->noise1, x + offset, y); -} diff --git a/src/Client/Noise.h b/src/Client/Noise.h deleted file mode 100644 index 798c18438..000000000 --- a/src/Client/Noise.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef CC_IMPROVED_NOISE_H -#define CC_IMPROVED_NOISE_H -#include "Random.h" -/* Implements perlin noise generation. - Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 -*/ - -#define NOISE_TABLE_SIZE 512 -void ImprovedNoise_Init(UInt8* p, Random* rnd); -Real32 ImprovedNoise_Calc(UInt8* p, Real32 x, Real32 y); - -/* since we need structure to be a fixed size */ -#define MAX_OCTAVES 8 -struct OctaveNoise { - UInt8 p[MAX_OCTAVES][NOISE_TABLE_SIZE]; - Int32 octaves; -}; - -void OctaveNoise_Init(struct OctaveNoise* n, Random* rnd, Int32 octaves); -Real32 OctaveNoise_Calc(struct OctaveNoise* n, Real32 x, Real32 y); - -struct CombinedNoise { - struct OctaveNoise noise1; - struct OctaveNoise noise2; -}; - -void CombinedNoise_Init(struct CombinedNoise* n, Random* rnd, Int32 octaves1, Int32 octaves2); -Real32 CombinedNoise_Calc(struct CombinedNoise* n, Real32 x, Real32 y); -#endif diff --git a/src/Client/PacketHandlers.c b/src/Client/PacketHandlers.c index 2d02aecc2..44782c258 100644 --- a/src/Client/PacketHandlers.c +++ b/src/Client/PacketHandlers.c @@ -114,7 +114,7 @@ static void Handlers_AddEntity(EntityID id, STRING_TRANSIENT String* displayName struct LocalPlayer* p = &LocalPlayer_Instance; if (id != ENTITIES_SELF_ID) { struct Entity* oldEntity = Entities_List[id]; - if (oldEntity != NULL) Entities_Remove(id); + if (oldEntity) Entities_Remove(id); struct NetPlayer* player = &NetPlayers_List[id]; NetPlayer_Init(player, displayName, skinName); @@ -159,7 +159,7 @@ void Handlers_RemoveEntity(EntityID id) { static void Handlers_UpdateLocation(EntityID playerId, struct LocationUpdate* update, bool interpolate) { struct Entity* entity = Entities_List[playerId]; - if (entity != NULL) { + if (entity) { entity->VTABLE->SetLocation(entity, update, interpolate); } } @@ -453,7 +453,7 @@ static void Classic_LevelDataChunk(struct Stream* stream) { static void Classic_LevelFinalise(struct Stream* stream) { Gui_ReplaceActive(NULL); Gui_Active = prevScreen; - if (prevScreen != NULL && prevCursorVisible != Game_GetCursorVisible()) { + if (prevScreen && prevCursorVisible != Game_GetCursorVisible()) { Game_SetCursorVisible(prevCursorVisible); } prevScreen = NULL; @@ -944,7 +944,7 @@ static void CPE_ChangeModel(struct Stream* stream) { String modelName = Handlers_ReadString(stream, modelNameBuffer); struct Entity* entity = Entities_List[id]; - if (entity != NULL) { Entity_SetModel(entity, &modelName); } + if (entity) { Entity_SetModel(entity, &modelName); } } static void CPE_EnvSetMapAppearance(struct Stream* stream) { diff --git a/src/Client/Screens.c b/src/Client/Screens.c index 86c5746b8..a045e2f93 100644 --- a/src/Client/Screens.c +++ b/src/Client/Screens.c @@ -819,7 +819,7 @@ static void ChatScreen_CheckOtherStatuses(struct ChatScreen* screen) { /* Is terrain / texture pack currently being downloaded? */ if (!hasRequest || !(String_Equals(&id, &terrain) || String_Equals(&id, &texPack))) { - if (screen->Status.Textures[1].ID != NULL) { + if (screen->Status.Textures[1].ID) { String empty = String_MakeNull(); TextGroupWidget_SetText(&screen->Status, 1, &empty); } diff --git a/src/Client/ServerConnection.c b/src/Client/ServerConnection.c index 34c6fa27a..2187fd753 100644 --- a/src/Client/ServerConnection.c +++ b/src/Client/ServerConnection.c @@ -189,7 +189,7 @@ static void SPConnection_BeginConnect(void) { } Random rnd; Random_InitFromCurrentTime(&rnd); - Get_SetDimensions(128, 64, 128); Gen_Vanilla = true; + Gen_SetDimensions(128, 64, 128); Gen_Vanilla = true; Gen_Seed = Random_Next(&rnd, Int32_MaxValue); Gui_ReplaceActive(GeneratingScreen_MakeInstance()); } @@ -213,7 +213,7 @@ static void SPConnection_AddPortion(STRING_PURE String* text) { String_UNSAFE_TrimEnd(&tmp); UInt8 col = Drawer2D_LastCol(&tmp, tmp.length); - if (col != NULL) SPConnection_LastCol = col; + if (col) SPConnection_LastCol = col; Chat_Add(&tmp); } diff --git a/src/Client/SkyboxRenderer.c b/src/Client/SkyboxRenderer.c index 97e094443..6a142d2d0 100644 --- a/src/Client/SkyboxRenderer.c +++ b/src/Client/SkyboxRenderer.c @@ -15,7 +15,7 @@ GfxResourceID skybox_tex, skybox_vb; #define SKYBOX_COUNT (6 * 4) bool SkyboxRenderer_ShouldRender(void) { - return skybox_tex != NULL && !EnvRenderer_Minimal; + return skybox_tex && !EnvRenderer_Minimal; } static void SkyboxRenderer_TexturePackChanged(void* obj) { @@ -49,11 +49,11 @@ void SkyboxRenderer_Render(Real64 deltaTime) { Matrix_MulBy(&m, &rotX); /* Rotate around camera */ - Vector3 pos = Game_CurrentCameraPos, zero = Vector3_Zero; + Vector3 camPos = Game_CurrentCameraPos, zero = Vector3_Zero; Game_CurrentCameraPos = zero; Camera_Active->GetView(&view); Matrix_MulBy(&m, &view); - Game_CurrentCameraPos = pos; + Game_CurrentCameraPos = camPos; Gfx_LoadMatrix(&m); Gfx_BindVb(skybox_vb); diff --git a/src/Client/Stream.c b/src/Client/Stream.c index 534d51dd4..4aa4b3bc6 100644 --- a/src/Client/Stream.c +++ b/src/Client/Stream.c @@ -433,6 +433,6 @@ void Stream_WriteLine(struct Stream* stream, STRING_TRANSIENT String* text) { } UInt8* ptr = Platform_NewLine; - while (*ptr != NULL) { buffer[j++] = *ptr++; } + while (*ptr) { buffer[j++] = *ptr++; } if (j > 0) Stream_Write(stream, buffer, j); } diff --git a/src/Client/String.c b/src/Client/String.c index abea0aaac..6045e7f73 100644 --- a/src/Client/String.c +++ b/src/Client/String.c @@ -3,6 +3,7 @@ #include "ErrorHandler.h" #include "Platform.h" #include "ExtMath.h" +#include "Stream.h" #define Char_MakeLower(ch) if ((ch) >= 'A' && (ch) <= 'Z') { (ch) += ' '; } UChar Char_ToLower(UChar c) { @@ -23,20 +24,21 @@ String String_InitAndClear(STRING_REF UChar* buffer, UInt16 capacity) { return str; } +UInt16 String_CalcLen(STRING_PURE UChar* raw, UInt16 capacity) { + UInt16 length = 0; + while (length < capacity && *raw) { raw++; length++; } + return length; +} + String String_MakeNull(void) { return String_Init(NULL, 0, 0); } String String_FromRaw(STRING_REF UChar* buffer, UInt16 capacity) { - UInt16 length = 0; - UChar* cur = buffer; - while (length < capacity && *cur != NULL) { cur++; length++; } - - return String_Init(buffer, length, capacity); + return String_Init(buffer, String_CalcLen(buffer, capacity), capacity); } String String_FromReadonly(STRING_REF const UChar* buffer) { - String str = String_FromRaw(buffer, UInt16_MaxValue); - str.capacity = str.length; - return str; + UInt16 len = String_CalcLen(buffer, UInt16_MaxValue); + return String_Init(buffer, len, len); } @@ -250,30 +252,28 @@ bool String_Hex64(STRING_TRANSIENT String* str, UInt64 value) { return String_AppendConst(str, hex); } -bool String_AppendConst(STRING_TRANSIENT String* str, const UChar* toAppend) { - UChar cur; - - while ((cur = *toAppend) != NULL) { - if (!String_Append(str, cur)) return false; - toAppend++; +bool String_AppendConst(STRING_TRANSIENT String* str, const UChar* src) { + while (*src) { + if (!String_Append(str, *src)) return false; + src++; } return true; } -bool String_AppendString(STRING_TRANSIENT String* str, STRING_PURE String* toAppend) { +bool String_AppendString(STRING_TRANSIENT String* str, STRING_PURE String* src) { Int32 i; - for (i = 0; i < toAppend->length; i++) { - if (!String_Append(str, toAppend->buffer[i])) return false; + for (i = 0; i < src->length; i++) { + if (!String_Append(str, src->buffer[i])) return false; } return true; } -bool String_AppendColorless(STRING_TRANSIENT String* str, STRING_PURE String* toAppend) { +bool String_AppendColorless(STRING_TRANSIENT String* str, STRING_PURE String* src) { Int32 i; - for (i = 0; i < toAppend->length; i++) { - UChar c = toAppend->buffer[i]; + for (i = 0; i < src->length; i++) { + UChar c = src->buffer[i]; if (c == '&') { i++; continue; } /* Skip over the following colour code */ if (!String_Append(str, c)) return false; } @@ -511,6 +511,17 @@ bool Convert_TryUnicodeToCP437(UInt16 c, UChar* value) { *value = '?'; return false; } +void String_DecodeUtf8(STRING_TRANSIENT String* str, UInt8* data, UInt32 len) { + String name = String_FromConst("Decoding UTF8"); + struct Stream mem; Stream_ReadonlyMemory(&mem, data, len, &name); + UInt16 codepoint; + + while (mem.Meta_Mem_Left > 0) { + if (!Stream_ReadUtf8Char(&mem, &codepoint)) break; + String_Append(str, Convert_UnicodeToCP437(codepoint)); + } +} + bool Convert_TryParseUInt8(STRING_PURE String* str, UInt8* value) { *value = 0; Int32 tmp; if (!Convert_TryParseInt32(str, &tmp) || tmp < 0 || tmp > UInt8_MaxValue) return false; diff --git a/src/Client/String.h b/src/Client/String.h index e972069b7..3f8e7e88d 100644 --- a/src/Client/String.h +++ b/src/Client/String.h @@ -27,6 +27,7 @@ typedef struct String_ { UInt16 capacity; /* Max number of characters that can be in buffer. */ } String; +UInt16 String_CalcLen(STRING_PURE UChar* raw, UInt16 capacity); String String_MakeNull(void); String String_Init(STRING_REF UChar* buffer, UInt16 length, UInt16 capacity); String String_InitAndClear(STRING_REF UChar* buffer, UInt16 capacity); @@ -67,9 +68,9 @@ bool String_AppendUInt64(STRING_TRANSIENT String* str, UInt64 num); bool String_AppendReal32(STRING_TRANSIENT String* str, Real32 num, Int32 fracDigits); /* TODO: Need to account for , or . for decimal */ bool String_Hex32(STRING_TRANSIENT String* str, UInt32 value); bool String_Hex64(STRING_TRANSIENT String* str, UInt64 value); -bool String_AppendConst(STRING_TRANSIENT String* str, const UChar* toAppend); -bool String_AppendString(STRING_TRANSIENT String* str, STRING_PURE String* toAppend); -bool String_AppendColorless(STRING_TRANSIENT String* str, STRING_PURE String* toAppend); +bool String_AppendConst(STRING_TRANSIENT String* str, const UChar* src); +bool String_AppendString(STRING_TRANSIENT String* str, STRING_PURE String* src); +bool String_AppendColorless(STRING_TRANSIENT String* str, STRING_PURE String* src); Int32 String_IndexOf(STRING_PURE String* str, UChar c, Int32 offset); Int32 String_LastIndexOf(STRING_PURE String* str, UChar c); @@ -93,6 +94,8 @@ void String_Format4(STRING_TRANSIENT String* str, const UChar* format, const voi UInt16 Convert_CP437ToUnicode(UChar c); UChar Convert_UnicodeToCP437(UInt16 c); bool Convert_TryUnicodeToCP437(UInt16 c, UChar* value); +void String_DecodeUtf8(STRING_TRANSIENT String* str, UInt8* data, UInt32 len); + bool Convert_TryParseUInt8(STRING_PURE String* str, UInt8* value); bool Convert_TryParseInt16(STRING_PURE String* str, Int16* value); bool Convert_TryParseUInt16(STRING_PURE String* str, UInt16* value); diff --git a/src/Client/TreeGen.c b/src/Client/TreeGen.c deleted file mode 100644 index e40bdfc3c..000000000 --- a/src/Client/TreeGen.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "TreeGen.h" -#include "BlockID.h" -#include "ExtMath.h" -#include "Vectors.h" - -bool TreeGen_CanGrow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 treeHeight) { - /* check tree base */ - Int32 baseHeight = treeHeight - 4; - Int32 x, y, z; - - for (y = treeY; y < treeY + baseHeight; y++) { - for (z = treeZ - 1; z <= treeZ + 1; z++) { - for (x = treeX - 1; x <= treeX + 1; x++) - { - if (x < 0 || y < 0 || z < 0 || x >= Tree_Width || y >= Tree_Height || z >= Tree_Length) - return false; - Int32 index = Tree_Pack(x, y, z); - if (Tree_Blocks[index] != BLOCK_AIR) return false; - } - } - } - - /* and also check canopy */ - for (y = treeY + baseHeight; y < treeY + treeHeight; y++) { - for (z = treeZ - 2; z <= treeZ + 2; z++) { - for (x = treeX - 2; x <= treeX + 2; x++) { - if (x < 0 || y < 0 || z < 0 || x >= Tree_Width || y >= Tree_Height || z >= Tree_Length) - return false; - Int32 index = Tree_Pack(x, y, z); - if (Tree_Blocks[index] != BLOCK_AIR) return false; - } - } - } - return true; -} - -#define TreeGen_Place(x, y, z, block)\ -coords[count].X = (x); coords[count].Y = (y); coords[count].Z = (z);\ -blocks[count] = block;\ -count++; - -Int32 TreeGen_Grow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 height, Vector3I* coords, BlockID* blocks) { - Int32 baseHeight = height - 4; - Int32 count = 0; - Int32 xx, y, zz; - - /* leaves bottom layer */ - for (y = treeY + baseHeight; y < treeY + baseHeight + 2; y++) { - for (zz = -2; zz <= 2; zz++) { - for (xx = -2; xx <= 2; xx++) { - Int32 x = treeX + xx, z = treeZ + zz; - - if (Math_AbsI(xx) == 2 && Math_AbsI(zz) == 2) { - if (Random_Float(Tree_Rnd) >= 0.5f) { - TreeGen_Place(x, y, z, BLOCK_LEAVES); - } - } else { - TreeGen_Place(x, y, z, BLOCK_LEAVES); - } - } - } - } - - /* leaves top layer */ - Int32 bottomY = treeY + baseHeight + 2; - for (y = treeY + baseHeight + 2; y < treeY + height; y++) { - for (zz = -1; zz <= 1; zz++) { - for (xx = -1; xx <= 1; xx++) { - Int32 x = xx + treeX, z = zz + treeZ; - - if (xx == 0 || zz == 0) { - TreeGen_Place(x, y, z, BLOCK_LEAVES); - } else if (y == bottomY && Random_Float(Tree_Rnd) >= 0.5f) { - TreeGen_Place(x, y, z, BLOCK_LEAVES); - } - } - } - } - - /* then place trunk */ - for (y = 0; y < height - 1; y++) { - TreeGen_Place(treeX, treeY + y, treeZ, BLOCK_LOG); - } - return count; -} diff --git a/src/Client/TreeGen.h b/src/Client/TreeGen.h deleted file mode 100644 index 84ddc2430..000000000 --- a/src/Client/TreeGen.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef CC_TREE_GEN_H -#define CC_TREE_GEN_H -#include "Random.h" -#include "Vectors.h" -/* Implements original classic vanilla map generation - Based on: https://github.com/UnknownShadow200/ClassicalSharp/wiki/Minecraft-Classic-map-generation-algorithm - Thanks to Jerralish for originally reverse engineering classic's algorithm, then preparing a high level overview of the algorithm. - I believe this process adheres to clean room reverse engineering. - Copyright 2014 - 2017 ClassicalSharp | Licensed under BSD-3 -*/ - -/* Dimensions of the map trees are generated on. */ -Int32 Tree_Width, Tree_Height, Tree_Length; -/* Blocks of the map trees are generated on. */ -BlockID* Tree_Blocks; -/* Random number generator used for trees. */ -Random* Tree_Rnd; - -/* Packs a coordinate into a single integer index. */ -#define Tree_Pack(x, y, z) (((y) * Tree_Length + (z)) * Tree_Width + (x)) -/* Appropriate buffer size to hold positions and blocks generated by the tree generator. */ -#define Tree_BufferCount 96 - -/* Returns whether a tree can grow at the specified coordinates. */ -bool TreeGen_CanGrow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 treeHeight); -/* Plants a tree of the given height at the given coordinates. -coords and blocks point to arrays which are filled with the generated positions and block ids. */ -Int32 TreeGen_Grow(Int32 treeX, Int32 treeY, Int32 treeZ, Int32 height, Vector3I* coords, BlockID* blocks); -#endif diff --git a/src/Client/Typedefs.h b/src/Client/Typedefs.h index 28e66e645..d21c2025e 100644 --- a/src/Client/Typedefs.h +++ b/src/Client/Typedefs.h @@ -14,7 +14,7 @@ typedef signed __int8 Int8; typedef signed __int16 Int16; typedef signed __int32 Int32; typedef signed __int64 Int64; -#elif (__STDC_VERSION__ >= 199901L) +#elif __GNUC__ || (__STDC_VERSION__ >= 199901L) #include typedef uint8_t UInt8; typedef uint16_t UInt16; diff --git a/src/Client/Widgets.c b/src/Client/Widgets.c index e96387ed0..7cecc97ed 100644 --- a/src/Client/Widgets.c +++ b/src/Client/Widgets.c @@ -43,7 +43,7 @@ static void TextWidget_Init(struct GuiElem* elem) { static void TextWidget_Render(struct GuiElem* elem, Real64 delta) { struct TextWidget* widget = (struct TextWidget*)elem; - if (widget->Texture.ID != NULL) { + if (widget->Texture.ID) { Texture_RenderShaded(&widget->Texture, widget->Col); } } @@ -713,7 +713,7 @@ static void TableWidget_Render(struct GuiElem* elem, Real64 delta) { } IsometricDrawer_EndBatch(); - if (widget->DescTex.ID != NULL) { + if (widget->DescTex.ID) { Texture_Render(&widget->DescTex); } Gfx_SetTexturing(false); @@ -949,7 +949,7 @@ static UChar InputWidget_GetLastCol(struct InputWidget* widget, Int32 indexX, In InputWidget_FormatLine(widget, y, &line); UChar code = Drawer2D_LastCol(&line, x); - if (code != NULL) return code; + if (code) return code; if (y > 0) { x = widget->Lines[y - 1].length; } } return NULL; @@ -992,7 +992,7 @@ static void InputWidget_UpdateCaret(struct InputWidget* widget) { /* Update the colour of the widget->CaretPos */ UChar code = InputWidget_GetLastCol(widget, widget->CaretX, widget->CaretY); - if (code != NULL) widget->CaretCol = Drawer2D_Cols[code]; + if (code) widget->CaretCol = Drawer2D_Cols[code]; } static void InputWidget_RenderCaret(struct InputWidget* widget, Real64 delta) { @@ -2265,7 +2265,7 @@ static Int32 TextGroupWidget_CalcY(struct TextGroupWidget* widget, Int32 index, void TextGroupWidget_SetUsePlaceHolder(struct TextGroupWidget* widget, Int32 index, bool placeHolder) { widget->PlaceholderHeight[index] = placeHolder; - if (widget->Textures[index].ID != NULL) return; + if (widget->Textures[index].ID) return; Int32 newHeight = placeHolder ? widget->DefaultHeight : 0; widget->Textures[index].Y = TextGroupWidget_CalcY(widget, index, newHeight); @@ -2277,7 +2277,7 @@ Int32 TextGroupWidget_UsedHeight(struct TextGroupWidget* widget) { struct Texture* textures = widget->Textures; for (i = 0; i < widget->LinesCount; i++) { - if (textures[i].ID != NULL) break; + if (textures[i].ID) break; } for (; i < widget->LinesCount; i++) { height += textures[i].Height; diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index b31a9a2ee..ad8f04ae9 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -173,32 +173,31 @@ ReturnCode Platform_DirectoryCreate(STRING_PURE String* path) { } ReturnCode Platform_EnumFiles(STRING_PURE String* path, void* obj, Platform_EnumFilesCallback callback) { - /* Need to do directory\* to search for files in directory */ - UChar searchPatternBuffer[FILENAME_SIZE + 10]; - String searchPattern = String_InitAndClearArray(searchPatternBuffer); - String_Format1(&searchPattern, "%s\\*", path); + WCHAR data[512]; Platform_UnicodeExpand(data, path); + /* Need to append \* to search for files in directory */ + data[path->length + 0] = '\\'; + data[path->length + 1] = '*'; + data[path->length + 2] = NULL; - WCHAR searchUnicode[String_BufferSize(FILENAME_SIZE)]; - Platform_UnicodeExpand(searchUnicode, &searchPattern); - - WIN32_FIND_DATAW data; - HANDLE find = FindFirstFileW(searchUnicode, &data); + WIN32_FIND_DATAW entry; + HANDLE find = FindFirstFileW(data, &entry); if (find == INVALID_HANDLE_VALUE) return GetLastError(); + UInt8 fileBuffer[String_BufferSize(MAX_PATH)]; + String file = String_InitAndClearArray(fileBuffer); + do { - if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; - String path = String_Init((UChar*)data.cFileName, 0, MAX_PATH); + if (entry.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) continue; + String_Clear(&file); Int32 i; - /* unicode to code page 437*/ - for (i = 0; i < MAX_PATH && data.cFileName[i] != NULL; i++) { - path.buffer[i] = Convert_UnicodeToCP437(data.cFileName[i]); + for (i = 0; i < MAX_PATH && entry.cFileName[i] != NULL; i++) { + String_Append(&file, Convert_UnicodeToCP437(entry.cFileName[i])); } - path.length = i; - String filename = path; Utils_UNSAFE_GetFilename(&filename); - callback(&filename, obj); - } while (FindNextFileW(find, &data)); + Utils_UNSAFE_GetFilename(&file); + callback(&file, obj); + } while (FindNextFileW(find, &entry)); ReturnCode code = GetLastError(); /* return code from FindNextFile */ FindClose(find); @@ -308,17 +307,12 @@ void Platform_ThreadFreeHandle(void* handle) { } } -CRITICAL_SECTION mutexList[3]; -Int32 mutexIndex; +CRITICAL_SECTION mutexList[3]; Int32 mutexIndex; void* Platform_MutexCreate(void) { - if (mutexIndex == Array_Elems(mutexList)) { - ErrorHandler_Fail("Cannot allocate another mutex"); - return NULL; - } else { - CRITICAL_SECTION* ptr = &mutexList[mutexIndex]; - InitializeCriticalSection(ptr); mutexIndex++; - return ptr; - } + if (mutexIndex == Array_Elems(mutexList)) ErrorHandler_Fail("Cannot allocate mutex"); + CRITICAL_SECTION* ptr = &mutexList[mutexIndex]; + InitializeCriticalSection(ptr); mutexIndex++; + return ptr; } void Platform_MutexFree(void* handle) { diff --git a/src/Client/WinWindow.c b/src/Client/WinWindow.c index 9d8eb5da9..6386f9799 100644 --- a/src/Client/WinWindow.c +++ b/src/Client/WinWindow.c @@ -380,7 +380,7 @@ static LRESULT CALLBACK Window_Procedure(HWND handle, UINT message, WPARAM wPara case WM_DESTROY: Window_Exists = false; UnregisterClassA(win_ClassName, win_Instance); - if (win_DC != NULL) ReleaseDC(win_Handle, win_DC); + if (win_DC) ReleaseDC(win_Handle, win_DC); Event_RaiseVoid(&WindowEvents_Closed); break; } @@ -449,12 +449,12 @@ void Window_GetClipboardText(STRING_TRANSIENT String* value) { UInt8 c; if (isUnicode) { UInt16* text = (UInt16*)src; - for (; *text != NULL; text++) { + for (; *text; text++) { if (Convert_TryUnicodeToCP437(*text, &c)) String_Append(value, c); } } else { UChar* text = (UChar*)src; - for (; *text != NULL; text++) { + for (; *text; text++) { if (Convert_TryUnicodeToCP437(*text, &c)) String_Append(value, c); } } @@ -611,7 +611,7 @@ void Window_ProcessEvents(void) { } HWND foreground = GetForegroundWindow(); - if (foreground != NULL) { + if (foreground) { Window_Focused = foreground == win_Handle; } } diff --git a/src/Client/PosixPlatform.c b/src/Client/X11Platform.c similarity index 74% rename from src/Client/PosixPlatform.c rename to src/Client/X11Platform.c index 2d2612c1b..19ec768a3 100644 --- a/src/Client/PosixPlatform.c +++ b/src/Client/X11Platform.c @@ -1,10 +1,10 @@ #include "Platform.h" -#define CC_BUILD_X11 0 #if CC_BUILD_X11 #include "PackedCol.h" #include "Drawer2D.h" #include "Stream.h" #include "ErrorHandler.h" +#include "Constants.h" #include #include #include @@ -35,8 +35,9 @@ static void Platform_UnicodeExpand(UInt8* dst, STRING_PURE String* src) { *dst = NULL; } -void Platform_Init(void); -void Platform_Free(void); +void Platform_Init(void) { } +void Platform_Free(void) { } + void Platform_Exit(ReturnCode code) { exit(code); } STRING_PURE String Platform_GetCommandLineArgs(void); @@ -123,15 +124,23 @@ ReturnCode Platform_EnumFiles(STRING_PURE String* path, void* obj, Platform_Enum DIR* dirPtr = opendir(data); if (dirPtr == NULL) return errno; + UInt8 fileBuffer[String_BufferSize(FILENAME_SIZE)]; + String file = String_InitAndClearArray(fileBuffer); struct dirent* entry; + + /* TODO: does this also include subdirectories */ while (entry = readdir(dirPtr)) { - puts(ep->d_name); - /* TODO: does this also include subdirectories */ + UInt16 len = String_CalcLen(entry->d_name, UInt16_MaxValue); + String_Clear(&file); + String_DecodeUtf8(&file, entry->d_name, len); + + Utils_UNSAFE_GetFilename(&file); + callback(&file, obj); } int result = errno; /* return code from readdir */ closedir(dirPtr); - return result; + return result; } ReturnCode Platform_FileGetModifiedTime(STRING_PURE String* path, DateTime* time) { @@ -200,17 +209,60 @@ ReturnCode Platform_FileLength(void* file, UInt32* length) { *length = st.st_size; return 0; } -void Platform_ThreadSleep(UInt32 milliseconds); -typedef void Platform_ThreadFunc(void); -void* Platform_ThreadStart(Platform_ThreadFunc* func); -void Platform_ThreadJoin(void* handle); -/* Frees handle to thread - NOT THE THREAD ITSELF */ -void Platform_ThreadFreeHandle(void* handle); +void Platform_ThreadSleep(UInt32 milliseconds) { + usleep(milliseconds * 1000); +} -void* Platform_MutexCreate(void); -void Platform_MutexFree(void* handle); -void Platform_MutexLock(void* handle); -void Platform_MutexUnlock(void* handle); +void* Platform_ThreadStartCallback(void* lpParam) { + Platform_ThreadFunc* func = (Platform_ThreadFunc*)lpParam; + (*func)(); + return NULL; +} + +pthread_t threadList[3]; Int32 threadIndex; +void* Platform_ThreadStart(Platform_ThreadFunc* func) { + if (threadIndex == Array_Elems(threadIndex)) ErrorHandler_Fail("Cannot allocate thread"); + pthread_t* ptr = &threadList[threadIndex]; + int result = pthread_create(ptr, NULL, Platform_ThreadStartCallback, func); + + ErrorHandler_CheckOrFail(result, "Creating thread"); + threadIndex++; return ptr; +} + +void Platform_ThreadJoin(void* handle) { + int result = pthread_join(*((pthread_t*)handle), NULL); + ErrorHandler_CheckOrFail(result, "Joining thread"); +} + +void Platform_ThreadFreeHandle(void* handle) { + int result = pthread_detach(*((pthread_t*)handle)); + ErrorHandler_CheckOrFail(result, "Detaching thread"); +} + +pthread_mutex_t mutexList[3]; Int32 mutexIndex; +void* Platform_MutexCreate(void) { + if (mutexIndex == Array_Elems(mutexList)) ErrorHandler_Fail("Cannot allocate mutex"); + pthread_mutex_t* ptr = &mutexList[mutexIndex]; + int result = pthread_mutex_init(ptr, NULL); + + ErrorHandler_CheckOrFail(result, "Creating mutex"); + mutexIndex++; return ptr; +} + +void Platform_MutexFree(void* handle) { + int result = pthread_mutex_destroy((pthread_mutex_t*)handle); + ErrorHandler_CheckOrFail(result, "Destroying mutex"); +} + +void Platform_MutexLock(void* handle) { + int result = pthread_mutex_lock((pthread_mutex_t*)handle); + ErrorHandler_CheckOrFail(result, "Locking mutex"); +} + +void Platform_MutexUnlock(void* handle) { + int result = pthread_mutex_unlock((pthread_mutex_t*)handle); + ErrorHandler_CheckOrFail(result, "Unlocking mutex"); +} void* Platform_EventCreate(void); void Platform_EventFree(void* handle); diff --git a/src/Client/X11Window.c b/src/Client/X11Window.c index c4a458f3b..a321a750f 100644 --- a/src/Client/X11Window.c +++ b/src/Client/X11Window.c @@ -261,7 +261,7 @@ UInt8 Window_GetWindowState(void) { Int32 maximised = 0, i; /* TODO: Check this works right */ - if (items > 0 && data != NULL) { + if (data && items) { for (i = 0; i < items; i++) { Atom atom = data[i]; @@ -274,8 +274,8 @@ UInt8 Window_GetWindowState(void) { fullscreen = true; } } - XFree(data); } + if (data) XFree(data); if (minimised) return WINDOW_STATE_MINIMISED; if (maximised == 2) return WINDOW_STATE_MAXIMISED; @@ -427,8 +427,8 @@ void Window_ToggleKey(XKeyEvent* keyEvent, bool pressed) { } Atom Window_GetSelectionProperty(XEvent* e) { - Atom property = e->xselectionrequest.property; - if (property != NULL) return property; + Atom prop = e->xselectionrequest.property; + if (prop) return prop; /* For obsolete clients. See ICCCM spec, selections chapter for reasoning. */ return e->xselectionrequest.target; @@ -479,17 +479,15 @@ void Window_ProcessEvents(void) { case KeyPress: { ToggleKey(&e.xkey, true); - UInt8 data[16]; + UInt8 data[16]; UInt8 convBuffer[16]; int status = XLookupString(&e.xkey, data, Array_Elems(data), NULL, NULL); - String name = String_FromConst("Translate key press"); - struct Stream mem; Stream_ReadonlyMemory(&mem, data, status, &name); - /* TODO: Is this even right... */ - UInt16 codepoint; - while (Stream_ReadUtf8Char(&mem, &codepoint)) { - Event_RaiseInt(&KeyEvents_Press, Convert_UnicodeToCP437(codepoint)); - } + String conv = String_FromEmptyArray(convBuffer); + String_DecodeUtf8(&conv, data, status); + + Int32 i; + for (i = 0; i < conv.length; i++) { Event_RaiseInt(&KeyEvents_Press, conv.buffer[i]); } } break; case KeyRelease: @@ -559,21 +557,13 @@ void Window_ProcessEvents(void) { XGetWindowProperty(win_display, win_handle, xa_data_sel, 0, 1024, false, NULL, &prop_type, &prop_format, items, &bytes_after, &data); - XDeleteProperty(win_display, win_handle, xa_data_sel); - if (items == 0) break; - - if (prop_type == xa_utf8_string) { - String name = String_FromConst("Clipboard get"); - struct Stream mem; Stream_ReadonlyMemory(&mem, data, items, &name); + if (data && items && prop_type == xa_utf8_string) { String_Clear(&clipboard_paste_text); - UInt16 codepoint; - while (Stream_ReadUtf8Char(&mem, &codepoint)) { - String_Append(&clipboard_paste_text, Convert_UnicodeToCP437(codepoint)); - } + String_DecodeUtf8(&clipboard_paste_text, data, items); } - XFree(data); + if (data) XFree(data); } break; @@ -737,10 +727,10 @@ static void GLContext_GetAttribs(struct GraphicsMode mode, Int32* attribs) { attribs[i++] = GLX_BLUE_SIZE; attribs[i++] = color.B; attribs[i++] = GLX_ALPHA_SIZE; attribs[i++] = color.A; - if (mode.DepthBits > 0) { + if (mode.DepthBits) { attribs[i++] = GLX_DEPTH_SIZE; attribs[i++] = mode.DepthBits; } - if (mode.StencilBits > 0) { + if (mode.StencilBits) { attribs[i++] = GLX_STENCIL_SIZE; attribs[i++] = mode.StencilBits; } if (mode.Buffers > 1) { @@ -761,7 +751,7 @@ static XVisualInfo GLContext_SelectVisual(struct GraphicsMode* mode) { if (major >= 1 && minor >= 3) { /* ChooseFBConfig returns an array of GLXFBConfig opaque structures */ GLXFBConfig* fbconfigs = glXChooseFBConfig(win_display, win_screen, attribs, &fbcount); - if (fbcount > 0 && fbconfigs != NULL) { + if (fbconfigs && fbcount) { /* Use the first GLXFBConfig from the fbconfigs array (best match) */ visual = glXGetVisualFromFBConfig(win_display, *fbconfigs); XFree(fbconfigs);