Skip to content

Commit

Permalink
(svn r20547) -Change: the way order backups are performed. Now restor…
Browse files Browse the repository at this point in the history
…ing an order doesn't require up to 765 commands.
  • Loading branch information
rubidium42 committed Aug 18, 2010
1 parent 04d6648 commit 926594b
Show file tree
Hide file tree
Showing 13 changed files with 237 additions and 130 deletions.
10 changes: 5 additions & 5 deletions src/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -221,15 +221,16 @@ 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
DEF_CMD(CmdSendTrainToDepot, 0), // CMD_SEND_TRAIN_TO_DEPOT
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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/command_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 3 additions & 1 deletion src/depot.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
7 changes: 1 addition & 6 deletions src/depot_gui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 2 additions & 0 deletions src/network/core/tcp_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "../network.h"
#include "../network_internal.h"
#include "../../core/pool_func.hpp"
#include "../../order_backup.h"

#include "table/strings.h"

Expand All @@ -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;
}
Expand Down
162 changes: 101 additions & 61 deletions src/order_backup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;
Expand All @@ -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 = &copy->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 (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 (t == INVALID_TILE || t == ob->tile) delete 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;
}
}
}

Expand Down

0 comments on commit 926594b

Please sign in to comment.