--- 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 <SDL_net.h>
#include <time.h>
+#include <string.h>
+#include <stdbool.h>
+
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);
+}