From 99687cf513905a04ae18dfbcbe6fd13c6cbe9694 Mon Sep 17 00:00:00 2001 From: darkvater Date: Sun, 12 Sep 2004 15:29:37 +0000 Subject: [PATCH] (svn r214) -Feature: CMD_NET_INSTANT [just in time command handling over network] (sign_de) -Fix: Only server can pause in network, action disabled for clients -Fix: Direct Connect editbox can handle up to max ~35 characters --- command.c | 11 ++++++++--- command.h | 1 + main_gui.c | 20 +++++++++++++------- network.c | 36 +++++++++++++++++++++++++++++++----- network_gui.c | 4 ++-- ttd.c | 6 ++++-- 6 files changed, 59 insertions(+), 19 deletions(-) diff --git a/command.c b/command.c index 5012c8919f..35ca10ce5d 100644 --- a/command.c +++ b/command.c @@ -445,9 +445,14 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, CommandCallback *callback, // put the command in a network queue and execute it later? if (_networking && !(cmd & CMD_DONT_NETWORK)) { - NetworkSendCommand(tile, p1, p2, cmd, callback); - _docommand_recursive = 0; - return true; + if (!(cmd & CMD_NET_INSTANT)) { + NetworkSendCommand(tile, p1, p2, cmd, callback); + _docommand_recursive = 0; + return true; + } else { + // Instant Command ... Relay and Process then + NetworkSendCommand(tile, p1, p2, cmd, callback); + } } // update last build coordinate of player. diff --git a/command.h b/command.h index 4dc4ad911a..051c1fbef3 100644 --- a/command.h +++ b/command.h @@ -168,6 +168,7 @@ enum { CMD_NO_WATER = 0x400, CMD_DONT_NETWORK = 0x800, // execute the command without sending it on the network CMD_ASYNC = 0x1000, // execute the command asynchronously without testing first in networking + CMD_NET_INSTANT = 0x2000, }; //#define return_cmd_error(errcode) do { _error_message=(errcode); return CMD_ERROR; } while(0) diff --git a/main_gui.c b/main_gui.c index 3465681c3c..17acb1256a 100644 --- a/main_gui.c +++ b/main_gui.c @@ -83,7 +83,9 @@ typedef void ToolbarButtonProc(Window *w); static void ToolbarPauseClick(Window *w) { - if (DoCommandP(0, _pause?0:1, 0, NULL, CMD_PAUSE)) + if (_networking && !_networking_server) { return;} // only server can pause the game + + if (DoCommandP(0, _pause?0:1, 0, NULL, CMD_PAUSE | CMD_NET_INSTANT)) SndPlayFx(0x13); } @@ -1654,14 +1656,11 @@ static void MainToolbarWndProc(Window *w, WindowEvent *e) GfxFillRect(0, 0, w->width-1, w->height-1, 0xB2); GfxFillRect(0, 0, w->width-1, w->height-1, 0x80B4); - // if networking, disable fast-forward button - if (_networking) w->disabled_state |= (1 << 1); - // if spectator, disable things if (_current_player == OWNER_SPECTATOR){ - w->disabled_state |= (1 << 0) | (1 << 19) | (1<<20) | (1<<21) | (1<<22) | (1<<23); + w->disabled_state |= (1 << 19) | (1<<20) | (1<<21) | (1<<22) | (1<<23); } else { - w->disabled_state &= ~((1 << 0) | (1 << 19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)); + w->disabled_state &= ~((1 << 19) | (1<<20) | (1<<21) | (1<<22) | (1<<23)); } DrawWindowWidgets(w); @@ -2225,7 +2224,14 @@ void SetupColorsAndInitialWindow() AssignWindowViewport(w, 0, 0, width, height, 0x8080, 0); w = AllocateWindowDesc(&_toolb_normal_desc); - w->disabled_state = 1 << 17; + w->disabled_state = 1 << 17; // disable zoon-in button (by default game is zoomed in) + + if (_networking) { // if networking, disable fast-forward button + w->disabled_state |= (1 << 1); + if (!_networking_server) // if not server, disable pause button + w->disabled_state |= (1 << 0); + } + w->flags4 &= ~WF_WHITE_BORDER_MASK; PositionMainToolbar(w); // already WC_MAIN_TOOLBAR passed (&_toolb_normal_desc) diff --git a/network.c b/network.c index 27f2d3065e..fa09e47028 100644 --- a/network.c +++ b/network.c @@ -235,6 +235,7 @@ enum { }; void NetworkUDPSend(bool client, struct sockaddr_in recv,struct UDPPacket packet); +static void HandleCommandPacket(ClientState *cs, CommandPacket *np); static void CloseClient(ClientState *cs); void NetworkSendWelcome(ClientState *cs, bool direct); @@ -451,7 +452,11 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comman QueuedCommand *qp; ClientState *cs; - qp = AllocQueuedCommand(_networking_server ? &_command_queue : &_ack_queue); + if (!(cmd & CMD_NET_INSTANT)) { + qp = AllocQueuedCommand(_networking_server ? &_command_queue : &_ack_queue); + } else { + qp = (QueuedCommand*)calloc(sizeof(QueuedCommand), 1); + } qp->cp.packet_type = PACKET_TYPE_COMMAND; qp->cp.tile = tile; qp->cp.p1 = p1; @@ -487,6 +492,9 @@ void NetworkSendCommand(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comman for(cs=_clients; cs->socket != INVALID_SOCKET; cs++) if (!cs->inactive) SendBytes(cs, &qp->cp, qp->cp.packet_length); #endif + if (cmd & CMD_NET_INSTANT) { + free(qp); + } } // client: @@ -505,13 +513,22 @@ static void HandleCommandPacket(ClientState *cs, CommandPacket *np) QueuedCommand *qp; ClientState *c; AckPacket ap; + uint16 cmd; DEBUG(net, 2) ("[NET] cmd size %d", np->packet_length); - assert(np->packet_length >= COMMAND_PACKET_BASE_SIZE); - // put it into the command queue - qp = AllocQueuedCommand(&_command_queue); + cmd = np->cmd; +#if defined(TTD_BIG_ENDIAN) + cmd = TO_LE16(cmd); +#endif + + if (!(cmd & CMD_NET_INSTANT)) { + // put it into the command queue + qp = AllocQueuedCommand(&_command_queue); + } else { + qp = (QueuedCommand*)calloc(sizeof(QueuedCommand), 1); + } qp->cp = *np; qp->frame = _frame_counter_max - GetNextSyncFrame(); @@ -530,7 +547,7 @@ static void HandleCommandPacket(ClientState *cs, CommandPacket *np) if (_networking_server) { for(c=_clients; c->socket != INVALID_SOCKET; c++) { if (c == cs) { - SendDirectBytes(c, &ap, ap.packet_length); + if (!(cmd & CMD_NET_INSTANT)) SendDirectBytes(c, &ap, ap.packet_length); } else { if (!cs->inactive) SendBytes(c, &qp->cp, qp->cp.packet_length); } @@ -546,6 +563,15 @@ static void HandleCommandPacket(ClientState *cs, CommandPacket *np) #endif qp->cmd = qp->cp.cmd; + + if (cmd & CMD_NET_INSTANT) { + byte p = _current_player; + _current_player = qp->cp.player; + memcpy(_decode_parameters, qp->cp.dp, (qp->cp.packet_length - COMMAND_PACKET_BASE_SIZE)); + DoCommandP(qp->cp.tile, qp->cp.p1, qp->cp.p2, qp->callback, qp->cmd | CMD_DONT_NETWORK); + free(qp); + _current_player = p; + } } // sent from server -> client periodically to tell the client about the current tick in the server diff --git a/network_gui.c b/network_gui.c index 005fe5069e..90a231dc4c 100644 --- a/network_gui.c +++ b/network_gui.c @@ -98,8 +98,8 @@ static void NetworkGameWindowWndProc(Window *w, WindowEvent *e) ShowQueryString( str, STR_NETWORK_ENTER_IP, - 15, - 160, + 50, // maximum 50 characters OR + 250, // characters up to width 250 pixels, whichever is satisfied first w->window_class, w->window_number); DeleteName(str); diff --git a/ttd.c b/ttd.c index ffc747724c..a60fbf76f8 100644 --- a/ttd.c +++ b/ttd.c @@ -878,6 +878,9 @@ normal_load: // That check is enforced in DoCommand. void StateGameLoop() { + // dont execute the state loop during pause + if (_pause) return; + _in_state_game_loop = true; _frame_counter++; @@ -1021,8 +1024,7 @@ void GameLoop() } } else { // server/client/standalone: not synced --> state game loop - if (!_pause) - StateGameLoop(); + StateGameLoop(); // server/client: process queued network commands if (_networking) NetworkProcessCommands(); }