diff --git a/src/command.cpp b/src/command.cpp index 0fe8b274d3..aa89966fc3 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -429,11 +429,11 @@ static const Command _command_proc_table[] = { DEF_CMD(CmdToggleRefitAsTemplate, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_REFIT_AS_TEMPLATE DEF_CMD(CmdToggleTemplateReplaceOldOnly, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_TOGGLE_TMPL_REPLACE_OLD_ONLY - DEF_CMD(CmdVirtualTrainFromTemplateVehicle, CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE - DEF_CMD(CmdVirtualTrainFromTrain, CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_VIRTUAL_TRAIN_FROM_TRAIN - DEF_CMD(CmdDeleteVirtualTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_VIRTUAL_TRAIN - DEF_CMD(CmdBuildVirtualRailVehicle, CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_BUILD_VIRTUAL_RAIL_VEHICLE - DEF_CMD(CmdReplaceTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_REPLACE_TEMPLATE_VEHICLE + DEF_CMD(CmdVirtualTrainFromTemplateVehicle, CMD_CLIENT_ID | CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_VIRTUAL_TRAIN_FROM_TEMPLATE_VEHICLE + DEF_CMD(CmdVirtualTrainFromTrain, CMD_CLIENT_ID | CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_VIRTUAL_TRAIN_FROM_TRAIN + DEF_CMD(CmdDeleteVirtualTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_DELETE_VIRTUAL_TRAIN + DEF_CMD(CmdBuildVirtualRailVehicle, CMD_CLIENT_ID | CMD_NO_TEST | CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_BUILD_VIRTUAL_RAIL_VEHICLE + DEF_CMD(CmdReplaceTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT), // CMD_REPLACE_TEMPLATE_VEHICLE DEF_CMD(CmdTemplateVehicleFromTrain, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_CLONE_TEMPLATE_VEHICLE_FROM_TRAIN DEF_CMD(CmdDeleteTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_TEMPLATE_VEHICLE diff --git a/src/network/network_server.cpp b/src/network/network_server.cpp index bd78225da9..34308dea45 100644 --- a/src/network/network_server.cpp +++ b/src/network/network_server.cpp @@ -230,6 +230,9 @@ ServerNetworkGameSocketHandler::~ServerNetworkGameSocketHandler() if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID; OrderBackup::ResetUser(this->client_id); + extern void RemoveVirtualTrainsOfUser(uint32 user); + RemoveVirtualTrainsOfUser(this->client_id); + if (this->savegame != nullptr) { this->savegame->Destroy(); this->savegame = nullptr; diff --git a/src/saveload/tbtr_template_veh_sl.cpp b/src/saveload/tbtr_template_veh_sl.cpp index a058980fb0..3abf270107 100644 --- a/src/saveload/tbtr_template_veh_sl.cpp +++ b/src/saveload/tbtr_template_veh_sl.cpp @@ -117,7 +117,7 @@ void AfterLoadTemplateVehiclesUpdateImage() if (tv->Prev() == nullptr) { Backup cur_company(_current_company, tv->owner, FILE_LINE); StringID err; - Train* t = VirtualTrainFromTemplateVehicle(tv, err); + Train* t = VirtualTrainFromTemplateVehicle(tv, err, 0); if (t != nullptr) { int tv_len = 0; for (TemplateVehicle *u = tv; u != nullptr; u = u->Next()) { @@ -154,7 +154,7 @@ void AfterLoadTemplateVehiclesUpdateProperties() if (tv->Prev() == nullptr) { Backup cur_company(_current_company, tv->owner, FILE_LINE); StringID err; - Train* t = VirtualTrainFromTemplateVehicle(tv, err); + Train* t = VirtualTrainFromTemplateVehicle(tv, err, 0); if (t != nullptr) { uint32 full_cargo_weight = 0; for (Train *u = t; u != nullptr; u = u->Next()) { diff --git a/src/tbtr_template_vehicle_func.h b/src/tbtr_template_vehicle_func.h index 744ca5d48c..a9d7b856a3 100644 --- a/src/tbtr_template_vehicle_func.h +++ b/src/tbtr_template_vehicle_func.h @@ -15,7 +15,7 @@ #include "tbtr_template_vehicle.h" -Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err); +Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err, uint32 user); void BuildTemplateGuiList(GUITemplateList*, Scrollbar*, Owner, RailType); diff --git a/src/train.h b/src/train.h index 716e86323a..25549649b3 100644 --- a/src/train.h +++ b/src/train.h @@ -417,8 +417,7 @@ protected: // These functions should not be called outside acceleration code. CommandCost CmdMoveRailVehicle(TileIndex, DoCommandFlag , uint32, uint32, const char *); CommandCost CmdMoveVirtualRailVehicle(TileIndex, DoCommandFlag, uint32, uint32, const char*); -Train* CmdBuildVirtualRailWagon(const Engine*); -Train* CmdBuildVirtualRailVehicle(EngineID, StringID &error); +Train* CmdBuildVirtualRailVehicle(EngineID, StringID &error, uint32 user); int GetTileMarginInFrontOfTrain(const Train *v, int x_pos, int y_pos); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index f13f2e4939..1fa41bb9d1 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -5350,7 +5350,7 @@ int GetDisplayImageWidth(Train *t, Point *offset) return t->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH; } -Train* CmdBuildVirtualRailWagon(const Engine *e) +Train* CmdBuildVirtualRailWagon(const Engine *e, uint32 user) { const RailVehicleInfo *rvi = &e->u.rail; @@ -5371,6 +5371,7 @@ Train* CmdBuildVirtualRailWagon(const Engine *e) v->track = TRACK_BIT_DEPOT; SetBit(v->flags, VRF_CONSIST_SPEED_REDUCTION); v->vehstatus = VS_HIDDEN | VS_DEFPAL; + v->motion_counter = user; v->SetWagon(); v->SetFreeWagon(); @@ -5407,7 +5408,7 @@ Train* CmdBuildVirtualRailWagon(const Engine *e) return v; } -Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) +Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error, uint32 user) { const Engine *e = Engine::GetIfValid(eid); if (e == nullptr || e->type != VEH_TRAIN) { @@ -5426,7 +5427,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) RegisterGameEvents(GEF_VIRT_TRAIN); if (rvi->railveh_type == RAILVEH_WAGON) { - return CmdBuildVirtualRailWagon(e); + return CmdBuildVirtualRailWagon(e, user); } Train *v = new Train(); @@ -5444,6 +5445,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) v->cargo_type = e->GetDefaultCargoType(); v->cargo_cap = rvi->capacity; v->last_station_visited = INVALID_STATION; + v->motion_counter = user; v->engine_type = e->index; v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback @@ -5492,7 +5494,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) * @param p1 various bitstuffed data * bits 0-15: vehicle type being built. * bits 24-31: refit cargo type. - * @param p2 unused + * @param p2 user * @param text unused * @return the cost of this operation or an error */ @@ -5512,7 +5514,7 @@ CommandCost CmdBuildVirtualRailVehicle(TileIndex tile, DoCommandFlag flags, uint if (should_execute) { StringID err = INVALID_STRING_ID; - Train* train = CmdBuildVirtualRailVehicle(eid, err); + Train* train = CmdBuildVirtualRailVehicle(eid, err, p2); if (train == nullptr) { return_cmd_error(err); diff --git a/src/vehicle.cpp b/src/vehicle.cpp index d479bb0c86..d87a3409b4 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1508,6 +1508,20 @@ void CallVehicleTicks() _vehicles_to_pay_repair.clear(); } +void RemoveVirtualTrainsOfUser(uint32 user) +{ + if (!_tick_caches_valid || HasChickenBit(DCBF_VEH_TICK_CACHE)) RebuildVehicleTickCaches(); + + Backup cur_company(_current_company, FILE_LINE); + for (const Train *front : _tick_train_front_cache) { + if (front->IsVirtual() && front->motion_counter == user) { + cur_company.Change(front->owner); + DoCommandP(0, front->index, 0, CMD_DELETE_VIRTUAL_TRAIN); + } + } + cur_company.Restore(); +} + /** * Add vehicle sprite for drawing to the screen. * @param v Vehicle to draw. diff --git a/src/vehicle_base.h b/src/vehicle_base.h index e1871d23b0..56a4bdbb2a 100644 --- a/src/vehicle_base.h +++ b/src/vehicle_base.h @@ -328,7 +328,7 @@ public: uint16 cur_speed; ///< current speed byte subspeed; ///< fractional speed byte acceleration; ///< used by train & aircraft - uint32 motion_counter; ///< counter to occasionally play a vehicle sound. + uint32 motion_counter; ///< counter to occasionally play a vehicle sound. (Also used as virtual train client ID). byte progress; ///< The percentage (if divided by 256) this vehicle already crossed the tile unit. byte random_bits; ///< Bits used for determining which randomized variational spritegroups to use when drawing. diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 7bf426ae0f..68bf04d3f9 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -993,7 +993,7 @@ CommandCost CmdVirtualTrainFromTemplateVehicle(TileIndex tile, DoCommandFlag fla if (should_execute) { StringID err = INVALID_STRING_ID; - Train* train = VirtualTrainFromTemplateVehicle(tv, err); + Train* train = VirtualTrainFromTemplateVehicle(tv, err, p2); if (train == nullptr) { return_cmd_error(err); @@ -1005,20 +1005,20 @@ CommandCost CmdVirtualTrainFromTemplateVehicle(TileIndex tile, DoCommandFlag fla CommandCost CmdDeleteVirtualTrain(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text); -Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err) +Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err, uint32 user) { CommandCost c; Train *tmp, *head, *tail; assert(tv->owner == _current_company); - head = CmdBuildVirtualRailVehicle(tv->engine_type, err); + head = CmdBuildVirtualRailVehicle(tv->engine_type, err, user); if (!head) return nullptr; tail = head; tv = tv->GetNextUnit(); while (tv) { - tmp = CmdBuildVirtualRailVehicle(tv->engine_type, err); + tmp = CmdBuildVirtualRailVehicle(tv->engine_type, err, user); if (!tmp) { CmdDeleteVirtualTrain(INVALID_TILE, DC_EXEC, head->index, 0, nullptr); return nullptr; @@ -1042,7 +1042,7 @@ Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err) * @param tile unused * @param flags type of operation * @param p1 the train index - * @param p2 unused + * @param p2 user * @param text unused * @return the cost of this operation or an error */ @@ -1064,13 +1064,13 @@ CommandCost CmdVirtualTrainFromTrain(TileIndex tile, DoCommandFlag flags, uint32 Train *tmp, *head, *tail; StringID err = INVALID_STRING_ID; - head = CmdBuildVirtualRailVehicle(train->engine_type, err); + head = CmdBuildVirtualRailVehicle(train->engine_type, err, p2); if (!head) return_cmd_error(err); tail = head; train = train->GetNextUnit(); while (train) { - tmp = CmdBuildVirtualRailVehicle(train->engine_type, err); + tmp = CmdBuildVirtualRailVehicle(train->engine_type, err, p2); if (!tmp) { CmdDeleteVirtualTrain(tile, flags, head->index, 0, nullptr); return_cmd_error(err);