1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-26 16:24:35 +01:00

Fix #9994: Game action tick collision during server connect and map load

This commit is contained in:
Matt
2019-10-05 13:09:21 +02:00
parent e4a2b1f9c5
commit 0c11bbd4e7
3 changed files with 36 additions and 0 deletions

View File

@@ -76,6 +76,7 @@ namespace GameActions
static GameActionFactory _actions[GAME_COMMAND_COUNT];
static std::multiset<QueuedGameAction> _actionQueue;
static uint32_t _nextUniqueId = 0;
static bool _suspended = false;
GameActionFactory Register(uint32_t id, GameActionFactory factory)
{
@@ -95,6 +96,16 @@ namespace GameActions
return false;
}
void SuspendQueue()
{
_suspended = true;
}
void ResumeQueue()
{
_suspended = false;
}
void Enqueue(const GameAction* ga, uint32_t tick)
{
auto action = Clone(ga);
@@ -114,6 +125,12 @@ namespace GameActions
void ProcessQueue()
{
if (_suspended)
{
// Do nothing if suspended, this is usually the case between connect and map loads.
return;
}
const uint32_t currentTick = gCurrentTicks;
while (_actionQueue.begin() != _actionQueue.end())

View File

@@ -255,6 +255,14 @@ namespace GameActions
void Register();
bool IsValidId(uint32_t id);
// Halts the queue processing until ResumeQueue is called, any calls to ProcessQueue
// will have no effect during suspension. It has no effect of actions that will not
// cross the network.
void SuspendQueue();
// Resumes queue processing.
void ResumeQueue();
void Enqueue(const GameAction* ga, uint32_t tick);
void Enqueue(GameAction::Ptr&& ga, uint32_t tick);
void ProcessQueue();

View File

@@ -417,6 +417,7 @@ void Network::Close()
client_connection_list.clear();
GameActions::ClearQueue();
GameActions::ResumeQueue();
player_list.clear();
group_list.clear();
_serverTickData.clear();
@@ -493,6 +494,11 @@ bool Network::BeginClient(const std::string& host, uint16_t port)
BeginChatLog();
BeginServerLog();
// We need to wait for the map load before we execute any actions.
// If the client has the title screen running then theres a potential
// risk of tick collision with the server map and title screen map.
GameActions::SuspendQueue();
utf8 keyPath[MAX_PATH];
network_get_private_key_path(keyPath, sizeof(keyPath), gConfigNetwork.player_name);
if (!platform_file_exists(keyPath))
@@ -2615,6 +2621,8 @@ void Network::Client_Handle_MAP([[maybe_unused]] NetworkConnection& connection,
// Start of a new map load, clear the queue now as we have to buffer them
// until the map is fully loaded.
GameActions::ClearQueue();
GameActions::SuspendQueue();
_serverTickData.clear();
_clientMapLoaded = false;
}
@@ -2637,6 +2645,9 @@ void Network::Client_Handle_MAP([[maybe_unused]] NetworkConnection& connection,
std::memcpy(&chunk_buffer[offset], (void*)packet.Read(chunksize), chunksize);
if (offset + chunksize == size)
{
// Allow queue processing of game actions again.
GameActions::ResumeQueue();
context_force_close_window_by_class(WC_NETWORK_STATUS);
bool has_to_free = false;
uint8_t* data = &chunk_buffer[0];