// // Created by rov on 12/27/25. // #include "network.h" #include #include #define NET_TIMEOUT 30000 typedef enum ConnectionResult { CONN_SUCCESS = 0, CONN_ERR_BAD_HOSTNAME = 1, CONN_ERR_NO_SERVER = 2 } CONNECTION_RESULT; void Gui_UpdateStatusBar(const Gui_t* gui, const char *message); bool Network_Init(Network_t *network) { if (!NET_Init()) { SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", "Failed to initialize SDL_net.", NULL); return false; } network->socket = NULL; return true; } void Network_Shutdown(const Network_t *network) { NET_DestroyStreamSocket(network->socket); NET_Quit(); } CONNECTION_RESULT ConnectToServer(Network_t *network, const ConfigParams_t *configParams, const Gui_t *gui) { Gui_UpdateStatusBar(gui, "Searching for hostname..."); NET_Address *netAddress = NET_ResolveHostname(configParams->serverAddress); const NET_Status resolveHostnameStatus = NET_WaitUntilResolved(netAddress, NET_TIMEOUT); if (resolveHostnameStatus != NET_SUCCESS) { NET_UnrefAddress(netAddress); return CONN_ERR_BAD_HOSTNAME; } Gui_UpdateStatusBar(gui, "Trying to connect..."); network->socket = NET_CreateClient(netAddress, configParams->serverPort); const NET_Status createClientStatus = NET_WaitUntilConnected(network->socket, NET_TIMEOUT); if (createClientStatus != NET_SUCCESS) { NET_DestroyStreamSocket(network->socket); network->socket = NULL; NET_UnrefAddress(netAddress); return CONN_ERR_NO_SERVER; } // TODO: is this okay? NET_UnrefAddress(netAddress); return CONN_SUCCESS; } void Network_ConnectAndReportStatus(Network_t *network, const ConfigParams_t *configParams, const Gui_t *gui) { if (network->socket != NULL) { return; } const CONNECTION_RESULT result = ConnectToServer(network, configParams, gui); const char *message = NULL; switch (result) { case CONN_SUCCESS: message = "Connection established."; break; case CONN_ERR_BAD_HOSTNAME: message = "Error: IP address or host not found."; break; case CONN_ERR_NO_SERVER: message = "Error: No server running on host."; break; } Gui_UpdateStatusBar(gui, message); } void Network_Send(NET_StreamSocket* socket, uint8_t* packetBuf, const uint16_t packetLen) { const uint16_t payloadLength = packetLen - 2; *(uint16_t*) packetBuf = payloadLength; if (!NET_WriteToStreamSocket(socket, packetBuf, packetLen)) { SDL_LogError(SDL_LOG_CATEGORY_CUSTOM, "Network_Send: Failed to send packet."); } } void Network_HandleLoginOrCreateChar(const uint16_t opcode, uint8_t* packetBuf, uint16_t* packetLen, const void* data, const int dataLength) { // Copy the opcode packetBuf[*packetLen] = (uint8_t) opcode; *packetLen += 1; // Write unk0 const uint16_t unk0 = 1; memcpy(&packetBuf[*packetLen], &unk0, 2); *packetLen += 2; // Write unk1 const uint16_t unk1 = 'g'; memcpy(&packetBuf[*packetLen], &unk1, 2); *packetLen += 2; memcpy(&packetBuf[*packetLen], data, dataLength); *packetLen += dataLength; } void Network_SendPacket(const Network_t* network, const PACKET_HANDLER handler, const uint16_t opcode, void* data, const int dataLength) { if (network->socket == NULL) { return; } uint8_t packetBuf[1050]; uint16_t packetLen = 2; // TODO: need this? memset(packetBuf, 0, 1049); // Write handler to buffer at offset 2 memcpy(&packetBuf[packetLen], &handler, 2); packetLen += 2; switch (handler) { case HANDLER_LOGIN_OR_CREATE_CHAR: Network_HandleLoginOrCreateChar(opcode, packetBuf, &packetLen, data, dataLength); break; default: break; } Network_Send(network->socket, packetBuf, packetLen); }