majorly optimise and simplify packet read/write in C client

This commit is contained in:
UnknownShadow200 2018-08-17 03:08:31 +10:00
parent 54291552b5
commit 4345ea9588
9 changed files with 472 additions and 501 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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) {

View File

@ -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);

View File

@ -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);