mirror of https://github.com/OpenTTD/OpenTTD.git
(svn r20547) -Change: the way order backups are performed. Now restoring an order doesn't require up to 765 commands.
This commit is contained in:
parent
04d6648c5e
commit
926594b599
|
@ -88,12 +88,12 @@ CommandProc CmdSendTrainToDepot;
|
|||
CommandProc CmdForceTrainProceed;
|
||||
CommandProc CmdReverseTrainDirection;
|
||||
|
||||
CommandProc CmdClearOrderBackup;
|
||||
CommandProc CmdModifyOrder;
|
||||
CommandProc CmdSkipToOrder;
|
||||
CommandProc CmdDeleteOrder;
|
||||
CommandProc CmdInsertOrder;
|
||||
CommandProc CmdChangeServiceInt;
|
||||
CommandProc CmdRestoreOrderIndex;
|
||||
|
||||
CommandProc CmdBuildIndustry;
|
||||
|
||||
|
@ -221,8 +221,8 @@ static const Command _command_proc_table[] = {
|
|||
DEF_CMD(CmdBuildBuoy, CMD_AUTO), // CMD_BUILD_BUOY
|
||||
DEF_CMD(CmdPlantTree, CMD_AUTO), // CMD_PLANT_TREE
|
||||
|
||||
DEF_CMD(CmdBuildVehicle, 0), // CMD_BUILD_VEHICLE
|
||||
DEF_CMD(CmdSellVehicle, 0), // CMD_SELL_VEHICLE
|
||||
DEF_CMD(CmdBuildVehicle, CMD_CLIENT_ID), // CMD_BUILD_VEHICLE
|
||||
DEF_CMD(CmdSellVehicle, CMD_CLIENT_ID), // CMD_SELL_VEHICLE
|
||||
DEF_CMD(CmdRefitVehicle, 0), // CMD_REFIT_VEHICLE
|
||||
|
||||
DEF_CMD(CmdMoveRailVehicle, 0), // CMD_MOVE_RAIL_VEHICLE
|
||||
|
@ -230,6 +230,7 @@ static const Command _command_proc_table[] = {
|
|||
DEF_CMD(CmdForceTrainProceed, 0), // CMD_FORCE_TRAIN_PROCEED
|
||||
DEF_CMD(CmdReverseTrainDirection, 0), // CMD_REVERSE_TRAIN_DIRECTION
|
||||
|
||||
DEF_CMD(CmdClearOrderBackup, CMD_CLIENT_ID), // CMD_CLEAR_ORDER_BACKUP
|
||||
DEF_CMD(CmdModifyOrder, 0), // CMD_MODIFY_ORDER
|
||||
DEF_CMD(CmdSkipToOrder, 0), // CMD_SKIP_TO_ORDER
|
||||
DEF_CMD(CmdDeleteOrder, 0), // CMD_DELETE_ORDER
|
||||
|
@ -288,7 +289,6 @@ static const Command _command_proc_table[] = {
|
|||
|
||||
DEF_CMD(CmdLevelLand, CMD_ALL_TILES | CMD_NO_TEST | CMD_AUTO), // CMD_LEVEL_LAND; test run might clear tiles multiple times, in execution that only happens once
|
||||
|
||||
DEF_CMD(CmdRestoreOrderIndex, 0), // CMD_RESTORE_ORDER_INDEX
|
||||
DEF_CMD(CmdBuildLock, CMD_AUTO), // CMD_BUILD_LOCK
|
||||
|
||||
DEF_CMD(CmdBuildSignalTrack, CMD_AUTO), // CMD_BUILD_SIGNAL_TRACK
|
||||
|
@ -502,7 +502,7 @@ bool DoCommandP(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallbac
|
|||
|
||||
#ifdef ENABLE_NETWORK
|
||||
/* Only set p2 when the command does not come from the network. */
|
||||
if (!(cmd & CMD_NETWORK_COMMAND) && GetCommandFlags(cmd) & CMD_CLIENT_ID) p2 = CLIENT_ID_SERVER;
|
||||
if (!(cmd & CMD_NETWORK_COMMAND) && GetCommandFlags(cmd) & CMD_CLIENT_ID && p2 == 0) p2 = CLIENT_ID_SERVER;
|
||||
#endif
|
||||
|
||||
CommandCost res = DoCommandPInternal(tile, p1, p2, cmd, callback, text, my_cmd, estimate_only);
|
||||
|
|
|
@ -186,6 +186,7 @@ enum Commands {
|
|||
CMD_FORCE_TRAIN_PROCEED, ///< proceed a train to pass a red signal
|
||||
CMD_REVERSE_TRAIN_DIRECTION, ///< turn a train around
|
||||
|
||||
CMD_CLEAR_ORDER_BACKUP, ///< clear the order backup of a given user/tile
|
||||
CMD_MODIFY_ORDER, ///< modify an order (like set full-load)
|
||||
CMD_SKIP_TO_ORDER, ///< skip an order to the next of specific one
|
||||
CMD_DELETE_ORDER, ///< delete an order
|
||||
|
@ -242,7 +243,6 @@ enum Commands {
|
|||
CMD_COMPANY_CTRL, ///< used in multiplayer to create a new companies etc.
|
||||
CMD_LEVEL_LAND, ///< level land
|
||||
|
||||
CMD_RESTORE_ORDER_INDEX, ///< restore vehicle order-index and service interval
|
||||
CMD_BUILD_LOCK, ///< build a lock
|
||||
|
||||
CMD_BUILD_SIGNAL_TRACK, ///< add signals along a track (by dragging)
|
||||
|
|
|
@ -27,12 +27,14 @@ Depot::~Depot()
|
|||
{
|
||||
if (CleaningPool()) return;
|
||||
|
||||
/* Clear the order backup. */
|
||||
OrderBackup::Reset(this->xy, false);
|
||||
|
||||
/* Clear the depot from all order-lists */
|
||||
RemoveOrderFromAllVehicles(OT_GOTO_DEPOT, this->index);
|
||||
|
||||
/* Delete the depot-window */
|
||||
DeleteWindowById(WC_VEHICLE_DEPOT, this->xy);
|
||||
OrderBackup::Reset(this->xy);
|
||||
|
||||
/* Delete the depot list */
|
||||
WindowNumber wno = (this->index << 16) | VLW_DEPOT_LIST | GetTileOwner(this->xy);
|
||||
|
|
|
@ -976,12 +976,7 @@ struct DepotWindow : Window {
|
|||
this->SetDirty();
|
||||
|
||||
int sell_cmd = (v->type == VEH_TRAIN && (widget == DEPOT_WIDGET_SELL_CHAIN || _ctrl_pressed)) ? 1 : 0;
|
||||
|
||||
bool is_engine = (v->type != VEH_TRAIN || Train::From(v)->IsFrontEngine());
|
||||
|
||||
if (is_engine) OrderBackup::Backup(v);
|
||||
|
||||
if (!DoCommandP(v->tile, v->index | sell_cmd << 16, 0, GetCmdSellVeh(v->type)) && is_engine) OrderBackup::Reset(this->window_number);
|
||||
DoCommandP(v->tile, v->index | sell_cmd << 16 | MAKE_ORDER_BACKUP_FLAG, 0, GetCmdSellVeh(v->type));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "../network.h"
|
||||
#include "../network_internal.h"
|
||||
#include "../../core/pool_func.hpp"
|
||||
#include "../../order_backup.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -37,6 +38,7 @@ NetworkClientSocket::NetworkClientSocket(ClientID client_id)
|
|||
NetworkClientSocket::~NetworkClientSocket()
|
||||
{
|
||||
if (_redirect_console_to_client == this->client_id) _redirect_console_to_client = INVALID_CLIENT_ID;
|
||||
if (_network_server) OrderBackup::ResetUser(this->client_id);
|
||||
this->client_id = INVALID_CLIENT_ID;
|
||||
this->status = STATUS_INACTIVE;
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
#include "stdafx.h"
|
||||
#include "command_func.h"
|
||||
#include "core/pool_func.hpp"
|
||||
#include "network/network.h"
|
||||
#include "network/network_func.h"
|
||||
#include "order_backup.h"
|
||||
#include "order_base.h"
|
||||
#include "vehicle_base.h"
|
||||
|
@ -23,11 +25,20 @@ INSTANTIATE_POOL_METHODS(OrderBackup)
|
|||
OrderBackup::~OrderBackup()
|
||||
{
|
||||
free(this->name);
|
||||
free(this->orders);
|
||||
|
||||
if (CleaningPool()) return;
|
||||
|
||||
Order *o = this->orders;
|
||||
while (o != NULL) {
|
||||
Order *next = o->next;
|
||||
delete o;
|
||||
o = next;
|
||||
}
|
||||
}
|
||||
|
||||
OrderBackup::OrderBackup(const Vehicle *v)
|
||||
OrderBackup::OrderBackup(const Vehicle *v, uint32 user)
|
||||
{
|
||||
this->user = user;
|
||||
this->tile = v->tile;
|
||||
this->orderindex = v->cur_order_index;
|
||||
this->group = v->group_id;
|
||||
|
@ -40,99 +51,128 @@ OrderBackup::OrderBackup(const Vehicle *v)
|
|||
this->clone = (v->FirstShared() == v) ? v->NextShared() : v->FirstShared();
|
||||
} else {
|
||||
/* Else copy the orders */
|
||||
Order **tail = &this->orders;
|
||||
|
||||
/* Count the number of orders */
|
||||
uint cnt = 0;
|
||||
const Order *order;
|
||||
FOR_VEHICLE_ORDERS(v, order) cnt++;
|
||||
|
||||
/* Allocate memory for the orders plus an end-of-orders marker */
|
||||
this->orders = MallocT<Order>(cnt + 1);
|
||||
|
||||
Order *dest = this->orders;
|
||||
|
||||
/* Copy the orders */
|
||||
FOR_VEHICLE_ORDERS(v, order) {
|
||||
memcpy(dest, order, sizeof(Order));
|
||||
dest++;
|
||||
Order *copy = new Order();
|
||||
copy->AssignOrder(*order);
|
||||
*tail = copy;
|
||||
tail = ©->next;
|
||||
}
|
||||
/* End the list with an empty order */
|
||||
dest->Free();
|
||||
}
|
||||
}
|
||||
|
||||
void OrderBackup::DoRestore(const Vehicle *v)
|
||||
void OrderBackup::DoRestore(Vehicle *v)
|
||||
{
|
||||
/* If we have a custom name, process that */
|
||||
if (this->name != NULL) DoCommandP(0, v->index, 0, CMD_RENAME_VEHICLE, NULL, this->name);
|
||||
v->name = this->name;
|
||||
this->name = NULL;
|
||||
|
||||
/* If we had shared orders, recover that */
|
||||
if (this->clone != NULL) {
|
||||
DoCommandP(0, v->index | (this->clone->index << 16), CO_SHARE, CMD_CLONE_ORDER);
|
||||
} else if (this->orders != NULL) {
|
||||
|
||||
/* CMD_NO_TEST_IF_IN_NETWORK is used here, because CMD_INSERT_ORDER checks if the
|
||||
* order number is one more than the current amount of orders, and because
|
||||
* in network the commands are queued before send, the second insert always
|
||||
* fails in test mode. By bypassing the test-mode, that no longer is a problem. */
|
||||
for (uint i = 0; !this->orders[i].IsType(OT_NOTHING); i++) {
|
||||
Order o = this->orders[i];
|
||||
/* Conditional orders need to have their destination to be valid on insertion. */
|
||||
if (o.IsType(OT_CONDITIONAL)) o.SetConditionSkipToOrder(0);
|
||||
|
||||
if (!DoCommandP(0, v->index + (i << 16), o.Pack(),
|
||||
CMD_INSERT_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* Copy timetable if enabled */
|
||||
if (_settings_game.order.timetabling && !DoCommandP(0, v->index | (i << 16) | (1 << 25),
|
||||
o.wait_time << 16 | o.travel_time,
|
||||
CMD_CHANGE_TIMETABLE | CMD_NO_TEST_IF_IN_NETWORK)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix the conditional orders' destination. */
|
||||
for (uint i = 0; !this->orders[i].IsType(OT_NOTHING); i++) {
|
||||
if (!this->orders[i].IsType(OT_CONDITIONAL)) continue;
|
||||
|
||||
if (!DoCommandP(0, v->index + (i << 16), MOF_LOAD | (this->orders[i].GetConditionSkipToOrder() << 4),
|
||||
CMD_MODIFY_ORDER | CMD_NO_TEST_IF_IN_NETWORK)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DoCommand(0, v->index | (this->clone->index << 16), CO_SHARE, DC_EXEC, CMD_CLONE_ORDER);
|
||||
} else if (this->orders != NULL && OrderList::CanAllocateItem()) {
|
||||
v->orders.list = new OrderList(this->orders, v);
|
||||
this->orders = NULL;
|
||||
}
|
||||
|
||||
/* Restore vehicle order-index and service interval */
|
||||
DoCommandP(0, v->index, this->orderindex | (this->service_interval << 16), CMD_RESTORE_ORDER_INDEX);
|
||||
uint num_orders = v->GetNumOrders();
|
||||
if (num_orders != 0) v->cur_order_index = this->orderindex % num_orders;
|
||||
v->service_interval = this->service_interval;
|
||||
|
||||
/* Restore vehicle group */
|
||||
DoCommandP(0, this->group, v->index, CMD_ADD_VEHICLE_GROUP);
|
||||
DoCommand(0, this->group, v->index, DC_EXEC, CMD_ADD_VEHICLE_GROUP);
|
||||
}
|
||||
|
||||
/* static */ void OrderBackup::Backup(const Vehicle *v)
|
||||
/* static */ void OrderBackup::Backup(const Vehicle *v, uint32 user)
|
||||
{
|
||||
OrderBackup::Reset();
|
||||
new OrderBackup(v);
|
||||
/* Don't use reset as that broadcasts over the network to reset the variable,
|
||||
* which is what we are doing at the moment. */
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
if (ob->user == user) delete ob;
|
||||
}
|
||||
new OrderBackup(v, user);
|
||||
}
|
||||
|
||||
/* static */ void OrderBackup::Restore(const Vehicle *v)
|
||||
/* static */ void OrderBackup::Restore(Vehicle *v, uint32 user)
|
||||
{
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
if (v->tile != ob->tile) continue;
|
||||
if (v->tile != ob->tile || ob->user != user) continue;
|
||||
|
||||
ob->DoRestore(v);
|
||||
delete ob;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void OrderBackup::Reset(TileIndex t)
|
||||
/* static */ void OrderBackup::ResetOfUser(TileIndex tile, uint32 user)
|
||||
{
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
if (t == INVALID_TILE || t == ob->tile) delete ob;
|
||||
if (ob->user == user && (ob->tile == tile || tile == INVALID_TILE)) delete ob;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear an OrderBackup
|
||||
* @param tile Tile related to the to-be-cleared OrderBackup.
|
||||
* @param flags For command.
|
||||
* @param p1 Unused.
|
||||
* @param p2 User that had the OrderBackup.
|
||||
* @param text Unused.
|
||||
* @return The cost of this operation or an error.
|
||||
*/
|
||||
CommandCost CmdClearOrderBackup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
/* No need to check anything. If the tile or user don't exist we just ignore it. */
|
||||
if (flags & DC_EXEC) OrderBackup::ResetOfUser(tile == 0 ? INVALID_TILE : tile, p2);
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
/* static */ void OrderBackup::ResetUser(uint32 user)
|
||||
{
|
||||
assert(_network_server);
|
||||
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
/* If it's not an backup of us, so ignore it. */
|
||||
if (ob->user != user) continue;
|
||||
|
||||
DoCommandP(0, 0, user, CMD_CLEAR_ORDER_BACKUP);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void OrderBackup::Reset(TileIndex t, bool from_gui)
|
||||
{
|
||||
/* The user has CLIENT_ID_SERVER as default when network play is not active,
|
||||
* but compiled it. A network client has its own variable for the unique
|
||||
* client/user identifier. Finally if networking isn't compiled in the
|
||||
* default is just plain and simple: 0. */
|
||||
#ifdef ENABLE_NETWORK
|
||||
uint32 user = _networking && !_network_server ? _network_own_client_id : CLIENT_ID_SERVER;
|
||||
#else
|
||||
uint32 user = 0;
|
||||
#endif
|
||||
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
/* If it's not an backup of us, so ignore it. */
|
||||
if (ob->user != user) continue;
|
||||
/* If it's not for our chosen tile either, ignore it. */
|
||||
if (t != INVALID_TILE && t != ob->tile) continue;
|
||||
|
||||
if (from_gui) {
|
||||
DoCommandP(ob->tile, 0, 0, CMD_CLEAR_ORDER_BACKUP);
|
||||
} else {
|
||||
/* The command came from the game logic, i.e. the clearing of a tile.
|
||||
* In that case we have no need to actually sync this, just do it. */
|
||||
delete ob;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,12 +28,18 @@ typedef Pool<OrderBackup, OrderBackupID, 1, 256> OrderBackupPool;
|
|||
/** The pool with order backups. */
|
||||
extern OrderBackupPool _order_backup_pool;
|
||||
|
||||
/** Flag to pass to the vehicle construction command when an order should be preserved. */
|
||||
static const uint32 MAKE_ORDER_BACKUP_FLAG = 1 << 31;
|
||||
|
||||
/**
|
||||
* Data for backing up an order of a vehicle so it can be
|
||||
* restored after a vehicle is rebuilt in the same depot.
|
||||
*/
|
||||
struct OrderBackup : OrderBackupPool::PoolItem<&_order_backup_pool> {
|
||||
private:
|
||||
friend const struct SaveLoad *GetOrderBackupDescription(); ///< Saving and loading of order backups.
|
||||
friend void Load_BKOR(); ///< Creating empty orders upon savegame loading.
|
||||
uint32 user; ///< The user that requested the backup.
|
||||
TileIndex tile; ///< Tile of the depot where the order was changed.
|
||||
GroupID group; ///< The group the vehicle was part of.
|
||||
uint16 service_interval; ///< The service interval of the vehicle.
|
||||
|
@ -43,17 +49,21 @@ private:
|
|||
VehicleOrderID orderindex; ///< The order-index the vehicle had.
|
||||
Order *orders; ///< The actual orders if the vehicle was not a clone.
|
||||
|
||||
/** Creation for savegame restoration. */
|
||||
OrderBackup() {}
|
||||
|
||||
/**
|
||||
* Create an order backup for the given vehicle.
|
||||
* @param v The vehicle to make a backup of.
|
||||
* @param v The vehicle to make a backup of.
|
||||
* @param user The user that is requesting the backup.
|
||||
*/
|
||||
OrderBackup(const Vehicle *v);
|
||||
OrderBackup(const Vehicle *v, uint32 user);
|
||||
|
||||
/**
|
||||
* Restore the data of this order to the given vehicle.
|
||||
* @param v The vehicle to restore to.
|
||||
*/
|
||||
void DoRestore(const Vehicle *v);
|
||||
void DoRestore(Vehicle *v);
|
||||
|
||||
public:
|
||||
/** Free everything that is allocated. */
|
||||
|
@ -61,23 +71,43 @@ public:
|
|||
|
||||
/**
|
||||
* Create an order backup for the given vehicle.
|
||||
* @param v The vehicle to make a backup of.
|
||||
* @param v The vehicle to make a backup of.
|
||||
* @param user The user that is requesting the backup.
|
||||
* @note Will automatically remove any previous backups of this user.
|
||||
*/
|
||||
static void Backup(const Vehicle *v);
|
||||
static void Backup(const Vehicle *v, uint32 user);
|
||||
|
||||
/**
|
||||
* Restore the data of this order to the given vehicle.
|
||||
* @param v The vehicle to restore to.
|
||||
* @param v The vehicle to restore to.
|
||||
* @param user The user that built the vehicle, thus wants to restore.
|
||||
* @note After restoration the backup will automatically be removed.
|
||||
*/
|
||||
static void Restore(const Vehicle *v);
|
||||
static void Restore(Vehicle *v, uint32 user);
|
||||
|
||||
/**
|
||||
* Reset the OrderBackups.
|
||||
* @param tile The tile of the order backup.
|
||||
* Reset an OrderBackup given a tile and user.
|
||||
* @param tile The tile associated with the OrderBackup.
|
||||
* @param user The user associated with the OrderBackup.
|
||||
* @note Must not be used from the GUI!
|
||||
*/
|
||||
static void Reset(TileIndex tile = INVALID_TILE);
|
||||
static void ResetOfUser(TileIndex tile, uint32 user);
|
||||
|
||||
/**
|
||||
* Reset an user's OrderBackup if needed.
|
||||
* @param user The user associated with the OrderBackup.
|
||||
* @pre _network_server.
|
||||
* @note Must not be used from a command.
|
||||
*/
|
||||
static void ResetUser(uint32 user);
|
||||
|
||||
/**
|
||||
* Reset the OrderBackups from GUI/game logic.
|
||||
* @param tile The tile of the order backup.
|
||||
* @param from_gui Whether the call came from the GUI, i.e. whether
|
||||
* it must be synced over the network.
|
||||
*/
|
||||
static void Reset(TileIndex tile = INVALID_TILE, bool from_gui = true);
|
||||
|
||||
/**
|
||||
* Clear the group of all backups having this group ID.
|
||||
|
|
|
@ -1328,45 +1328,6 @@ CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32
|
|||
return CommandCost();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the current order-index of a vehicle and sets service-interval.
|
||||
* @param tile unused
|
||||
* @param flags operation to perform
|
||||
* @param p1 the ID of the vehicle
|
||||
* @param p2 various bistuffed elements
|
||||
* - p2 = (bit 0-15) - current order-index (p2 & 0xFFFF)
|
||||
* - p2 = (bit 16-31) - service interval (p2 >> 16)
|
||||
* @param text unused
|
||||
* @return the cost of this operation or an error
|
||||
* @todo Unfortunately you cannot safely restore the unitnumber or the old vehicle
|
||||
* as far as I can see. We can store it in BackuppedOrders, and restore it, but
|
||||
* but we have no way of seeing it has been tampered with or not, as we have no
|
||||
* legit way of knowing what that ID was.@n
|
||||
* If we do want to backup/restore it, just add UnitID uid to BackuppedOrders, and
|
||||
* restore it as parameter 'y' (ugly hack I know) for example. "v->unitnumber = y;"
|
||||
*/
|
||||
CommandCost CmdRestoreOrderIndex(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text)
|
||||
{
|
||||
VehicleOrderID cur_ord = GB(p2, 0, 16);
|
||||
uint16 serv_int = GB(p2, 16, 16);
|
||||
|
||||
Vehicle *v = Vehicle::GetIfValid(p1);
|
||||
/* Check the vehicle type and ownership, and if the service interval and order are in range */
|
||||
if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR;
|
||||
|
||||
CommandCost ret = CheckOwnership(v->owner);
|
||||
if (ret.Failed()) return ret;
|
||||
|
||||
if (serv_int != GetServiceIntervalClamped(serv_int, v->owner) || cur_ord >= v->GetNumOrders()) return CMD_ERROR;
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
v->cur_order_index = cur_ord;
|
||||
v->service_interval = serv_int;
|
||||
}
|
||||
|
||||
return CommandCost();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
|
|
@ -11,7 +11,9 @@
|
|||
|
||||
#include "../stdafx.h"
|
||||
#include "../order_base.h"
|
||||
#include "../order_backup.h"
|
||||
#include "../settings_type.h"
|
||||
#include "../network/network.h"
|
||||
|
||||
#include "saveload.h"
|
||||
|
||||
|
@ -235,7 +237,65 @@ static void Ptrs_ORDL()
|
|||
}
|
||||
}
|
||||
|
||||
const SaveLoad *GetOrderBackupDescription()
|
||||
{
|
||||
static const SaveLoad _order_backup_desc[] = {
|
||||
SLE_VAR(OrderBackup, user, SLE_UINT32),
|
||||
SLE_VAR(OrderBackup, tile, SLE_UINT32),
|
||||
SLE_VAR(OrderBackup, group, SLE_UINT16),
|
||||
SLE_VAR(OrderBackup, service_interval, SLE_INT32),
|
||||
SLE_STR(OrderBackup, name, SLE_STR, 0),
|
||||
SLE_VAR(OrderBackup, clone, SLE_UINT16),
|
||||
SLE_VAR(OrderBackup, orderindex, SLE_UINT8),
|
||||
SLE_REF(OrderBackup, orders, REF_ORDER),
|
||||
SLE_END()
|
||||
};
|
||||
|
||||
return _order_backup_desc;
|
||||
}
|
||||
|
||||
static void Save_BKOR()
|
||||
{
|
||||
/* We only save this when we're a network server
|
||||
* as we want this information on our clients. For
|
||||
* normal games this information isn't needed. */
|
||||
if (!_networking || !_network_server) return;
|
||||
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
SlSetArrayIndex(ob->index);
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
}
|
||||
}
|
||||
|
||||
void Load_BKOR()
|
||||
{
|
||||
int index;
|
||||
|
||||
while ((index = SlIterateArray()) != -1) {
|
||||
/* set num_orders to 0 so it's a valid OrderList */
|
||||
OrderBackup *ob = new (index) OrderBackup();
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
}
|
||||
|
||||
/* If we are a network server, then we just loaded
|
||||
* a previously saved-by-server savegame. There are
|
||||
* no clients with a backup anymore, so clear it. */
|
||||
if (_networking && _network_server) {
|
||||
_order_backup_pool.CleanPool();
|
||||
}
|
||||
}
|
||||
|
||||
static void Ptrs_BKOR()
|
||||
{
|
||||
OrderBackup *ob;
|
||||
FOR_ALL_ORDER_BACKUPS(ob) {
|
||||
SlObject(ob, GetOrderBackupDescription());
|
||||
}
|
||||
}
|
||||
|
||||
extern const ChunkHandler _order_chunk_handlers[] = {
|
||||
{ 'BKOR', Save_BKOR, Load_BKOR, Ptrs_BKOR, NULL, CH_ARRAY},
|
||||
{ 'ORDR', Save_ORDR, Load_ORDR, Ptrs_ORDR, NULL, CH_ARRAY},
|
||||
{ 'ORDL', Save_ORDL, Load_ORDL, Ptrs_ORDL, NULL, CH_ARRAY | CH_LAST},
|
||||
};
|
||||
|
|
|
@ -2288,7 +2288,7 @@ static CommandCost RemoveAirport(TileIndex tile, DoCommandFlag flags)
|
|||
cost.AddCost(_price[PR_CLEAR_STATION_AIRPORT]);
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur);
|
||||
if (IsHangarTile(tile_cur)) OrderBackup::Reset(tile_cur, false);
|
||||
DeleteAnimatedTile(tile_cur);
|
||||
DoClearSquare(tile_cur);
|
||||
DeleteNewGRFInspectWindow(GSF_AIRPORTTILES, tile_cur);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "engine_base.h"
|
||||
#include "engine_func.h"
|
||||
#include "newgrf.h"
|
||||
#include "order_backup.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
#include "table/train_cmd.h"
|
||||
|
@ -1325,9 +1326,10 @@ CommandCost CmdMoveRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, u
|
|||
* - data = 0: only sell the single dragged wagon/engine (and any belonging rear-engines)
|
||||
* - data = 1: sell the vehicle and all vehicles following it in the chain
|
||||
* if the wagon is dragged, don't delete the possibly belonging rear-engine to some front
|
||||
* @param user the user for the order backup.
|
||||
* @return the cost of this operation or an error
|
||||
*/
|
||||
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data)
|
||||
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint32 user)
|
||||
{
|
||||
/* Check if we deleted a vehicle window */
|
||||
Window *w = NULL;
|
||||
|
@ -1381,6 +1383,8 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data)
|
|||
|
||||
/* If we deleted a window then open a new one for the 'new' train */
|
||||
if (IsLocalCompany() && w != NULL) ShowVehicleViewWindow(new_head);
|
||||
} else if (v->IsPrimaryVehicle() && data & (MAKE_ORDER_BACKUP_FLAG >> 16)) {
|
||||
OrderBackup::Backup(v, user);
|
||||
}
|
||||
|
||||
/* We need to update the information about the train. */
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "articulated_vehicles.h"
|
||||
#include "autoreplace_gui.h"
|
||||
#include "company_base.h"
|
||||
#include "order_backup.h"
|
||||
|
||||
#include "table/strings.h"
|
||||
|
||||
|
@ -144,12 +145,14 @@ CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint
|
|||
}
|
||||
|
||||
Company::Get(_current_company)->num_engines[eid]++;
|
||||
|
||||
if (v->IsPrimaryVehicle()) OrderBackup::Restore(v, p2);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *v, uint16 data);
|
||||
CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *v, uint16 data, uint32 user);
|
||||
|
||||
/**
|
||||
* Sell a vehicle.
|
||||
|
@ -157,7 +160,8 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *v, uint16 data);
|
|||
* @param flags for command.
|
||||
* @param p1 various bitstuffed data.
|
||||
* bits 0-15: vehicle ID being sold.
|
||||
* bits 16-31: vehicle type specific bits passed on to the vehicle build functions.
|
||||
* bits 16-30: vehicle type specific bits passed on to the vehicle build functions.
|
||||
* bit 31: make a backup of the vehicle's order (if an engine).
|
||||
* @param p2 unused.
|
||||
* @param text unused.
|
||||
* @return the cost of this operation or an error.
|
||||
|
@ -176,12 +180,23 @@ CommandCost CmdSellVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3
|
|||
|
||||
if (!front->IsStoppedInDepot()) return_cmd_error(STR_ERROR_TRAIN_MUST_BE_STOPPED_INSIDE_DEPOT + front->type);
|
||||
|
||||
/* Can we actually make the order backup, i.e. are there enough orders? */
|
||||
if (p1 & MAKE_ORDER_BACKUP_FLAG &&
|
||||
front->orders.list != NULL &&
|
||||
!front->orders.list->IsShared() &&
|
||||
!Order::CanAllocateItem(front->orders.list->GetNumOrders())) {
|
||||
/* Only happens in exceptional cases when there aren't enough orders anyhow.
|
||||
* Thus it should be safe to just drop the orders in that case. */
|
||||
p1 &= ~MAKE_ORDER_BACKUP_FLAG;
|
||||
}
|
||||
|
||||
if (v->type == VEH_TRAIN) {
|
||||
ret = CmdSellRailWagon(flags, v, GB(p1, 16, 16));
|
||||
ret = CmdSellRailWagon(flags, v, GB(p1, 16, 16), p2);
|
||||
} else {
|
||||
ret = CommandCost(EXPENSES_NEW_VEHICLES, -front->value);
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if (v->IsPrimaryVehicle() && p1 & MAKE_ORDER_BACKUP_FLAG) OrderBackup::Backup(v, p2);
|
||||
delete front;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include "engine_func.h"
|
||||
#include "newgrf.h"
|
||||
#include "station_base.h"
|
||||
#include "order_backup.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
|
@ -2373,6 +2372,5 @@ void CcBuildPrimaryVehicle(const CommandCost &result, TileIndex tile, uint32 p1,
|
|||
if (result.Failed()) return;
|
||||
|
||||
const Vehicle *v = Vehicle::Get(_new_vehicle_id);
|
||||
OrderBackup::Restore(v);
|
||||
ShowVehicleViewWindow(v);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue