Network: Add state checksum which is check in network sync
This commit is contained in:
@@ -460,6 +460,7 @@ core/alloc_type.hpp
|
|||||||
core/backup_type.hpp
|
core/backup_type.hpp
|
||||||
core/bitmath_func.cpp
|
core/bitmath_func.cpp
|
||||||
core/bitmath_func.hpp
|
core/bitmath_func.hpp
|
||||||
|
core/checksum_func.hpp
|
||||||
core/container_func.hpp
|
core/container_func.hpp
|
||||||
core/dyn_arena_alloc.hpp
|
core/dyn_arena_alloc.hpp
|
||||||
core/endian_func.hpp
|
core/endian_func.hpp
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include "disaster_vehicle.h"
|
#include "disaster_vehicle.h"
|
||||||
#include "newgrf_airporttiles.h"
|
#include "newgrf_airporttiles.h"
|
||||||
#include "framerate_type.h"
|
#include "framerate_type.h"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@@ -2127,6 +2128,7 @@ static bool AircraftEventHandler(Aircraft *v, int loop)
|
|||||||
|
|
||||||
bool Aircraft::Tick()
|
bool Aircraft::Tick()
|
||||||
{
|
{
|
||||||
|
UpdateStateChecksum((((uint64) this->x_pos) << 32) | this->y_pos);
|
||||||
if (!this->IsNormalAircraft()) return true;
|
if (!this->IsNormalAircraft()) return true;
|
||||||
|
|
||||||
this->tick_counter++;
|
this->tick_counter++;
|
||||||
|
33
src/core/checksum_func.hpp
Normal file
33
src/core/checksum_func.hpp
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file checksum_func.hpp Checksum utility functions. */
|
||||||
|
|
||||||
|
#ifndef CHECKSUM_FUNC_HPP
|
||||||
|
#define CHECKSUM_FUNC_HPP
|
||||||
|
|
||||||
|
#include "bitmath_func.hpp"
|
||||||
|
|
||||||
|
struct SimpleChecksum64 {
|
||||||
|
uint64 state = 0;
|
||||||
|
|
||||||
|
void Update(uint64 input)
|
||||||
|
{
|
||||||
|
this->state = ROL(this->state, 1) ^ input ^ 0x123456789ABCDEF7ULL;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern SimpleChecksum64 _state_checksum;
|
||||||
|
|
||||||
|
inline void UpdateStateChecksum(uint64 input)
|
||||||
|
{
|
||||||
|
_state_checksum.Update(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* CHECKSUM_FUNC_HPP */
|
@@ -12,6 +12,8 @@
|
|||||||
#ifndef RANDOM_FUNC_HPP
|
#ifndef RANDOM_FUNC_HPP
|
||||||
#define RANDOM_FUNC_HPP
|
#define RANDOM_FUNC_HPP
|
||||||
|
|
||||||
|
#include "bitmath_func.hpp"
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
/* Apple already has Random declared */
|
/* Apple already has Random declared */
|
||||||
#define Random OTTD_Random
|
#define Random OTTD_Random
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
#include "company_base.h"
|
#include "company_base.h"
|
||||||
#include "core/random_func.hpp"
|
#include "core/random_func.hpp"
|
||||||
#include "core/backup_type.hpp"
|
#include "core/backup_type.hpp"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@@ -707,6 +708,7 @@ static DisasterVehicleTickProc * const _disastervehicle_tick_procs[] = {
|
|||||||
|
|
||||||
bool DisasterVehicle::Tick()
|
bool DisasterVehicle::Tick()
|
||||||
{
|
{
|
||||||
|
UpdateStateChecksum((((uint64) this->x_pos) << 32) | this->y_pos);
|
||||||
return _disastervehicle_tick_procs[this->subtype](this);
|
return _disastervehicle_tick_procs[this->subtype](this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
#include "animated_tile_func.h"
|
#include "animated_tile_func.h"
|
||||||
#include "effectvehicle_func.h"
|
#include "effectvehicle_func.h"
|
||||||
#include "effectvehicle_base.h"
|
#include "effectvehicle_base.h"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -670,6 +671,7 @@ EffectVehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, Eff
|
|||||||
|
|
||||||
bool EffectVehicle::Tick()
|
bool EffectVehicle::Tick()
|
||||||
{
|
{
|
||||||
|
UpdateStateChecksum((((uint64) this->x_pos) << 32) | this->y_pos);
|
||||||
return _effect_tick_procs[this->subtype](this);
|
return _effect_tick_procs[this->subtype](this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include "../core/pool_func.hpp"
|
#include "../core/pool_func.hpp"
|
||||||
#include "../gfx_func.h"
|
#include "../gfx_func.h"
|
||||||
#include "../error.h"
|
#include "../error.h"
|
||||||
|
#include "../core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "../safeguards.h"
|
#include "../safeguards.h"
|
||||||
|
|
||||||
@@ -74,6 +75,7 @@ uint32 _sync_seed_1; ///< Seed to compare during sync checks.
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
uint32 _sync_seed_2; ///< Second part of the seed.
|
uint32 _sync_seed_2; ///< Second part of the seed.
|
||||||
#endif
|
#endif
|
||||||
|
uint64 _sync_state_checksum; ///< State checksum to compare during sync checks.
|
||||||
uint32 _sync_frame; ///< The frame to perform the sync check.
|
uint32 _sync_frame; ///< The frame to perform the sync check.
|
||||||
bool _network_first_time; ///< Whether we have finished joining or not.
|
bool _network_first_time; ///< Whether we have finished joining or not.
|
||||||
bool _network_udp_server; ///< Is the UDP server started?
|
bool _network_udp_server; ///< Is the UDP server started?
|
||||||
@@ -1028,6 +1030,7 @@ void NetworkGameLoop()
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
_sync_seed_2 = _random.state[1];
|
_sync_seed_2 = _random.state[1];
|
||||||
#endif
|
#endif
|
||||||
|
_sync_state_checksum = _state_checksum.state;
|
||||||
|
|
||||||
NetworkServer_Tick(send_frame);
|
NetworkServer_Tick(send_frame);
|
||||||
} else {
|
} else {
|
||||||
|
@@ -32,6 +32,7 @@
|
|||||||
#include "../core/backup_type.hpp"
|
#include "../core/backup_type.hpp"
|
||||||
#include "../thread.h"
|
#include "../thread.h"
|
||||||
#include "../crashlog.h"
|
#include "../crashlog.h"
|
||||||
|
#include "../core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@@ -282,9 +283,9 @@ void ClientNetworkGameSocketHandler::ClientError(NetworkRecvStatus res)
|
|||||||
if (_sync_frame != 0) {
|
if (_sync_frame != 0) {
|
||||||
if (_sync_frame == _frame_counter) {
|
if (_sync_frame == _frame_counter) {
|
||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1]) {
|
if (_sync_seed_1 != _random.state[0] || _sync_seed_2 != _random.state[1] || _sync_state_checksum != _state_checksum.state) {
|
||||||
#else
|
#else
|
||||||
if (_sync_seed_1 != _random.state[0]) {
|
if (_sync_seed_1 != _random.state[0] || _sync_state_checksum != _state_checksum.state) {
|
||||||
#endif
|
#endif
|
||||||
NetworkError(STR_NETWORK_ERROR_DESYNC);
|
NetworkError(STR_NETWORK_ERROR_DESYNC);
|
||||||
DEBUG(desync, 1, "sync_err: date{%08x; %02x; %02x}", _date, _date_fract, _tick_skip_counter);
|
DEBUG(desync, 1, "sync_err: date{%08x; %02x; %02x}", _date, _date_fract, _tick_skip_counter);
|
||||||
@@ -945,6 +946,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FRAME(Packet *p
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
_sync_seed_2 = p->Recv_uint32();
|
_sync_seed_2 = p->Recv_uint32();
|
||||||
#endif
|
#endif
|
||||||
|
_sync_state_checksum = p->Recv_uint64();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
/* Receive the token. */
|
/* Receive the token. */
|
||||||
@@ -972,6 +974,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_SYNC(Packet *p)
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
_sync_seed_2 = p->Recv_uint32();
|
_sync_seed_2 = p->Recv_uint32();
|
||||||
#endif
|
#endif
|
||||||
|
_sync_state_checksum = p->Recv_uint64();
|
||||||
|
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
@@ -118,6 +118,7 @@ extern uint32 _sync_seed_1;
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
extern uint32 _sync_seed_2;
|
extern uint32 _sync_seed_2;
|
||||||
#endif
|
#endif
|
||||||
|
extern uint64 _sync_state_checksum;
|
||||||
extern uint32 _sync_frame;
|
extern uint32 _sync_frame;
|
||||||
extern bool _network_first_time;
|
extern bool _network_first_time;
|
||||||
/* Vars needed for the join-GUI */
|
/* Vars needed for the join-GUI */
|
||||||
|
@@ -689,6 +689,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendFrame()
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
p->Send_uint32(_sync_seed_2);
|
p->Send_uint32(_sync_seed_2);
|
||||||
#endif
|
#endif
|
||||||
|
p->Send_uint64(_sync_state_checksum);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If token equals 0, we need to make a new token and send that. */
|
/* If token equals 0, we need to make a new token and send that. */
|
||||||
@@ -711,6 +712,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendSync()
|
|||||||
#ifdef NETWORK_SEND_DOUBLE_SEED
|
#ifdef NETWORK_SEND_DOUBLE_SEED
|
||||||
p->Send_uint32(_sync_seed_2);
|
p->Send_uint32(_sync_seed_2);
|
||||||
#endif
|
#endif
|
||||||
|
p->Send_uint64(_sync_state_checksum);
|
||||||
this->SendPacket(p);
|
this->SendPacket(p);
|
||||||
return NETWORK_RECV_STATUS_OKAY;
|
return NETWORK_RECV_STATUS_OKAY;
|
||||||
}
|
}
|
||||||
|
@@ -77,6 +77,7 @@
|
|||||||
#include "string_func_extra.h"
|
#include "string_func_extra.h"
|
||||||
#include "industry.h"
|
#include "industry.h"
|
||||||
#include "cargopacket.h"
|
#include "cargopacket.h"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "linkgraph/linkgraphschedule.h"
|
#include "linkgraph/linkgraphschedule.h"
|
||||||
#include "tracerestrict.h"
|
#include "tracerestrict.h"
|
||||||
@@ -103,6 +104,8 @@ GameEventFlags _game_events_overall;
|
|||||||
|
|
||||||
time_t _game_load_time;
|
time_t _game_load_time;
|
||||||
|
|
||||||
|
SimpleChecksum64 _state_checksum;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Error handling for fatal user errors.
|
* Error handling for fatal user errors.
|
||||||
* @param s the string to print.
|
* @param s the string to print.
|
||||||
@@ -1749,6 +1752,11 @@ void StateGameLoop()
|
|||||||
CallWindowGameTickEvent();
|
CallWindowGameTickEvent();
|
||||||
NewsLoop();
|
NewsLoop();
|
||||||
cur_company.Restore();
|
cur_company.Restore();
|
||||||
|
|
||||||
|
Company *c;
|
||||||
|
FOR_ALL_COMPANIES(c) {
|
||||||
|
UpdateStateChecksum(c->money);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(IsLocalCompany());
|
assert(IsLocalCompany());
|
||||||
|
@@ -39,6 +39,7 @@
|
|||||||
#include "framerate_type.h"
|
#include "framerate_type.h"
|
||||||
#include "scope_info.h"
|
#include "scope_info.h"
|
||||||
#include "string_func.h"
|
#include "string_func.h"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@@ -1061,6 +1062,7 @@ static Trackdir RoadFindPathToDest(RoadVehicle *v, TileIndex tile, DiagDirection
|
|||||||
|
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
UpdateStateChecksum((((uint64) v->index) << 32) | (path_found << 16) | best_track);
|
||||||
v->HandlePathfindingResult(path_found);
|
v->HandlePathfindingResult(path_found);
|
||||||
|
|
||||||
found_best_track:;
|
found_best_track:;
|
||||||
@@ -1726,6 +1728,8 @@ Money RoadVehicle::GetRunningCost() const
|
|||||||
|
|
||||||
bool RoadVehicle::Tick()
|
bool RoadVehicle::Tick()
|
||||||
{
|
{
|
||||||
|
UpdateStateChecksum((((uint64) this->x_pos) << 32) | this->y_pos);
|
||||||
|
UpdateStateChecksum((((uint64) this->state) << 32) | this->frame);
|
||||||
if (this->IsFrontEngine()) {
|
if (this->IsFrontEngine()) {
|
||||||
if (!(this->IsRoadVehicleStopped())) this->running_ticks++;
|
if (!(this->IsRoadVehicleStopped())) this->running_ticks++;
|
||||||
return RoadVehController(this);
|
return RoadVehController(this);
|
||||||
|
@@ -108,6 +108,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
|
|||||||
{ XSLFI_GAME_EVENTS, XSCF_NULL, 1, 1, "game_events", nullptr, nullptr, nullptr },
|
{ XSLFI_GAME_EVENTS, XSCF_NULL, 1, 1, "game_events", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_ROAD_LAYOUT_CHANGE_CTR, XSCF_NULL, 1, 1, "road_layout_change_ctr", nullptr, nullptr, nullptr },
|
{ XSLFI_ROAD_LAYOUT_CHANGE_CTR, XSCF_NULL, 1, 1, "road_layout_change_ctr", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_TOWN_CARGO_MATRIX, XSCF_NULL, 1, 1, "town_cargo_matrix", nullptr, nullptr, nullptr },
|
{ XSLFI_TOWN_CARGO_MATRIX, XSCF_NULL, 1, 1, "town_cargo_matrix", nullptr, nullptr, nullptr },
|
||||||
|
{ XSLFI_STATE_CHECKSUM, XSCF_NULL, 1, 1, "state_checksum", nullptr, nullptr, nullptr },
|
||||||
{ XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" },
|
{ XSLFI_DEBUG, XSCF_IGNORABLE_ALL, 1, 1, "debug", nullptr, nullptr, "DBGL" },
|
||||||
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
{ XSLFI_NULL, XSCF_NULL, 0, 0, nullptr, nullptr, nullptr, nullptr },// This is the end marker
|
||||||
};
|
};
|
||||||
|
@@ -75,6 +75,7 @@ enum SlXvFeatureIndex {
|
|||||||
XSLFI_GAME_EVENTS, ///< Game event flags
|
XSLFI_GAME_EVENTS, ///< Game event flags
|
||||||
XSLFI_ROAD_LAYOUT_CHANGE_CTR, ///< Road layout change counter
|
XSLFI_ROAD_LAYOUT_CHANGE_CTR, ///< Road layout change counter
|
||||||
XSLFI_TOWN_CARGO_MATRIX, ///< Town cargo matrix savegame format changes
|
XSLFI_TOWN_CARGO_MATRIX, ///< Town cargo matrix savegame format changes
|
||||||
|
XSLFI_STATE_CHECKSUM, ///< State checksum
|
||||||
XSLFI_DEBUG, ///< Debugging info
|
XSLFI_DEBUG, ///< Debugging info
|
||||||
|
|
||||||
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
XSLFI_RIFF_HEADER_60_BIT, ///< Size field in RIFF chunk header is 60 bit
|
||||||
|
@@ -19,6 +19,7 @@
|
|||||||
#include "../core/random_func.hpp"
|
#include "../core/random_func.hpp"
|
||||||
#include "../fios.h"
|
#include "../fios.h"
|
||||||
#include "../road_type.h"
|
#include "../road_type.h"
|
||||||
|
#include "../core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "saveload.h"
|
#include "saveload.h"
|
||||||
|
|
||||||
@@ -86,6 +87,7 @@ static const SaveLoadGlobVarList _date_desc[] = {
|
|||||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_120),
|
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_120),
|
||||||
SLEG_VAR(_random.state[0], SLE_UINT32),
|
SLEG_VAR(_random.state[0], SLE_UINT32),
|
||||||
SLEG_VAR(_random.state[1], SLE_UINT32),
|
SLEG_VAR(_random.state[1], SLE_UINT32),
|
||||||
|
SLEG_CONDVAR_X(_state_checksum.state, SLE_UINT64, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_STATE_CHECKSUM)),
|
||||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_10),
|
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_10),
|
||||||
SLE_CONDNULL(4, SLV_10, SLV_120),
|
SLE_CONDNULL(4, SLV_10, SLV_120),
|
||||||
SLEG_VAR(_cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32),
|
SLEG_VAR(_cur_company_tick_index, SLE_FILE_U8 | SLE_VAR_U32),
|
||||||
@@ -114,6 +116,7 @@ static const SaveLoadGlobVarList _date_check_desc[] = {
|
|||||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_120),
|
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_120),
|
||||||
SLE_NULL(4), // _random.state[0]
|
SLE_NULL(4), // _random.state[0]
|
||||||
SLE_NULL(4), // _random.state[1]
|
SLE_NULL(4), // _random.state[1]
|
||||||
|
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_STATE_CHECKSUM)), // _state_checksum.state
|
||||||
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_10),
|
SLE_CONDNULL(1, SL_MIN_VERSION, SLV_10),
|
||||||
SLE_CONDNULL(4, SLV_10, SLV_120),
|
SLE_CONDNULL(4, SLV_10, SLV_120),
|
||||||
SLE_NULL(1), // _cur_company_tick_index
|
SLE_NULL(1), // _cur_company_tick_index
|
||||||
|
@@ -36,6 +36,7 @@
|
|||||||
#include "tunnelbridge_map.h"
|
#include "tunnelbridge_map.h"
|
||||||
#include "zoom_func.h"
|
#include "zoom_func.h"
|
||||||
#include "framerate_type.h"
|
#include "framerate_type.h"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
|
|
||||||
@@ -523,6 +524,7 @@ static Track ChooseShipTrack(Ship *v, TileIndex tile, DiagDirection enterdir, Tr
|
|||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
UpdateStateChecksum((((uint64) v->index) << 32) | (path_found << 16) | track);
|
||||||
|
|
||||||
v->HandlePathfindingResult(path_found);
|
v->HandlePathfindingResult(path_found);
|
||||||
return track;
|
return track;
|
||||||
@@ -948,6 +950,7 @@ reverse_direction:
|
|||||||
|
|
||||||
bool Ship::Tick()
|
bool Ship::Tick()
|
||||||
{
|
{
|
||||||
|
UpdateStateChecksum((((uint64) this->x_pos) << 32) | this->y_pos);
|
||||||
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
|
if (!(this->vehstatus & VS_STOPPED)) this->running_ticks++;
|
||||||
|
|
||||||
ShipController(this);
|
ShipController(this);
|
||||||
|
@@ -43,6 +43,7 @@
|
|||||||
#include "engine_func.h"
|
#include "engine_func.h"
|
||||||
#include "bridge_signal_map.h"
|
#include "bridge_signal_map.h"
|
||||||
#include "scope_info.h"
|
#include "scope_info.h"
|
||||||
|
#include "core/checksum_func.hpp"
|
||||||
|
|
||||||
#include "table/strings.h"
|
#include "table/strings.h"
|
||||||
#include "table/train_cmd.h"
|
#include "table/train_cmd.h"
|
||||||
@@ -3127,6 +3128,7 @@ static Track ChooseTrainTrack(Train *v, TileIndex tile, DiagDirection enterdir,
|
|||||||
TileIndex new_tile = res_dest.tile;
|
TileIndex new_tile = res_dest.tile;
|
||||||
|
|
||||||
Track next_track = DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
|
Track next_track = DoTrainPathfind(v, new_tile, dest_enterdir, tracks, path_found, do_track_reservation, &res_dest);
|
||||||
|
UpdateStateChecksum((((uint64) v->index) << 32) | (path_found << 16) | next_track);
|
||||||
if (new_tile == tile) best_track = next_track;
|
if (new_tile == tile) best_track = next_track;
|
||||||
v->HandlePathfindingResult(path_found);
|
v->HandlePathfindingResult(path_found);
|
||||||
}
|
}
|
||||||
@@ -4971,6 +4973,7 @@ Money Train::GetRunningCost() const
|
|||||||
*/
|
*/
|
||||||
bool Train::Tick()
|
bool Train::Tick()
|
||||||
{
|
{
|
||||||
|
UpdateStateChecksum((((uint64) this->x_pos) << 32) | (this->y_pos << 16) | this->track );
|
||||||
if (this->IsFrontEngine()) {
|
if (this->IsFrontEngine()) {
|
||||||
if (!(this->vehstatus & VS_STOPPED) || this->cur_speed > 0) this->running_ticks++;
|
if (!(this->vehstatus & VS_STOPPED) || this->cur_speed > 0) this->running_ticks++;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user