diff --git a/callback_table.c b/callback_table.c index 65e140742a..3e1ef2b1ba 100644 --- a/callback_table.c +++ b/callback_table.c @@ -31,6 +31,7 @@ CommandCallback CcPlaySound10; CommandCallback CcPlaceSign; CommandCallback CcTerraform; CommandCallback CcBuildTown; +CommandCallback CcGiveMoney; /* rail_gui.c */ CommandCallback CcPlaySound1E; @@ -85,7 +86,8 @@ CommandCallback *_callback_table[] = { /* 0x17 */ CcCloneShip, /* 0x18 */ CcCloneTrain, /* 0x19 */ CcAI, - /* 0x1A */ CcCloneVehicle + /* 0x1A */ CcCloneVehicle, + /* 0x1B */ CcGiveMoney, }; const int _callback_table_count = lengthof(_callback_table); diff --git a/dock_gui.c b/dock_gui.c index 166714fc20..ae08ddd98d 100644 --- a/dock_gui.c +++ b/dock_gui.c @@ -236,14 +236,16 @@ static void BuildDockStationWndProc(Window *w, WindowEvent *e) case WE_CREATE: LowerWindowWidget(w, _station_show_coverage + 3); break; case WE_PAINT: { - int rad; + int rad = (_patches.modified_catchment) ? CA_DOCK : 4; if (WP(w,def_d).close) return; DrawWindowWidgets(w); - rad = (_patches.modified_catchment) ? CA_DOCK : 4; - - if (_station_show_coverage) SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); + if (_station_show_coverage) { + SetTileSelectBigSize(-rad, -rad, 2 * rad, 2 * rad); + } else { + SetTileSelectSize(1, 1); + } DrawStationCoverageAreaText(4, 50, (uint)-1, rad); break; diff --git a/main_gui.c b/main_gui.c index abee2978b4..88fec4d8dd 100644 --- a/main_gui.c +++ b/main_gui.c @@ -53,6 +53,18 @@ static int _scengen_town_size = 2; // depress medium-sized towns per default extern void GenerateIndustries(void); extern bool GenerateTowns(void); +void CcGiveMoney(bool success, TileIndex tile, uint32 p1, uint32 p2) +{ + char msg[20]; + if (!success) return; + /* Inform the player of this action */ + snprintf(msg, sizeof(msg), "%d", p1); + if (!_network_server) { + SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg); + } else { + NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX); + } +} void HandleOnEditText(WindowEvent *e) { @@ -75,21 +87,11 @@ void HandleOnEditText(WindowEvent *e) case 3: { /* Give money, you can only give money in excess of loan */ const Player *p = GetPlayer(_current_player); int32 money = min(p->money64 - p->current_loan, atoi(e->we.edittext.str) / _currency->rate); - char msg[20]; money = clamp(money, 0, 20000000); // Clamp between 20 million and 0 // Give 'id' the money, and substract it from ourself - if (!DoCommandP(0, money, id, NULL, CMD_GIVE_MONEY | CMD_MSG(STR_INSUFFICIENT_FUNDS))) break; - - // Inform the player of this action - snprintf(msg, sizeof(msg), "%d", money); - - if (!_network_server) { - SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, id, msg); - } else { - NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, id, msg, NETWORK_SERVER_INDEX); - } + DoCommandP(0, money, id, CcGiveMoney, CMD_GIVE_MONEY | CMD_MSG(STR_INSUFFICIENT_FUNDS)); break; } #endif /* ENABLE_NETWORK */ diff --git a/network_data.c b/network_data.c index 0fec5139d6..8d179b914f 100644 --- a/network_data.c +++ b/network_data.c @@ -429,34 +429,24 @@ void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp) // Prepare a DoCommand to be send over the network void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback) { - CommandPacket *c = malloc(sizeof(CommandPacket)); - byte temp_callback; + CommandPacket c; - c->player = _local_player; - c->next = NULL; - c->tile = tile; - c->p1 = p1; - c->p2 = p2; - c->cmd = cmd; - c->callback = 0; + c.player = _local_player; + c.next = NULL; + c.tile = tile; + c.p1 = p1; + c.p2 = p2; + c.cmd = cmd; + c.callback = 0; - temp_callback = 0; - - while (temp_callback < _callback_table_count && _callback_table[temp_callback] != callback) - temp_callback++; - if (temp_callback == _callback_table_count) { + while (c.callback < _callback_table_count && _callback_table[c.callback] != callback) + c.callback++; + if (c.callback == _callback_table_count) { DEBUG(net, 0) ("[NET] Unknown callback. (Pointer: %p) No callback sent.", callback); - temp_callback = 0; /* _callback_table[0] == NULL */ + c.callback = 0; /* _callback_table[0] == NULL */ } - if (_network_server) { - // We are the server, so set the command to be executed next possible frame - c->frame = _frame_counter_max + 1; - } else { - c->frame = 0; // The client can't tell which frame, so just make it 0 - } - - ttd_strlcpy(c->text, (_cmd_text != NULL) ? _cmd_text : "", lengthof(c->text)); + ttd_strlcpy(c.text, (_cmd_text != NULL) ? _cmd_text : "", lengthof(c.text)); if (_network_server) { // If we are the server, we queue the command in our 'special' queue. @@ -464,30 +454,38 @@ void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, Comma // client on the server can do everything 1 tick faster than others. // So to keep the game fair, we delay the command with 1 tick // which gives about the same speed as most clients. - NetworkClientState *cs; - - // And we queue it for delivery to the clients - FOR_ALL_CLIENTS(cs) { - if (cs->status > STATUS_AUTH) NetworkAddCommandQueue(cs, c); - } - // Only the server gets the callback, because clients should not get them - c->callback = temp_callback; + + // We are the server, so set the command to be executed next possible frame + + NetworkClientState *cs; + CommandPacket *new_cp = malloc(sizeof(CommandPacket)); + + c.frame = _frame_counter_max + 1; + *new_cp = c; + if (_local_command_queue == NULL) { - _local_command_queue = c; + _local_command_queue = new_cp; } else { // Find last packet CommandPacket *cp = _local_command_queue; while (cp->next != NULL) cp = cp->next; - cp->next = c; + cp->next = new_cp; + } + + c.callback = 0; + + // And we queue it for delivery to the clients + FOR_ALL_CLIENTS(cs) { + if (cs->status > STATUS_AUTH) NetworkAddCommandQueue(cs, &c); } return; } // Clients send their command to the server and forget all about the packet - c->callback = temp_callback; - SEND_COMMAND(PACKET_CLIENT_COMMAND)(c); + c.frame = 0; + SEND_COMMAND(PACKET_CLIENT_COMMAND)(&c); } // Execute a DoCommand we received from the network diff --git a/network_server.c b/network_server.c index 4ef1090734..f652db7711 100644 --- a/network_server.c +++ b/network_server.c @@ -835,8 +835,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) NetworkClientState *new_cs; const NetworkClientInfo *ci; byte callback; - - CommandPacket *cp = malloc(sizeof(CommandPacket)); + CommandPacket *cp; // The client was never joined.. so this is impossible, right? // Ignore the packet, give the client a warning, and close his connection @@ -845,6 +844,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) return; } + cp = malloc(sizeof(CommandPacket)); cp->player = NetworkRecv_uint8(cs, p); cp->cmd = NetworkRecv_uint32(cs, p); cp->p1 = NetworkRecv_uint32(cs, p); @@ -854,7 +854,10 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) callback = NetworkRecv_uint8(cs, p); - if (cs->has_quit) return; + if (cs->has_quit) { + free(cp); + return; + } ci = DEREF_CLIENT_INFO(cs); @@ -862,11 +865,13 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) if (!IsValidCommand(cp->cmd)) { IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci)); SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED); + free(cp); return; } if (!CheckCommandFlags(cp, ci)) { SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED); + free(cp); return; } @@ -878,6 +883,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...", ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1); SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH); + free(cp); return; } @@ -889,6 +895,7 @@ DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND) if (cp->cmd == CMD_PLAYER_CTRL) { if (cp->p1 != 0) { SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER); + free(cp); return; } diff --git a/vehicle.c b/vehicle.c index a24db1b045..b5bac57c60 100644 --- a/vehicle.c +++ b/vehicle.c @@ -2924,7 +2924,7 @@ PalSpriteID GetVehiclePalette(const Vehicle *v) { if (v->type == VEH_Train) { return GetEngineColourMap( - (v->u.rail.first_engine != INVALID_ENGINE && (IsArticulatedPart(v) || UsesWagonOverride(v))) ? + (v->u.rail.first_engine != INVALID_ENGINE && (UsesWagonOverride(v) || (IsArticulatedPart(v) && (RailVehInfo(v->engine_type)->flags & RVI_WAGON) != 0))) ? v->u.rail.first_engine : v->engine_type, v->owner, v->u.rail.first_engine,