mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-18 12:05:14 -04:00
Multiplayer of C client connects (Although pretty much doing anything causes a crash)
This commit is contained in:
parent
1eca5206f2
commit
ca000b317c
@ -195,7 +195,7 @@ void Animations_Draw(AnimationData* data, Int32 texId, Int32 size) {
|
|||||||
UInt8* ptr = buffer;
|
UInt8* ptr = buffer;
|
||||||
if (size > ANIMS_FAST_SIZE) {
|
if (size > ANIMS_FAST_SIZE) {
|
||||||
/* cannot allocate memory on the stack for very big animation.png frames */
|
/* cannot allocate memory on the stack for very big animation.png frames */
|
||||||
ptr = Platform_MemAlloc(Bitmap_DataSize(size, size));
|
ptr = Platform_MemAlloc(size * size, BITMAP_SIZEOF_PIXEL);
|
||||||
if (ptr == NULL) ErrorHandler_Fail("Failed to allocate memory for anim frame");
|
if (ptr == NULL) ErrorHandler_Fail("Failed to allocate memory for anim frame");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ void Bitmap_CopyBlock(Int32 srcX, Int32 srcY, Int32 dstX, Int32 dstY, Bitmap* sr
|
|||||||
void Bitmap_Allocate(Bitmap* bmp, Int32 width, Int32 height) {
|
void Bitmap_Allocate(Bitmap* bmp, Int32 width, Int32 height) {
|
||||||
bmp->Width = width; bmp->Height = height;
|
bmp->Width = width; bmp->Height = height;
|
||||||
bmp->Stride = width * BITMAP_SIZEOF_PIXEL;
|
bmp->Stride = width * BITMAP_SIZEOF_PIXEL;
|
||||||
bmp->Scan0 = Platform_MemAlloc(Bitmap_DataSize(width, height));
|
bmp->Scan0 = Platform_MemAlloc(width * height, BITMAP_SIZEOF_PIXEL);
|
||||||
|
|
||||||
if (bmp->Scan0 == NULL) {
|
if (bmp->Scan0 == NULL) {
|
||||||
ErrorHandler_Fail("Bitmap - failed to allocate memory");
|
ErrorHandler_Fail("Bitmap - failed to allocate memory");
|
||||||
@ -324,7 +324,7 @@ void Bitmap_DecodePng(Bitmap* bmp, Stream* stream) {
|
|||||||
if (bmp->Height < 0 || bmp->Height > PNG_MAX_DIMS) ErrorHandler_Fail("PNG image too tall");
|
if (bmp->Height < 0 || bmp->Height > PNG_MAX_DIMS) ErrorHandler_Fail("PNG image too tall");
|
||||||
|
|
||||||
bmp->Stride = bmp->Width * BITMAP_SIZEOF_PIXEL;
|
bmp->Stride = bmp->Width * BITMAP_SIZEOF_PIXEL;
|
||||||
bmp->Scan0 = Platform_MemAlloc(Bitmap_DataSize(bmp->Width, bmp->Height));
|
bmp->Scan0 = Platform_MemAlloc(bmp->Width * bmp->Height, BITMAP_SIZEOF_PIXEL);
|
||||||
if (bmp->Scan0 == NULL) ErrorHandler_Fail("Failed to allocate memory for PNG bitmap");
|
if (bmp->Scan0 == NULL) ErrorHandler_Fail("Failed to allocate memory for PNG bitmap");
|
||||||
|
|
||||||
bitsPerSample = Stream_ReadU8(stream);
|
bitsPerSample = Stream_ReadU8(stream);
|
||||||
|
@ -46,7 +46,7 @@ void TickQueue_Resize(TickQueue* queue) {
|
|||||||
UInt32 capacity = queue->BufferSize * 2;
|
UInt32 capacity = queue->BufferSize * 2;
|
||||||
if (capacity < 32) capacity = 32;
|
if (capacity < 32) capacity = 32;
|
||||||
|
|
||||||
UInt32* newBuffer = Platform_MemAlloc(capacity * sizeof(UInt32));
|
UInt32* newBuffer = Platform_MemAlloc(capacity, sizeof(UInt32));
|
||||||
if (newBuffer == NULL) {
|
if (newBuffer == NULL) {
|
||||||
ErrorHandler_Fail("TickQueue - failed to allocate memory");
|
ErrorHandler_Fail("TickQueue - failed to allocate memory");
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ void BordersRenderer_RebuildSides(Int32 y, Int32 axisSize) {
|
|||||||
VertexP3fT2fC4b v[4096];
|
VertexP3fT2fC4b v[4096];
|
||||||
VertexP3fT2fC4b* ptr = v;
|
VertexP3fT2fC4b* ptr = v;
|
||||||
if (borders_sidesVertices > 4096) {
|
if (borders_sidesVertices > 4096) {
|
||||||
ptr = Platform_MemAlloc(borders_sidesVertices * sizeof(VertexP3fT2fC4b));
|
ptr = Platform_MemAlloc(borders_sidesVertices, sizeof(VertexP3fT2fC4b));
|
||||||
if (ptr == NULL) ErrorHandler_Fail("BordersRenderer_Sides - failed to allocate memory");
|
if (ptr == NULL) ErrorHandler_Fail("BordersRenderer_Sides - failed to allocate memory");
|
||||||
}
|
}
|
||||||
VertexP3fT2fC4b* temp = ptr;
|
VertexP3fT2fC4b* temp = ptr;
|
||||||
@ -223,7 +223,7 @@ void BordersRenderer_RebuildEdges(Int32 y, Int32 axisSize) {
|
|||||||
VertexP3fT2fC4b v[4096];
|
VertexP3fT2fC4b v[4096];
|
||||||
VertexP3fT2fC4b* ptr = v;
|
VertexP3fT2fC4b* ptr = v;
|
||||||
if (borders_edgesVertices > 4096) {
|
if (borders_edgesVertices > 4096) {
|
||||||
ptr = Platform_MemAlloc(borders_edgesVertices * sizeof(VertexP3fT2fC4b));
|
ptr = Platform_MemAlloc(borders_edgesVertices, sizeof(VertexP3fT2fC4b));
|
||||||
if (ptr == NULL) ErrorHandler_Fail("BordersRenderer_Edges - failed to allocate memory");
|
if (ptr == NULL) ErrorHandler_Fail("BordersRenderer_Edges - failed to allocate memory");
|
||||||
}
|
}
|
||||||
VertexP3fT2fC4b* temp = ptr;
|
VertexP3fT2fC4b* temp = ptr;
|
||||||
|
@ -63,7 +63,7 @@ void Builder1DPart_Prepare(Builder1DPart* part) {
|
|||||||
if (vCount > part->verticesBufferCount) {
|
if (vCount > part->verticesBufferCount) {
|
||||||
Platform_MemFree(&part->vertices);
|
Platform_MemFree(&part->vertices);
|
||||||
|
|
||||||
part->vertices = Platform_MemAlloc((vCount + 2) * sizeof(VertexP3fT2fC4b));
|
part->vertices = Platform_MemAlloc(vCount + 2, sizeof(VertexP3fT2fC4b));
|
||||||
part->verticesBufferCount = vCount;
|
part->verticesBufferCount = vCount;
|
||||||
if (part->vertices == NULL) {
|
if (part->vertices == NULL) {
|
||||||
ErrorHandler_Fail("Builder1DPart_Prepare - failed to allocate memory");
|
ErrorHandler_Fail("Builder1DPart_Prepare - failed to allocate memory");
|
||||||
|
@ -125,23 +125,23 @@ void ChunkUpdater_FreeAllocations(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ChunkUpdater_PerformAllocations(void) {
|
void ChunkUpdater_PerformAllocations(void) {
|
||||||
MapRenderer_Chunks = Platform_MemAlloc(MapRenderer_ChunksCount * sizeof(ChunkInfo));
|
MapRenderer_Chunks = Platform_MemAlloc(MapRenderer_ChunksCount, sizeof(ChunkInfo));
|
||||||
if (MapRenderer_Chunks == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate chunk info");
|
if (MapRenderer_Chunks == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate chunk info");
|
||||||
|
|
||||||
MapRenderer_SortedChunks = Platform_MemAlloc(MapRenderer_ChunksCount * sizeof(ChunkInfo*));
|
MapRenderer_SortedChunks = Platform_MemAlloc(MapRenderer_ChunksCount, sizeof(ChunkInfo*));
|
||||||
if (MapRenderer_Chunks == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate sorted chunk info");
|
if (MapRenderer_Chunks == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate sorted chunk info");
|
||||||
|
|
||||||
MapRenderer_RenderChunks = Platform_MemAlloc(MapRenderer_ChunksCount * sizeof(ChunkInfo*));
|
MapRenderer_RenderChunks = Platform_MemAlloc(MapRenderer_ChunksCount, sizeof(ChunkInfo*));
|
||||||
if (MapRenderer_RenderChunks == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate render chunk info");
|
if (MapRenderer_RenderChunks == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate render chunk info");
|
||||||
|
|
||||||
ChunkUpdater_Distances = Platform_MemAlloc(MapRenderer_ChunksCount * sizeof(Int32));
|
ChunkUpdater_Distances = Platform_MemAlloc(MapRenderer_ChunksCount, sizeof(Int32));
|
||||||
if (ChunkUpdater_Distances == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate chunk distances");
|
if (ChunkUpdater_Distances == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate chunk distances");
|
||||||
|
|
||||||
UInt32 partsCount = MapRenderer_ChunksCount * MapRenderer_1DUsedCount;
|
UInt32 partsCount = MapRenderer_ChunksCount * MapRenderer_1DUsedCount;
|
||||||
UInt32 partsSize = (partsCount * (UInt32)sizeof(ChunkPartInfo)) * 2;
|
MapRenderer_PartsBuffer_Raw = Platform_MemAlloc(partsCount * 2, sizeof(ChunkPartInfo));
|
||||||
MapRenderer_PartsBuffer_Raw = Platform_MemAlloc(partsSize);
|
|
||||||
if (MapRenderer_PartsBuffer_Raw == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate chunk parts buffer");
|
if (MapRenderer_PartsBuffer_Raw == NULL) ErrorHandler_Fail("ChunkUpdater - failed to allocate chunk parts buffer");
|
||||||
|
|
||||||
|
UInt32 partsSize = partsCount * 2 * (UInt32)sizeof(ChunkPartInfo);
|
||||||
Platform_MemSet(MapRenderer_PartsBuffer_Raw, 0, partsSize);
|
Platform_MemSet(MapRenderer_PartsBuffer_Raw, 0, partsSize);
|
||||||
MapRenderer_PartsNormal = MapRenderer_PartsBuffer_Raw;
|
MapRenderer_PartsNormal = MapRenderer_PartsBuffer_Raw;
|
||||||
MapRenderer_PartsTranslucent = MapRenderer_PartsBuffer_Raw + partsCount;
|
MapRenderer_PartsTranslucent = MapRenderer_PartsBuffer_Raw + partsCount;
|
||||||
|
@ -205,9 +205,8 @@ void D3D9_DoMipmaps(IDirect3DTexture9* texture, Int32 x, Int32 y, Bitmap* bmp, b
|
|||||||
x /= 2; y /= 2;
|
x /= 2; y /= 2;
|
||||||
if (width > 1) width /= 2;
|
if (width > 1) width /= 2;
|
||||||
if (height > 1) height /= 2;
|
if (height > 1) height /= 2;
|
||||||
UInt32 size = Bitmap_DataSize(width, height);
|
|
||||||
|
|
||||||
UInt8* cur = Platform_MemAlloc(size);
|
UInt8* cur = Platform_MemAlloc(width * height, BITMAP_SIZEOF_PIXEL);
|
||||||
if (cur == NULL) ErrorHandler_Fail("Allocating memory for mipmaps");
|
if (cur == NULL) ErrorHandler_Fail("Allocating memory for mipmaps");
|
||||||
GfxCommon_GenMipmaps(width, height, cur, prev);
|
GfxCommon_GenMipmaps(width, height, cur, prev);
|
||||||
|
|
||||||
|
@ -142,6 +142,7 @@ typedef struct NetPlayer_ {
|
|||||||
bool ShouldRender;
|
bool ShouldRender;
|
||||||
} NetPlayer;
|
} NetPlayer;
|
||||||
void NetPlayer_Init(NetPlayer* player, STRING_PURE String* displayName, STRING_PURE String* skinName);
|
void NetPlayer_Init(NetPlayer* player, STRING_PURE String* displayName, STRING_PURE String* skinName);
|
||||||
|
NetPlayer NetPlayers_List[ENTITIES_SELF_ID];
|
||||||
|
|
||||||
/* Represents the user/player's own entity. */
|
/* Represents the user/player's own entity. */
|
||||||
typedef struct LocalPlayer_ {
|
typedef struct LocalPlayer_ {
|
||||||
|
@ -138,7 +138,7 @@ void EnvRenderer_UpdateFog(void) {
|
|||||||
Gfx_SetFogDensity((Real32)density);
|
Gfx_SetFogDensity((Real32)density);
|
||||||
} else {
|
} else {
|
||||||
Gfx_SetFogMode(FOG_LINEAR);
|
Gfx_SetFogMode(FOG_LINEAR);
|
||||||
Gfx_SetFogEnd(Game_ViewDistance);
|
Gfx_SetFogEnd((Real32)Game_ViewDistance);
|
||||||
}
|
}
|
||||||
Gfx_ClearColour(fogCol);
|
Gfx_ClearColour(fogCol);
|
||||||
Gfx_SetFogColour(fogCol);
|
Gfx_SetFogColour(fogCol);
|
||||||
@ -214,7 +214,7 @@ void EnvRenderer_RebuildClouds(Int32 extent, Int32 axisSize) {
|
|||||||
VertexP3fT2fC4b v[4096];
|
VertexP3fT2fC4b v[4096];
|
||||||
VertexP3fT2fC4b* ptr = v;
|
VertexP3fT2fC4b* ptr = v;
|
||||||
if (env_cloudVertices > 4096) {
|
if (env_cloudVertices > 4096) {
|
||||||
ptr = Platform_MemAlloc(env_cloudVertices * sizeof(VertexP3fT2fC4b));
|
ptr = Platform_MemAlloc(env_cloudVertices, sizeof(VertexP3fT2fC4b));
|
||||||
if (ptr == NULL) ErrorHandler_Fail("EnvRenderer_Clouds - failed to allocate memory");
|
if (ptr == NULL) ErrorHandler_Fail("EnvRenderer_Clouds - failed to allocate memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,7 +233,7 @@ void EnvRenderer_RebuildSky(Int32 extent, Int32 axisSize) {
|
|||||||
VertexP3fC4b v[4096];
|
VertexP3fC4b v[4096];
|
||||||
VertexP3fC4b* ptr = v;
|
VertexP3fC4b* ptr = v;
|
||||||
if (env_skyVertices > 4096) {
|
if (env_skyVertices > 4096) {
|
||||||
ptr = Platform_MemAlloc(env_skyVertices * sizeof(VertexP3fC4b));
|
ptr = Platform_MemAlloc(env_skyVertices, sizeof(VertexP3fC4b));
|
||||||
if (ptr == NULL) ErrorHandler_Fail("EnvRenderer_Sky - failed to allocate memory");
|
if (ptr == NULL) ErrorHandler_Fail("EnvRenderer_Sky - failed to allocate memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
void Map_ReadBlocks(Stream* stream) {
|
void Map_ReadBlocks(Stream* stream) {
|
||||||
World_BlocksSize = World_Width * World_Length * World_Height;
|
World_BlocksSize = World_Width * World_Length * World_Height;
|
||||||
World_Blocks = Platform_MemAlloc(World_BlocksSize);
|
World_Blocks = Platform_MemAlloc(World_BlocksSize, sizeof(BlockID));
|
||||||
if (World_Blocks == NULL) {
|
if (World_Blocks == NULL) {
|
||||||
ErrorHandler_Fail("Failed to allocate memory for reading blocks array from file");
|
ErrorHandler_Fail("Failed to allocate memory for reading blocks array from file");
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ void Nbt_ReadTag(UInt8 typeId, bool readTagName, Stream* stream, NbtTag* parent,
|
|||||||
if (count < NBT_SMALL_SIZE) {
|
if (count < NBT_SMALL_SIZE) {
|
||||||
Stream_Read(stream, tag.DataSmall, count);
|
Stream_Read(stream, tag.DataSmall, count);
|
||||||
} else {
|
} else {
|
||||||
tag.DataBig = Platform_MemAlloc(count);
|
tag.DataBig = Platform_MemAlloc(count, sizeof(UInt8));
|
||||||
if (tag.DataBig == NULL) ErrorHandler_Fail("Nbt_ReadTag - allocating memory");
|
if (tag.DataBig == NULL) ErrorHandler_Fail("Nbt_ReadTag - allocating memory");
|
||||||
Stream_Read(stream, tag.DataBig, count);
|
Stream_Read(stream, tag.DataBig, count);
|
||||||
}
|
}
|
||||||
@ -396,7 +396,7 @@ bool Cw_Callback_1(NbtTag* tag) {
|
|||||||
if (IsTag(tag, "BlockArray")) {
|
if (IsTag(tag, "BlockArray")) {
|
||||||
World_BlocksSize = tag->DataSize;
|
World_BlocksSize = tag->DataSize;
|
||||||
if (tag->DataSize < NBT_SMALL_SIZE) {
|
if (tag->DataSize < NBT_SMALL_SIZE) {
|
||||||
World_Blocks = Platform_MemAlloc(World_BlocksSize);
|
World_Blocks = Platform_MemAlloc(World_BlocksSize, sizeof(UInt8));
|
||||||
if (World_Blocks == NULL) ErrorHandler_Fail("Failed to allocate memory for map");
|
if (World_Blocks == NULL) ErrorHandler_Fail("Failed to allocate memory for map");
|
||||||
Platform_MemCpy(World_Blocks, tag->DataSmall, tag->DataSize);
|
Platform_MemCpy(World_Blocks, tag->DataSmall, tag->DataSize);
|
||||||
} else {
|
} else {
|
||||||
|
@ -173,7 +173,8 @@ void Game_UpdateProjection(void) {
|
|||||||
void Game_Disconnect(STRING_PURE String* title, STRING_PURE String* reason) {
|
void Game_Disconnect(STRING_PURE String* title, STRING_PURE String* reason) {
|
||||||
World_Reset();
|
World_Reset();
|
||||||
Event_RaiseVoid(&WorldEvents_NewMap);
|
Event_RaiseVoid(&WorldEvents_NewMap);
|
||||||
Gui_SetNewScreen(DisconnectScreen_MakeInstance(title, reason));
|
Gui_FreeActive();
|
||||||
|
Gui_SetActive(DisconnectScreen_MakeInstance(title, reason));
|
||||||
|
|
||||||
Drawer2D_Init();
|
Drawer2D_Init();
|
||||||
Block_Reset();
|
Block_Reset();
|
||||||
@ -530,7 +531,8 @@ void Game_Load(void) {
|
|||||||
String_Format2(&loadTitle, "Connecting to %s:%i..", &Game_IPAddress, &Game_Port);
|
String_Format2(&loadTitle, "Connecting to %s:%i..", &Game_IPAddress, &Game_Port);
|
||||||
String loadMsg = String_MakeNull();
|
String loadMsg = String_MakeNull();
|
||||||
|
|
||||||
Gui_SetNewScreen(LoadingScreen_MakeInstance(&loadTitle, &loadMsg));
|
Gui_FreeActive();
|
||||||
|
Gui_SetActive(LoadingScreen_MakeInstance(&loadTitle, &loadMsg));
|
||||||
ServerConnection_Connect(&Game_IPAddress, Game_Port);
|
ServerConnection_Connect(&Game_IPAddress, Game_Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -672,7 +674,8 @@ void Game_RenderFrame(Real64 delta) {
|
|||||||
|
|
||||||
Camera_Active->UpdateMouse();
|
Camera_Active->UpdateMouse();
|
||||||
if (!Window_GetFocused() && !Gui_GetActiveScreen()->HandlesAllInput) {
|
if (!Window_GetFocused() && !Gui_GetActiveScreen()->HandlesAllInput) {
|
||||||
Gui_SetNewScreen(PauseScreen_MakeInstance());
|
Gui_FreeActive();
|
||||||
|
Gui_SetActive(PauseScreen_MakeInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool allowZoom = Gui_Active == NULL && !Gui_HUD->HandlesAllInput;
|
bool allowZoom = Gui_Active == NULL && !Gui_HUD->HandlesAllInput;
|
||||||
@ -779,7 +782,6 @@ void Cw_Save(Stream* stream) { }
|
|||||||
void Dat_Load(Stream* stream) { }
|
void Dat_Load(Stream* stream) { }
|
||||||
void Schematic_Save(Stream* stream) { }
|
void Schematic_Save(Stream* stream) { }
|
||||||
void Gfx_MakeApiInfo(void) { }
|
void Gfx_MakeApiInfo(void) { }
|
||||||
void ServerConnection_InitMultiplayer(void) { }
|
|
||||||
bool Convert_TryParseInt64(STRING_PURE String* str, Int64* value) { return true; }
|
bool Convert_TryParseInt64(STRING_PURE String* str, Int64* value) { return true; }
|
||||||
DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; }
|
DateTime DateTime_FromTotalMs(Int64 ms) { DateTime time; return time; }
|
||||||
Screen* UrlWarningOverlay_MakeInstance(STRING_PURE String* url) { return NULL; }
|
Screen* UrlWarningOverlay_MakeInstance(STRING_PURE String* url) { return NULL; }
|
||||||
|
@ -23,8 +23,8 @@ IGameComponent GameMode_MakeComponent(void) {
|
|||||||
bool GameMode_HandlesKeyDown(Key key) {
|
bool GameMode_HandlesKeyDown(Key key) {
|
||||||
Screen* activeScreen = Gui_GetActiveScreen();
|
Screen* activeScreen = Gui_GetActiveScreen();
|
||||||
if (key == KeyBind_Get(KeyBind_Inventory) && activeScreen == Gui_HUD) {
|
if (key == KeyBind_Get(KeyBind_Inventory) && activeScreen == Gui_HUD) {
|
||||||
Screen* screen = InventoryScreen_MakeInstance();
|
Gui_FreeActive();
|
||||||
Gui_SetNewScreen(screen);
|
Gui_SetActive(InventoryScreen_MakeInstance());
|
||||||
return true;
|
return true;
|
||||||
} else if (key == KeyBind_Get(KeyBind_DropBlock) && !Game_ClassicMode) {
|
} else if (key == KeyBind_Get(KeyBind_DropBlock) && !Game_ClassicMode) {
|
||||||
if (Inventory_CanChangeSelected() && Inventory_SelectedBlock != BLOCK_AIR) {
|
if (Inventory_CanChangeSelected() && Inventory_SelectedBlock != BLOCK_AIR) {
|
||||||
|
@ -112,7 +112,7 @@ void Gui_Reset(void) {
|
|||||||
|
|
||||||
void Gui_Free(void) {
|
void Gui_Free(void) {
|
||||||
Event_UnregisterStream(&TextureEvents_FileChanged, NULL, Gui_FileChanged);
|
Event_UnregisterStream(&TextureEvents_FileChanged, NULL, Gui_FileChanged);
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
Elem_TryFree(Gui_Status);
|
Elem_TryFree(Gui_Status);
|
||||||
|
|
||||||
if (Gui_Active != NULL) { Elem_TryFree(Gui_Active); }
|
if (Gui_Active != NULL) { Elem_TryFree(Gui_Active); }
|
||||||
@ -138,9 +138,16 @@ Screen* Gui_GetUnderlyingScreen(void) {
|
|||||||
return Gui_Active == NULL ? Gui_HUD : Gui_Active;
|
return Gui_Active == NULL ? Gui_HUD : Gui_Active;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui_SetScreen(Screen* screen, bool freeOld) {
|
void Gui_ReplaceActive(Screen* screen) {
|
||||||
|
Gui_FreeActive();
|
||||||
|
Gui_SetActive(screen);
|
||||||
|
}
|
||||||
|
void Gui_FreeActive(void) {
|
||||||
|
if (Gui_Active != NULL) { Elem_TryFree(Gui_Active); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gui_SetActive(Screen* screen) {
|
||||||
InputHandler_ScreenChanged(Gui_Active, screen);
|
InputHandler_ScreenChanged(Gui_Active, screen);
|
||||||
if (Gui_Active != NULL && freeOld) { Elem_TryFree(Gui_Active); }
|
|
||||||
|
|
||||||
if (screen == NULL) {
|
if (screen == NULL) {
|
||||||
Game_SetCursorVisible(false);
|
Game_SetCursorVisible(false);
|
||||||
@ -152,8 +159,6 @@ void Gui_SetScreen(Screen* screen, bool freeOld) {
|
|||||||
if (screen != NULL) { Elem_Init(screen); }
|
if (screen != NULL) { Elem_Init(screen); }
|
||||||
Gui_Active = screen;
|
Gui_Active = screen;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gui_SetNewScreen(Screen* screen) { Gui_SetScreen(screen, true); }
|
|
||||||
void Gui_RefreshHud(void) { Elem_Recreate(Gui_HUD); }
|
void Gui_RefreshHud(void) { Elem_Recreate(Gui_HUD); }
|
||||||
|
|
||||||
void Gui_ShowOverlay_Impl(Screen* overlay, bool atFront) {
|
void Gui_ShowOverlay_Impl(Screen* overlay, bool atFront) {
|
||||||
|
@ -77,8 +77,11 @@ Screen* Gui_GetActiveScreen(void);
|
|||||||
/* Gets the non-overlay screen that the user is currently interacting with.
|
/* Gets the non-overlay screen that the user is currently interacting with.
|
||||||
This means if an overlay is active, it will return the screen under it. */
|
This means if an overlay is active, it will return the screen under it. */
|
||||||
Screen* Gui_GetUnderlyingScreen(void);
|
Screen* Gui_GetUnderlyingScreen(void);
|
||||||
void Gui_SetScreen(Screen* screen, bool freeOld);
|
|
||||||
void Gui_SetNewScreen(Screen* screen);
|
void Gui_ReplaceActive(Screen* screen);
|
||||||
|
void Gui_FreeActive(void);
|
||||||
|
/* This doesn't free old active screen - you probably want Gui_ReplaceActive */
|
||||||
|
void Gui_SetActive(Screen* screen);
|
||||||
void Gui_RefreshHud(void);
|
void Gui_RefreshHud(void);
|
||||||
void Gui_ShowOverlay(Screen* overlay, bool atFront);
|
void Gui_ShowOverlay(Screen* overlay, bool atFront);
|
||||||
void Gui_RenderGui(Real64 delta);
|
void Gui_RenderGui(Real64 delta);
|
||||||
|
@ -174,8 +174,8 @@ bool InputHandler_HandleCoreKey(Key key) {
|
|||||||
InputHandler_CycleDistanceForwards(viewDists, count);
|
InputHandler_CycleDistanceForwards(viewDists, count);
|
||||||
}
|
}
|
||||||
} else if ((key == KeyBind_Get(KeyBind_PauseOrExit) || key == Key_Pause) && World_Blocks != NULL) {
|
} else if ((key == KeyBind_Get(KeyBind_PauseOrExit) || key == Key_Pause) && World_Blocks != NULL) {
|
||||||
Screen* screen = PauseScreen_MakeInstance();
|
Gui_FreeActive();
|
||||||
Gui_SetNewScreen(screen);
|
Gui_SetActive(PauseScreen_MakeInstance());
|
||||||
} else if (GameMode_HandlesKeyDown(key)) {
|
} else if (GameMode_HandlesKeyDown(key)) {
|
||||||
} else if (key == KeyBind_Get(KeyBind_IDOverlay)) {
|
} else if (key == KeyBind_Get(KeyBind_IDOverlay)) {
|
||||||
if (Gui_OverlaysCount > 0) return true;
|
if (Gui_OverlaysCount > 0) return true;
|
||||||
|
@ -331,8 +331,7 @@ void Lighting_OnNewMap(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Lighting_OnNewMapLoaded(void) {
|
void Lighting_OnNewMapLoaded(void) {
|
||||||
UInt32 size = World_Width * World_Length * sizeof(Int16);
|
Lighting_heightmap = Platform_MemAlloc(World_Width * World_Length, sizeof(Int16));
|
||||||
Lighting_heightmap = Platform_MemAlloc(size);
|
|
||||||
if (Lighting_heightmap == NULL) {
|
if (Lighting_heightmap == NULL) {
|
||||||
ErrorHandler_Fail("WorldLighting - failed to allocate heightmap");
|
ErrorHandler_Fail("WorldLighting - failed to allocate heightmap");
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ void Gen_Init(void) {
|
|||||||
Gen_CurrentProgress = 0.0f;
|
Gen_CurrentProgress = 0.0f;
|
||||||
Gen_CurrentState = "";
|
Gen_CurrentState = "";
|
||||||
|
|
||||||
Gen_Blocks = Platform_MemAlloc(Gen_Width * Gen_Height * Gen_Length * sizeof(BlockID));
|
Gen_Blocks = Platform_MemAlloc(Gen_Width * Gen_Height * Gen_Length, sizeof(BlockID));
|
||||||
if (Gen_Blocks == NULL) {
|
if (Gen_Blocks == NULL) {
|
||||||
ErrorHandler_Fail("MapGen - failed to allocate Blocks array");
|
ErrorHandler_Fail("MapGen - failed to allocate Blocks array");
|
||||||
}
|
}
|
||||||
@ -465,7 +465,7 @@ void NotchyGen_PlantTrees(void) {
|
|||||||
|
|
||||||
void NotchyGen_Generate(void) {
|
void NotchyGen_Generate(void) {
|
||||||
Gen_Init();
|
Gen_Init();
|
||||||
Heightmap = Platform_MemAlloc(Gen_Width * Gen_Length * sizeof(Int16));
|
Heightmap = Platform_MemAlloc(Gen_Width * Gen_Length, sizeof(Int16));
|
||||||
if (Heightmap == NULL) {
|
if (Heightmap == NULL) {
|
||||||
ErrorHandler_Fail("NotchyGen - Failed to allocate Heightmap array");
|
ErrorHandler_Fail("NotchyGen - Failed to allocate Heightmap array");
|
||||||
}
|
}
|
||||||
|
@ -242,30 +242,30 @@ Int32 Menu_Int32(STRING_PURE String* v) { Int32 value; Convert_TryParseInt32(v,
|
|||||||
Real32 Menu_Real32(STRING_PURE String* v) { Real32 value; Convert_TryParseReal32(v, &value); return value; }
|
Real32 Menu_Real32(STRING_PURE String* v) { Real32 value; Convert_TryParseReal32(v, &value); return value; }
|
||||||
PackedCol Menu_HexCol(STRING_PURE String* v) { PackedCol value; PackedCol_TryParseHex(v, &value); return value; }
|
PackedCol Menu_HexCol(STRING_PURE String* v) { PackedCol value; PackedCol_TryParseHex(v, &value); return value; }
|
||||||
|
|
||||||
void Menu_SwitchOptions(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(OptionsGroupScreen_MakeInstance()); }
|
void Menu_SwitchOptions(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(OptionsGroupScreen_MakeInstance()); }
|
||||||
void Menu_SwitchPause(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(PauseScreen_MakeInstance()); }
|
void Menu_SwitchPause(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(PauseScreen_MakeInstance()); }
|
||||||
void Menu_SwitchClassicOptions(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(ClassicOptionsScreen_MakeInstance()); }
|
void Menu_SwitchClassicOptions(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(ClassicOptionsScreen_MakeInstance()); }
|
||||||
|
|
||||||
void Menu_SwitchKeysClassic(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(ClassicKeyBindingsScreen_MakeInstance()); }
|
void Menu_SwitchKeysClassic(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(ClassicKeyBindingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchKeysClassicHacks(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(ClassicHacksKeyBindingsScreen_MakeInstance()); }
|
void Menu_SwitchKeysClassicHacks(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(ClassicHacksKeyBindingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchKeysNormal(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(NormalKeyBindingsScreen_MakeInstance()); }
|
void Menu_SwitchKeysNormal(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(NormalKeyBindingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchKeysHacks(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(HacksKeyBindingsScreen_MakeInstance()); }
|
void Menu_SwitchKeysHacks(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(HacksKeyBindingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchKeysOther(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(OtherKeyBindingsScreen_MakeInstance()); }
|
void Menu_SwitchKeysOther(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(OtherKeyBindingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchKeysMouse(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(MouseKeyBindingsScreen_MakeInstance()); }
|
void Menu_SwitchKeysMouse(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(MouseKeyBindingsScreen_MakeInstance()); }
|
||||||
|
|
||||||
void Menu_SwitchMisc(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(MiscOptionsScreen_MakeInstance()); }
|
void Menu_SwitchMisc(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(MiscOptionsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchGui(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(GuiOptionsScreen_MakeInstance()); }
|
void Menu_SwitchGui(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(GuiOptionsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchGfx(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(GraphicsOptionsScreen_MakeInstance()); }
|
void Menu_SwitchGfx(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(GraphicsOptionsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchHacks(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(HacksSettingsScreen_MakeInstance()); }
|
void Menu_SwitchHacks(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(HacksSettingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchEnv(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(EnvSettingsScreen_MakeInstance()); }
|
void Menu_SwitchEnv(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(EnvSettingsScreen_MakeInstance()); }
|
||||||
void Menu_SwitchNostalgia(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(NostalgiaScreen_MakeInstance()); }
|
void Menu_SwitchNostalgia(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(NostalgiaScreen_MakeInstance()); }
|
||||||
|
|
||||||
void Menu_SwitchGenLevel(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(GenLevelScreen_MakeInstance()); }
|
void Menu_SwitchGenLevel(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(GenLevelScreen_MakeInstance()); }
|
||||||
void Menu_SwitchClassicGenLevel(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(ClassicGenScreen_MakeInstance()); }
|
void Menu_SwitchClassicGenLevel(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(ClassicGenScreen_MakeInstance()); }
|
||||||
void Menu_SwitchLoadLevel(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(LoadLevelScreen_MakeInstance()); }
|
void Menu_SwitchLoadLevel(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(LoadLevelScreen_MakeInstance()); }
|
||||||
void Menu_SwitchSaveLevel(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(SaveLevelScreen_MakeInstance()); }
|
void Menu_SwitchSaveLevel(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(SaveLevelScreen_MakeInstance()); }
|
||||||
void Menu_SwitchTexPacks(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(TexturePackScreen_MakeInstance()); }
|
void Menu_SwitchTexPacks(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(TexturePackScreen_MakeInstance()); }
|
||||||
void Menu_SwitchHotkeys(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(HotkeyListScreen_MakeInstance()); }
|
void Menu_SwitchHotkeys(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(HotkeyListScreen_MakeInstance()); }
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
@ -408,7 +408,7 @@ void ListScreen_Free(GuiElement* elem) {
|
|||||||
bool ListScreen_HandlesKeyDown(GuiElement* elem, Key key) {
|
bool ListScreen_HandlesKeyDown(GuiElement* elem, Key key) {
|
||||||
ListScreen* screen = (ListScreen*)elem;
|
ListScreen* screen = (ListScreen*)elem;
|
||||||
if (key == Key_Escape) {
|
if (key == Key_Escape) {
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
} else if (key == Key_Left) {
|
} else if (key == Key_Left) {
|
||||||
ListScreen_PageClick(screen, false);
|
ListScreen_PageClick(screen, false);
|
||||||
} else if (key == Key_Right) {
|
} else if (key == Key_Right) {
|
||||||
@ -485,7 +485,7 @@ bool MenuScreen_HandlesMouseUp(GuiElement* elem, Int32 x, Int32 y, MouseButton b
|
|||||||
bool MenuScreen_HandlesMouseScroll(GuiElement* elem, Real32 delta) { return true; }
|
bool MenuScreen_HandlesMouseScroll(GuiElement* elem, Real32 delta) { return true; }
|
||||||
|
|
||||||
bool MenuScreen_HandlesKeyDown(GuiElement* elem, Key key) {
|
bool MenuScreen_HandlesKeyDown(GuiElement* elem, Key key) {
|
||||||
if (key == Key_Escape) { Gui_SetNewScreen(NULL); }
|
if (key == Key_Escape) { Gui_ReplaceActive(NULL); }
|
||||||
return key < Key_F1 || key > Key_F35;
|
return key < Key_F1 || key > Key_F35;
|
||||||
}
|
}
|
||||||
bool MenuScreen_HandlesKeyPress(GuiElement* elem, UInt8 key) { return true; }
|
bool MenuScreen_HandlesKeyPress(GuiElement* elem, UInt8 key) { return true; }
|
||||||
@ -596,7 +596,7 @@ void PauseScreen_MakeClassic(PauseScreen* screen, Int32 i, Int32 y, const UInt8*
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PauseScreen_Quit(GuiElement* a, GuiElement* b) { Window_Close(); }
|
void PauseScreen_Quit(GuiElement* a, GuiElement* b) { Window_Close(); }
|
||||||
void PauseScreen_Game(GuiElement* a, GuiElement* b) { Gui_SetNewScreen(NULL); }
|
void PauseScreen_Game(GuiElement* a, GuiElement* b) { Gui_ReplaceActive(NULL); }
|
||||||
|
|
||||||
void PauseScreen_CheckHacksAllowed(void* obj) {
|
void PauseScreen_CheckHacksAllowed(void* obj) {
|
||||||
if (Game_UseClassicOptions) return;
|
if (Game_UseClassicOptions) return;
|
||||||
@ -913,7 +913,7 @@ void EditHotkeyScreen_SaveChanges(GuiElement* elem, GuiElement* widget) {
|
|||||||
Hotkeys_Add(hotkey.BaseKey, hotkey.Flags, &text, hotkey.StaysOpen);
|
Hotkeys_Add(hotkey.BaseKey, hotkey.Flags, &text, hotkey.StaysOpen);
|
||||||
Hotkeys_UserAddedHotkey(hotkey.BaseKey, hotkey.Flags, hotkey.StaysOpen, &text);
|
Hotkeys_UserAddedHotkey(hotkey.BaseKey, hotkey.Flags, hotkey.StaysOpen, &text);
|
||||||
}
|
}
|
||||||
Gui_SetNewScreen(HotkeyListScreen_MakeInstance());
|
Gui_ReplaceActive(HotkeyListScreen_MakeInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditHotkeyScreen_RemoveHotkey(GuiElement* elem, GuiElement* widget) {
|
void EditHotkeyScreen_RemoveHotkey(GuiElement* elem, GuiElement* widget) {
|
||||||
@ -923,7 +923,7 @@ void EditHotkeyScreen_RemoveHotkey(GuiElement* elem, GuiElement* widget) {
|
|||||||
Hotkeys_Remove(hotkey.BaseKey, hotkey.Flags);
|
Hotkeys_Remove(hotkey.BaseKey, hotkey.Flags);
|
||||||
Hotkeys_UserRemovedHotkey(hotkey.BaseKey, hotkey.Flags);
|
Hotkeys_UserRemovedHotkey(hotkey.BaseKey, hotkey.Flags);
|
||||||
}
|
}
|
||||||
Gui_SetNewScreen(HotkeyListScreen_MakeInstance());
|
Gui_ReplaceActive(HotkeyListScreen_MakeInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditHotkeyScreen_Init(GuiElement* elem) {
|
void EditHotkeyScreen_Init(GuiElement* elem) {
|
||||||
@ -1351,7 +1351,7 @@ void SaveLevelScreen_Render(GuiElement* elem, Real64 delta) {
|
|||||||
String_Format1(&msg, "&eSaved map to: %s", &path);
|
String_Format1(&msg, "&eSaved map to: %s", &path);
|
||||||
Chat_Add(&msg);
|
Chat_Add(&msg);
|
||||||
|
|
||||||
Gui_SetNewScreen(PauseScreen_MakeInstance());
|
Gui_ReplaceActive(PauseScreen_MakeInstance());
|
||||||
String_Clear(&path);
|
String_Clear(&path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1479,7 +1479,7 @@ void HotkeyListScreen_EntryClick(GuiElement* screenElem, GuiElement* w) {
|
|||||||
HotkeyData original = { 0 };
|
HotkeyData original = { 0 };
|
||||||
|
|
||||||
if (String_CaselessEqualsConst(&text, LIST_SCREEN_EMPTY)) {
|
if (String_CaselessEqualsConst(&text, LIST_SCREEN_EMPTY)) {
|
||||||
Gui_SetNewScreen(EditHotkeyScreen_MakeInstance(original)); return;
|
Gui_ReplaceActive(EditHotkeyScreen_MakeInstance(original)); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Int32 sepIndex = String_IndexOf(&text, '|', 0);
|
Int32 sepIndex = String_IndexOf(&text, '|', 0);
|
||||||
@ -1501,7 +1501,7 @@ void HotkeyListScreen_EntryClick(GuiElement* screenElem, GuiElement* w) {
|
|||||||
HotkeyData h = HotkeysList[i];
|
HotkeyData h = HotkeysList[i];
|
||||||
if (h.BaseKey == baseKey && h.Flags == flags) { original = h; break; }
|
if (h.BaseKey == baseKey && h.Flags == flags) { original = h; break; }
|
||||||
}
|
}
|
||||||
Gui_SetNewScreen(EditHotkeyScreen_MakeInstance(original));
|
Gui_ReplaceActive(EditHotkeyScreen_MakeInstance(original));
|
||||||
}
|
}
|
||||||
|
|
||||||
Screen* HotkeyListScreen_MakeInstance(void) {
|
Screen* HotkeyListScreen_MakeInstance(void) {
|
||||||
|
@ -107,9 +107,8 @@ void GL_DoMipmaps(GfxResourceID texId, Int32 x, Int32 y, Bitmap* bmp, bool parti
|
|||||||
x /= 2; y /= 2;
|
x /= 2; y /= 2;
|
||||||
if (width > 1) width /= 2;
|
if (width > 1) width /= 2;
|
||||||
if (height > 1) height /= 2;
|
if (height > 1) height /= 2;
|
||||||
UInt32 size = Bitmap_DataSize(width, height);
|
|
||||||
|
|
||||||
UInt8* cur = Platform_MemAlloc(size);
|
UInt8* cur = Platform_MemAlloc(width * height, BITMAP_SIZEOF_PIXEL);
|
||||||
if (cur == NULL) ErrorHandler_Fail("Allocating memory for mipmaps");
|
if (cur == NULL) ErrorHandler_Fail("Allocating memory for mipmaps");
|
||||||
GfxCommon_GenMipmaps(width, height, cur, prev);
|
GfxCommon_GenMipmaps(width, height, cur, prev);
|
||||||
|
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
#include "AsyncDownloader.h"
|
#include "AsyncDownloader.h"
|
||||||
#include "Drawer2D.h"
|
#include "Drawer2D.h"
|
||||||
#include "ErrorHandler.h"
|
#include "ErrorHandler.h"
|
||||||
|
#include "TexturePack.h"
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*-----------------------------------------------------Common handlers-----------------------------------------------------*
|
*-----------------------------------------------------Common handlers-----------------------------------------------------*
|
||||||
@ -68,73 +69,6 @@ void Handlers_RemoveEndPlus(STRING_TRANSIENT String* value) {
|
|||||||
String_DeleteAt(value, value->length - 1);
|
String_DeleteAt(value, value->length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Handlers_CheckName(EntityID id, STRING_TRANSIENT String* displayName, STRING_TRANSIENT String* skinName) {
|
|
||||||
String_StripCols(&skinName);
|
|
||||||
Handlers_RemoveEndPlus(displayName);
|
|
||||||
Handlers_RemoveEndPlus(skinName);
|
|
||||||
/* Server is only allowed to change our own name colours. */
|
|
||||||
if (id != ENTITIES_SELF_ID) return;
|
|
||||||
|
|
||||||
UInt8 nameNoColsBuffer[String_BufferSize(STRING_SIZE)];
|
|
||||||
String nameNoCols = String_InitAndClearArray(nameNoColsBuffer);
|
|
||||||
String_AppendColorless(&nameNoCols, displayName);
|
|
||||||
|
|
||||||
if (!String_Equals(&nameNoCols, &Game_Username)) { String_Set(displayName, &Game_Username); }
|
|
||||||
if (skinName->length == 0) { String_Set(skinName, &Game_Username); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void Handlers_AddEntity(EntityID id, STRING_TRANSIENT String* displayName, STRING_TRANSIENT String* skinName, bool readPosition) {
|
|
||||||
LocalPlayer* p = &LocalPlayer_Instance;
|
|
||||||
if (id != ENTITIES_SELF_ID) {
|
|
||||||
Entity* oldEntity = Entities_List[id];
|
|
||||||
if (oldEntity != NULL) Entities_Remove(id);
|
|
||||||
|
|
||||||
game.Entities.List[id] = new NetPlayer(displayName, skinName, game);
|
|
||||||
Event_RaiseInt(&EntityEvents_Added, id);
|
|
||||||
} else {
|
|
||||||
p->Base.VTABLE->Despawn(&p->Base);
|
|
||||||
/* Always reset the texture here, in case other network players are using the same skin as us */
|
|
||||||
/* In that case, we don't want the fetching of new skin for us to delete the texture used by them */
|
|
||||||
Player_ResetSkin((Player*)p);
|
|
||||||
p->FetchedSkin = false;
|
|
||||||
|
|
||||||
String player_name = String_InitAndClearArray(p->DisplayNameRaw);
|
|
||||||
String_Set(&player_name, displayName);
|
|
||||||
String player_skin = String_InitAndClearArray(p->SkinNameRaw);
|
|
||||||
String_Set(&player_skin, skinName);
|
|
||||||
Player_UpdateName((Player*)p);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!readPosition) return;
|
|
||||||
Stream* stream = ServerConnection_ReadStream();
|
|
||||||
Classic_ReadAbsoluteLocation(stream, id, false);
|
|
||||||
if (id != ENTITIES_SELF_ID) return;
|
|
||||||
|
|
||||||
p->Spawn = p->Base.Position;
|
|
||||||
p->SpawnRotY = p->Base.HeadY;
|
|
||||||
p->SpawnHeadX = p->Base.HeadX;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Handlers_RemoveEntity(EntityID id) {
|
|
||||||
Entity* entity = Entities_List[id];
|
|
||||||
if (entity == NULL) return;
|
|
||||||
if (id != ENTITIES_SELF_ID) Entities_Remove(id);
|
|
||||||
|
|
||||||
/* See comment about some servers in Classic_AddEntity */
|
|
||||||
Int32 mask = id >> 3, bit = 1 << (id & 0x7);
|
|
||||||
if (!addEntityHack || (needRemoveNames[mask] & bit) == 0) return;
|
|
||||||
|
|
||||||
Handlers_RemoveTablistEntry(id);
|
|
||||||
needRemoveNames[mask] &= (UInt8)~bit;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Handlers_UpdateLocation(EntityID playerId, LocationUpdate* update, bool interpolate) {
|
|
||||||
Entity* entity = Entities_List[playerId];
|
|
||||||
if (entity != NULL) {
|
|
||||||
entity->VTABLE->SetLocation(entity, update, interpolate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Handlers_AddTablistEntry(EntityID id, STRING_PURE String* playerName, STRING_PURE String* listName, STRING_PURE String* groupName, UInt8 groupRank) {
|
void Handlers_AddTablistEntry(EntityID id, STRING_PURE String* playerName, STRING_PURE String* listName, STRING_PURE String* groupName, UInt8 groupRank) {
|
||||||
/* Only redraw the tab list if something changed. */
|
/* Only redraw the tab list if something changed. */
|
||||||
if (TabList_Valid(id)) {
|
if (TabList_Valid(id)) {
|
||||||
@ -160,6 +94,76 @@ void Handlers_RemoveTablistEntry(EntityID id) {
|
|||||||
TabList_Remove(id);
|
TabList_Remove(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Handlers_CheckName(EntityID id, STRING_TRANSIENT String* displayName, STRING_TRANSIENT String* skinName) {
|
||||||
|
String_StripCols(skinName);
|
||||||
|
Handlers_RemoveEndPlus(displayName);
|
||||||
|
Handlers_RemoveEndPlus(skinName);
|
||||||
|
/* Server is only allowed to change our own name colours. */
|
||||||
|
if (id != ENTITIES_SELF_ID) return;
|
||||||
|
|
||||||
|
UInt8 nameNoColsBuffer[String_BufferSize(STRING_SIZE)];
|
||||||
|
String nameNoCols = String_InitAndClearArray(nameNoColsBuffer);
|
||||||
|
String_AppendColorless(&nameNoCols, displayName);
|
||||||
|
|
||||||
|
if (!String_Equals(&nameNoCols, &Game_Username)) { String_Set(displayName, &Game_Username); }
|
||||||
|
if (skinName->length == 0) { String_Set(skinName, &Game_Username); }
|
||||||
|
}
|
||||||
|
|
||||||
|
void Classic_ReadAbsoluteLocation(Stream* stream, EntityID id, bool interpolate);
|
||||||
|
void Handlers_AddEntity(EntityID id, STRING_TRANSIENT String* displayName, STRING_TRANSIENT String* skinName, bool readPosition) {
|
||||||
|
LocalPlayer* p = &LocalPlayer_Instance;
|
||||||
|
if (id != ENTITIES_SELF_ID) {
|
||||||
|
Entity* oldEntity = Entities_List[id];
|
||||||
|
if (oldEntity != NULL) Entities_Remove(id);
|
||||||
|
|
||||||
|
NetPlayer* player = &NetPlayers_List[id];
|
||||||
|
NetPlayer_Init(player, displayName, skinName);
|
||||||
|
Entities_List[id] = &player->Base;
|
||||||
|
Event_RaiseInt(&EntityEvents_Added, id);
|
||||||
|
} else {
|
||||||
|
p->Base.VTABLE->Despawn(&p->Base);
|
||||||
|
/* Always reset the texture here, in case other network players are using the same skin as us */
|
||||||
|
/* In that case, we don't want the fetching of new skin for us to delete the texture used by them */
|
||||||
|
Player_ResetSkin((Player*)p);
|
||||||
|
p->FetchedSkin = false;
|
||||||
|
|
||||||
|
String player_name = String_InitAndClearArray(p->DisplayNameRaw);
|
||||||
|
String_Set(&player_name, displayName);
|
||||||
|
String player_skin = String_InitAndClearArray(p->SkinNameRaw);
|
||||||
|
String_Set(&player_skin, skinName);
|
||||||
|
Player_UpdateName((Player*)p);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readPosition) return;
|
||||||
|
Stream* stream = ServerConnection_ReadStream();
|
||||||
|
Classic_ReadAbsoluteLocation(stream, id, false);
|
||||||
|
if (id != ENTITIES_SELF_ID) return;
|
||||||
|
|
||||||
|
p->Spawn = p->Base.Position;
|
||||||
|
p->SpawnRotY = p->Base.HeadY;
|
||||||
|
p->SpawnHeadX = p->Base.HeadX;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Handlers_RemoveEntity(EntityID id) {
|
||||||
|
Entity* entity = Entities_List[id];
|
||||||
|
if (entity == NULL) return;
|
||||||
|
if (id != ENTITIES_SELF_ID) Entities_Remove(id);
|
||||||
|
|
||||||
|
/* See comment about some servers in Classic_AddEntity */
|
||||||
|
Int32 mask = id >> 3, bit = 1 << (id & 0x7);
|
||||||
|
if (!addEntityHack || (needRemoveNames[mask] & bit) == 0) return;
|
||||||
|
|
||||||
|
Handlers_RemoveTablistEntry(id);
|
||||||
|
needRemoveNames[mask] &= (UInt8)~bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Handlers_UpdateLocation(EntityID playerId, LocationUpdate* update, bool interpolate) {
|
||||||
|
Entity* entity = Entities_List[playerId];
|
||||||
|
if (entity != NULL) {
|
||||||
|
entity->VTABLE->SetLocation(entity, update, interpolate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Handlers_DisableAddEntityHack(void) {
|
void Handlers_DisableAddEntityHack(void) {
|
||||||
if (!addEntityHack) return;
|
if (!addEntityHack) return;
|
||||||
addEntityHack = false;
|
addEntityHack = false;
|
||||||
@ -169,30 +173,146 @@ void Handlers_DisableAddEntityHack(void) {
|
|||||||
Int32 mask = id >> 3, bit = 1 << (id & 0x7);
|
Int32 mask = id >> 3, bit = 1 << (id & 0x7);
|
||||||
if (!(needRemoveNames[mask] & bit)) continue;
|
if (!(needRemoveNames[mask] & bit)) continue;
|
||||||
|
|
||||||
RemoveTablistEntry((EntityID)id);
|
Handlers_RemoveTablistEntry((EntityID)id);
|
||||||
needRemoveNames[mask] &= (UInt8)~bit;
|
needRemoveNames[mask] &= (UInt8)~bit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Handlers_Reset(void) {
|
|
||||||
addEntityHack = true;
|
/*########################################################################################################################*
|
||||||
Classic_Reset();
|
*------------------------------------------------------WoM protocol-------------------------------------------------------*
|
||||||
CPE_Reset();
|
*#########################################################################################################################*/
|
||||||
BlockDefs_Reset();
|
/* Partially based on information from http://files.worldofminecraft.com/texturing/ */
|
||||||
WoM_Reset();
|
/* NOTE: http://files.worldofminecraft.com/ has been down for quite a while, so support was removed on Oct 10, 2015 */
|
||||||
|
|
||||||
|
UInt8 wom_identifierBuffer[String_BufferSize(STRING_SIZE)];
|
||||||
|
String wom_identifier = String_FromEmptyArray(wom_identifierBuffer);
|
||||||
|
Int32 wom_counter;
|
||||||
|
bool wom_sendId, wom_sentId;
|
||||||
|
|
||||||
|
void WoM_UpdateIdentifier(void) {
|
||||||
|
String_Clear(&wom_identifier);
|
||||||
|
String_Format1(&wom_identifier, "womenv_%i", &wom_counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Handlers_Tick(void) {
|
void WoM_CheckMotd(void) {
|
||||||
Classic_Tick();
|
String motd = ServerConnection_ServerMOTD;
|
||||||
CPE_Tick();
|
if (motd.length == 0) return;
|
||||||
WoM_Tick();
|
|
||||||
|
String cfg = String_FromConst("cfg=");
|
||||||
|
Int32 index = String_IndexOfString(&motd, &cfg);
|
||||||
|
if (Game_PureClassic || index == -1) return;
|
||||||
|
|
||||||
|
UInt8 urlBuffer[String_BufferSize(STRING_SIZE)];
|
||||||
|
String url = String_InitAndClearArray(urlBuffer);
|
||||||
|
String host = String_UNSAFE_SubstringAt(&motd, index + cfg.length);
|
||||||
|
String_Format1(&url, "http://%s", &host);
|
||||||
|
/* TODO: Replace $U with username */
|
||||||
|
/*url = url.Replace("$U", game.Username); */
|
||||||
|
|
||||||
|
/* Ensure that if the user quickly changes to a different world, env settings from old world aren't
|
||||||
|
applied in the new world if the async 'get env request' didn't complete before the old world was unloaded */
|
||||||
|
wom_counter++;
|
||||||
|
WoM_UpdateIdentifier();
|
||||||
|
AsyncDownloader_Download(&url, true, REQUEST_TYPE_STRING, &wom_identifier);
|
||||||
|
wom_sendId = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WoM_CheckSendWomID(void) {
|
||||||
|
if (wom_sendId && !wom_sentId) {
|
||||||
|
String msg = String_FromConst("/womid WoMClient-2.0.7")
|
||||||
|
ServerConnection_SendChat(&msg);
|
||||||
|
wom_sentId = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PackedCol WoM_ParseCol(STRING_PURE String* value, PackedCol defaultCol) {
|
||||||
|
Int32 argb;
|
||||||
|
if (!Convert_TryParseInt32(value, &argb)) return defaultCol;
|
||||||
|
|
||||||
|
PackedCol col; col.A = 255;
|
||||||
|
col.R = (UInt8)(argb >> 16);
|
||||||
|
col.G = (UInt8)(argb >> 8);
|
||||||
|
col.B = (UInt8)argb;
|
||||||
|
return col;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WoM_ReadLine(STRING_REF String* page, Int32* start, STRING_TRANSIENT String* line) {
|
||||||
|
Int32 i, offset = *start;
|
||||||
|
if (offset == -1) return false;
|
||||||
|
|
||||||
|
for (i = offset; i < page->length; i++) {
|
||||||
|
UInt8 c = page->buffer[i];
|
||||||
|
if (c != '\r' && c != '\n') continue;
|
||||||
|
|
||||||
|
*line = String_UNSAFE_Substring(page, offset, i - offset);
|
||||||
|
offset = i + 1;
|
||||||
|
if (c == '\r' && offset < page->length && page->buffer[offset] == '\n') {
|
||||||
|
offset++; /* we stop at the \r, so make sure to skip following \n */
|
||||||
|
}
|
||||||
|
|
||||||
|
*start = offset; return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*line = String_UNSAFE_SubstringAt(page, offset);
|
||||||
|
|
||||||
|
*start = -1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Wom_ParseConfig(STRING_PURE String* page) {
|
||||||
|
String line;
|
||||||
|
Int32 start = 0;
|
||||||
|
|
||||||
|
while (WoM_ReadLine(page, &start, &line)) {
|
||||||
|
Platform_Log(&line);
|
||||||
|
Int32 sepIndex = String_IndexOf(&line, '=', 0);
|
||||||
|
if (sepIndex == -1) continue;
|
||||||
|
|
||||||
|
String key = String_UNSAFE_Substring(&line, 0, sepIndex);
|
||||||
|
String_UNSAFE_TrimEnd(&key);
|
||||||
|
String value = String_UNSAFE_SubstringAt(&line, sepIndex + 1);
|
||||||
|
String_UNSAFE_TrimStart(&value);
|
||||||
|
|
||||||
|
if (String_CaselessEqualsConst(&key, "environment.cloud")) {
|
||||||
|
PackedCol col = WoM_ParseCol(&value, WorldEnv_DefaultCloudsCol);
|
||||||
|
WorldEnv_SetCloudsCol(col);
|
||||||
|
} else if (String_CaselessEqualsConst(&key, "environment.sky")) {
|
||||||
|
PackedCol col = WoM_ParseCol(&value, WorldEnv_DefaultSkyCol);
|
||||||
|
WorldEnv_SetSkyCol(col);
|
||||||
|
} else if (String_CaselessEqualsConst(&key, "environment.fog")) {
|
||||||
|
PackedCol col = WoM_ParseCol(&value, WorldEnv_DefaultFogCol);
|
||||||
|
WorldEnv_SetFogCol(col);
|
||||||
|
} else if (String_CaselessEqualsConst(&key, "environment.level")) {
|
||||||
|
Int32 waterLevel;
|
||||||
|
if (Convert_TryParseInt32(&value, &waterLevel)) {
|
||||||
|
WorldEnv_SetEdgeHeight(waterLevel);
|
||||||
|
}
|
||||||
|
} else if (String_CaselessEqualsConst(&key, "user.detail") && !cpe_useMessageTypes) {
|
||||||
|
Chat_AddOf(&value, MSG_TYPE_STATUS_2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WoM_Reset(void) {
|
||||||
|
wom_counter = 0;
|
||||||
|
WoM_UpdateIdentifier();
|
||||||
|
wom_sendId = false; wom_sentId = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WoM_Tick(void) {
|
||||||
|
AsyncRequest item;
|
||||||
|
bool success = AsyncDownloader_Get(&wom_identifier, &item);
|
||||||
|
if (success && item.ResultString.length > 0) {
|
||||||
|
Wom_ParseConfig(&item.ResultString);
|
||||||
|
Platform_MemFree(&item.ResultString.buffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*----------------------------------------------------Classic protocol-----------------------------------------------------*
|
*----------------------------------------------------Classic protocol-----------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
bool receivedFirstPosition;
|
|
||||||
DateTime mapReceiveStart;
|
DateTime mapReceiveStart;
|
||||||
InflateState mapInflateState;
|
InflateState mapInflateState;
|
||||||
Stream mapInflateStream;
|
Stream mapInflateStream;
|
||||||
@ -205,10 +325,54 @@ Stream mapPartStream;
|
|||||||
Screen* prevScreen;
|
Screen* prevScreen;
|
||||||
bool prevCursorVisible, receivedFirstPosition;
|
bool prevCursorVisible, receivedFirstPosition;
|
||||||
|
|
||||||
|
void Classic_WriteChat(Stream* stream, STRING_PURE String* text, bool partial) {
|
||||||
|
Int32 payload = !ServerConnection_SupportsPartialMessages ? ENTITIES_SELF_ID : (partial ? 1 : 0);
|
||||||
|
Stream_WriteU8(stream, OPCODE_MESSAGE);
|
||||||
|
Stream_WriteU8(stream, (UInt8)payload);
|
||||||
|
Handlers_WriteString(stream, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Classic_WritePosition(Stream* stream, Vector3 pos, Real32 rotY, Real32 headX) {
|
||||||
|
Int32 payload = cpe_sendHeldBlock ? Inventory_SelectedBlock : ENTITIES_SELF_ID;
|
||||||
|
Stream_WriteU8(stream, OPCODE_ENTITY_TELEPORT);
|
||||||
|
Handlers_WriteBlock(stream, (BlockID)payload); /* held block when using HeldBlock, otherwise just 255 */
|
||||||
|
|
||||||
|
if (cpe_extEntityPos) {
|
||||||
|
Stream_WriteI32_BE(stream, (Int32)(pos.X * 32));
|
||||||
|
Stream_WriteI32_BE(stream, (Int32)((Int32)(pos.Y * 32) + 51));
|
||||||
|
Stream_WriteI32_BE(stream, (Int32)(pos.Z * 32));
|
||||||
|
} else {
|
||||||
|
Stream_WriteI16_BE(stream, (Int16)(pos.X * 32));
|
||||||
|
Stream_WriteI16_BE(stream, (Int16)((Int32)(pos.Y * 32) + 51));
|
||||||
|
Stream_WriteI16_BE(stream, (Int16)(pos.Z * 32));
|
||||||
|
}
|
||||||
|
Stream_WriteU8(stream, Math_Deg2Packed(rotY));
|
||||||
|
Stream_WriteU8(stream, Math_Deg2Packed(headX));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Classic_WriteSetBlock(Stream* stream, Int32 x, Int32 y, Int32 z, bool place, BlockID block) {
|
||||||
|
Stream_WriteU8(stream, OPCODE_SET_BLOCK_CLIENT);
|
||||||
|
Stream_WriteI16_BE(stream, x);
|
||||||
|
Stream_WriteI16_BE(stream, y);
|
||||||
|
Stream_WriteI16_BE(stream, z);
|
||||||
|
Stream_WriteU8(stream, place ? 1 : 0);
|
||||||
|
Handlers_WriteBlock(stream, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Classic_WriteLogin(Stream* stream, STRING_PURE String* username, STRING_PURE String* verKey) {
|
||||||
|
UInt8 payload = Game_UseCPE ? 0x42 : 0x00;
|
||||||
|
Stream_WriteU8(stream, OPCODE_HANDSHAKE);
|
||||||
|
|
||||||
|
Stream_WriteU8(stream, 7); /* protocol version */
|
||||||
|
Handlers_WriteString(stream, username);
|
||||||
|
Handlers_WriteString(stream, verKey);
|
||||||
|
Stream_WriteU8(stream, payload);
|
||||||
|
}
|
||||||
|
|
||||||
void Classic_Handshake(Stream* stream) {
|
void Classic_Handshake(Stream* stream) {
|
||||||
UInt8 protocolVer = Stream_ReadU8(stream);
|
UInt8 protocolVer = Stream_ReadU8(stream);
|
||||||
ReadString(stream, &ServerConnection_ServerName);
|
Handlers_ReadString(stream, ServerConnection_ServerName.buffer);
|
||||||
ReadString(stream, &ServerConnection_ServerMOTD);
|
Handlers_ReadString(stream, ServerConnection_ServerMOTD.buffer);
|
||||||
Chat_SetLogName(&ServerConnection_ServerName);
|
Chat_SetLogName(&ServerConnection_ServerName);
|
||||||
|
|
||||||
HacksComp* hacks = &LocalPlayer_Instance.Hacks;
|
HacksComp* hacks = &LocalPlayer_Instance.Hacks;
|
||||||
@ -221,31 +385,20 @@ void Classic_Handshake(Stream* stream) {
|
|||||||
|
|
||||||
void Classic_Ping(Stream* stream) { }
|
void Classic_Ping(Stream* stream) { }
|
||||||
|
|
||||||
void Classic_LevelInit(Stream* stream) {
|
|
||||||
if (!mapInflateInited) Classic_StartLoading(stream);
|
|
||||||
|
|
||||||
/* Fast map puts volume in header, doesn't bother with gzip */
|
|
||||||
if (cpe_fastMap) {
|
|
||||||
mapVolume = Stream_ReadI32_BE(stream);
|
|
||||||
gzHeader.Done = true;
|
|
||||||
mapSizeIndex = 4;
|
|
||||||
map = Platform_MemAlloc(mapVolume);
|
|
||||||
if (map == NULL) ErrorHandler_Fail("Failed to allocate memory for map");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Classic_StartLoading(Stream* stream) {
|
void Classic_StartLoading(Stream* stream) {
|
||||||
World_Reset();
|
World_Reset();
|
||||||
Event_RaiseVoid(&WorldEvents_NewMap);
|
Event_RaiseVoid(&WorldEvents_NewMap);
|
||||||
mapPartStream = *stream;
|
mapPartStream = *stream;
|
||||||
|
|
||||||
prevScreen = Gui_Active;
|
prevScreen = Gui_Active;
|
||||||
if (prevScreen is LoadingMapScreen) {
|
if (prevScreen == LoadingScreen_UNSAFE_RawPointer) {
|
||||||
|
/* otherwise replacing LoadingScreen with LoadingScreen will cause issues */
|
||||||
|
Gui_FreeActive();
|
||||||
prevScreen = NULL;
|
prevScreen = NULL;
|
||||||
}
|
}
|
||||||
prevCursorVisible = Game_GetCursorVisible();
|
prevCursorVisible = Game_GetCursorVisible();
|
||||||
|
|
||||||
Gui_SetNewScreen(new LoadingMapScreen(game, net.ServerName, net.ServerMotd), false);
|
Gui_SetActive(LoadingScreen_MakeInstance(&ServerConnection_ServerName, &ServerConnection_ServerMOTD));
|
||||||
WoM_CheckMotd();
|
WoM_CheckMotd();
|
||||||
receivedFirstPosition = false;
|
receivedFirstPosition = false;
|
||||||
GZipHeader_Init(&gzHeader);
|
GZipHeader_Init(&gzHeader);
|
||||||
@ -258,6 +411,19 @@ void Classic_StartLoading(Stream* stream) {
|
|||||||
Platform_CurrentUTCTime(&mapReceiveStart);
|
Platform_CurrentUTCTime(&mapReceiveStart);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Classic_LevelInit(Stream* stream) {
|
||||||
|
if (!mapInflateInited) Classic_StartLoading(stream);
|
||||||
|
|
||||||
|
/* Fast map puts volume in header, doesn't bother with gzip */
|
||||||
|
if (cpe_fastMap) {
|
||||||
|
mapVolume = Stream_ReadI32_BE(stream);
|
||||||
|
gzHeader.Done = true;
|
||||||
|
mapSizeIndex = 4;
|
||||||
|
map = Platform_MemAlloc(mapVolume, sizeof(BlockID));
|
||||||
|
if (map == NULL) ErrorHandler_Fail("Failed to allocate memory for map");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Classic_LevelDataChunk(Stream* stream) {
|
void Classic_LevelDataChunk(Stream* stream) {
|
||||||
/* Workaround for some servers that send LevelDataChunk before LevelInit due to their async sending behaviour */
|
/* Workaround for some servers that send LevelDataChunk before LevelInit due to their async sending behaviour */
|
||||||
if (!mapInflateInited) Classic_StartLoading(stream);
|
if (!mapInflateInited) Classic_StartLoading(stream);
|
||||||
@ -281,7 +447,7 @@ void Classic_LevelDataChunk(Stream* stream) {
|
|||||||
if (mapSizeIndex == 4) {
|
if (mapSizeIndex == 4) {
|
||||||
if (map == NULL) {
|
if (map == NULL) {
|
||||||
mapVolume = (mapSize[0] << 24) | (mapSize[1] << 16) | (mapSize[2] << 8) | mapSize[3];
|
mapVolume = (mapSize[0] << 24) | (mapSize[1] << 16) | (mapSize[2] << 8) | mapSize[3];
|
||||||
map = Platform_MemAlloc(mapVolume);
|
map = Platform_MemAlloc(mapVolume, sizeof(BlockID));
|
||||||
if (map == NULL) ErrorHandler_Fail("Failed to allocate memory for map");
|
if (map == NULL) ErrorHandler_Fail("Failed to allocate memory for map");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,7 +463,7 @@ void Classic_LevelDataChunk(Stream* stream) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Classic_LevelFinalise(Stream* stream) {
|
void Classic_LevelFinalise(Stream* stream) {
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
Gui_Active = prevScreen;
|
Gui_Active = prevScreen;
|
||||||
if (prevScreen != NULL && prevCursorVisible != Game_GetCursorVisible()) {
|
if (prevScreen != NULL && prevCursorVisible != Game_GetCursorVisible()) {
|
||||||
Game_SetCursorVisible(prevCursorVisible);
|
Game_SetCursorVisible(prevCursorVisible);
|
||||||
@ -314,7 +480,7 @@ void Classic_LevelFinalise(Stream* stream) {
|
|||||||
|
|
||||||
World_SetNewMap(map, mapVolume, mapWidth, mapHeight, mapLength);
|
World_SetNewMap(map, mapVolume, mapWidth, mapHeight, mapLength);
|
||||||
Event_RaiseVoid(&WorldEvents_MapLoaded);
|
Event_RaiseVoid(&WorldEvents_MapLoaded);
|
||||||
Wom_CheckSendWomID();
|
WoM_CheckSendWomID();
|
||||||
|
|
||||||
map = NULL;
|
map = NULL;
|
||||||
mapInflateInited = false;
|
mapInflateInited = false;
|
||||||
@ -430,7 +596,7 @@ void Classic_Kick(Stream* stream) {
|
|||||||
void Classic_SetPermission(Stream* stream) {
|
void Classic_SetPermission(Stream* stream) {
|
||||||
HacksComp* hacks = &LocalPlayer_Instance.Hacks;
|
HacksComp* hacks = &LocalPlayer_Instance.Hacks;
|
||||||
HacksComp_SetUserType(hacks, Stream_ReadU8(stream), !cpe_blockPerms);
|
HacksComp_SetUserType(hacks, Stream_ReadU8(stream), !cpe_blockPerms);
|
||||||
HacksComp_UpdateHacksState(hacks);
|
HacksComp_UpdateState(hacks);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Classic_ReadAbsoluteLocation(Stream* stream, EntityID id, bool interpolate) {
|
void Classic_ReadAbsoluteLocation(Stream* stream, EntityID id, bool interpolate) {
|
||||||
@ -453,50 +619,6 @@ void Classic_ReadAbsoluteLocation(Stream* stream, EntityID id, bool interpolate)
|
|||||||
Handlers_UpdateLocation(id, &update, interpolate);
|
Handlers_UpdateLocation(id, &update, interpolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Classic_WriteChat(Stream* stream, STRING_PURE String* text, bool partial) {
|
|
||||||
Int32 payload = !ServerConnection_SupportsPartialMessages ? ENTITIES_SELF_ID : (partial ? 1 : 0);
|
|
||||||
Stream_WriteU8(stream, OPCODE_MESSAGE);
|
|
||||||
Stream_WriteU8(stream, (UInt8)payload);
|
|
||||||
Handlers_WriteString(stream, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Classic_WritePosition(Stream* stream, Vector3 pos, Real32 rotY, Real32 headX) {
|
|
||||||
Int32 payload = cpe_sendHeldBlock ? Inventory_SelectedBlock : ENTITIES_SELF_ID;
|
|
||||||
Stream_WriteU8(stream, OPCODE_ENTITY_TELEPORT);
|
|
||||||
Handlers_WriteBlock(stream, (BlockID)payload); /* held block when using HeldBlock, otherwise just 255 */
|
|
||||||
|
|
||||||
if (cpe_extEntityPos) {
|
|
||||||
Stream_WriteI32_BE(stream, (Int32)(pos.X * 32));
|
|
||||||
Stream_WriteI32_BE(stream, (Int32)((Int32)(pos.Y * 32) + 51));
|
|
||||||
Stream_WriteI32_BE(stream, (Int32)(pos.Z * 32));
|
|
||||||
} else {
|
|
||||||
Stream_WriteI16_BE(stream, (Int16)(pos.X * 32));
|
|
||||||
Stream_WriteI16_BE(stream, (Int16)((Int32)(pos.Y * 32) + 51));
|
|
||||||
Stream_WriteI16_BE(stream, (Int16)(pos.Z * 32));
|
|
||||||
}
|
|
||||||
Stream_WriteU8(stream, Math_Deg2Packed(rotY));
|
|
||||||
Stream_WriteU8(stream, Math_Deg2Packed(headX));
|
|
||||||
}
|
|
||||||
|
|
||||||
void Classic_WriteSetBlock(Stream* stream, Int32 x, Int32 y, Int32 z, bool place, BlockID block) {
|
|
||||||
Stream_WriteU8(stream, OPCODE_SET_BLOCK_CLIENT);
|
|
||||||
Stream_WriteI16_BE(stream, x);
|
|
||||||
Stream_WriteI16_BE(stream, y);
|
|
||||||
Stream_WriteI16_BE(stream, z);
|
|
||||||
Stream_WriteU8(stream, place ? 1 : 0);
|
|
||||||
Handlers_WriteBlock(stream, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Classic_WriteLogin(Stream* stream, STRING_PURE String* username, STRING_PURE String* verKey) {
|
|
||||||
UInt8 payload = Game_UseCPE ? 0x42 : 0x00;
|
|
||||||
Stream_WriteU8(stream, OPCODE_HANDSHAKE);
|
|
||||||
|
|
||||||
Stream_WriteU8(stream, 7); /* protocol version */
|
|
||||||
Handlers_WriteString(stream, username);
|
|
||||||
Handlers_WriteString(stream, verKey);
|
|
||||||
Stream_WriteU8(stream, payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Classic_Reset(void) {
|
void Classic_Reset(void) {
|
||||||
mapInflateInited = false;
|
mapInflateInited = false;
|
||||||
receivedFirstPosition = false;
|
receivedFirstPosition = false;
|
||||||
@ -533,17 +655,94 @@ void Classic_Tick(void) {
|
|||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
|
|
||||||
Int32 cpe_serverExtensionsCount, cpe_pingTicks;
|
Int32 cpe_serverExtensionsCount, cpe_pingTicks;
|
||||||
bool cpe_sendHeldBlock, cpe_useMessageTypes;
|
|
||||||
Int32 cpe_envMapVer = 2, cpe_blockDefsExtVer = 2;
|
Int32 cpe_envMapVer = 2, cpe_blockDefsExtVer = 2;
|
||||||
bool cpe_needD3Fix, cpe_extEntityPos, cpe_twoWayPing, cpe_blockPerms, cpe_fastMap;
|
bool cpe_twoWayPing;
|
||||||
|
|
||||||
const UInt8** cpe_clientExtensions[28] = {
|
const UInt8* cpe_clientExtensions[28] = {
|
||||||
"ClickDistance", "CustomBlocks", "HeldBlock", "EmoteFix", "TextHotKey", "ExtPlayerList",
|
"ClickDistance", "CustomBlocks", "HeldBlock", "EmoteFix", "TextHotKey", "ExtPlayerList",
|
||||||
"EnvColors", "SelectionCuboid", "BlockPermissions", "ChangeModel", "EnvMapAppearance",
|
"EnvColors", "SelectionCuboid", "BlockPermissions", "ChangeModel", "EnvMapAppearance",
|
||||||
"EnvWeatherType", "MessageTypes", "HackControl", "PlayerClick", "FullCP437", "LongerMessages",
|
"EnvWeatherType", "MessageTypes", "HackControl", "PlayerClick", "FullCP437", "LongerMessages",
|
||||||
"BlockDefinitions", "BlockDefinitionsExt", "BulkBlockUpdate", "TextColors", "EnvMapAspect",
|
"BlockDefinitions", "BlockDefinitionsExt", "BulkBlockUpdate", "TextColors", "EnvMapAspect",
|
||||||
"EntityProperty", "ExtEntityPositions", "TwoWayPing", "InventoryOrder", "InstantMOTD", "FastMap",
|
"EntityProperty", "ExtEntityPositions", "TwoWayPing", "InventoryOrder", "InstantMOTD", "FastMap",
|
||||||
};
|
};
|
||||||
|
void CPE_SetMapEnvUrl(Stream* stream);
|
||||||
|
|
||||||
|
#define Ext_Deg2Packed(x) ((Int16)((x) * 65536.0f / 360.0f))
|
||||||
|
void CPE_WritePlayerClick(Stream* stream, MouseButton button, bool buttonDown, UInt8 targetId, PickedPos* pos) {
|
||||||
|
Entity* p = &LocalPlayer_Instance.Base;
|
||||||
|
Stream_WriteU8(stream, OPCODE_CPE_PLAYER_CLICK);
|
||||||
|
Stream_WriteU8(stream, button);
|
||||||
|
Stream_WriteU8(stream, buttonDown ? 0 : 1);
|
||||||
|
Stream_WriteI16_BE(stream, Ext_Deg2Packed(p->HeadY));
|
||||||
|
Stream_WriteI16_BE(stream, Ext_Deg2Packed(p->HeadX));
|
||||||
|
|
||||||
|
Stream_WriteU8(stream, targetId);
|
||||||
|
Stream_WriteI16_BE(stream, pos->BlockPos.X);
|
||||||
|
Stream_WriteI16_BE(stream, pos->BlockPos.Y);
|
||||||
|
Stream_WriteI16_BE(stream, pos->BlockPos.Z);
|
||||||
|
|
||||||
|
UInt8 face = 255;
|
||||||
|
/* Our own face values differ from CPE block face */
|
||||||
|
switch (pos->ClosestFace) {
|
||||||
|
case FACE_XMAX: face = 0; break;
|
||||||
|
case FACE_XMIN: face = 1; break;
|
||||||
|
case FACE_YMAX: face = 2; break;
|
||||||
|
case FACE_YMIN: face = 3; break;
|
||||||
|
case FACE_ZMAX: face = 4; break;
|
||||||
|
case FACE_ZMIN: face = 5; break;
|
||||||
|
}
|
||||||
|
Stream_WriteU8(stream, face);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPE_WriteExtInfo(Stream* stream, STRING_PURE String* appName, Int32 extensionsCount) {
|
||||||
|
Stream_WriteU8(stream, OPCODE_CPE_EXT_INFO);
|
||||||
|
Handlers_WriteString(stream, appName);
|
||||||
|
Stream_WriteU16_BE(stream, extensionsCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPE_WriteExtEntry(Stream* stream, STRING_PURE String* extensionName, Int32 extensionVersion) {
|
||||||
|
Stream_WriteU8(stream, OPCODE_CPE_EXT_ENTRY);
|
||||||
|
Handlers_WriteString(stream, extensionName);
|
||||||
|
Stream_WriteI32_BE(stream, extensionVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPE_WriteCustomBlockLevel(Stream* stream, UInt8 version) {
|
||||||
|
Stream_WriteU8(stream, OPCODE_CPE_CUSTOM_BLOCK_LEVEL);
|
||||||
|
Stream_WriteU8(stream, version);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPE_WriteTwoWayPing(Stream* stream, bool serverToClient, UInt16 data) {
|
||||||
|
Stream_WriteU8(stream, OPCODE_CPE_TWO_WAY_PING);
|
||||||
|
Stream_WriteU8(stream, serverToClient ? 1 : 0);
|
||||||
|
Stream_WriteU16_BE(stream, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CPE_SendCpeExtInfoReply(void) {
|
||||||
|
if (cpe_serverExtensionsCount != 0) return;
|
||||||
|
Int32 count = Array_Elems(cpe_clientExtensions);
|
||||||
|
if (!Game_AllowCustomBlocks) count -= 2;
|
||||||
|
Stream* stream = ServerConnection_WriteStream();
|
||||||
|
|
||||||
|
CPE_WriteExtInfo(stream, &ServerConnection_AppName, count);
|
||||||
|
Net_SendPacket();
|
||||||
|
Int32 i, ver;
|
||||||
|
|
||||||
|
for (i = 0; i < Array_Elems(cpe_clientExtensions); i++) {
|
||||||
|
String name = String_FromReadonly(cpe_clientExtensions[i]);
|
||||||
|
ver = 1;
|
||||||
|
if (String_CaselessEqualsConst(&name, "ExtPlayerList")) ver = 2;
|
||||||
|
if (String_CaselessEqualsConst(&name, "EnvMapAppearance")) ver = cpe_envMapVer;
|
||||||
|
if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) ver = cpe_blockDefsExtVer;
|
||||||
|
|
||||||
|
if (!Game_AllowCustomBlocks) {
|
||||||
|
if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) continue;
|
||||||
|
if (String_CaselessEqualsConst(&name, "BlockDefinitions")) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CPE_WriteExtEntry(stream, &name, ver);
|
||||||
|
Net_SendPacket();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CPE_ExtInfo(Stream* stream) {
|
void CPE_ExtInfo(Stream* stream) {
|
||||||
UInt8 appNameBuffer[String_BufferSize(STRING_SIZE)];
|
UInt8 appNameBuffer[String_BufferSize(STRING_SIZE)];
|
||||||
@ -669,8 +868,8 @@ void CPE_ExtAddPlayerName(Stream* stream) {
|
|||||||
UInt8 groupRank = Stream_ReadU8(stream);
|
UInt8 groupRank = Stream_ReadU8(stream);
|
||||||
|
|
||||||
String_StripCols(&playerName);
|
String_StripCols(&playerName);
|
||||||
Handler_RemoveEndPlus(&playerName);
|
Handlers_RemoveEndPlus(&playerName);
|
||||||
Handler_RemoveEndPlus(&listName);
|
Handlers_RemoveEndPlus(&listName);
|
||||||
|
|
||||||
/* Some server software will declare they support ExtPlayerList, but send AddEntity then AddPlayerName */
|
/* Some server software will declare they support ExtPlayerList, but send AddEntity then AddPlayerName */
|
||||||
/* We need to workaround this case by removing all the tab names we added for the AddEntity packets */
|
/* We need to workaround this case by removing all the tab names we added for the AddEntity packets */
|
||||||
@ -755,7 +954,7 @@ void CPE_SetBlockPermission(Stream* stream) {
|
|||||||
void CPE_ChangeModel(Stream* stream) {
|
void CPE_ChangeModel(Stream* stream) {
|
||||||
UInt8 modelNameBuffer[String_BufferSize(STRING_SIZE)];
|
UInt8 modelNameBuffer[String_BufferSize(STRING_SIZE)];
|
||||||
UInt8 id = Stream_ReadU8(stream);
|
UInt8 id = Stream_ReadU8(stream);
|
||||||
String modelName = Handlers_ReadString(stream, &modelNameBuffer);
|
String modelName = Handlers_ReadString(stream, modelNameBuffer);
|
||||||
|
|
||||||
String_MakeLowercase(&modelName);
|
String_MakeLowercase(&modelName);
|
||||||
Entity* entity = Entities_List[id];
|
Entity* entity = Entities_List[id];
|
||||||
@ -920,13 +1119,13 @@ void CPE_SetEntityProperty(Stream* stream) {
|
|||||||
Real32 scale;
|
Real32 scale;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
update.Flags |= LOCATIONUPDATE_FLAG_ROTX;
|
update.Flags |= LOCATIONUPDATE_FLAG_ROTX;
|
||||||
update.RotX = LocationUpdate_Clamp(value); break;
|
update.RotX = LocationUpdate_Clamp((Real32)value); break;
|
||||||
case 1:
|
case 1:
|
||||||
update.Flags |= LOCATIONUPDATE_FLAG_HEADY;
|
update.Flags |= LOCATIONUPDATE_FLAG_HEADY;
|
||||||
update.HeadY = LocationUpdate_Clamp(value); break;
|
update.HeadY = LocationUpdate_Clamp((Real32)value); break;
|
||||||
case 2:
|
case 2:
|
||||||
update.Flags |= LOCATIONUPDATE_FLAG_ROTZ;
|
update.Flags |= LOCATIONUPDATE_FLAG_ROTZ;
|
||||||
update.RotZ = LocationUpdate_Clamp(value); break;
|
update.RotZ = LocationUpdate_Clamp((Real32)value); break;
|
||||||
|
|
||||||
case 3:
|
case 3:
|
||||||
case 4:
|
case 4:
|
||||||
@ -965,83 +1164,6 @@ void CPE_SetInventoryOrder(Stream* stream) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define Ext_Deg2Packed(x) ((Int16)((x) * 65536.0f / 360.0f))
|
|
||||||
void CPE_WritePlayerClick(Stream* stream, MouseButton button, bool buttonDown, UInt8 targetId, PickedPos* pos) {
|
|
||||||
Entity* p = &LocalPlayer_Instance.Base;
|
|
||||||
Stream_WriteU8(stream, OPCODE_CPE_PLAYER_CLICK);
|
|
||||||
Stream_WriteU8(stream, button);
|
|
||||||
Stream_WriteU8(stream, buttonDown ? 0 : 1);
|
|
||||||
Stream_WriteI16_BE(stream, Ext_Deg2Packed(p->HeadY));
|
|
||||||
Stream_WriteI16_BE(stream, Ext_Deg2Packed(p->HeadX));
|
|
||||||
|
|
||||||
Stream_WriteU8(stream, targetId);
|
|
||||||
Stream_WriteI16_BE(stream, pos->BlockPos.X);
|
|
||||||
Stream_WriteI16_BE(stream, pos->BlockPos.Y);
|
|
||||||
Stream_WriteI16_BE(stream, pos->BlockPos.Z);
|
|
||||||
|
|
||||||
UInt8 face = 255;
|
|
||||||
/* Our own face values differ from CPE block face */
|
|
||||||
switch (pos->ClosestFace) {
|
|
||||||
case FACE_XMAX: face = 0; break;
|
|
||||||
case FACE_XMIN: face = 1; break;
|
|
||||||
case FACE_YMAX: face = 2; break;
|
|
||||||
case FACE_YMIN: face = 3; break;
|
|
||||||
case FACE_ZMAX: face = 4; break;
|
|
||||||
case FACE_ZMIN: face = 5; break;
|
|
||||||
}
|
|
||||||
Stream_WriteU8(stream, face);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPE_WriteExtInfo(Stream* stream, STRING_PURE String* appName, Int32 extensionsCount) {
|
|
||||||
Stream_WriteU8(stream, OPCODE_CPE_EXT_INFO);
|
|
||||||
Handlers_WriteString(stream, appName);
|
|
||||||
Stream_WriteU16_BE(stream, extensionsCount);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPE_WriteExtEntry(Stream* stream, STRING_PURE String* extensionName, Int32 extensionVersion) {
|
|
||||||
Stream_WriteU8(stream, OPCODE_CPE_EXT_ENTRY);
|
|
||||||
Handlers_WriteString(stream, extensionName);
|
|
||||||
Stream_WriteI32_BE(stream, extensionVersion);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPE_WriteCustomBlockLevel(Stream* stream, UInt8 version) {
|
|
||||||
Stream_WriteU8(stream, OPCODE_CPE_CUSTOM_BLOCK_LEVEL);
|
|
||||||
Stream_WriteU8(stream, version);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPE_WriteTwoWayPing(Stream* stream, bool serverToClient, UInt16 data) {
|
|
||||||
Stream_WriteU8(stream, OPCODE_CPE_TWO_WAY_PING);
|
|
||||||
Stream_WriteU8(stream, serverToClient ? 1 : 0);
|
|
||||||
Stream_WriteU16_BE(stream, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPE_SendCpeExtInfoReply(void) {
|
|
||||||
if (cpe_serverExtensionsCount != 0) return;
|
|
||||||
Int32 count = Array_Elems(cpe_clientExtensions);
|
|
||||||
if (!Game_AllowCustomBlocks) count -= 2;
|
|
||||||
Stream* stream = ServerConnection_WriteStream();
|
|
||||||
|
|
||||||
CPE_WriteExtInfo(stream, &ServerConnection_AppName, count);
|
|
||||||
Net_SendPacket();
|
|
||||||
Int32 i, ver;
|
|
||||||
|
|
||||||
for (i = 0; i < Array_Elems(cpe_clientExtensions); i++) {
|
|
||||||
String name = String_FromReadonly(cpe_clientExtensions[i]);
|
|
||||||
ver = 1;
|
|
||||||
if (String_CaselessEqualsConst(&name, "ExtPlayerList")) ver = 2;
|
|
||||||
if (String_CaselessEqualsConst(&name, "EnvMapAppearance")) ver = cpe_envMapVer;
|
|
||||||
if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) ver = cpe_blockDefsExtVer;
|
|
||||||
|
|
||||||
if (!Game_AllowCustomBlocks) {
|
|
||||||
if (String_CaselessEqualsConst(&name, "BlockDefinitionsExt")) continue;
|
|
||||||
if (String_CaselessEqualsConst(&name, "BlockDefinitions")) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
CPE_WriteExtEntry(stream, &name, ver);
|
|
||||||
Net_SendPacket();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CPE_Reset(void) {
|
void CPE_Reset(void) {
|
||||||
cpe_serverExtensionsCount = 0; cpe_pingTicks = 0;
|
cpe_serverExtensionsCount = 0; cpe_pingTicks = 0;
|
||||||
cpe_sendHeldBlock = false; cpe_useMessageTypes = false;
|
cpe_sendHeldBlock = false; cpe_useMessageTypes = false;
|
||||||
@ -1084,7 +1206,7 @@ void CPE_Tick(void) {
|
|||||||
cpe_pingTicks++;
|
cpe_pingTicks++;
|
||||||
if (cpe_pingTicks >= 20 && cpe_twoWayPing) {
|
if (cpe_pingTicks >= 20 && cpe_twoWayPing) {
|
||||||
Stream* stream = ServerConnection_WriteStream();
|
Stream* stream = ServerConnection_WriteStream();
|
||||||
CPE_WriteTwoWayPing(stream, false, PingList_NextTwoWayPingData());
|
CPE_WriteTwoWayPing(stream, false, PingList_NextPingData());
|
||||||
cpe_pingTicks = 0;
|
cpe_pingTicks = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1093,65 +1215,16 @@ void CPE_Tick(void) {
|
|||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*------------------------------------------------------Custom blocks------------------------------------------------------*
|
*------------------------------------------------------Custom blocks------------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
void BlockDefs_DefineBlock(Stream* stream) {
|
|
||||||
BlockID block = BlockDefs_DefineBlockCommonStart(stream, false);
|
|
||||||
|
|
||||||
UInt8 shape = Stream_ReadU8(stream);
|
|
||||||
if (shape > 0 && shape <= 16) {
|
|
||||||
Block_MaxBB[block].Y = shape / 16.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockDefs_DefineBlockCommonEnd(stream, shape, block);
|
|
||||||
/* Update sprite BoundingBox if necessary */
|
|
||||||
if (Block_Draw[block] == DRAW_SPRITE) {
|
|
||||||
Block_RecalculateBB(block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void BlockDefs_UndefineBlock(Stream* stream) {
|
|
||||||
BlockID block = Handlers_ReadBlock(stream);
|
|
||||||
bool didBlockLight = Block_BlocksLight[block];
|
|
||||||
|
|
||||||
Bloc_ResetBlockProps(block);
|
|
||||||
OnBlockUpdated(block, didBlockLight);
|
|
||||||
Block_UpdateCulling(block);
|
|
||||||
|
|
||||||
Inventory_Remove(block);
|
|
||||||
if (block < BLOCK_CPE_COUNT) { Inventory_AddDefault(block); }
|
|
||||||
|
|
||||||
Block_SetCustomDefined(block, false);
|
|
||||||
Event_RaiseVoid(&BlockEvents_BlockDefChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void OnBlockUpdated(BlockID block, bool didBlockLight) {
|
void OnBlockUpdated(BlockID block, bool didBlockLight) {
|
||||||
if (World_Blocks == NULL) return;
|
if (World_Blocks == NULL) return;
|
||||||
/* Need to refresh lighting when a block's light blocking state changes */
|
/* Need to refresh lighting when a block's light blocking state changes */
|
||||||
if (Block_BlocksLight[block] != didBlockLight) { Lighting_Refresh(); }
|
if (Block_BlocksLight[block] != didBlockLight) { Lighting_Refresh(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BlockDefs_ReadCoord(x) x = Stream_ReadU8(stream) / 16.0f; if (x > 1.0f) x = 1.0f;
|
|
||||||
void BlockDefs_DefineBlockExt(Stream* stream) {
|
|
||||||
BlockID block = BlockDefs_DefineBlockCommonStart(stream, cpe_blockDefsExtVer >= 2);
|
|
||||||
|
|
||||||
Vector3 minBB;
|
|
||||||
BlockDefs_ReadCoord(minBB.X);
|
|
||||||
BlockDefs_ReadCoord(minBB.Y);
|
|
||||||
BlockDefs_ReadCoord(minBB.Z);
|
|
||||||
|
|
||||||
Vector3 maxBB;
|
|
||||||
BlockDefs_ReadCoord(maxBB.X);
|
|
||||||
BlockDefs_ReadCoord(maxBB.Y);
|
|
||||||
BlockDefs_ReadCoord(maxBB.Z);
|
|
||||||
|
|
||||||
Block_MinBB[block] = minBB;
|
|
||||||
Block_MaxBB[block] = maxBB;
|
|
||||||
BlockDefs_DefineBlockCommonEnd(stream, 1, block);
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockID BlockDefs_DefineBlockCommonStart(Stream* stream, bool uniqueSideTexs) {
|
BlockID BlockDefs_DefineBlockCommonStart(Stream* stream, bool uniqueSideTexs) {
|
||||||
BlockID block = Handlers_ReadBlock(stream);
|
BlockID block = Handlers_ReadBlock(stream);
|
||||||
bool didBlockLight = Block_BlocksLight[block];
|
bool didBlockLight = Block_BlocksLight[block];
|
||||||
Block_ResetBlockProps(block);
|
Block_ResetProps(block);
|
||||||
|
|
||||||
UInt8 nameBuffer[String_BufferSize(STRING_SIZE)];
|
UInt8 nameBuffer[String_BufferSize(STRING_SIZE)];
|
||||||
String name = Handlers_ReadString(stream, nameBuffer);
|
String name = Handlers_ReadString(stream, nameBuffer);
|
||||||
@ -1202,6 +1275,55 @@ void BlockDefs_DefineBlockCommonEnd(Stream* stream, UInt8 shape, BlockID block)
|
|||||||
Block_DefineCustom(block);
|
Block_DefineCustom(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BlockDefs_DefineBlock(Stream* stream) {
|
||||||
|
BlockID block = BlockDefs_DefineBlockCommonStart(stream, false);
|
||||||
|
|
||||||
|
UInt8 shape = Stream_ReadU8(stream);
|
||||||
|
if (shape > 0 && shape <= 16) {
|
||||||
|
Block_MaxBB[block].Y = shape / 16.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockDefs_DefineBlockCommonEnd(stream, shape, block);
|
||||||
|
/* Update sprite BoundingBox if necessary */
|
||||||
|
if (Block_Draw[block] == DRAW_SPRITE) {
|
||||||
|
Block_RecalculateBB(block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BlockDefs_UndefineBlock(Stream* stream) {
|
||||||
|
BlockID block = Handlers_ReadBlock(stream);
|
||||||
|
bool didBlockLight = Block_BlocksLight[block];
|
||||||
|
|
||||||
|
Block_ResetProps(block);
|
||||||
|
OnBlockUpdated(block, didBlockLight);
|
||||||
|
Block_UpdateCulling(block);
|
||||||
|
|
||||||
|
Inventory_Remove(block);
|
||||||
|
if (block < BLOCK_CPE_COUNT) { Inventory_AddDefault(block); }
|
||||||
|
|
||||||
|
Block_SetCustomDefined(block, false);
|
||||||
|
Event_RaiseVoid(&BlockEvents_BlockDefChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define BlockDefs_ReadCoord(x) x = Stream_ReadU8(stream) / 16.0f; if (x > 1.0f) x = 1.0f;
|
||||||
|
void BlockDefs_DefineBlockExt(Stream* stream) {
|
||||||
|
BlockID block = BlockDefs_DefineBlockCommonStart(stream, cpe_blockDefsExtVer >= 2);
|
||||||
|
|
||||||
|
Vector3 minBB;
|
||||||
|
BlockDefs_ReadCoord(minBB.X);
|
||||||
|
BlockDefs_ReadCoord(minBB.Y);
|
||||||
|
BlockDefs_ReadCoord(minBB.Z);
|
||||||
|
|
||||||
|
Vector3 maxBB;
|
||||||
|
BlockDefs_ReadCoord(maxBB.X);
|
||||||
|
BlockDefs_ReadCoord(maxBB.Y);
|
||||||
|
BlockDefs_ReadCoord(maxBB.Z);
|
||||||
|
|
||||||
|
Block_MinBB[block] = minBB;
|
||||||
|
Block_MaxBB[block] = maxBB;
|
||||||
|
BlockDefs_DefineBlockCommonEnd(stream, 1, block);
|
||||||
|
}
|
||||||
|
|
||||||
#if FALSE
|
#if FALSE
|
||||||
void HandleDefineModel(void) {
|
void HandleDefineModel(void) {
|
||||||
int start = reader.index - 1;
|
int start = reader.index - 1;
|
||||||
@ -1240,130 +1362,18 @@ void BlockDefs_Reset(void) {
|
|||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
*------------------------------------------------------WoM protocol-------------------------------------------------------*
|
*-----------------------------------------------------Public handlers-----------------------------------------------------*
|
||||||
*#########################################################################################################################*/
|
*#########################################################################################################################*/
|
||||||
/* Partially based on information from http://files.worldofminecraft.com/texturing/ */
|
void Handlers_Reset(void) {
|
||||||
/* NOTE: http://files.worldofminecraft.com/ has been down for quite a while, so support was removed on Oct 10, 2015 */
|
addEntityHack = true;
|
||||||
|
Classic_Reset();
|
||||||
UInt8 wom_identifierBuffer[String_BufferSize(STRING_SIZE)];
|
CPE_Reset();
|
||||||
String wom_identifier = String_FromEmptyArray(wom_identifierBuffer);
|
BlockDefs_Reset();
|
||||||
Int32 wom_counter;
|
WoM_Reset();
|
||||||
bool wom_sendId, wom_sentId;
|
|
||||||
|
|
||||||
void WoM_UpdateIdentifier(void) {
|
|
||||||
String_Clear(&wom_identifier);
|
|
||||||
String_Format1(&wom_identifier, "womenv_%i", &wom_counter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WoM_CheckMotd(void) {
|
void Handlers_Tick(void) {
|
||||||
String motd = ServerConnection_ServerMOTD;
|
Classic_Tick();
|
||||||
if (motd.length == 0) return;
|
CPE_Tick();
|
||||||
|
WoM_Tick();
|
||||||
String cfg = String_FromConst("cfg=");
|
|
||||||
Int32 index = String_IndexOfString(&motd, &cfg);
|
|
||||||
if (Game_PureClassic || index == -1) return;
|
|
||||||
|
|
||||||
UInt8 urlBuffer[String_BufferSize(STRING_SIZE)];
|
|
||||||
String url = String_InitAndClearArray(urlBuffer);
|
|
||||||
String host = String_UNSAFE_SubstringAt(&motd, index + cfg.length);
|
|
||||||
String_Format1(&url, "http://%s", &host);
|
|
||||||
/* TODO: Replace $U with username */
|
|
||||||
/*url = url.Replace("$U", game.Username); */
|
|
||||||
|
|
||||||
/* Ensure that if the user quickly changes to a different world, env settings from old world aren't
|
|
||||||
applied in the new world if the async 'get env request' didn't complete before the old world was unloaded */
|
|
||||||
wom_counter++;
|
|
||||||
WoM_UpdateIdentifier();
|
|
||||||
AsyncDownloader_Download(&url, true, REQUEST_TYPE_STRING, &wom_identifier);
|
|
||||||
wom_sendId = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WoM_CheckSendWomID(void) {
|
|
||||||
if (wom_sendId && !wom_sentId) {
|
|
||||||
String msg = String_FromConst("/womid WoMClient-2.0.7")
|
|
||||||
ServerConnection_SendChat(&msg);
|
|
||||||
wom_sentId = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PackedCol WoM_ParseCol(STRING_PURE String* value, PackedCol defaultCol) {
|
|
||||||
Int32 argb;
|
|
||||||
if (!Convert_TryParseInt32(value, &argb)) return defaultCol;
|
|
||||||
|
|
||||||
PackedCol col; col.A = 255;
|
|
||||||
col.R = (UInt8)(argb >> 16);
|
|
||||||
col.G = (UInt8)(argb >> 8);
|
|
||||||
col.B = (UInt8)argb;
|
|
||||||
return col;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WoM_ReadLine(STRING_REF String* page, Int32* start, STRING_TRANSIENT String* line) {
|
|
||||||
Int32 i, offset = *start;
|
|
||||||
if (offset == -1) return false;
|
|
||||||
|
|
||||||
for (i = offset; i < page->length; i++) {
|
|
||||||
UInt8 c = page->buffer[i];
|
|
||||||
if (c != '\r' && c != '\n') continue;
|
|
||||||
|
|
||||||
*line = String_UNSAFE_Substring(page, offset, i - offset);
|
|
||||||
offset = i + 1;
|
|
||||||
if (c == '\r' && offset < page->length && page->buffer[offset] == '\n') {
|
|
||||||
offset++; /* we stop at the \r, so make sure to skip following \n */
|
|
||||||
}
|
|
||||||
|
|
||||||
start = offset; return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
*line = String_UNSAFE_SubstringAt(page, offset);
|
|
||||||
start = -1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Wom_ParseConfig(STRING_PURE String* page) {
|
|
||||||
String line;
|
|
||||||
Int32 start = 0;
|
|
||||||
|
|
||||||
while (WoM_ReadLine(page, &start, &line)) {
|
|
||||||
Platform_Log(&line);
|
|
||||||
Int32 sepIndex = String_IndexOf(&line, '=', 0);
|
|
||||||
if (sepIndex == -1) continue;
|
|
||||||
|
|
||||||
String key = String_UNSAFE_Substring(&line, 0, sepIndex);
|
|
||||||
String_UNSAFE_TrimEnd(&key);
|
|
||||||
String value = String_UNSAFE_SubstringAt(&line, sepIndex + 1);
|
|
||||||
String_UNSAFE_TrimStart(&value);
|
|
||||||
|
|
||||||
if (String_CaselessEqualsConst(&key, "environment.cloud")) {
|
|
||||||
PackedCol col = WoM_ParseCol(&value, WorldEnv_DefaultCloudsCol);
|
|
||||||
WorldEnv_SetCloudsCol(col);
|
|
||||||
} else if (String_CaselessEqualsConst(&key, "environment.sky")) {
|
|
||||||
PackedCol col = WoM_ParseCol(&value, WorldEnv_DefaultSkyCol);
|
|
||||||
WorldEnv_SetSkyCol(col);
|
|
||||||
} else if (String_CaselessEqualsConst(&key, "environment.fog")) {
|
|
||||||
PackedCol col = WoM_ParseCol(&value, WorldEnv_DefaultFogCol);
|
|
||||||
WorldEnv_SetFogCol(col);
|
|
||||||
} else if (String_CaselessEqualsConst(&key, "environment.level")) {
|
|
||||||
Int32 waterLevel;
|
|
||||||
if (Convert_TryParseInt32(&value, &waterLevel)) {
|
|
||||||
WorldEnv_SetEdgeHeight(waterLevel);
|
|
||||||
}
|
|
||||||
} else if (String_CaselessEqualsConst(&key, "user.detail") && !cpe_useMessageTypes) {
|
|
||||||
Chat_AddOf(&value, MSG_TYPE_STATUS_2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void WoM_Reset(void) {
|
|
||||||
wom_counter = 0;
|
|
||||||
WoM_UpdateIdentifier();
|
|
||||||
wom_sendId = false; wom_sentId = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void WoM_Tick(void) {
|
|
||||||
AsyncRequest item;
|
|
||||||
bool success = AsyncDownloader_Get(&wom_identifier, &item);
|
|
||||||
if (success && item.ResultString.length > 0) {
|
|
||||||
ParseWomConfig(&item.ResultString);
|
|
||||||
Platform_MemFree(&item.ResultString.buffer);
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -9,10 +9,12 @@
|
|||||||
|
|
||||||
typedef struct PickedPos_ PickedPos;
|
typedef struct PickedPos_ PickedPos;
|
||||||
typedef struct Stream_ Stream;
|
typedef struct Stream_ Stream;
|
||||||
|
void Handlers_RemoveEntity(EntityID id);
|
||||||
void Handlers_Reset(void);
|
void Handlers_Reset(void);
|
||||||
void Handlers_Tick(void);
|
void Handlers_Tick(void);
|
||||||
|
|
||||||
void Handlers_RemoveEntity(EntityID id);
|
void Handlers_RemoveEntity(EntityID id);
|
||||||
|
|
||||||
|
bool cpe_sendHeldBlock, cpe_useMessageTypes, cpe_needD3Fix, cpe_extEntityPos, cpe_blockPerms, cpe_fastMap;
|
||||||
void Classic_WriteChat(Stream* stream, STRING_PURE String* text, bool partial);
|
void Classic_WriteChat(Stream* stream, STRING_PURE String* text, bool partial);
|
||||||
void Classic_WritePosition(Stream* stream, Vector3 pos, Real32 rotY, Real32 headX);
|
void Classic_WritePosition(Stream* stream, Vector3 pos, Real32 rotY, Real32 headX);
|
||||||
void Classic_WriteSetBlock(Stream* stream, Int32 x, Int32 y, Int32 z, bool place, BlockID block);
|
void Classic_WriteSetBlock(Stream* stream, Int32 x, Int32 y, Int32 z, bool place, BlockID block);
|
||||||
|
@ -169,7 +169,7 @@ Int32 Searcher_FindReachableBlocks(Entity* entity, AABB* entityBB, AABB* entityE
|
|||||||
}
|
}
|
||||||
Searcher_StatesCount = elements;
|
Searcher_StatesCount = elements;
|
||||||
|
|
||||||
Searcher_States = Platform_MemAlloc(elements * sizeof(SearcherState));
|
Searcher_States = Platform_MemAlloc(elements, sizeof(SearcherState));
|
||||||
if (Searcher_States == NULL) {
|
if (Searcher_States == NULL) {
|
||||||
ErrorHandler_Fail("Failed to allocate memory for Searcher_FindReachableBlocks");
|
ErrorHandler_Fail("Failed to allocate memory for Searcher_FindReachableBlocks");
|
||||||
}
|
}
|
||||||
|
@ -17,8 +17,8 @@ void Platform_Init(void);
|
|||||||
void Platform_Free(void);
|
void Platform_Free(void);
|
||||||
void Platform_Exit(ReturnCode code);
|
void Platform_Exit(ReturnCode code);
|
||||||
|
|
||||||
void* Platform_MemAlloc(UInt32 numBytes);
|
void* Platform_MemAlloc(UInt32 numElems, UInt32 elemsSize);
|
||||||
void* Platform_MemRealloc(void* mem, UInt32 numBytes);
|
void* Platform_MemRealloc(void* mem, UInt32 numElems, UInt32 elemsSize);
|
||||||
void Platform_MemFree(void** mem);
|
void Platform_MemFree(void** mem);
|
||||||
void Platform_MemSet(void* dst, UInt8 value, UInt32 numBytes);
|
void Platform_MemSet(void* dst, UInt8 value, UInt32 numBytes);
|
||||||
void Platform_MemCpy(void* dst, void* src, UInt32 numBytes);
|
void Platform_MemCpy(void* dst, void* src, UInt32 numBytes);
|
||||||
@ -72,4 +72,5 @@ ReturnCode Platform_SocketRead(void* socket, UInt8* buffer, UInt32 count, UInt32
|
|||||||
ReturnCode Platform_SocketWrite(void* socket, UInt8* buffer, UInt32 count, UInt32* modified);
|
ReturnCode Platform_SocketWrite(void* socket, UInt8* buffer, UInt32 count, UInt32* modified);
|
||||||
ReturnCode Platform_SocketClose(void* socket);
|
ReturnCode Platform_SocketClose(void* socket);
|
||||||
ReturnCode Platform_SocketAvailable(void* socket, UInt32* available);
|
ReturnCode Platform_SocketAvailable(void* socket, UInt32* available);
|
||||||
|
ReturnCode Platform_SocketSelectRead(void* socket, Int32 microseconds, bool* success);
|
||||||
#endif
|
#endif
|
@ -47,8 +47,11 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String title = String_FromConst(PROGRAM_APP_NAME);
|
String title = String_FromConst(PROGRAM_APP_NAME);
|
||||||
// if (argc == 1 || arc == 2) {
|
argc = 5;
|
||||||
if (true) {
|
char* default_argv[5] = { "path", "UnknownShadow200", "mppass", "127.0.0.1", "25566" };
|
||||||
|
argv = default_argv;
|
||||||
|
|
||||||
|
if (argc == 1 || argc == 2) {
|
||||||
//String_AppendConst(&Game_Username, argc > 1 ? argv[1] : "Singleplayer");
|
//String_AppendConst(&Game_Username, argc > 1 ? argv[1] : "Singleplayer");
|
||||||
String_AppendConst(&Game_Username, "Singleplayer");
|
String_AppendConst(&Game_Username, "Singleplayer");
|
||||||
} else if (argc < 5) {
|
} else if (argc < 5) {
|
||||||
|
@ -174,12 +174,12 @@ bool InventoryScreen_HandlesKeyDown(GuiElement* elem, Key key) {
|
|||||||
TableWidget* table = &screen->Table;
|
TableWidget* table = &screen->Table;
|
||||||
|
|
||||||
if (key == KeyBind_Get(KeyBind_PauseOrExit)) {
|
if (key == KeyBind_Get(KeyBind_PauseOrExit)) {
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
} else if (key == KeyBind_Get(KeyBind_Inventory) && screen->ReleasedInv) {
|
} else if (key == KeyBind_Get(KeyBind_Inventory) && screen->ReleasedInv) {
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
} else if (key == Key_Enter && table->SelectedIndex != -1) {
|
} else if (key == Key_Enter && table->SelectedIndex != -1) {
|
||||||
Inventory_SetSelectedBlock(table->Elements[table->SelectedIndex]);
|
Inventory_SetSelectedBlock(table->Elements[table->SelectedIndex]);
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
} else if (Elem_HandlesKeyDown(table, key)) {
|
} else if (Elem_HandlesKeyDown(table, key)) {
|
||||||
} else {
|
} else {
|
||||||
HUDScreen* hud = (HUDScreen*)Gui_HUD;
|
HUDScreen* hud = (HUDScreen*)Gui_HUD;
|
||||||
@ -207,7 +207,7 @@ bool InventoryScreen_HandlesMouseDown(GuiElement* elem, Int32 x, Int32 y, MouseB
|
|||||||
bool handled = Elem_HandlesMouseDown(table, x, y, btn);
|
bool handled = Elem_HandlesMouseDown(table, x, y, btn);
|
||||||
if ((!handled || table->PendingClose) && btn == MouseButton_Left) {
|
if ((!handled || table->PendingClose) && btn == MouseButton_Left) {
|
||||||
bool hotbar = Key_IsControlPressed() || Key_IsShiftPressed();
|
bool hotbar = Key_IsControlPressed() || Key_IsShiftPressed();
|
||||||
if (!hotbar) Gui_SetNewScreen(NULL);
|
if (!hotbar) Gui_ReplaceActive(NULL);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -618,6 +618,7 @@ Screen* LoadingScreen_MakeInstance(STRING_PURE String* title, STRING_PURE String
|
|||||||
LoadingScreen_Make(screen, &LoadingScreen_VTABLE, title, message);
|
LoadingScreen_Make(screen, &LoadingScreen_VTABLE, title, message);
|
||||||
return (Screen*)screen;
|
return (Screen*)screen;
|
||||||
}
|
}
|
||||||
|
extern Screen* LoadingScreen_UNSAFE_RawPointer = (Screen*)&LoadingScreen_Instance;
|
||||||
|
|
||||||
|
|
||||||
/*########################################################################################################################*
|
/*########################################################################################################################*
|
||||||
@ -1519,8 +1520,7 @@ bool DisconnectScreen_HandlesMouseDown(GuiElement* elem, Int32 x, Int32 y, Mouse
|
|||||||
String empty = String_MakeNull();
|
String empty = String_MakeNull();
|
||||||
String_Format2(&connect, "Connecting to %s: %i..", &Game_IPAddress, &Game_Port);
|
String_Format2(&connect, "Connecting to %s: %i..", &Game_IPAddress, &Game_Port);
|
||||||
|
|
||||||
Screen* loadScreen = LoadingScreen_MakeInstance(&connect, &empty);
|
Gui_ReplaceActive(LoadingScreen_MakeInstance(&connect, &empty));
|
||||||
Gui_SetNewScreen(loadScreen);
|
|
||||||
ServerConnection_Connect(&Game_IPAddress, Game_Port);
|
ServerConnection_Connect(&Game_IPAddress, Game_Port);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
#ifndef CC_SCREENS_H
|
#ifndef CC_SCREENS_H
|
||||||
#define CC_SCREENS_H
|
#define CC_SCREENS_H
|
||||||
#include "Gui.h"
|
#include "Gui.h"
|
||||||
|
|
||||||
/* Contains all 2D non-menu screen implementations.
|
/* Contains all 2D non-menu screen implementations.
|
||||||
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
|
||||||
*/
|
*/
|
||||||
@ -17,6 +16,8 @@ Screen* DisconnectScreen_MakeInstance(STRING_PURE String* title, STRING_PURE Str
|
|||||||
|
|
||||||
/* Raw pointer to inventory screen. DO NOT USE THIS. Use InventoryScreen_MakeInstance() */
|
/* Raw pointer to inventory screen. DO NOT USE THIS. Use InventoryScreen_MakeInstance() */
|
||||||
extern Screen* InventoryScreen_UNSAFE_RawPointer;
|
extern Screen* InventoryScreen_UNSAFE_RawPointer;
|
||||||
|
/* Raw pointer to loading screen. DO NOT USE THIS. Use LoadingScreen_MakeInstance() */
|
||||||
|
extern Screen* LoadingScreen_UNSAFE_RawPointer;
|
||||||
void HUDScreen_OpenInput(Screen* hud, STRING_PURE String* text);
|
void HUDScreen_OpenInput(Screen* hud, STRING_PURE String* text);
|
||||||
void HUDScreen_AppendInput(Screen* hud, STRING_PURE String* text);
|
void HUDScreen_AppendInput(Screen* hud, STRING_PURE String* text);
|
||||||
Widget* HUDScreen_GetHotbar(Screen* hud);
|
Widget* HUDScreen_GetHotbar(Screen* hud);
|
||||||
|
@ -127,7 +127,7 @@ UInt32 selections_count;
|
|||||||
SelectionBox selections_list[SELECTIONS_MAX];
|
SelectionBox selections_list[SELECTIONS_MAX];
|
||||||
UInt8 selections_ids[SELECTIONS_MAX];
|
UInt8 selections_ids[SELECTIONS_MAX];
|
||||||
GfxResourceID selections_VB, selections_LineVB;
|
GfxResourceID selections_VB, selections_LineVB;
|
||||||
bool selections_allocated;
|
bool selections_used;
|
||||||
|
|
||||||
void Selections_Add(UInt8 id, Vector3I p1, Vector3I p2, PackedCol col) {
|
void Selections_Add(UInt8 id, Vector3I p1, Vector3I p2, PackedCol col) {
|
||||||
SelectionBox sel;
|
SelectionBox sel;
|
||||||
@ -163,7 +163,7 @@ void Selections_ContextLost(void* obj) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Selections_ContextRecreated(void* obj) {
|
void Selections_ContextRecreated(void* obj) {
|
||||||
if (!selections_allocated) return;
|
if (!selections_used) return;
|
||||||
selections_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FC4B, SELECTIONS_MAX_VERTICES);
|
selections_VB = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FC4B, SELECTIONS_MAX_VERTICES);
|
||||||
selections_LineVB = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FC4B, SELECTIONS_MAX_VERTICES);
|
selections_LineVB = Gfx_CreateDynamicVb(VERTEX_FORMAT_P3FC4B, SELECTIONS_MAX_VERTICES);
|
||||||
}
|
}
|
||||||
@ -197,9 +197,9 @@ void Selections_Render(Real64 delta) {
|
|||||||
}
|
}
|
||||||
Selections_QuickSort(0, selections_count - 1);
|
Selections_QuickSort(0, selections_count - 1);
|
||||||
|
|
||||||
if (!selections_allocated) { /* lazy init as most servers don't use this */
|
if (selections_VB == NULL) { /* lazy init as most servers don't use this */
|
||||||
|
selections_used = true;
|
||||||
Selections_ContextRecreated(NULL);
|
Selections_ContextRecreated(NULL);
|
||||||
selections_allocated = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VertexP3fC4b vertices[SELECTIONS_MAX_VERTICES]; VertexP3fC4b* ptr = vertices;
|
VertexP3fC4b vertices[SELECTIONS_MAX_VERTICES]; VertexP3fC4b* ptr = vertices;
|
||||||
|
@ -89,7 +89,8 @@ void ServerConnection_BeginGeneration(Int32 width, Int32 height, Int32 length, I
|
|||||||
Event_RaiseVoid(&WorldEvents_NewMap);
|
Event_RaiseVoid(&WorldEvents_NewMap);
|
||||||
Gen_Done = false;
|
Gen_Done = false;
|
||||||
|
|
||||||
Gui_SetNewScreen(GeneratingScreen_MakeInstance());
|
Gui_FreeActive();
|
||||||
|
Gui_SetActive(GeneratingScreen_MakeInstance());
|
||||||
Gen_Width = width; Gen_Height = height; Gen_Length = length; Gen_Seed = seed;
|
Gen_Width = width; Gen_Height = height; Gen_Length = length; Gen_Seed = seed;
|
||||||
|
|
||||||
void* threadHandle;
|
void* threadHandle;
|
||||||
@ -103,7 +104,7 @@ void ServerConnection_BeginGeneration(Int32 width, Int32 height, Int32 length, I
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ServerConnection_EndGeneration(void) {
|
void ServerConnection_EndGeneration(void) {
|
||||||
Gui_SetNewScreen(NULL);
|
Gui_ReplaceActive(NULL);
|
||||||
Gen_Done = false;
|
Gen_Done = false;
|
||||||
|
|
||||||
if (Gen_Blocks == NULL) {
|
if (Gen_Blocks == NULL) {
|
||||||
@ -285,7 +286,20 @@ UInt8 net_writeBuffer[131];
|
|||||||
Int32 net_maxHandledPacket;
|
Int32 net_maxHandledPacket;
|
||||||
bool net_writeFailed;
|
bool net_writeFailed;
|
||||||
Int32 net_ticks;
|
Int32 net_ticks;
|
||||||
|
Real64 net_discAccumulator;
|
||||||
|
|
||||||
|
void MPConnection_BlockChanged(void* obj, Vector3I coords, BlockID oldBlock, BlockID block) {
|
||||||
|
Vector3I p = coords;
|
||||||
|
if (block == BLOCK_AIR) {
|
||||||
|
block = Inventory_SelectedBlock;
|
||||||
|
Classic_WriteSetBlock(&net_writeStream, p.X, p.Y, p.Z, false, block);
|
||||||
|
} else {
|
||||||
|
Classic_WriteSetBlock(&net_writeStream, p.X, p.Y, p.Z, true, block);
|
||||||
|
}
|
||||||
|
Net_SendPacket();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ServerConnection_Free(void);
|
||||||
void MPConnection_Connect(STRING_PURE String* ip, Int32 port) {
|
void MPConnection_Connect(STRING_PURE String* ip, Int32 port) {
|
||||||
Platform_SocketCreate(&net_socket);
|
Platform_SocketCreate(&net_socket);
|
||||||
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
|
Event_RegisterBlock(&UserEvents_BlockChanged, NULL, MPConnection_BlockChanged);
|
||||||
@ -293,9 +307,16 @@ void MPConnection_Connect(STRING_PURE String* ip, Int32 port) {
|
|||||||
|
|
||||||
ReturnCode result = Platform_SocketConnect(net_socket, &Game_IPAddress, Game_Port);
|
ReturnCode result = Platform_SocketConnect(net_socket, &Game_IPAddress, Game_Port);
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
ErrorHandler.LogError("connecting to server", ex);
|
UInt8 msgBuffer[String_BufferSize(STRING_SIZE * 2)];
|
||||||
game.Disconnect("Failed to connect to " + address + ":" + port,
|
String msg = String_InitAndClearArray(msgBuffer);
|
||||||
"You failed to connect to the server. It's probably down!");
|
String_Format3(&msg, "Error connecting to %s:%i: %i", ip, &port, &result);
|
||||||
|
ErrorHandler_Log(&msg);
|
||||||
|
|
||||||
|
String_Clear(&msg);
|
||||||
|
String_Format2(&msg, "Failed to connect to %s:%i", ip, &port);
|
||||||
|
String reason = String_FromConst("You failed to connect to the server. It's probably down!");
|
||||||
|
Game_Disconnect(&msg, &reason);
|
||||||
|
|
||||||
ServerConnection_Free();
|
ServerConnection_Free();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -303,6 +324,7 @@ void MPConnection_Connect(STRING_PURE String* ip, Int32 port) {
|
|||||||
String streamName = String_FromConst("network socket");
|
String streamName = String_FromConst("network socket");
|
||||||
Stream_ReadonlyMemory(&net_readStream, net_readBuffer, sizeof(net_readBuffer), &streamName);
|
Stream_ReadonlyMemory(&net_readStream, net_readBuffer, sizeof(net_readBuffer), &streamName);
|
||||||
Stream_WriteonlyMemory(&net_writeStream, net_writeBuffer, sizeof(net_writeBuffer), &streamName);
|
Stream_WriteonlyMemory(&net_writeStream, net_writeBuffer, sizeof(net_writeBuffer), &streamName);
|
||||||
|
net_readStream.Meta_Mem_Count = 0; /* initally no memory to read */
|
||||||
|
|
||||||
Handlers_Reset();
|
Handlers_Reset();
|
||||||
Classic_WriteLogin(&net_writeStream, &Game_Username, &Game_Mppass);
|
Classic_WriteLogin(&net_writeStream, &Game_Username, &Game_Mppass);
|
||||||
@ -335,13 +357,16 @@ void MPConnection_SendPlayerClick(MouseButton button, bool buttonDown, EntityID
|
|||||||
Net_SendPacket();
|
Net_SendPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
double testAcc = 0;
|
void MPConnection_CheckDisconnection(Real64 delta) {
|
||||||
void CheckDisconnection(double delta) {
|
net_discAccumulator += delta;
|
||||||
testAcc += delta;
|
if (net_discAccumulator < 1.0) return;
|
||||||
if (testAcc < 1) return;
|
net_discAccumulator = 0.0;
|
||||||
testAcc = 0;
|
|
||||||
|
|
||||||
if (net_writeFailed || (socket.Poll(1000, SelectMode.SelectRead) && socket.Available == 0)) {
|
UInt32 available = 0; bool selected = false;
|
||||||
|
ReturnCode availResult = Platform_SocketAvailable(net_socket, &available);
|
||||||
|
ReturnCode selectResult = Platform_SocketSelectRead(net_socket, 1000, &selected);
|
||||||
|
|
||||||
|
if (net_writeFailed || availResult != 0 || selectResult != 0 || (selected && available == 0)) {
|
||||||
String title = String_FromConst("Disconnected!");
|
String title = String_FromConst("Disconnected!");
|
||||||
String reason = String_FromConst("You've lost connection to the server");
|
String reason = String_FromConst("You've lost connection to the server");
|
||||||
Game_Disconnect(&title, &reason);
|
Game_Disconnect(&title, &reason);
|
||||||
@ -351,9 +376,8 @@ void CheckDisconnection(double delta) {
|
|||||||
void MPConnection_Tick(ScheduledTask* task) {
|
void MPConnection_Tick(ScheduledTask* task) {
|
||||||
if (ServerConnection_Disconnected) return;
|
if (ServerConnection_Disconnected) return;
|
||||||
DateTime now; Platform_CurrentUTCTime(&now);
|
DateTime now; Platform_CurrentUTCTime(&now);
|
||||||
|
|
||||||
if (DateTime_MsBetween(&net_lastPacket, &now) >= 30 * 1000) {
|
if (DateTime_MsBetween(&net_lastPacket, &now) >= 30 * 1000) {
|
||||||
CheckDisconnection(task.Interval);
|
MPConnection_CheckDisconnection(task->Interval);
|
||||||
}
|
}
|
||||||
if (ServerConnection_Disconnected) return;
|
if (ServerConnection_Disconnected) return;
|
||||||
|
|
||||||
@ -365,16 +389,23 @@ void MPConnection_Tick(ScheduledTask* task) {
|
|||||||
recvResult = Platform_SocketRead(net_socket, src, 4096 * 4, &modified);
|
recvResult = Platform_SocketRead(net_socket, src, 4096 * 4, &modified);
|
||||||
net_readStream.Meta_Mem_Count += modified;
|
net_readStream.Meta_Mem_Count += modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (recvResult != 0) {
|
if (recvResult != 0) {
|
||||||
ErrorHandler.LogError("reading packets", ex);
|
UInt8 msgBuffer[String_BufferSize(STRING_SIZE * 2)];
|
||||||
game.Disconnect("&eLost connection to the server", "I/O error when reading packets");
|
String msg = String_InitAndClearArray(msgBuffer);
|
||||||
|
String_Format3(&msg, "Error reading from %s:%i: %i", &Game_IPAddress, &Game_Port, &recvResult);
|
||||||
|
ErrorHandler_Log(&msg);
|
||||||
|
|
||||||
|
String title = String_FromConst("&eLost connection to the server");
|
||||||
|
String reason = String_FromConst("I/O error when reading packets");
|
||||||
|
Game_Disconnect(&title, &reason);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (net_readStream.Meta_Mem_Count > 0) {
|
while (net_readStream.Meta_Mem_Count > 0) {
|
||||||
UInt8 opcode = net_readStream.Meta_Mem_Buffer[0];
|
UInt8 opcode = net_readStream.Meta_Mem_Buffer[0];
|
||||||
/* Workaround for older D3 servers which wrote one byte too many for HackControl packets */
|
/* Workaround for older D3 servers which wrote one byte too many for HackControl packets */
|
||||||
if (cpeData.needD3Fix && net_lastOpcode == OPCODE_CPE_HACK_CONTROL && (opcode == 0x00 || opcode == 0xFF)) {
|
if (cpe_needD3Fix && net_lastOpcode == OPCODE_CPE_HACK_CONTROL && (opcode == 0x00 || opcode == 0xFF)) {
|
||||||
Platform_LogConst("Skipping invalid HackControl byte from D3 server");
|
Platform_LogConst("Skipping invalid HackControl byte from D3 server");
|
||||||
Stream_Skip(&net_readStream, 1);
|
Stream_Skip(&net_readStream, 1);
|
||||||
|
|
||||||
@ -384,9 +415,7 @@ void MPConnection_Tick(ScheduledTask* task) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opcode > net_maxHandledPacket) {
|
if (opcode > net_maxHandledPacket) { ErrorHandler_Fail("Invalid opcode"); }
|
||||||
throw new InvalidOperationException("Invalid opcode: " + opcode);
|
|
||||||
}
|
|
||||||
if (net_readStream.Meta_Mem_Count < Net_PacketSizes[opcode]) break;
|
if (net_readStream.Meta_Mem_Count < Net_PacketSizes[opcode]) break;
|
||||||
|
|
||||||
Stream_Skip(&net_readStream, 1); /* remove opcode */
|
Stream_Skip(&net_readStream, 1); /* remove opcode */
|
||||||
@ -394,13 +423,16 @@ void MPConnection_Tick(ScheduledTask* task) {
|
|||||||
Net_Handler handler = Net_Handlers[opcode];
|
Net_Handler handler = Net_Handlers[opcode];
|
||||||
Platform_CurrentUTCTime(&net_lastPacket);
|
Platform_CurrentUTCTime(&net_lastPacket);
|
||||||
|
|
||||||
if (handler == NULL) {
|
if (handler == NULL) { ErrorHandler_Fail("Unsupported opcode"); }
|
||||||
throw new InvalidOperationException("Unsupported opcode: " + opcode);
|
|
||||||
}
|
|
||||||
handler(&net_readStream);
|
handler(&net_readStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.RemoveProcessed();
|
/* Keep last few unprocessed bytes, don't care about rest since they'll be overwritten on socket read */
|
||||||
|
Int32 i;
|
||||||
|
for (i = 0; i < net_readStream.Meta_Mem_Count; i++) {
|
||||||
|
net_readBuffer[i] = net_readStream.Meta_Mem_Buffer[i];
|
||||||
|
}
|
||||||
|
net_readStream.Meta_Mem_Buffer = net_readBuffer;
|
||||||
|
|
||||||
/* Network is ticked 60 times a second. We only send position updates 20 times a second */
|
/* Network is ticked 60 times a second. We only send position updates 20 times a second */
|
||||||
if ((net_ticks % 3) == 0) {
|
if ((net_ticks % 3) == 0) {
|
||||||
@ -434,17 +466,6 @@ void Net_SendPacket(void) {
|
|||||||
net_writeStream.Meta_Mem_Count = sizeof(net_writeBuffer);
|
net_writeStream.Meta_Mem_Count = sizeof(net_writeBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MPConnection_BlockChanged(void* obj, Vector3I coords, BlockID oldBlock, BlockID block) {
|
|
||||||
Vector3I p = coords;
|
|
||||||
if (block == BLOCK_AIR) {
|
|
||||||
block = Inventory_SelectedBlock;
|
|
||||||
Classic_WriteSetBlock(&net_writeStream, p.X, p.Y, p.Z, false, block);
|
|
||||||
} else {
|
|
||||||
Classic_WriteSetBlock(&net_writeStream, p.X, p.Y, p.Z, true, block);
|
|
||||||
}
|
|
||||||
Net_SendPacket();
|
|
||||||
}
|
|
||||||
|
|
||||||
Stream* MPConnection_ReadStream(void) { return &net_readStream; }
|
Stream* MPConnection_ReadStream(void) { return &net_readStream; }
|
||||||
Stream* MPConnection_WriteStream(void) { return &net_writeStream; }
|
Stream* MPConnection_WriteStream(void) { return &net_writeStream; }
|
||||||
void ServerConnection_InitMultiplayer(void) {
|
void ServerConnection_InitMultiplayer(void) {
|
||||||
@ -467,7 +488,7 @@ void MPConnection_OnNewMap(void) {
|
|||||||
/* wipe all existing entity states */
|
/* wipe all existing entity states */
|
||||||
Int32 i;
|
Int32 i;
|
||||||
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
|
for (i = 0; i < ENTITIES_MAX_COUNT; i++) {
|
||||||
classic.RemoveEntity((byte)i);
|
Handlers_RemoveEntity((EntityID)i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -625,14 +625,14 @@ void StringsBuffer_Resize(void** buffer, UInt32* elems, UInt32 elemSize, UInt32
|
|||||||
/* We use a statically allocated buffer initally, so can't realloc first time */
|
/* We use a statically allocated buffer initally, so can't realloc first time */
|
||||||
void* dst;
|
void* dst;
|
||||||
void* cur = *buffer;
|
void* cur = *buffer;
|
||||||
|
UInt32 curElems = *elems;
|
||||||
|
|
||||||
UInt32 curElems = *elems, newSize = (curElems + expandElems) * elemSize;
|
|
||||||
if (curElems <= defElems) {
|
if (curElems <= defElems) {
|
||||||
dst = Platform_MemAlloc(newSize);
|
dst = Platform_MemAlloc(curElems + expandElems, elemSize);
|
||||||
if (dst == NULL) ErrorHandler_Fail("Failed allocating memory for StringsBuffer");
|
if (dst == NULL) ErrorHandler_Fail("Failed allocating memory for StringsBuffer");
|
||||||
Platform_MemCpy(dst, cur, curElems * elemSize);
|
Platform_MemCpy(dst, cur, curElems * elemSize);
|
||||||
} else {
|
} else {
|
||||||
dst = Platform_MemRealloc(cur, newSize);
|
dst = Platform_MemRealloc(cur, curElems + expandElems, elemSize);
|
||||||
if (dst == NULL) ErrorHandler_Fail("Failed allocating memory for resizing StringsBuffer");
|
if (dst == NULL) ErrorHandler_Fail("Failed allocating memory for resizing StringsBuffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ void Matrix_OrthographicOffCenter(Matrix* result, Real32 left, Real32 right, Rea
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Matrix_PerspectiveFieldOfView(Matrix* result, Real32 fovy, Real32 aspect, Real32 zNear, Real32 zFar) {
|
void Matrix_PerspectiveFieldOfView(Matrix* result, Real32 fovy, Real32 aspect, Real32 zNear, Real32 zFar) {
|
||||||
Real32 c = (Real32)(zNear * Math_TanF(0.5 * fovy));
|
Real32 c = zNear * Math_TanF(0.5f * fovy);
|
||||||
Matrix_PerspectiveOffCenter(result, -c * aspect, c * aspect, -c, c, zNear, zFar);
|
Matrix_PerspectiveOffCenter(result, -c * aspect, c * aspect, -c, c, zNear, zFar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +26,7 @@ Real64 weather_accumulator;
|
|||||||
Vector3I weather_lastPos;
|
Vector3I weather_lastPos;
|
||||||
|
|
||||||
void WeatherRenderer_InitHeightmap(void) {
|
void WeatherRenderer_InitHeightmap(void) {
|
||||||
Weather_Heightmap = Platform_MemAlloc(World_Width * World_Length * sizeof(Int16));
|
Weather_Heightmap = Platform_MemAlloc(World_Width * World_Length, sizeof(Int16));
|
||||||
if (Weather_Heightmap == NULL) {
|
if (Weather_Heightmap == NULL) {
|
||||||
ErrorHandler_Fail("WeatherRenderer - Failed to allocate heightmap");
|
ErrorHandler_Fail("WeatherRenderer - Failed to allocate heightmap");
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <ws2tcpip.h>
|
#include <ws2tcpip.h>
|
||||||
|
|
||||||
|
#pragma comment(lib, "ws2_32.lib")
|
||||||
HDC hdc;
|
HDC hdc;
|
||||||
HANDLE heap;
|
HANDLE heap;
|
||||||
bool stopwatch_highResolution;
|
bool stopwatch_highResolution;
|
||||||
@ -74,12 +75,14 @@ void Platform_Exit(ReturnCode code) {
|
|||||||
ExitProcess(code);
|
ExitProcess(code);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Platform_MemAlloc(UInt32 numBytes) {
|
void* Platform_MemAlloc(UInt32 numElems, UInt32 elemsSize) {
|
||||||
|
UInt32 numBytes = numElems * elemsSize; /* TODO: avoid overflow here */
|
||||||
return malloc(numBytes);
|
return malloc(numBytes);
|
||||||
//return HeapAlloc(heap, 0, numBytes);
|
//return HeapAlloc(heap, 0, numBytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void* Platform_MemRealloc(void* mem, UInt32 numBytes) {
|
void* Platform_MemRealloc(void* mem, UInt32 numElems, UInt32 elemsSize) {
|
||||||
|
UInt32 numBytes = numElems * elemsSize; /* TODO: avoid overflow here */
|
||||||
return realloc(mem, numBytes);
|
return realloc(mem, numBytes);
|
||||||
//return HeapReAlloc(heap, 0, mem, numBytes);
|
//return HeapReAlloc(heap, 0, mem, numBytes);
|
||||||
}
|
}
|
||||||
@ -439,5 +442,22 @@ ReturnCode Platform_SocketClose(void* socket) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ReturnCode Platform_SocketAvailable(void* socket, UInt32* available) {
|
ReturnCode Platform_SocketAvailable(void* socket, UInt32* available) {
|
||||||
return ioctlsocket(socket, FIONBIO, available);
|
return ioctlsocket(socket, FIONREAD, available);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnCode Platform_SocketSelectRead(void* socket, Int32 microseconds, bool* success) {
|
||||||
|
void* args[2];
|
||||||
|
args[0] = (void*)1;
|
||||||
|
args[1] = socket;
|
||||||
|
|
||||||
|
TIMEVAL time;
|
||||||
|
time.tv_usec = microseconds % (1000 * 1000);
|
||||||
|
time.tv_sec = microseconds / (1000 * 1000);
|
||||||
|
|
||||||
|
Int32 selectCount = select(1, &args, NULL, NULL, &time);
|
||||||
|
if (selectCount == SOCKET_ERROR) {
|
||||||
|
*success = false; return WSAGetLastError();
|
||||||
|
} else {
|
||||||
|
*success = args[0] != 0; return 0;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user