TBTR: Delete orphaned virtual trains on client disconnection

pull/199/head
Jonathan G Rennison 4 years ago
parent 348178e9eb
commit cce6d731a1

@ -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(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(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(CmdVirtualTrainFromTemplateVehicle, CMD_CLIENT_ID | 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(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(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(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(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(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 DEF_CMD(CmdDeleteTemplateVehicle, CMD_ALL_TILES, CMDT_VEHICLE_MANAGEMENT ), // CMD_DELETE_TEMPLATE_VEHICLE

@ -230,6 +230,9 @@ ServerNetworkGameSocketHandler::~ServerNetworkGameSocketHandler()
if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID; if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
OrderBackup::ResetUser(this->client_id); OrderBackup::ResetUser(this->client_id);
extern void RemoveVirtualTrainsOfUser(uint32 user);
RemoveVirtualTrainsOfUser(this->client_id);
if (this->savegame != nullptr) { if (this->savegame != nullptr) {
this->savegame->Destroy(); this->savegame->Destroy();
this->savegame = nullptr; this->savegame = nullptr;

@ -117,7 +117,7 @@ void AfterLoadTemplateVehiclesUpdateImage()
if (tv->Prev() == nullptr) { if (tv->Prev() == nullptr) {
Backup<CompanyID> cur_company(_current_company, tv->owner, FILE_LINE); Backup<CompanyID> cur_company(_current_company, tv->owner, FILE_LINE);
StringID err; StringID err;
Train* t = VirtualTrainFromTemplateVehicle(tv, err); Train* t = VirtualTrainFromTemplateVehicle(tv, err, 0);
if (t != nullptr) { if (t != nullptr) {
int tv_len = 0; int tv_len = 0;
for (TemplateVehicle *u = tv; u != nullptr; u = u->Next()) { for (TemplateVehicle *u = tv; u != nullptr; u = u->Next()) {
@ -154,7 +154,7 @@ void AfterLoadTemplateVehiclesUpdateProperties()
if (tv->Prev() == nullptr) { if (tv->Prev() == nullptr) {
Backup<CompanyID> cur_company(_current_company, tv->owner, FILE_LINE); Backup<CompanyID> cur_company(_current_company, tv->owner, FILE_LINE);
StringID err; StringID err;
Train* t = VirtualTrainFromTemplateVehicle(tv, err); Train* t = VirtualTrainFromTemplateVehicle(tv, err, 0);
if (t != nullptr) { if (t != nullptr) {
uint32 full_cargo_weight = 0; uint32 full_cargo_weight = 0;
for (Train *u = t; u != nullptr; u = u->Next()) { for (Train *u = t; u != nullptr; u = u->Next()) {

@ -15,7 +15,7 @@
#include "tbtr_template_vehicle.h" #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); void BuildTemplateGuiList(GUITemplateList*, Scrollbar*, Owner, RailType);

@ -417,8 +417,7 @@ protected: // These functions should not be called outside acceleration code.
CommandCost CmdMoveRailVehicle(TileIndex, DoCommandFlag , uint32, uint32, const char *); CommandCost CmdMoveRailVehicle(TileIndex, DoCommandFlag , uint32, uint32, const char *);
CommandCost CmdMoveVirtualRailVehicle(TileIndex, DoCommandFlag, uint32, uint32, const char*); CommandCost CmdMoveVirtualRailVehicle(TileIndex, DoCommandFlag, uint32, uint32, const char*);
Train* CmdBuildVirtualRailWagon(const Engine*); Train* CmdBuildVirtualRailVehicle(EngineID, StringID &error, uint32 user);
Train* CmdBuildVirtualRailVehicle(EngineID, StringID &error);
int GetTileMarginInFrontOfTrain(const Train *v, int x_pos, int y_pos); int GetTileMarginInFrontOfTrain(const Train *v, int x_pos, int y_pos);

@ -5350,7 +5350,7 @@ int GetDisplayImageWidth(Train *t, Point *offset)
return t->gcache.cached_veh_length * reference_width / VEHICLE_LENGTH; 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; const RailVehicleInfo *rvi = &e->u.rail;
@ -5371,6 +5371,7 @@ Train* CmdBuildVirtualRailWagon(const Engine *e)
v->track = TRACK_BIT_DEPOT; v->track = TRACK_BIT_DEPOT;
SetBit(v->flags, VRF_CONSIST_SPEED_REDUCTION); SetBit(v->flags, VRF_CONSIST_SPEED_REDUCTION);
v->vehstatus = VS_HIDDEN | VS_DEFPAL; v->vehstatus = VS_HIDDEN | VS_DEFPAL;
v->motion_counter = user;
v->SetWagon(); v->SetWagon();
v->SetFreeWagon(); v->SetFreeWagon();
@ -5407,7 +5408,7 @@ Train* CmdBuildVirtualRailWagon(const Engine *e)
return v; return v;
} }
Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error) Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error, uint32 user)
{ {
const Engine *e = Engine::GetIfValid(eid); const Engine *e = Engine::GetIfValid(eid);
if (e == nullptr || e->type != VEH_TRAIN) { if (e == nullptr || e->type != VEH_TRAIN) {
@ -5426,7 +5427,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error)
RegisterGameEvents(GEF_VIRT_TRAIN); RegisterGameEvents(GEF_VIRT_TRAIN);
if (rvi->railveh_type == RAILVEH_WAGON) { if (rvi->railveh_type == RAILVEH_WAGON) {
return CmdBuildVirtualRailWagon(e); return CmdBuildVirtualRailWagon(e, user);
} }
Train *v = new Train(); Train *v = new Train();
@ -5444,6 +5445,7 @@ Train* CmdBuildVirtualRailVehicle(EngineID eid, StringID &error)
v->cargo_type = e->GetDefaultCargoType(); v->cargo_type = e->GetDefaultCargoType();
v->cargo_cap = rvi->capacity; v->cargo_cap = rvi->capacity;
v->last_station_visited = INVALID_STATION; v->last_station_visited = INVALID_STATION;
v->motion_counter = user;
v->engine_type = e->index; v->engine_type = e->index;
v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback 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 * @param p1 various bitstuffed data
* bits 0-15: vehicle type being built. * bits 0-15: vehicle type being built.
* bits 24-31: refit cargo type. * bits 24-31: refit cargo type.
* @param p2 unused * @param p2 user
* @param text unused * @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
@ -5512,7 +5514,7 @@ CommandCost CmdBuildVirtualRailVehicle(TileIndex tile, DoCommandFlag flags, uint
if (should_execute) { if (should_execute) {
StringID err = INVALID_STRING_ID; StringID err = INVALID_STRING_ID;
Train* train = CmdBuildVirtualRailVehicle(eid, err); Train* train = CmdBuildVirtualRailVehicle(eid, err, p2);
if (train == nullptr) { if (train == nullptr) {
return_cmd_error(err); return_cmd_error(err);

@ -1508,6 +1508,20 @@ void CallVehicleTicks()
_vehicles_to_pay_repair.clear(); _vehicles_to_pay_repair.clear();
} }
void RemoveVirtualTrainsOfUser(uint32 user)
{
if (!_tick_caches_valid || HasChickenBit(DCBF_VEH_TICK_CACHE)) RebuildVehicleTickCaches();
Backup<CompanyID> 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. * Add vehicle sprite for drawing to the screen.
* @param v Vehicle to draw. * @param v Vehicle to draw.

@ -328,7 +328,7 @@ public:
uint16 cur_speed; ///< current speed uint16 cur_speed; ///< current speed
byte subspeed; ///< fractional speed byte subspeed; ///< fractional speed
byte acceleration; ///< used by train & aircraft 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 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. byte random_bits; ///< Bits used for determining which randomized variational spritegroups to use when drawing.

@ -993,7 +993,7 @@ CommandCost CmdVirtualTrainFromTemplateVehicle(TileIndex tile, DoCommandFlag fla
if (should_execute) { if (should_execute) {
StringID err = INVALID_STRING_ID; StringID err = INVALID_STRING_ID;
Train* train = VirtualTrainFromTemplateVehicle(tv, err); Train* train = VirtualTrainFromTemplateVehicle(tv, err, p2);
if (train == nullptr) { if (train == nullptr) {
return_cmd_error(err); 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); 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; CommandCost c;
Train *tmp, *head, *tail; Train *tmp, *head, *tail;
assert(tv->owner == _current_company); assert(tv->owner == _current_company);
head = CmdBuildVirtualRailVehicle(tv->engine_type, err); head = CmdBuildVirtualRailVehicle(tv->engine_type, err, user);
if (!head) return nullptr; if (!head) return nullptr;
tail = head; tail = head;
tv = tv->GetNextUnit(); tv = tv->GetNextUnit();
while (tv) { while (tv) {
tmp = CmdBuildVirtualRailVehicle(tv->engine_type, err); tmp = CmdBuildVirtualRailVehicle(tv->engine_type, err, user);
if (!tmp) { if (!tmp) {
CmdDeleteVirtualTrain(INVALID_TILE, DC_EXEC, head->index, 0, nullptr); CmdDeleteVirtualTrain(INVALID_TILE, DC_EXEC, head->index, 0, nullptr);
return nullptr; return nullptr;
@ -1042,7 +1042,7 @@ Train* VirtualTrainFromTemplateVehicle(TemplateVehicle* tv, StringID &err)
* @param tile unused * @param tile unused
* @param flags type of operation * @param flags type of operation
* @param p1 the train index * @param p1 the train index
* @param p2 unused * @param p2 user
* @param text unused * @param text unused
* @return the cost of this operation or an error * @return the cost of this operation or an error
*/ */
@ -1064,13 +1064,13 @@ CommandCost CmdVirtualTrainFromTrain(TileIndex tile, DoCommandFlag flags, uint32
Train *tmp, *head, *tail; Train *tmp, *head, *tail;
StringID err = INVALID_STRING_ID; StringID err = INVALID_STRING_ID;
head = CmdBuildVirtualRailVehicle(train->engine_type, err); head = CmdBuildVirtualRailVehicle(train->engine_type, err, p2);
if (!head) return_cmd_error(err); if (!head) return_cmd_error(err);
tail = head; tail = head;
train = train->GetNextUnit(); train = train->GetNextUnit();
while (train) { while (train) {
tmp = CmdBuildVirtualRailVehicle(train->engine_type, err); tmp = CmdBuildVirtualRailVehicle(train->engine_type, err, p2);
if (!tmp) { if (!tmp) {
CmdDeleteVirtualTrain(tile, flags, head->index, 0, nullptr); CmdDeleteVirtualTrain(tile, flags, head->index, 0, nullptr);
return_cmd_error(err); return_cmd_error(err);

Loading…
Cancel
Save