279 } |
281 } |
280 return -1; |
282 return -1; |
281 } |
283 } |
282 |
284 |
283 int flib_gameconn_send_quit(flib_gameconn *conn) { |
285 int flib_gameconn_send_quit(flib_gameconn *conn) { |
284 if(log_badargs_if(conn==NULL)) { |
286 return flib_gameconn_send_cmd(conn, "efinish"); |
|
287 } |
|
288 |
|
289 int flib_gameconn_send_cmd(flib_gameconn *conn, const char *cmdString) { |
|
290 if(log_badargs_if2(conn==NULL, cmdString==NULL)) { |
285 return -1; |
291 return -1; |
286 } |
292 } |
287 const char *msg = "\x07""efinish"; |
293 int result = -1; |
288 if(!flib_ipcbase_send_raw(conn->ipcBase, msg, msg[0]+1)) { |
294 uint8_t converted[256]; |
289 demo_append(conn, msg, msg[0]+1); |
295 size_t msglen = strlen(cmdString); |
290 return 0; |
296 if(!log_e_if(msglen>255, "Message too long: %s", cmdString)) { |
291 } |
297 strcpy(converted+1, cmdString); |
292 return -1; |
298 converted[0] = msglen; |
|
299 if(!flib_ipcbase_send_raw(conn->ipcBase, converted, msglen+1)) { |
|
300 demo_append(conn, converted, msglen+1); |
|
301 result = 0; |
|
302 } |
|
303 } |
|
304 return result; |
293 } |
305 } |
294 |
306 |
295 /** |
307 /** |
296 * This macro generates a callback setter function. It uses the name of the callback to |
308 * This macro generates a callback setter function. It uses the name of the callback to |
297 * automatically generate the function name and the fields to set, so a consistent naming |
309 * automatically generate the function name and the fields to set, so a consistent naming |
382 case 'Q': // Game interrupted |
394 case 'Q': // Game interrupted |
383 case 'H': // Game halted |
395 case 'H': // Game halted |
384 case 'q': // game finished |
396 case 'q': // game finished |
385 { |
397 { |
386 int reason = msgbuffer[1]=='Q' ? GAME_END_INTERRUPTED : msgbuffer[1]=='H' ? GAME_END_HALTED : GAME_END_FINISHED; |
398 int reason = msgbuffer[1]=='Q' ? GAME_END_INTERRUPTED : msgbuffer[1]=='H' ? GAME_END_HALTED : GAME_END_FINISHED; |
|
399 conn->disconnectReason = reason; |
387 bool savegame = (reason != GAME_END_FINISHED) && !conn->netgame; |
400 bool savegame = (reason != GAME_END_FINISHED) && !conn->netgame; |
388 if(conn->demoBuffer) { |
401 if(conn->demoBuffer) { |
389 flib_buffer demoBuffer = flib_vector_as_buffer(conn->demoBuffer); |
402 flib_buffer demoBuffer = flib_vector_as_buffer(conn->demoBuffer); |
390 demo_replace_gamemode(demoBuffer, savegame ? 'S' : 'D'); |
403 demo_replace_gamemode(demoBuffer, savegame ? 'S' : 'D'); |
391 conn->onGameRecordedCb(conn->onGameRecordedCtx, demoBuffer.data, demoBuffer.size, savegame); |
404 conn->onGameRecordedCb(conn->onGameRecordedCtx, demoBuffer.data, demoBuffer.size, savegame); |
392 if(conn->destroyRequested) { |
405 if(conn->destroyRequested) { |
393 return; |
406 return; |
394 } |
407 } |
395 } |
408 } |
396 conn->state = FINISHED; |
|
397 conn->onDisconnectCb(conn->onDisconnectCtx, reason); |
|
398 return; |
409 return; |
399 } |
410 } |
400 case 's': // Chat message |
411 case 's': // Chat message |
401 if(len>=3) { |
412 if(len>=3) { |
402 msgbuffer[len-2] = 0; |
413 msgbuffer[len-2] = 0; |
420 } |
431 } |
421 } |
432 } |
422 |
433 |
423 if(flib_ipcbase_state(conn->ipcBase) == IPC_NOT_CONNECTED) { |
434 if(flib_ipcbase_state(conn->ipcBase) == IPC_NOT_CONNECTED) { |
424 conn->state = FINISHED; |
435 conn->state = FINISHED; |
425 conn->onDisconnectCb(conn->onDisconnectCtx, GAME_END_ERROR); |
436 conn->onDisconnectCb(conn->onDisconnectCtx, conn->disconnectReason); |
426 } |
437 } |
427 } |
438 } |
428 |
439 |
429 void flib_gameconn_tick(flib_gameconn *conn) { |
440 void flib_gameconn_tick(flib_gameconn *conn) { |
430 if(!log_badargs_if(conn == NULL) |
441 if(!log_badargs_if(conn == NULL) |