mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-16 11:06:06 -04:00
majorly optimise and simplify packet read/write in C client
This commit is contained in:
parent
54291552b5
commit
4345ea9588
@ -254,7 +254,7 @@ void HacksComp_CheckConsistency(struct HacksComp* hacks) {
|
||||
hacks->Speeding = false; hacks->HalfSpeeding = false;
|
||||
}
|
||||
|
||||
hacks->CanDoubleJump = hacks->CanAnyHacks && hacks->Enabled && hacks->CanSpeed;
|
||||
hacks->CanDoubleJump = hacks->CanAnyHacks && hacks->Enabled && hacks->CanSpeed;
|
||||
hacks->CanSeeAllNames = hacks->CanAnyHacks && hacks->CanSeeAllNames;
|
||||
|
||||
if (!hacks->CanUseThirdPersonCamera || !hacks->Enabled) {
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,9 +14,9 @@ void Handlers_Reset(void);
|
||||
void Handlers_Tick(void);
|
||||
|
||||
bool cpe_sendHeldBlock, cpe_useMessageTypes, cpe_needD3Fix, cpe_extEntityPos, cpe_blockPerms, cpe_fastMap;
|
||||
void Classic_WriteChat(struct Stream* stream, STRING_PURE String* text, bool partial);
|
||||
void Classic_WritePosition(struct Stream* stream, Vector3 pos, Real32 rotY, Real32 headX);
|
||||
void Classic_WriteSetBlock(struct Stream* stream, Int32 x, Int32 y, Int32 z, bool place, BlockID block);
|
||||
void Classic_WriteLogin(struct Stream* stream, STRING_PURE String* username, STRING_PURE String* verKey);
|
||||
void CPE_WritePlayerClick(struct Stream* stream, MouseButton button, bool buttonDown, UInt8 targetId, struct PickedPos* pos);
|
||||
void Classic_WriteChat(STRING_PURE String* text, bool partial);
|
||||
void Classic_WritePosition(Vector3 pos, Real32 rotY, Real32 headX);
|
||||
void Classic_WriteSetBlock(Int32 x, Int32 y, Int32 z, bool place, BlockID block);
|
||||
void Classic_WriteLogin(STRING_PURE String* username, STRING_PURE String* verKey);
|
||||
void CPE_WritePlayerClick(MouseButton button, bool buttonDown, UInt8 targetId, struct PickedPos* pos);
|
||||
#endif
|
||||
|
@ -92,7 +92,7 @@ int main(void) {
|
||||
String title = String_FromConst(PROGRAM_APP_NAME);
|
||||
String rawArgs = Platform_GetCommandLineArgs();
|
||||
/* NOTE: Make sure to comment this out before pushing a commit */
|
||||
//rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565");
|
||||
rawArgs = String_FromReadonly("UnknownShadow200 fff 127.0.0.1 25565");
|
||||
|
||||
String args[5]; Int32 argsCount = Array_Elems(args);
|
||||
String_UNSAFE_Split(&rawArgs, ' ', args, &argsCount);
|
||||
|
@ -234,8 +234,7 @@ void ServerConnection_InitSingleplayer(void) {
|
||||
ServerConnection_SendPlayerClick = SPConnection_SendPlayerClick;
|
||||
ServerConnection_Tick = SPConnection_Tick;
|
||||
|
||||
ServerConnection_ReadStream = NULL;
|
||||
ServerConnection_WriteStream = NULL;
|
||||
ServerConnection_WriteBuffer = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -243,10 +242,9 @@ void ServerConnection_InitSingleplayer(void) {
|
||||
*--------------------------------------------------Multiplayer connection-------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
SocketPtr net_socket;
|
||||
struct Stream net_readStream;
|
||||
struct Stream net_writeStream;
|
||||
UInt8 net_readBuffer[4096 * 5];
|
||||
UInt8 net_writeBuffer[131];
|
||||
UInt8* net_readCurrent;
|
||||
|
||||
bool net_writeFailed;
|
||||
Int32 net_ticks;
|
||||
@ -262,9 +260,9 @@ static void MPConnection_BlockChanged(void* obj, Vector3I coords, BlockID oldBlo
|
||||
Vector3I p = coords;
|
||||
if (block == BLOCK_AIR) {
|
||||
block = Inventory_SelectedBlock;
|
||||
Classic_WriteSetBlock(&net_writeStream, p.X, p.Y, p.Z, false, block);
|
||||
Classic_WriteSetBlock(p.X, p.Y, p.Z, false, block);
|
||||
} else {
|
||||
Classic_WriteSetBlock(&net_writeStream, p.X, p.Y, p.Z, true, block);
|
||||
Classic_WriteSetBlock(p.X, p.Y, p.Z, true, block);
|
||||
}
|
||||
Net_SendPacket();
|
||||
}
|
||||
@ -273,16 +271,11 @@ static void ServerConnection_Free(void);
|
||||
static void MPConnection_FinishConnect(void) {
|
||||
net_connecting = false;
|
||||
Event_RaiseReal(&WorldEvents_Loading, 0.0f);
|
||||
|
||||
String streamName = String_FromConst("network socket");
|
||||
Stream_ReadonlyMemory(&net_readStream, net_readBuffer, sizeof(net_readBuffer), &streamName);
|
||||
Stream_WriteonlyMemory(&net_writeStream, net_writeBuffer, sizeof(net_writeBuffer), &streamName);
|
||||
|
||||
net_readStream.Meta.Mem.Left = 0; /* initally no memory to read */
|
||||
net_readStream.Meta.Mem.Length = 0;
|
||||
net_readCurrent = net_readBuffer;
|
||||
ServerConnection_WriteBuffer = net_writeBuffer;
|
||||
|
||||
Handlers_Reset();
|
||||
Classic_WriteLogin(&net_writeStream, &Game_Username, &Game_Mppass);
|
||||
Classic_WriteLogin(&Game_Username, &Game_Mppass);
|
||||
Net_SendPacket();
|
||||
DateTime_CurrentUTC(&net_lastPacket);
|
||||
}
|
||||
@ -353,22 +346,22 @@ static void MPConnection_SendChat(STRING_PURE String* text) {
|
||||
|
||||
while (remaining.length > STRING_SIZE) {
|
||||
String portion = String_UNSAFE_Substring(&remaining, 0, STRING_SIZE);
|
||||
Classic_WriteChat(&net_writeStream, &portion, true);
|
||||
Classic_WriteChat(&portion, true);
|
||||
Net_SendPacket();
|
||||
remaining = String_UNSAFE_SubstringAt(&remaining, STRING_SIZE);
|
||||
}
|
||||
|
||||
Classic_WriteChat(&net_writeStream, &remaining, false);
|
||||
Classic_WriteChat(&remaining, false);
|
||||
Net_SendPacket();
|
||||
}
|
||||
|
||||
static void MPConnection_SendPosition(Vector3 pos, Real32 rotY, Real32 headX) {
|
||||
Classic_WritePosition(&net_writeStream, pos, rotY, headX);
|
||||
Classic_WritePosition(pos, rotY, headX);
|
||||
Net_SendPacket();
|
||||
}
|
||||
|
||||
static void MPConnection_SendPlayerClick(MouseButton button, bool buttonDown, EntityID targetId, struct PickedPos* pos) {
|
||||
CPE_WritePlayerClick(&net_writeStream, button, buttonDown, targetId, pos);
|
||||
CPE_WritePlayerClick(button, buttonDown, targetId, pos);
|
||||
Net_SendPacket();
|
||||
}
|
||||
|
||||
@ -399,19 +392,19 @@ static void MPConnection_Tick(struct ScheduledTask* task) {
|
||||
if (ServerConnection_Disconnected) return;
|
||||
|
||||
UInt32 pending = 0;
|
||||
ReturnCode recvResult = Socket_Available(net_socket, &pending);
|
||||
if (recvResult == 0 && pending) {
|
||||
/* NOTE: Always using a read call that is a multiple of 4096 (appears to?) improve read performance */
|
||||
UInt8* src = net_readBuffer + net_readStream.Meta.Mem.Left;
|
||||
recvResult = Socket_Read(net_socket, src, 4096 * 4, &pending);
|
||||
net_readStream.Meta.Mem.Left += pending;
|
||||
net_readStream.Meta.Mem.Length += pending;
|
||||
ReturnCode res = Socket_Available(net_socket, &pending);
|
||||
UInt8* readEnd = net_readCurrent;
|
||||
|
||||
if (!res && pending) {
|
||||
/* NOTE: Always using a read call that is a multiple of 4096 (appears to?) improve read performance */
|
||||
res = Socket_Read(net_socket, net_readCurrent, 4096 * 4, &pending);
|
||||
readEnd += pending;
|
||||
}
|
||||
|
||||
if (recvResult) {
|
||||
if (res) {
|
||||
UChar msgBuffer[String_BufferSize(STRING_SIZE * 2)];
|
||||
String msg = String_InitAndClearArray(msgBuffer);
|
||||
String_Format3(&msg, "Error reading from %s:%i: %i", &Game_IPAddress, &Game_Port, &recvResult);
|
||||
String_Format3(&msg, "Error reading from %s:%i: %i", &Game_IPAddress, &Game_Port, &res);
|
||||
ErrorHandler_Log(&msg);
|
||||
|
||||
String title = String_FromConst("&eLost connection to the server");
|
||||
@ -420,12 +413,13 @@ static void MPConnection_Tick(struct ScheduledTask* task) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (net_readStream.Meta.Mem.Left) {
|
||||
UInt8 opcode = net_readStream.Meta.Mem.Cur[0];
|
||||
net_readCurrent = net_readBuffer;
|
||||
while (net_readCurrent < readEnd) {
|
||||
UInt8 opcode = net_readCurrent[0];
|
||||
/* Workaround for older D3 servers which wrote one byte too many for HackControl packets */
|
||||
if (cpe_needD3Fix && net_lastOpcode == OPCODE_CPE_HACK_CONTROL && (opcode == 0x00 || opcode == 0xFF)) {
|
||||
if (cpe_needD3Fix && net_lastOpcode == OPCODE_HACK_CONTROL && (opcode == 0x00 || opcode == 0xFF)) {
|
||||
Platform_LogConst("Skipping invalid HackControl byte from D3 server");
|
||||
Stream_Skip(&net_readStream, 1);
|
||||
net_readCurrent++;
|
||||
|
||||
struct LocalPlayer* p = &LocalPlayer_Instance;
|
||||
p->Physics.JumpVel = 0.42f; /* assume default jump height */
|
||||
@ -438,9 +432,8 @@ static void MPConnection_Tick(struct ScheduledTask* task) {
|
||||
String msg = String_FromConst("Server sent invalid packet!");
|
||||
Game_Disconnect(&title, &msg); return;
|
||||
}
|
||||
if (net_readStream.Meta.Mem.Left < Net_PacketSizes[opcode]) break;
|
||||
|
||||
Stream_Skip(&net_readStream, 1); /* remove opcode */
|
||||
if (net_readCurrent + Net_PacketSizes[opcode] > readEnd) break;
|
||||
net_lastOpcode = opcode;
|
||||
DateTime_CurrentUTC(&net_lastPacket);
|
||||
|
||||
@ -450,23 +443,24 @@ static void MPConnection_Tick(struct ScheduledTask* task) {
|
||||
String msg = String_FromConst("Server sent invalid packet!");
|
||||
Game_Disconnect(&title, &msg); return;
|
||||
}
|
||||
handler(&net_readStream);
|
||||
|
||||
handler(net_readCurrent + 1); /* skip opcode */
|
||||
net_readCurrent += Net_PacketSizes[opcode];
|
||||
}
|
||||
|
||||
/* Keep last few unprocessed bytes, don't care about rest since they'll be overwritten on socket read */
|
||||
UInt32 i;
|
||||
for (i = 0; i < net_readStream.Meta.Mem.Left; i++) {
|
||||
net_readBuffer[i] = net_readStream.Meta.Mem.Cur[i];
|
||||
UInt32 i, remaining = (UInt32)(readEnd - net_readCurrent);
|
||||
for (i = 0; i < remaining; i++) {
|
||||
net_readBuffer[i] = net_readCurrent[i];
|
||||
}
|
||||
net_readStream.Meta.Mem.Cur = net_readStream.Meta.Mem.Base;
|
||||
net_readStream.Meta.Mem.Length = net_readStream.Meta.Mem.Left;
|
||||
net_readCurrent = net_readBuffer + remaining;
|
||||
|
||||
/* Network is ticked 60 times a second. We only send position updates 20 times a second */
|
||||
if ((net_ticks % 3) == 0) {
|
||||
ServerConnection_CheckAsyncResources();
|
||||
Handlers_Tick();
|
||||
/* Have any packets been written? */
|
||||
if (net_writeStream.Meta.Mem.Cur != net_writeStream.Meta.Mem.Base) {
|
||||
if (ServerConnection_WriteBuffer != net_writeBuffer) {
|
||||
Net_SendPacket();
|
||||
}
|
||||
}
|
||||
@ -479,23 +473,21 @@ void Net_Set(UInt8 opcode, Net_Handler handler, UInt16 packetSize) {
|
||||
}
|
||||
|
||||
void Net_SendPacket(void) {
|
||||
if (!ServerConnection_Disconnected) {
|
||||
/* NOTE: Not immediately disconnecting here, as otherwise we sometimes miss out on kick messages */
|
||||
UInt32 count = (UInt32)(net_writeStream.Meta.Mem.Cur - net_writeStream.Meta.Mem.Base), wrote = 0;
|
||||
UInt32 count = (UInt32)(ServerConnection_WriteBuffer - net_writeBuffer);
|
||||
ServerConnection_WriteBuffer = net_writeBuffer;
|
||||
if (ServerConnection_Disconnected) return;
|
||||
|
||||
while (count) {
|
||||
ReturnCode res = Socket_Write(net_socket, net_writeBuffer, count, &wrote);
|
||||
if (res || !wrote) { net_writeFailed = true; break; }
|
||||
count -= wrote;
|
||||
}
|
||||
/* NOTE: Not immediately disconnecting here, as otherwise we sometimes miss out on kick messages */
|
||||
UInt32 wrote = 0;
|
||||
UInt8* ptr = net_writeBuffer;
|
||||
|
||||
while (count) {
|
||||
ReturnCode res = Socket_Write(net_socket, ptr, count, &wrote);
|
||||
if (res || !wrote) { net_writeFailed = true; break; }
|
||||
ptr += wrote; count -= wrote;
|
||||
}
|
||||
|
||||
net_writeStream.Meta.Mem.Cur = net_writeStream.Meta.Mem.Base;
|
||||
net_writeStream.Meta.Mem.Left = net_writeStream.Meta.Mem.Length;
|
||||
}
|
||||
|
||||
static struct Stream* MPConnection_ReadStream(void) { return &net_readStream; }
|
||||
static struct Stream* MPConnection_WriteStream(void) { return &net_writeStream; }
|
||||
void ServerConnection_InitMultiplayer(void) {
|
||||
ServerConnection_ResetState();
|
||||
ServerConnection_IsSinglePlayer = false;
|
||||
@ -506,8 +498,8 @@ void ServerConnection_InitMultiplayer(void) {
|
||||
ServerConnection_SendPlayerClick = MPConnection_SendPlayerClick;
|
||||
ServerConnection_Tick = MPConnection_Tick;
|
||||
|
||||
ServerConnection_ReadStream = MPConnection_ReadStream;
|
||||
ServerConnection_WriteStream = MPConnection_WriteStream;
|
||||
net_readCurrent = net_readBuffer;
|
||||
ServerConnection_WriteBuffer = net_writeBuffer;
|
||||
}
|
||||
|
||||
|
||||
|
@ -7,52 +7,31 @@
|
||||
*/
|
||||
|
||||
enum OPCODE_ {
|
||||
OPCODE_HANDSHAKE,
|
||||
OPCODE_PING,
|
||||
OPCODE_LEVEL_INIT,
|
||||
OPCODE_LEVEL_DATA_CHUNK,
|
||||
OPCODE_LEVEL_FINALISE,
|
||||
OPCODE_SET_BLOCK_CLIENT,
|
||||
OPCODE_SET_BLOCK,
|
||||
OPCODE_ADD_ENTITY,
|
||||
OPCODE_ENTITY_TELEPORT,
|
||||
OPCODE_RELPOS_AND_ORIENTATION_UPDATE,
|
||||
OPCODE_RELPOS_UPDATE,
|
||||
OPCODE_ORIENTATION_UPDATE,
|
||||
OPCODE_REMOVE_ENTITY,
|
||||
OPCODE_MESSAGE ,
|
||||
OPCODE_KICK,
|
||||
OPCODE_HANDSHAKE, OPCODE_PING,
|
||||
OPCODE_LEVEL_BEGIN, OPCODE_LEVEL_DATA, OPCODE_LEVEL_END,
|
||||
OPCODE_SET_BLOCK_CLIENT, OPCODE_SET_BLOCK,
|
||||
OPCODE_ADD_ENTITY, OPCODE_ENTITY_TELEPORT,
|
||||
OPCODE_RELPOS_AND_ORI_UPDATE, OPCODE_RELPOS_UPDATE,
|
||||
OPCODE_ORI_UPDATE, OPCODE_REMOVE_ENTITY,
|
||||
OPCODE_MESSAGE, OPCODE_KICK,
|
||||
OPCODE_SET_PERMISSION,
|
||||
|
||||
OPCODE_CPE_EXT_INFO,
|
||||
OPCODE_CPE_EXT_ENTRY,
|
||||
OPCODE_CPE_SET_CLICK_DISTANCE,
|
||||
OPCODE_CPE_CUSTOM_BLOCK_LEVEL,
|
||||
OPCODE_CPE_HOLD_THIS,
|
||||
OPCODE_CPE_SET_TEXT_HOTKEY,
|
||||
OPCODE_CPE_EXT_ADD_PLAYER_NAME,
|
||||
OPCODE_CPE_EXT_ADD_ENTITY,
|
||||
OPCODE_CPE_EXT_REMOVE_PLAYER_NAME,
|
||||
OPCODE_CPE_ENV_SET_COLOR,
|
||||
OPCODE_CPE_MAKE_SELECTION,
|
||||
OPCODE_CPE_REMOVE_SELECTION,
|
||||
OPCODE_CPE_SET_BLOCK_PERMISSION,
|
||||
OPCODE_CPE_SET_MODEL,
|
||||
OPCODE_CPE_ENV_SET_MAP_APPEARANCE,
|
||||
OPCODE_CPE_ENV_SET_WEATHER,
|
||||
OPCODE_CPE_HACK_CONTROL,
|
||||
OPCODE_CPE_EXT_ADD_ENTITY2,
|
||||
OPCODE_CPE_PLAYER_CLICK,
|
||||
OPCODE_CPE_DEFINE_BLOCK,
|
||||
OPCODE_CPE_UNDEFINE_BLOCK,
|
||||
OPCODE_CPE_DEFINE_BLOCK_EXT,
|
||||
OPCODE_CPE_BULK_BLOCK_UPDATE,
|
||||
OPCODE_CPE_SET_TEXT_COLOR,
|
||||
OPCODE_CPE_ENV_SET_MAP_URL,
|
||||
OPCODE_CPE_ENV_SET_MAP_PROPERTY,
|
||||
OPCODE_CPE_SET_ENTITY_PROPERTY,
|
||||
OPCODE_CPE_TWO_WAY_PING,
|
||||
OPCODE_CPE_SET_INVENTORY_ORDER,
|
||||
/* CPE packets */
|
||||
OPCODE_EXT_INFO, OPCODE_EXT_ENTRY,
|
||||
OPCODE_SET_REACH, OPCODE_CUSTOM_BLOCK_LEVEL,
|
||||
OPCODE_HOLD_THIS, OPCODE_SET_TEXT_HOTKEY,
|
||||
OPCODE_EXT_ADD_PLAYER_NAME, OPCODE_EXT_ADD_ENTITY,
|
||||
OPCODE_EXT_REMOVE_PLAYER_NAME, OPCODE_ENV_SET_COLOR,
|
||||
OPCODE_MAKE_SELECTION, OPCODE_REMOVE_SELECTION,
|
||||
OPCODE_SET_BLOCK_PERMISSION, OPCODE_SET_MODEL,
|
||||
OPCODE_ENV_SET_MAP_APPEARANCE, OPCODE_ENV_SET_WEATHER,
|
||||
OPCODE_HACK_CONTROL, OPCODE_EXT_ADD_ENTITY2,
|
||||
OPCODE_PLAYER_CLICK, OPCODE_DEFINE_BLOCK,
|
||||
OPCODE_UNDEFINE_BLOCK, OPCODE_DEFINE_BLOCK_EXT,
|
||||
OPCODE_BULK_BLOCK_UPDATE, OPCODE_SET_TEXT_COLOR,
|
||||
OPCODE_ENV_SET_MAP_URL, OPCODE_ENV_SET_MAP_PROPERTY,
|
||||
OPCODE_SET_ENTITY_PROPERTY, OPCODE_TWO_WAY_PING,
|
||||
OPCODE_SET_INVENTORY_ORDER,
|
||||
|
||||
OPCODE_COUNT,
|
||||
};
|
||||
@ -77,8 +56,7 @@ void (*ServerConnection_SendChat)(STRING_PURE String* text);
|
||||
void (*ServerConnection_SendPosition)(Vector3 pos, Real32 rotY, Real32 headX);
|
||||
void (*ServerConnection_SendPlayerClick)(MouseButton button, bool isDown, EntityID targetId, struct PickedPos* pos);
|
||||
void (*ServerConnection_Tick)(struct ScheduledTask* task);
|
||||
struct Stream* (*ServerConnection_ReadStream)(void);
|
||||
struct Stream* (*ServerConnection_WriteStream)(void);
|
||||
UInt8* ServerConnection_WriteBuffer;
|
||||
|
||||
bool ServerConnection_SupportsExtPlayerList;
|
||||
bool ServerConnection_SupportsPlayerClick;
|
||||
@ -91,7 +69,7 @@ void ServerConnection_InitSingleplayer(void);
|
||||
void ServerConnection_InitMultiplayer(void);
|
||||
void ServerConnection_MakeComponent(struct IGameComponent* comp);
|
||||
|
||||
typedef void (*Net_Handler)(struct Stream* stream);
|
||||
typedef void (*Net_Handler)(UInt8* data);
|
||||
UInt16 Net_PacketSizes[OPCODE_COUNT];
|
||||
Net_Handler Net_Handlers[OPCODE_COUNT];
|
||||
void Net_Set(UInt8 opcode, Net_Handler handler, UInt16 size);
|
||||
|
@ -38,17 +38,6 @@ ReturnCode Stream_Read(struct Stream* stream, UInt8* buffer, UInt32 count) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Stream_WriteOrFail(struct Stream* stream, UInt8* buffer, UInt32 count) {
|
||||
UInt32 write;
|
||||
while (count) {
|
||||
ReturnCode res = stream->Write(stream, buffer, count, &write);
|
||||
if (!write || res) { Stream_Fail(stream, res, "writing to"); }
|
||||
|
||||
buffer += write;
|
||||
count -= write;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnCode Stream_Write(struct Stream* stream, UInt8* buffer, UInt32 count) {
|
||||
UInt32 write;
|
||||
while (count) {
|
||||
|
@ -35,7 +35,6 @@ struct Stream {
|
||||
|
||||
void Stream_ReadOrFail(struct Stream* stream, UInt8* buffer, UInt32 count);
|
||||
ReturnCode Stream_Read(struct Stream* stream, UInt8* buffer, UInt32 count);
|
||||
void Stream_WriteOrFail(struct Stream* stream, UInt8* buffer, UInt32 count);
|
||||
ReturnCode Stream_Write(struct Stream* stream, UInt8* buffer, UInt32 count);
|
||||
void Stream_Init(struct Stream* stream, STRING_PURE String* name);
|
||||
void Stream_Skip(struct Stream* stream, UInt32 count);
|
||||
|
@ -475,18 +475,18 @@ void TexturePack_ExtractCurrent(STRING_PURE String* url) {
|
||||
/* e.g. 404 errors */
|
||||
if (World_TextureUrl.length) TexturePack_ExtractDefault();
|
||||
} else {
|
||||
String zip = String_FromConst(".zip");
|
||||
String zipExt = String_FromConst(".zip");
|
||||
ReturnCode res = 0;
|
||||
|
||||
if (String_Equals(url, &World_TextureUrl)) {
|
||||
} else {
|
||||
bool zip = String_ContainsString(url, &zip);
|
||||
bool zip = String_ContainsString(url, &zipExt);
|
||||
String_Set(&World_TextureUrl, url);
|
||||
const UChar* operation = zip ? "extracting" : "decoding";
|
||||
|
||||
res = zip ? TexturePack_ExtractZip(&stream) :
|
||||
TexturePack_ExtractTerrainPng(&stream);
|
||||
if (res) { ErrorHandler_LogError_Path(res, operation, &url); }
|
||||
if (res) { ErrorHandler_LogError_Path(res, operation, url); }
|
||||
}
|
||||
|
||||
res = stream.Close(&stream);
|
||||
|
Loading…
x
Reference in New Issue
Block a user