From 3330813d959499cd48f6638d27927779fe523cdc Mon Sep 17 00:00:00 2001 From: rubidium Date: Sat, 30 Apr 2011 20:42:50 +0000 Subject: [PATCH] (svn r22391) [1.1] -Backport from trunk: - Fix: Vehicles skipped orders when inserting automatic orders failed (r22324) - Fix: [NewGRF] When determining refittability use the cargo translation table of the GRF setting the refitmask instead of the GRF defining the action 3 (r22316) - Fix: Make road vehicles, ships and aircraft skip orders if they are leaving a depot and heading to the same one again; just like trains (r22309) - Fix: Waiting on a server could kick the client, or rather the client would kick itself due to an unexpected packet [FS#4574] (r22308) --- src/aircraft_cmd.cpp | 6 ++++ src/network/network_client.cpp | 9 ++---- src/network/network_server.cpp | 57 ++++++++++++++++++---------------- src/newgrf.cpp | 8 ++++- src/roadveh_cmd.cpp | 6 ++++ src/ship_cmd.cpp | 17 +++++++--- src/vehicle.cpp | 7 +++++ 7 files changed, 73 insertions(+), 37 deletions(-) diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 098e30c447..a330280be9 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -1311,6 +1311,12 @@ static void AircraftEventHandler_InHangar(Aircraft *v, const AirportFTAClass *ap !v->current_order.IsType(OT_GOTO_DEPOT)) return; + /* We are leaving a hangar, but have to go to the exact same one; re-enter */ + if (v->current_order.IsType(OT_GOTO_DEPOT) && v->current_order.GetDestination() == v->targetairport) { + VehicleEnterDepot(v); + return; + } + /* if the block of the next position is busy, stay put */ if (AirportHasBlock(v, &apc->layout[v->pos], apc)) return; diff --git a/src/network/network_client.cpp b/src/network/network_client.cpp index 1bd288a2ef..66eff8fdb5 100644 --- a/src/network/network_client.cpp +++ b/src/network/network_client.cpp @@ -719,17 +719,14 @@ DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WELCOME) DEF_GAME_RECEIVE_COMMAND(Client, PACKET_SERVER_WAIT) { - if (this->status != STATUS_AUTHORIZED) return NETWORK_RECV_STATUS_MALFORMED_PACKET; - this->status = STATUS_MAP_WAIT; + /* We set the internal wait state when requesting the map. */ + if (this->status != STATUS_MAP_WAIT) return NETWORK_RECV_STATUS_MALFORMED_PACKET; + /* But... only now we set the join status to waiting, instead of requesting. */ _network_join_status = NETWORK_JOIN_STATUS_WAITING; _network_join_waiting = p->Recv_uint8(); SetWindowDirty(WC_NETWORK_STATUS_WINDOW, 0); - /* We are put on hold for receiving the map.. we need GUI for this ;) */ - DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." ); - DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting); - return NETWORK_RECV_STATUS_OKAY; } diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index 0b86031cb2..cd4008c628 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -539,9 +539,11 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() if (this->status == STATUS_MAP) { if (this->savegame_mutex != NULL) this->savegame_mutex->BeginCritical(); + bool last_packet = false; + for (uint i = 0; i < sent_packets && this->savegame_packets != NULL; i++) { Packet *p = this->savegame_packets; - bool last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE; + last_packet = p->buffer[2] == PACKET_SERVER_MAP_DONE; /* Remove the packet from the savegame queue and put it in the real queue. */ this->savegame_packets = p->next; @@ -549,31 +551,6 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() this->NetworkTCPSocketHandler::SendPacket(p); if (last_packet) { - /* Done reading! */ - - /* Set the status to DONE_MAP, no we will wait for the client - * to send it is ready (maybe that happens like never ;)) */ - this->status = STATUS_DONE_MAP; - - NetworkClientSocket *new_cs; - bool new_map_client = false; - /* Check if there is a client waiting for receiving the map - * and start sending him the map */ - FOR_ALL_CLIENT_SOCKETS(new_cs) { - if (new_cs->status == STATUS_MAP_WAIT) { - /* Check if we already have a new client to send the map to */ - if (!new_map_client) { - /* If not, this client will get the map */ - new_cs->status = STATUS_AUTHORIZED; - new_map_client = true; - new_cs->SendMap(); - } else { - /* Else, send the other clients how many clients are in front of them */ - new_cs->SendWait(); - } - } - } - /* There is no more data, so break the for */ break; } @@ -581,6 +558,34 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap() if (this->savegame_mutex != NULL) this->savegame_mutex->EndCritical(); + if (last_packet) { + /* Done reading, make sure saving is done as well */ + WaitTillSaved(); + + /* Set the status to DONE_MAP, no we will wait for the client + * to send it is ready (maybe that happens like never ;)) */ + this->status = STATUS_DONE_MAP; + + NetworkClientSocket *new_cs; + bool new_map_client = false; + /* Check if there is a client waiting for receiving the map + * and start sending him the map */ + FOR_ALL_CLIENT_SOCKETS(new_cs) { + if (new_cs->status == STATUS_MAP_WAIT) { + /* Check if we already have a new client to send the map to */ + if (!new_map_client) { + /* If not, this client will get the map */ + new_cs->status = STATUS_AUTHORIZED; + new_map_client = true; + new_cs->SendMap(); + } else { + /* Else, send the other clients how many clients are in front of them */ + new_cs->SendWait(); + } + } + } + } + switch (this->SendPackets()) { case SPS_CLOSED: return NETWORK_RECV_STATUS_CONN_LOST; diff --git a/src/newgrf.cpp b/src/newgrf.cpp index bc150ff2dd..502e6dd1c6 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -188,6 +188,7 @@ struct GRFTempEngineData { uint16 cargo_allowed; uint16 cargo_disallowed; RailTypeLabel railtypelabel; + const GRFFile *refitmask_grf; ///< GRF providing the cargo translation table for the refitmask. bool refitmask_valid; ///< Did the newgrf set any refittability property? If not, default refittability will be applied. bool prop27_set; ///< Did the NewGRF set property 27 (misc flags)? uint8 rv_max_speed; ///< Temporary storage of RV prop 15, maximum speed in mph/0.8 @@ -700,6 +701,7 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop case 0x1D: // Refit cargo ei->refit_mask = buf->ReadDWord(); _gted[e->index].refitmask_valid = true; + _gted[e->index].refitmask_grf = _cur_grffile; break; case 0x1E: // Callback @@ -857,6 +859,7 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop case 0x16: // Cargos available for refitting ei->refit_mask = buf->ReadDWord(); _gted[e->index].refitmask_valid = true; + _gted[e->index].refitmask_grf = _cur_grffile; break; case 0x17: // Callback mask @@ -986,6 +989,7 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop case 0x11: // Cargos available for refitting ei->refit_mask = buf->ReadDWord(); _gted[e->index].refitmask_valid = true; + _gted[e->index].refitmask_grf = _cur_grffile; break; case 0x12: // Callback mask @@ -1116,6 +1120,7 @@ static ChangeInfoResult AircraftVehicleChangeInfo(uint engine, int numinfo, int case 0x13: // Cargos available for refitting ei->refit_mask = buf->ReadDWord(); _gted[e->index].refitmask_valid = true; + _gted[e->index].refitmask_grf = _cur_grffile; break; case 0x14: // Callback mask @@ -7431,7 +7436,8 @@ static void CalculateRefitMasks() /* Did the newgrf specify any refitting? If not, use defaults. */ if (_gted[engine].refitmask_valid) { if (ei->refit_mask != 0) { - const GRFFile *file = e->grf_prop.grffile; + const GRFFile *file = _gted[engine].refitmask_grf; + if (file == NULL) file = e->grf_prop.grffile; if (file != NULL && file->cargo_max != 0) { /* Apply cargo translation table to the refit mask */ uint num_cargo = min(32, file->cargo_max); diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 69c1a555d0..5ef0946c54 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -941,6 +941,12 @@ static bool RoadVehLeaveDepot(RoadVehicle *v, bool first) int y = TileY(v->tile) * TILE_SIZE + (rdp[RVC_DEPOT_START_FRAME].y & 0xF); if (first) { + /* We are leaving a depot, but have to go to the exact same one; re-enter */ + if (v->current_order.IsType(OT_GOTO_DEPOT) && v->tile == v->dest_tile) { + VehicleEnterDepot(v); + return true; + } + if (RoadVehFindCloseTo(v, x, y, v->direction, false) != NULL) return true; VehicleServiceInDepot(v); diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index 6eb03ebbf2..ccc0c33b54 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -266,9 +266,16 @@ static const TileIndexDiffC _ship_leave_depot_offs[] = { { 0, -1} }; -static void CheckShipLeaveDepot(Ship *v) +static bool CheckShipLeaveDepot(Ship *v) { - if (!v->IsInDepot()) return; + if (!v->IsInDepot()) return false; + + /* We are leaving a depot, but have to go to the exact same one; re-enter */ + if (v->current_order.IsType(OT_GOTO_DEPOT) && + IsShipDepotTile(v->tile) && GetDepotIndex(v->tile) == v->current_order.GetDestination()) { + VehicleEnterDepot(v); + return true; + } TileIndex tile = v->tile; Axis axis = GetShipDepotAxis(tile); @@ -280,7 +287,7 @@ static void CheckShipLeaveDepot(Ship *v) } else if (DiagdirReachesTracks((DiagDirection)(axis + 2)) & GetTileShipTrackStatus(TILE_ADD(tile, -2 * ToTileIndexDiff(_ship_leave_depot_offs[axis])))) { v->direction = AxisToDirection(axis); } else { - return; + return false; } v->state = AxisToTrackBits(axis); @@ -294,6 +301,8 @@ static void CheckShipLeaveDepot(Ship *v) VehicleServiceInDepot(v); InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); SetWindowClassesDirty(WC_SHIPS_LIST); + + return false; } static bool ShipAccelerate(Vehicle *v) @@ -446,7 +455,7 @@ static void ShipController(Ship *v) if (v->current_order.IsType(OT_LOADING)) return; - CheckShipLeaveDepot(v); + if (CheckShipLeaveDepot(v)) return; v->ShowVisualEffect(); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index ec78d8f428..696286fc88 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1919,6 +1919,13 @@ void Vehicle::HandleLoading(bool mode) this->LeaveStation(); + /* Only advance to next order if we just loaded at the current one */ + const Order *order = this->GetOrder(this->cur_auto_order_index); + if (order == NULL || + (!order->IsType(OT_AUTOMATIC) && !order->IsType(OT_GOTO_STATION)) || + order->GetDestination() != this->last_station_visited) { + return; + } break; }