diff --git a/ClassicalSharp/Network/NetworkProcessor.cs b/ClassicalSharp/Network/NetworkProcessor.cs index 423ecbaae..19ea9b3f6 100644 --- a/ClassicalSharp/Network/NetworkProcessor.cs +++ b/ClassicalSharp/Network/NetworkProcessor.cs @@ -159,10 +159,6 @@ namespace ClassicalSharp.Network { handler(); } - internal void SkipPacketData(byte opcode) { - reader.Skip(packetSizes[opcode] - 1); - } - internal void Reset() { UsingExtPlayerList = false; UsingPlayerClick = false; diff --git a/ClassicalSharp/Network/Protocols/BlockDefs.cs b/ClassicalSharp/Network/Protocols/BlockDefs.cs index dfc724281..906e3d400 100644 --- a/ClassicalSharp/Network/Protocols/BlockDefs.cs +++ b/ClassicalSharp/Network/Protocols/BlockDefs.cs @@ -61,9 +61,6 @@ namespace ClassicalSharp.Network.Protocols { } void HandleDefineBlockExt() { - if (!game.AllowCustomBlocks) { - net.SkipPacketData(Opcode.CpeDefineBlockExt); return; - } BlockID block = HandleDefineBlockCommonStart(reader, net.cpeData.blockDefsExtVer >= 2); Vector3 min, max; diff --git a/ClassicalSharp/Utils/StringBuffer.cs b/ClassicalSharp/Utils/StringBuffer.cs index 6cb1a1158..6c6a7bf56 100644 --- a/ClassicalSharp/Utils/StringBuffer.cs +++ b/ClassicalSharp/Utils/StringBuffer.cs @@ -73,7 +73,7 @@ namespace ClassicalSharp { } public StringBuffer InsertAt(int index, char c) { - for (int i = Length - 1; i > index; i--) { + for (int i = Length; i > index; i--) { value[i] = value[i - 1]; } diff --git a/src/Client/AsyncDownloader.h b/src/Client/AsyncDownloader.h index 627f37334..a7738f514 100644 --- a/src/Client/AsyncDownloader.h +++ b/src/Client/AsyncDownloader.h @@ -3,6 +3,7 @@ #include "Constants.h" #include "Utils.h" #include "GameStructs.h" +#include "Bitmap.h" /* Downloads images, texture packs, skins, etc in async manner. Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 */ diff --git a/src/Client/D3D9Api.c b/src/Client/D3D9Api.c index 2f6046b7b..64ae1a00d 100644 --- a/src/Client/D3D9Api.c +++ b/src/Client/D3D9Api.c @@ -35,12 +35,6 @@ ErrorHandler_CheckOrFail(hresult, name) hresult = IDirect3DDevice9_SetRenderState(device, state, value); \ ErrorHandler_CheckOrFail(hresult, name) -#define D3D9_LogLeakedResource(msg, i) \ -String_Clear(&logMsg);\ -String_AppendConst(&logMsg, msg);\ -String_AppendInt32(&logMsg, i);\ -Platform_Log(&logMsg); - /* Forward declarations for these two functions. */ static void D3D9_SetDefaultRenderStates(void); diff --git a/src/Client/EntityComponents.c b/src/Client/EntityComponents.c index 0a69988c5..420734847 100644 --- a/src/Client/EntityComponents.c +++ b/src/Client/EntityComponents.c @@ -808,8 +808,7 @@ void Collisions_CollideWithReachableBlocks(CollisionsComp* comp, Int32 count, AA Real32 tx, ty, tz; Searcher_CalcTime(&entity->Velocity, entityBB, &blockBB, &tx, &ty, &tz); if (tx > 1.0f || ty > 1.0f || tz > 1.0f) { - String warn = String_FromConst("t > 1 in physics calculation.. this shouldn't have happened."); - Platform_Log(&warn); + Platform_LogConst("t > 1 in physics calculation.. this shouldn't have happened."); } /* Calculate the location of the entity when it collides with this block */ diff --git a/src/Client/GraphicsCommon.c b/src/Client/GraphicsCommon.c index 2068bf859..f58effafa 100644 --- a/src/Client/GraphicsCommon.c +++ b/src/Client/GraphicsCommon.c @@ -24,9 +24,7 @@ void GfxCommon_Free(void) { void GfxCommon_LoseContext(const UInt8* reason) { Gfx_LostContext = true; - String logMsg = String_FromConst("Lost graphics context:"); - Platform_Log(&logMsg); - Platform_LogConst(reason); + Platform_Log1("Lost graphics context: %c", reason); Event_RaiseVoid(&GfxEvents_ContextLost); GfxCommon_Free(); @@ -34,8 +32,7 @@ void GfxCommon_LoseContext(const UInt8* reason) { void GfxCommon_RecreateContext(void) { Gfx_LostContext = false; - String logMsg = String_FromConst("Recreating graphics context"); - Platform_Log(&logMsg); + Platform_LogConst("Recreating graphics context"); Event_RaiseVoid(&GfxEvents_ContextRecreated); GfxCommon_Init(); diff --git a/src/Client/PacketHandlers.c b/src/Client/PacketHandlers.c index f1c37f52a..1287ae508 100644 --- a/src/Client/PacketHandlers.c +++ b/src/Client/PacketHandlers.c @@ -59,6 +59,7 @@ void Handlers_WriteString(Stream* stream, STRING_PURE String* value) { #define Handlers_ReadBlock(stream) Stream_ReadU8(stream) #define Handlers_WriteBlock(stream, value) Stream_WriteU8(stream, value) + /*########################################################################################################################* *----------------------------------------------------Classic protocol-----------------------------------------------------* *#########################################################################################################################*/ @@ -107,7 +108,7 @@ void HandleHandshake(Stream* stream) { Chat_SetLogName(&ServerConnection_ServerName); HacksComp* hacks = &LocalPlayer_Instance.Hacks; - HacksComp_SetUserType(hacks, Stream_ReadU8(stream), !net.cpeData.blockPerms); + HacksComp_SetUserType(hacks, Stream_ReadU8(stream), !cpe_blockPerms); String_Set(&hacks->HacksFlags, &ServerConnection_ServerName); String_AppendString(&hacks->HacksFlags, &ServerConnection_ServerMOTD); @@ -119,8 +120,8 @@ void HandlePing(Stream* stream) { } void HandleLevelInit(Stream* stream) { if (gzipStream == null) StartLoadingState(); - // Fast map puts volume in header, doesn't bother with gzip - if (net.cpeData.fastMap) { + /* Fast map puts volume in header, doesn't bother with gzip */ + if (cpe_fastMap) { mapVolume = Stream_ReadI32_BE(stream); gzipHeader.Done = true; mapSizeIndex = 4; @@ -212,7 +213,7 @@ void HandleSetBlock(Stream* stream) { Int32 y = Stream_ReadU16_BE(stream); Int32 z = Stream_ReadU16_BE(stream); - BlockID block = Stream_ReadU8(block); + BlockID block = Handlers_ReadBlock(stream); if (World_IsValidPos(x, y, z)) { Game_UpdateBlock(x, y, z, block); } @@ -229,7 +230,7 @@ void HandleAddEntity(Stream* stream) { // Workaround for some servers that declare they support ExtPlayerList, // but doesn't send ExtAddPlayerName packets. net.AddTablistEntry(id, name, name, "Players", 0); - net.needRemoveNames[id >> 3] |= (byte)(1 << (id & 0x7)); + net.needRemoveNames[id >> 3] |= (UInt8)(1 << (id & 0x7)); } void HandleEntityTeleport(Stream* stream) { @@ -278,9 +279,9 @@ void HandleRemoveEntity(Stream* stream) { void HandleMessage(Stream* stream) { UInt8 type = Stream_ReadU8(stream); /* Original vanilla server uses player ids in message types, 255 for server messages. */ - bool prepend = !net.cpeData.useMessageTypes && type == 0xFF; + bool prepend = !cpe_useMessageTypes && type == 0xFF; - if (!net.cpeData.useMessageTypes) type = MSG_TYPE_NORMAL; + if (!cpe_useMessageTypes) type = MSG_TYPE_NORMAL; string text = reader.ReadChatString(ref type); if (prepend) text = "&e" + text; @@ -299,13 +300,13 @@ void HandleKick(Stream* stream) { void HandleSetPermission(Stream* stream) { HacksComp* hacks = &LocalPlayer_Instance.Hacks; - HacksComp_SetUserType(hacks, Stream_ReadU8(stream), !net.cpeData.blockPerms); + HacksComp_SetUserType(hacks, Stream_ReadU8(stream), !cpe_blockPerms); HacksComp_UpdateHacksState(hacks); } void ReadAbsoluteLocation(Stream* stream, EntityID id, bool interpolate) { Int32 x, y, z; - if (ExtendedPositions) { + if (cpe_extEntityPos) { x = Stream_ReadI32_BE(stream); y = Stream_ReadI32_BE(stream); z = Stream_ReadI32_BE(stream); } else { x = Stream_ReadI16_BE(stream); y = Stream_ReadI16_BE(stream); z = Stream_ReadI16_BE(stream); @@ -331,11 +332,11 @@ void WriteChat(Stream* stream, STRING_PURE String* text, bool partial) { } void WritePosition(Stream* stream, Vector3 pos, Real32 rotY, Real32 headX) { - Int32 payload = net.cpeData.sendHeldBlock ? Inventory_SelectedBlock : ENTITIES_SELF_ID; + 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 (ExtendedPositions) { + 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)); @@ -371,6 +372,30 @@ void WriteLogin(Stream* stream, STRING_PURE String* username, STRING_PURE String /*########################################################################################################################* *------------------------------------------------------CPE protocol-------------------------------------------------------* *#########################################################################################################################*/ + +Int32 cpe_serverExtensionsCount; +bool cpe_sendHeldBlock, cpe_useMessageTypes; +Int32 cpe_envMapVer = 2, cpe_blockDefsExtVer = 2; +bool cpe_needD3Fix, cpe_extEntityPos, cpe_twoWayPing, cpe_blockPerms, cpe_fastMap; + +void Reset(Game game) { + cpe_serverExtensionsCount = 0; + cpe_sendHeldBlock = false; cpe_useMessageTypes = false; + cpe_envMapVer = 2; cpe_blockDefsExtVer = 2; + cpe_needD3Fix = false; cpe_extEntityPos = false; cpe_twoWayPing = false; cpe_fastMap = false; + game.SupportsCPEBlocks = false; + NetworkProcessor net = (NetworkProcessor)game.Server; + net.Reset(); +} + + public static string[] ClientExtensions = new string[]{ + "ClickDistance", "CustomBlocks", "HeldBlock", "EmoteFix", "TextHotKey", "ExtPlayerList", + "EnvColors", "SelectionCuboid", "BlockPermissions", "ChangeModel", "EnvMapAppearance", + "EnvWeatherType", "MessageTypes", "HackControl", "PlayerClick", "FullCP437", "LongerMessages", + "BlockDefinitions", "BlockDefinitionsExt", "BulkBlockUpdate", "TextColors", "EnvMapAspect", + "EntityProperty", "ExtEntityPositions", "TwoWayPing", "InventoryOrder", "InstantMOTD", "FastMap", + }; + void CPEProtocol_Init() { Reset(); } @@ -412,12 +437,15 @@ void HandleExtInfo(Stream* stream) { UInt8 appNameBuffer[String_BufferSize(STRING_SIZE)]; String appName = Handlers_ReadString(stream, appNameBuffer); game.Chat.Add("Server software: " + appName); - if (Utils.CaselessStarts(appName, "D3 server")) - net.cpeData.needD3Fix = true; + + String d3Server = String_FromConst("D3 server"); + if (String_CaselessStarts(&appName, &d3Server)) { + cpe_needD3Fix = true; + } /* Workaround for old MCGalaxy that send ExtEntry sync but ExtInfo async. This means ExtEntry may sometimes arrive before ExtInfo, thus have to use += instead of = */ - net.cpeData.ServerExtensionsCount += Stream_ReadI16_BE(stream); + cpe_serverExtensionsCount += Stream_ReadI16_BE(stream); SendCpeExtInfoReply(); } @@ -425,10 +453,45 @@ void HandleExtEntry(Stream* stream) { UInt8 extNameBuffer[String_BufferSize(STRING_SIZE)]; String extName = Handlers_ReadString(stream, extNameBuffer); Int32 extVersion = Stream_ReadI32_BE(stream); - Utils.LogDebug("cpe ext: {0}, {1}", extName, extVersion); + Platform_Log2("cpe ext: %s, %i", &extName, &extVersion); - net.cpeData.HandleEntry(extName, extVersion, net); - SendCpeExtInfoReply(); + cpe_serverExtensionsCount--; + SendCpeExtInfoReply(); + + /* update support state */ + if (ext == "HeldBlock") { + cpe_sendHeldBlock = true; + } else if (ext == "MessageTypes") { + cpe_useMessageTypes = true; + } else if (ext == "ExtPlayerList") { + ServerConnection_SupportsExtPlayerList = true; + } else if (ext == "BlockPermissions") { + cpe_blockPerms = true; + } else if (ext == "PlayerClick") { + ServerConnection_SupportsPlayerClick = true; + } else if (ext == "EnvMapAppearance") { + cpe_envMapVer = extVersion; + if (extVersion == 1) return; + net.packetSizes[Opcode.CpeEnvSetMapApperance] += 4; + } else if (ext == "LongerMessages") { + ServerConnection_SupportsPartialMessages = true; + } else if (ext == "FullCP437") { + ServerConnection_SupportsFullCP437 = true; + } else if (ext == "BlockDefinitionsExt") { + cpe_blockDefsExtVer = extVersion; + if (extVersion == 1) return; + net.packetSizes[Opcode.CpeDefineBlockExt] += 3; + } else if (ext == "ExtEntityPositions") { + net.packetSizes[Opcode.EntityTeleport] += 6; + net.packetSizes[Opcode.AddEntity] += 6; + net.packetSizes[Opcode.CpeExtAddEntity2] += 6; + cpe_extEntityPos = true; + } else if (ext == "TwoWayPing") { + cpe_twoWayPing = true; + } else if (ext == "FastMap") { + net.packetSizes[OPCODE_LEVEL_INIT] += 4; + cpe_fastMap = true; + } } void HandleSetClickDistance(Stream* stream) { @@ -466,11 +529,7 @@ void HandleSetTextHotkey(Stream* stream) { Key key = Hotkeys_LWJGL[keyCode]; if (key == Key_None) return; - - UInt8 logMsgBuffer[String_BufferSize(STRING_SIZE * 2)]; - String logMsg = String_InitAndClearArray(logMsgBuffer); - String_Format3(&logMsg, "CPE hotkey added: %c, %b: %s", Key_Names[key], &keyMods, &action); - Platform_Log(&logMsg); + Platform_Log3("CPE hotkey added: %c, %b: %s", Key_Names[key], &keyMods, &action); if (action.length == 0) { Hotkeys_Remove(key, keyMods); @@ -582,7 +641,7 @@ void HandleEnvSetMapAppearance(Stream* stream) { WorldEnv_SetSidesBlock(Stream_ReadU8(stream)); WorldEnv_SetEdgeBlock(Stream_ReadU8(stream)); WorldEnv_SetEdgeHeight(Stream_ReadI16_BE(stream)); - if (net.cpeData.envMapVer == 1) return; + if (cpe_envMapVer == 1) return; /* Version 2 */ WorldEnv_SetCloudsHeight(Stream_ReadI16_BE(stream)); @@ -632,7 +691,7 @@ void HandleBulkBlockUpdate(Stream* stream) { for (i = 0; i < count; i++) { indices[i] = Stream_ReadI32_BE(stream); } - reader.Skip((bulkCount - count) * sizeof(int)); + Stream_Skip(stream, (BULK_MAX_BLOCKS - count) * (UInt32)sizeof(Int32)); BlockID blocks[BULK_MAX_BLOCKS]; for (i = 0; i < count; i++) { @@ -679,7 +738,7 @@ void HandleSetMapEnvUrl(Stream* stream) { } else if (Utils_IsUrlPrefix(&url, 0)) { ServerConnection_RetrieveTexturePack(&url); } - Utils.LogDebug("Image url: " + url); + Platform_Log1("Image url: %s", &url); } void HandleSetMapEnvProperty(Stream* stream) { @@ -829,7 +888,7 @@ void WriteTwoWayPing(Stream* stream, bool serverToClient, UInt16 data) { } void SendCpeExtInfoReply() { - if (net.cpeData.ServerExtensionsCount != 0) return; + if (cpe_serverExtensionsCount != 0) return; string[] clientExts = CPESupport.ClientExtensions; int count = clientExts.Length; if (!Game_AllowCustomBlocks) count -= 2; @@ -840,8 +899,8 @@ void SendCpeExtInfoReply() { string name = clientExts[i]; int ver = 1; if (name == "ExtPlayerList") ver = 2; - if (name == "EnvMapAppearance") ver = net.cpeData.envMapVer; - if (name == "BlockDefinitionsExt") ver = net.cpeData.blockDefsExtVer; + if (name == "EnvMapAppearance") ver = cpe_envMapVer; + if (name == "BlockDefinitionsExt") ver = cpe_blockDefsExtVer; if (!Game_AllowCustomBlocks && name == "BlockDefinitionsExt") continue; if (!Game_AllowCustomBlocks && name == "BlockDefinitions") continue; @@ -901,10 +960,7 @@ void OnBlockUpdated(BlockID block, bool didBlockLight) { } void HandleDefineBlockExt(Stream* stream) { - if (!Game_AllowCustomBlocks) { - net.SkipPacketData(Opcode.CpeDefineBlockExt); return; - } - BlockID block = HandleDefineBlockCommonStart(stream, net.cpeData.blockDefsExtVer >= 2); + BlockID block = HandleDefineBlockCommonStart(stream, cpe_blockDefsExtVer >= 2); Vector3 min, max; min.X = Stream_ReadU8(stream) / 16.0f; Utils.Clamp(ref min.X, 0.0f, 15.0f / 16.0f); @@ -1072,29 +1128,33 @@ PackedCol WoM_ParseCol(STRING_PURE String* value, PackedCol defaultCol) { return col; } -static string ReadLine(ref int start, string value) { - if (start == -1) return null; - for (int i = start; i < value.Length; i++) { - char c = value[i]; +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; - string line = value.Substring(start, i - start); - start = i + 1; - if (c == '\r' && start < value.Length && value[start] == '\n') - start++; // we stop at the \r, so make sure to skip following \n - return line; + *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; } - string last = value.Substring(start); + *line = String_UNSAFE_SubstringAt(page, offset); start = -1; - return last; + return true; } void Wom_ParseConfig(STRING_PURE String* page) { String line; Int32 start = 0; - while ((line = ReadLine(ref start, page)) != null) { + while (WoM_ReadLine(page, &start, &line)) { Platform_Log(&line); Int32 sepIndex = String_IndexOf(&line, '=', 0); if (sepIndex == -1) continue; @@ -1118,7 +1178,7 @@ void Wom_ParseConfig(STRING_PURE String* page) { if (Convert_TryParseInt32(&value, &waterLevel)) { WorldEnv_SetEdgeHeight(waterLevel); } - } else if (String_CaselessEqualsConst(&key, "user.detail") && !net.cpeData.useMessageTypes) { + } else if (String_CaselessEqualsConst(&key, "user.detail") && !cpe_useMessageTypes) { Chat_AddOf(&value, MSG_TYPE_STATUS_2); } } diff --git a/src/Client/Platform.h b/src/Client/Platform.h index 9c9b44207..217aa15f7 100644 --- a/src/Client/Platform.h +++ b/src/Client/Platform.h @@ -25,6 +25,10 @@ void Platform_MemCpy(void* dst, void* src, UInt32 numBytes); void Platform_Log(STRING_PURE String* message); void Platform_LogConst(const UInt8* message); +#define Platform_Log1(format, a1) Platform_Log4(format, a1, NULL, NULL, NULL) +#define Platform_Log2(format, a1, a2) Platform_Log4(format, a1, a2, NULL, NULL) +#define Platform_Log3(format, a1, a2, a3) Platform_Log4(format, a1, a2, a3, NULL) +void Platform_Log4(const UInt8* format, const void* a1, const void* a2, const void* a3, const void* a4); void Platform_CurrentUTCTime(DateTime* time); void Platform_CurrentLocalTime(DateTime* time); diff --git a/src/Client/Screens.c b/src/Client/Screens.c index fce41a748..778a8a53b 100644 --- a/src/Client/Screens.c +++ b/src/Client/Screens.c @@ -263,27 +263,20 @@ GuiElementVTABLE StatusScreen_VTABLE; StatusScreen StatusScreen_Instance; void StatusScreen_MakeText(StatusScreen* screen, STRING_TRANSIENT String* status) { screen->FPS = (Int32)(screen->Frames / screen->Accumulator); - String_AppendInt32(status, screen->FPS); - String_AppendConst(status, " fps, "); + String_Format1(status, "%i fps, ", &screen->FPS); if (Game_ClassicMode) { - String_AppendInt32(status, Game_ChunkUpdates); - String_AppendConst(status, " chunk updates"); + String_Format1(status, "%i chunk updates", &Game_ChunkUpdates); } else { if (Game_ChunkUpdates > 0) { - String_AppendInt32(status, Game_ChunkUpdates); - String_AppendConst(status, " chunks/s, "); + String_Format1(status, "%i chunks/s, ", &Game_ChunkUpdates); } - Int32 indices = ICOUNT(Game_Vertices); - String_AppendInt32(status, indices); - String_AppendConst(status, " vertices"); + String_Format1(status, "%i vertices", &indices); Int32 ping = PingList_AveragePingMs(); if (ping) { - String_AppendConst(status, ", ping "); - String_AppendInt32(status, ping); - String_AppendConst(status, " ms"); + String_Format1(status, ", ping %i ms", &ping); } } } diff --git a/src/Client/ServerConnection.h b/src/Client/ServerConnection.h index d814f0496..c9b15779f 100644 --- a/src/Client/ServerConnection.h +++ b/src/Client/ServerConnection.h @@ -2,6 +2,7 @@ #define CC_SERVERCONNECTION_H #include "Input.h" #include "GameStructs.h" +#include "Vectors.h" /* Represents a connection to either a singleplayer or multiplayer server. Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 */ diff --git a/src/Client/TerrainAtlas.c b/src/Client/TerrainAtlas.c index 612de1b88..dce9f85ea 100644 --- a/src/Client/TerrainAtlas.c +++ b/src/Client/TerrainAtlas.c @@ -77,11 +77,7 @@ void Atlas1D_Make1DTexture(Int32 i, Int32 atlas1DHeight, Int32* index) { void Atlas1D_Convert2DTo1D(Int32 atlasesCount, Int32 atlas1DHeight) { Atlas1D_Count = atlasesCount; - UInt8 logBuffer[String_BufferSize(STRING_SIZE * 2)]; - String log = String_InitAndClearArray(logBuffer); - - String_Format2(&log, "Loaded new atlas: %i bmps, %i per bmp", &atlasesCount, &Atlas1D_ElementsPerBitmap); - Platform_Log(&log); + Platform_Log2("Loaded new atlas: %i bmps, %i per bmp", &atlasesCount, &Atlas1D_ElementsPerBitmap); Int32 index = 0, i; for (i = 0; i < atlasesCount; i++) { diff --git a/src/Client/TexturePack.c b/src/Client/TexturePack.c index fabc83c76..9bc4e883d 100644 --- a/src/Client/TexturePack.c +++ b/src/Client/TexturePack.c @@ -50,8 +50,8 @@ void Zip_ReadLocalFileHeader(ZipState* state, ZipEntry* entry) { ReturnCode code = Stream_Skip(stream, extraFieldLen); ErrorHandler_CheckOrFail(code, "Zip - skipping local header extra"); if (versionNeeded > 20) { - String warnMsg = String_FromConst("May not be able to properly extract a .zip enty with a version later than 2.0"); - Platform_LogConst(&warnMsg); + Int32 version = versionNeeded; + Platform_Log1("May not be able to properly extract a .zip enty with version %i", &version); } Stream portion, compStream; @@ -64,8 +64,8 @@ void Zip_ReadLocalFileHeader(ZipState* state, ZipEntry* entry) { Inflate_MakeStream(&compStream, &inflate, &portion); state->ProcessEntry(&filename, &compStream, entry); } else { - String warnMsg = String_FromConst("Unsupported .zip entry compression method"); - Platform_Log(&warnMsg); + Int32 method = compressionMethod; + Platform_Log1("Unsupported.zip entry compression method: %i", &method); } } diff --git a/src/Client/WinPlatform.c b/src/Client/WinPlatform.c index 92a14d277..772c5ab6f 100644 --- a/src/Client/WinPlatform.c +++ b/src/Client/WinPlatform.c @@ -103,6 +103,13 @@ void Platform_LogConst(const UInt8* message) { OutputDebugStringA(message); } +void Platform_Log4(const UInt8* format, const void* a1, const void* a2, const void* a3, const void* a4) { + UInt8 msgBuffer[String_BufferSize(512)]; + String msg = String_InitAndClearArray(msgBuffer); + String_Format4(&msg, format, a1, a2, a3, a4); + Platform_Log(&msg); +} + void Platform_FromSysTime(DateTime* time, SYSTEMTIME* sysTime) { time->Year = sysTime->wYear; time->Month = (UInt8)sysTime->wMonth;