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(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

@ -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;

@ -117,7 +117,7 @@ void AfterLoadTemplateVehiclesUpdateImage()
if (tv->Prev() == nullptr) {
Backup<CompanyID> 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<CompanyID> 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()) {

@ -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);

@ -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);

@ -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);

@ -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<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.
* @param v Vehicle to draw.

@ -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.

@ -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);

Loading…
Cancel
Save