diff -r c42949cfdd92 -r fe76d24a25d7 project_files/frontlib/ipcconn.c --- a/project_files/frontlib/ipcconn.c Thu May 31 18:54:40 2012 +0200 +++ b/project_files/frontlib/ipcconn.c Sat Jun 02 14:26:52 2012 +0200 @@ -4,23 +4,32 @@ #include #include +#include +#include + static TCPsocket ipcListenSocket; static NonBlockSocket ipcConnSocket; static uint8_t ipcReadBuffer[256]; static int ipcReadBufferSize; +static flib_vector demoBuffer; +static char localPlayerName[255]; + void flib_ipcconn_init() { ipcListenSocket = NULL; ipcConnSocket = NULL; ipcReadBufferSize = 0; + demoBuffer=NULL; + strncpy(localPlayerName, "Local Player", 255); } void flib_ipcconn_quit() { + flib_vector_destroy(&demoBuffer); flib_ipcconn_close(); } -int flib_ipcconn_listen() { +int flib_ipcconn_start(bool recordDemo) { if(ipcListenSocket || ipcConnSocket) { flib_log_e("flib_ipcconn_listen: Already listening or connected."); return -1; @@ -42,6 +51,10 @@ flib_log_w("Failed to start an IPC listening socket on port %i: %s", ipcPort, SDLNet_GetError()); } else { flib_log_i("Listening for IPC connections on port %i.", ipcPort); + if(recordDemo) { + flib_vector_destroy(&demoBuffer); + demoBuffer = flib_vector_create(); + } return ipcPort; } } @@ -68,6 +81,44 @@ } } +static void demo_record(const void *data, size_t len) { + if(demoBuffer) { + if(flib_vector_append(demoBuffer, data, len) < len) { + // Out of memory, fail demo recording + flib_vector_destroy(&demoBuffer); + } + } +} + +static void demo_record_from_engine(const uint8_t *message) { + if(!demoBuffer || message[0]==0) { + return; + } + if(strchr("?CEiQqHb", message[1])) { + // Those message types are not recorded in a demo. + return; + } + + if(message[1] == 's') { + if(message[0] >= 3) { + // Chat messages get a special once-over to make them look as if they were received, not sent. + // Get the actual chat message as c string + char chatMsg[256]; + memcpy(chatMsg, message+2, message[0]-3); + chatMsg[message[0]-3] = 0; + + char converted[257]; + bool memessage = message[0] >= 7 && !memcmp(message+2, "/me ", 4); + const char *template = memessage ? "s\x02* %s %s " : "s\x01%s: %s "; + int size = snprintf(converted+1, 256, template, localPlayerName, chatMsg); + converted[0] = size>255 ? 255 : size; + demo_record(converted, converted[0]+1); + } + } else { + demo_record(message, message[0]+1); + } +} + /** * Receive a single message and copy it into the data buffer. * Returns the length of the received message, -1 when nothing is received. @@ -86,6 +137,7 @@ int msgsize = ipcReadBuffer[0]; if(ipcReadBufferSize > msgsize) { + demo_record_from_engine(ipcReadBuffer); memcpy(data, ipcReadBuffer+1, msgsize); memmove(ipcReadBuffer, ipcReadBuffer+msgsize+1, ipcReadBufferSize-(msgsize+1)); ipcReadBufferSize -= (msgsize+1); @@ -114,15 +166,20 @@ uint8_t sendbuf[256]; sendbuf[0] = len; memcpy(sendbuf+1, data, len); - if(flib_nbsocket_blocksend(ipcConnSocket, sendbuf, len+1) < len+1) { + if(flib_nbsocket_blocksend(ipcConnSocket, sendbuf, len+1) == len+1) { + demo_record(sendbuf, len+1); + return 0; + } else { flib_log_w("Failed or incomplete ICP write: engine connection lost."); flib_nbsocket_close(&ipcConnSocket); return -1; - } else { - return 0; } } +int flib_ipcconn_send_messagestr(char *data) { + return flib_ipcconn_send_message(data, strlen(data)); +} + void flib_ipcconn_tick() { if(!ipcConnSocket && ipcListenSocket) { ipcConnSocket = flib_nbsocket_accept(ipcListenSocket, true); @@ -132,3 +189,32 @@ } } } + +static void replace_gamemode(flib_buffer buf, char gamemode) { + size_t msgStart = 0; + char *data = (char*)buf.data; + while(msgStart+2 < buf.size) { + if(!memcmp(data+msgStart, "\x02T", 2)) { + data[msgStart+2] = gamemode; + } + msgStart += (uint8_t)data[msgStart]+1; + } +} + +flib_constbuffer flib_ipcconn_getdemo() { + if(!demoBuffer) { + flib_constbuffer result = {NULL, 0}; + return result; + } + replace_gamemode(flib_vector_as_buffer(demoBuffer), 'D'); + return flib_vector_as_constbuffer(demoBuffer); +} + +flib_constbuffer flib_ipcconn_getsave() { + if(!demoBuffer) { + flib_constbuffer result = {NULL, 0}; + return result; + } + replace_gamemode(flib_vector_as_buffer(demoBuffer), 'S'); + return flib_vector_as_constbuffer(demoBuffer); +}