mirror of
https://github.com/OpenTTD/OpenTTD.git
synced 2025-03-06 06:15:04 +00:00
(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
This commit is contained in:
parent
f64c1bda4b
commit
99687cf513
11
command.c
11
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.
|
||||
|
@ -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)
|
||||
|
20
main_gui.c
20
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)
|
||||
|
36
network.c
36
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
|
||||
|
@ -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);
|
||||
|
6
ttd.c
6
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();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user