Merge pull request #5979 from IntelOrca/refactor/gamestate

Create new GameState class
This commit is contained in:
Aaron van Geffen 2018-06-01 00:05:59 +02:00 committed by GitHub
commit df1e8af737
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 473 additions and 339 deletions

View File

@ -62,6 +62,10 @@
93F9DA3920B46FB800D1BE92 /* ObjectJsonHelpers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4CE9AAAB1FDA7B14004093C6 /* ObjectJsonHelpers.cpp */; };
93F9DA3A20B46FCA00D1BE92 /* SceneryObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C1A53EC205FD19F000F8EF5 /* SceneryObject.cpp */; };
93F9DA3B20B4701100D1BE92 /* StdInOutConsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4C3B423720591513000C5BB7 /* StdInOutConsole.cpp */; };
93DE9750209C3C1000FB1CC8 /* GameState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93DE974E209C3C0F00FB1CC8 /* GameState.cpp */; };
93DE9751209C3C1000FB1CC8 /* GameState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93DE974E209C3C0F00FB1CC8 /* GameState.cpp */; };
93DE9752209C3C1000FB1CC8 /* GameState.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 93DE974E209C3C0F00FB1CC8 /* GameState.cpp */; };
93DE9753209C3C1000FB1CC8 /* GameState.h in Headers */ = {isa = PBXBuildFile; fileRef = 93DE974F209C3C0F00FB1CC8 /* GameState.h */; };
C61ADB1F1FB6A0A70024F2EF /* TopToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */; };
C61ADB211FB7DC060024F2EF /* Scenery.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB201FB7DC060024F2EF /* Scenery.cpp */; };
C61ADB231FBBCB8B0024F2EF /* GameBottomToolbar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */; };
@ -1119,6 +1123,8 @@
93CBA4C220A7502E00867D56 /* Imaging.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Imaging.cpp; sourceTree = "<group>"; };
93CBA4C720A7504400867D56 /* ImageImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ImageImporter.cpp; sourceTree = "<group>"; };
93CBA4C820A7504500867D56 /* ImageImporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ImageImporter.h; sourceTree = "<group>"; };
93DE974E209C3C0F00FB1CC8 /* GameState.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameState.cpp; sourceTree = "<group>"; };
93DE974F209C3C0F00FB1CC8 /* GameState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GameState.h; sourceTree = "<group>"; };
C61ADB1E1FB6A0A60024F2EF /* TopToolbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TopToolbar.cpp; sourceTree = "<group>"; };
C61ADB201FB7DC060024F2EF /* Scenery.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Scenery.cpp; sourceTree = "<group>"; };
C61ADB221FBBCB8A0024F2EF /* GameBottomToolbar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GameBottomToolbar.cpp; sourceTree = "<group>"; };
@ -2313,6 +2319,8 @@
4CC4B8E21FE00C4100660D62 /* CmdlineSprite.cpp */,
4CC4B8E31FE00C4200660D62 /* CmdlineSprite.h */,
F76C836C1EC4E7CC00FA49E2 /* common.h */,
93DE974E209C3C0F00FB1CC8 /* GameState.cpp */,
93DE974F209C3C0F00FB1CC8 /* GameState.h */,
F76C83761EC4E7CC00FA49E2 /* Context.cpp */,
F76C83771EC4E7CC00FA49E2 /* Context.h */,
4C5DFF401FAC69D200CB093A /* Date.cpp */,
@ -3245,6 +3253,7 @@
C62D838B1FD36D6F008C04F1 /* EditorObjectSelectionSession.h in Headers */,
93CBA4C320A7502E00867D56 /* Imaging.h in Headers */,
9308DA05209908090079EE96 /* Surface.h in Headers */,
93DE9753209C3C1000FB1CC8 /* GameState.h in Headers */,
C6352B841F477022006CCEE3 /* DataSerialiser.h in Headers */,
C67B28162002D67A00109C93 /* Window.h in Headers */,
C6352B961F477032006CCEE3 /* RideSetStatus.hpp in Headers */,
@ -3600,6 +3609,7 @@
C666ED761F33DBB20061AA04 /* ShortcutKeyChange.cpp in Sources */,
C685E51C1F8907850090598F /* Map.cpp in Sources */,
F7CB864A1EEDA1330030C877 /* KeyboardShortcuts.cpp in Sources */,
93DE9750209C3C1000FB1CC8 /* GameState.cpp in Sources */,
C654DF381F69C0430040F43D /* StaffFirePrompt.cpp in Sources */,
C68313D51FDB4F4C006DB3D8 /* Graph.cpp in Sources */,
C685E51D1F8907850090598F /* Research.cpp in Sources */,
@ -3761,6 +3771,7 @@
C688790B20289B9B0084B384 /* WoodenWildMouse.cpp in Sources */,
F76C86031EC4E88300FA49E2 /* Sprite.cpp in Sources */,
C688792320289B9B0084B384 /* MotionSimulator.cpp in Sources */,
93DE9751209C3C1000FB1CC8 /* GameState.cpp in Sources */,
C68878EF20289B9B0084B384 /* CompactInvertedCoaster.cpp in Sources */,
C68878E320289B9B0084B384 /* Android.cpp in Sources */,
F76C86051EC4E88300FA49E2 /* Editor.cpp in Sources */,
@ -3966,6 +3977,7 @@
93CBA4CB20A7504500867D56 /* ImageImporter.cpp in Sources */,
9346F9DD208A191900C77D91 /* GuestPathfinding.cpp in Sources */,
9346F9DA208A191900C77D91 /* Guest.cpp in Sources */,
93DE9752209C3C1000FB1CC8 /* GameState.cpp in Sources */,
F7D7749E1EC6713200BE6EBC /* Cli.cpp in Sources */,
93CBA4C620A7502E00867D56 /* Imaging.cpp in Sources */,
9308DA03209908090079EE96 /* Surface.cpp in Sources */,

View File

@ -17,6 +17,7 @@
#include "actions/ParkSetLoanAction.hpp"
#include "Cheats.h"
#include "config/Config.h"
#include "GameState.h"
#include "localisation/Localisation.h"
#include "network/network.h"
#include "ride/Ride.h"
@ -269,10 +270,11 @@ static void cheat_clear_loan()
static void cheat_generate_guests(sint32 count)
{
auto park = GetContext()->GetPark();
auto& park = GetContext()->GetGameState()->GetPark();
for (sint32 i = 0; i < count; i++)
park->GenerateGuest();
{
park.GenerateGuest();
}
window_invalidate_by_class(WC_BOTTOM_TOOLBAR);
}

View File

@ -38,6 +38,7 @@
#include "drawing/IDrawingEngine.h"
#include "localisation/Localisation.h"
#include "FileClassifier.h"
#include "GameState.h"
#include "network/network.h"
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
@ -105,7 +106,7 @@ namespace OpenRCT2
// Game states
std::unique_ptr<TitleScreen> _titleScreen;
std::unique_ptr<Park> _park;
std::unique_ptr<GameState> _gameState;
sint32 _drawingEngineType = DRAWING_ENGINE_SOFTWARE;
std::unique_ptr<IDrawingEngine> _drawingEngine;
@ -166,9 +167,9 @@ namespace OpenRCT2
return _uiContext;
}
Park * GetPark() override
GameState * GetGameState() override
{
return _park.get();
return _gameState.get();
}
std::shared_ptr<IPlatformEnvironment> GetPlatformEnvironment() override
@ -448,10 +449,11 @@ namespace OpenRCT2
util_srand((uint32)time(nullptr));
input_reset_place_obj_modifier();
viewport_init_all();
game_init_all(150);
_titleScreen = std::make_unique<TitleScreen>();
_park = std::make_unique<Park>();
_gameState = std::make_unique<GameState>();
_gameState->InitAll(150);
_titleScreen = std::make_unique<TitleScreen>(*_gameState);
return true;
}
@ -975,7 +977,7 @@ namespace OpenRCT2
}
else
{
game_update();
_gameState->Update();
}
#ifdef __ENABLE_DISCORD__

View File

@ -70,8 +70,8 @@ enum
namespace OpenRCT2
{
class GameState;
interface IPlatformEnvironment;
class Park;
namespace Audio
{
@ -102,7 +102,7 @@ namespace OpenRCT2
virtual std::shared_ptr<Audio::IAudioContext> GetAudioContext() abstract;
virtual std::shared_ptr<Ui::IUiContext> GetUiContext() abstract;
virtual Park * GetPark() abstract;
virtual GameState * GetGameState() abstract;
virtual std::shared_ptr<IPlatformEnvironment> GetPlatformEnvironment() abstract;
virtual Localisation::LocalisationService& GetLocalisationService() abstract;
virtual std::shared_ptr<IObjectManager> GetObjectManager() abstract;

View File

@ -21,6 +21,7 @@
#include "EditorObjectSelectionSession.h"
#include "FileClassifier.h"
#include "Game.h"
#include "GameState.h"
#include "OpenRCT2.h"
#include "ParkImporter.h"
#include "audio/audio.h"
@ -62,7 +63,7 @@ namespace Editor
audio_stop_all_music_and_sounds();
object_manager_unload_all_objects();
object_list_load();
game_init_all(150);
OpenRCT2::GetContext()->GetGameState()->InitAll(150);
gScreenFlags = SCREEN_FLAGS_SCENARIO_EDITOR;
gS6Info.editor_step = EDITOR_STEP_OBJECT_SELECTION;
gParkFlags |= PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
@ -141,7 +142,7 @@ namespace Editor
object_manager_unload_all_objects();
object_list_load();
game_init_all(150);
OpenRCT2::GetContext()->GetGameState()->InitAll(150);
SetAllLandOwned();
gS6Info.editor_step = EDITOR_STEP_OBJECT_SELECTION;
viewport_init_all();
@ -162,7 +163,7 @@ namespace Editor
object_manager_unload_all_objects();
object_list_load();
game_init_all(150);
OpenRCT2::GetContext()->GetGameState()->InitAll(150);
SetAllLandOwned();
gS6Info.editor_step = EDITOR_STEP_OBJECT_SELECTION;
viewport_init_all();

View File

@ -331,211 +331,6 @@ void update_palette_effects()
}
}
}
void game_update()
{
gInUpdateCode = true;
uint32 numUpdates;
// 0x006E3AEC // screen_game_process_mouse_input();
screenshot_check();
game_handle_keyboard_input();
if (game_is_not_paused() && gPreviewingTitleSequenceInGame)
{
title_sequence_player_update((ITitleSequencePlayer *) title_get_sequence_player());
}
// Determine how many times we need to update the game
if (gGameSpeed > 1)
{
numUpdates = 1 << (gGameSpeed - 1);
}
else
{
numUpdates = gTicksSinceLastUpdate / GAME_UPDATE_TIME_MS;
numUpdates = Math::Clamp(1u, numUpdates, (uint32) GAME_MAX_UPDATES);
}
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED && network_get_authstatus() == NETWORK_AUTH_OK)
{
if (network_get_server_tick() - gCurrentTicks >= 10)
{
// Make sure client doesn't fall behind the server too much
numUpdates += 10;
}
}
if (game_is_paused())
{
numUpdates = 0;
// Update the animation list. Note this does not
// increment the map animation.
map_animation_invalidate_all();
// Special case because we set numUpdates to 0, otherwise in game_logic_update.
network_update();
network_process_game_commands();
}
// Update the game one or more times
for (uint32 i = 0; i < numUpdates; i++)
{
game_logic_update();
if (gGameSpeed > 1)
continue;
if (input_get_state() == INPUT_STATE_RESET ||
input_get_state() == INPUT_STATE_NORMAL
)
{
if (input_test_flag(INPUT_FLAG_VIEWPORT_SCROLLING))
{
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, false);
break;
}
}
else
{
break;
}
}
if (!gOpenRCT2Headless)
{
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, false);
// the flickering frequency is reduced by 4, compared to the original
// it was done due to inability to reproduce original frequency
// and decision that the original one looks too fast
if (gCurrentTicks % 4 == 0)
gWindowMapFlashingFlags ^= (1 << 15);
// Handle guest map flashing
gWindowMapFlashingFlags &= ~(1 << 1);
if (gWindowMapFlashingFlags & (1 << 0))
gWindowMapFlashingFlags |= (1 << 1);
gWindowMapFlashingFlags &= ~(1 << 0);
// Handle staff map flashing
gWindowMapFlashingFlags &= ~(1 << 3);
if (gWindowMapFlashingFlags & (1 << 2))
gWindowMapFlashingFlags |= (1 << 3);
gWindowMapFlashingFlags &= ~(1 << 2);
context_update_map_tooltip();
// Input
gUnk141F568 = gUnk13CA740;
context_handle_input();
}
// Always perform autosave check, even when paused
if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) &&
!(gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) &&
!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER)
)
{
scenario_autosave_check();
}
window_dispatch_update_all();
gGameCommandNestLevel = 0;
gInUpdateCode = false;
}
void game_logic_update()
{
gScreenAge++;
if (gScreenAge == 0)
gScreenAge--;
network_update();
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED && network_get_authstatus() == NETWORK_AUTH_OK)
{
// Can't be in sync with server, round trips won't work if we are at same level.
if (gCurrentTicks >= network_get_server_tick())
{
// Don't run past the server
return;
}
}
if (network_get_mode() == NETWORK_MODE_SERVER)
{
// Send current tick out.
network_send_tick();
}
else if (network_get_mode() == NETWORK_MODE_CLIENT)
{
// Check desync.
network_check_desynchronization();
}
sub_68B089();
scenario_update();
climate_update();
map_update_tiles();
// Temporarily remove provisional paths to prevent peep from interacting with them
map_remove_provisional_elements();
map_update_path_wide_flags();
peep_update_all();
map_restore_provisional_elements();
vehicle_update_all();
sprite_misc_update_all();
ride_update_all();
GetContext()->GetPark()->Update();
research_update();
ride_ratings_update_all();
ride_measurements_update();
news_item_update_current();
map_animation_invalidate_all();
vehicle_sounds_update();
peep_update_crowd_noise();
climate_update_sound();
editor_open_windows_for_current_step();
// Update windows
//window_dispatch_update_all();
if (gErrorType != ERROR_TYPE_NONE)
{
rct_string_id title_text = STR_UNABLE_TO_LOAD_FILE;
rct_string_id body_text = gErrorStringId;
if (gErrorType == ERROR_TYPE_GENERIC)
{
title_text = gErrorStringId;
body_text = 0xFFFF;
}
gErrorType = ERROR_TYPE_NONE;
context_show_error(title_text, body_text);
}
// Start autosave timer after update
if (gLastAutoSaveUpdate == AUTOSAVE_PAUSE)
{
gLastAutoSaveUpdate = platform_get_ticks();
}
// Separated out processing commands in network_update which could call scenario_rand where gInUpdateCode is false.
// All commands that are received are first queued and then executed where gInUpdateCode is set to true.
network_process_game_commands();
network_flush();
gCurrentTicks++;
gScenarioTicks++;
gSavedAge++;
}
/**
*
* rct2: 0x0069C62C
@ -1625,39 +1420,6 @@ void game_load_or_quit_no_save_prompt()
}
}
/**
* Initialises the map, park etc. basically all S6 data.
*/
void game_init_all(sint32 mapSize)
{
gInMapInitCode = true;
map_init(mapSize);
park_init();
finance_init();
reset_park_entry();
banner_init();
ride_init_all();
reset_sprite_list();
staff_reset_modes();
date_reset();
climate_reset(CLIMATE_COOL_AND_WET);
news_item_init_queue();
user_string_clear_all();
gInMapInitCode = false;
gNextGuestNumber = 1;
context_init();
scenery_set_default_placement_configuration();
auto intent = Intent(INTENT_ACTION_CLEAR_TILE_INSPECTOR_CLIPBOARD);
context_broadcast_intent(&intent);
load_palette();
}
GAME_COMMAND_POINTER * new_game_command_table[GAME_COMMAND_COUNT] = {
game_command_set_ride_appearance,
game_command_set_land_height,

View File

@ -161,8 +161,6 @@ void game_increase_game_speed();
void game_reduce_game_speed();
void game_create_windows();
void game_update();
void game_logic_update();
void reset_all_sprite_quadrant_placements();
void update_palette_effects();
@ -188,4 +186,3 @@ void game_convert_strings_to_rct2(rct_s6_data * s6);
void utf8_to_rct2_self(char * buffer, size_t length);
void rct2_to_utf8_self(char * buffer, size_t length);
void game_fix_save_vars();
void game_init_all(sint32 mapSize);

288
src/openrct2/GameState.cpp Normal file
View File

@ -0,0 +1,288 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 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, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#include "GameState.h"
#include "Context.h"
#include "core/Math.hpp"
#include "Editor.h"
#include "Input.h"
#include "interface/Screenshot.h"
#include "localisation/Date.h"
#include "localisation/Localisation.h"
#include "management/NewsItem.h"
#include "network/network.h"
#include "OpenRCT2.h"
#include "platform/Platform2.h"
#include "scenario/Scenario.h"
#include "title/TitleScreen.h"
#include "title/TitleSequencePlayer.h"
#include "windows/Intent.h"
#include "world/Climate.h"
#include "world/MapAnimation.h"
#include "world/Park.h"
#include "world/Scenery.h"
using namespace OpenRCT2;
GameState::GameState()
{
_park = std::make_unique<Park>();
}
/**
* Initialises the map, park etc. basically all S6 data.
*/
void GameState::InitAll(sint32 mapSize)
{
gInMapInitCode = true;
map_init(mapSize);
_park->Initialise();
finance_init();
reset_park_entry();
banner_init();
ride_init_all();
reset_sprite_list();
staff_reset_modes();
date_reset();
climate_reset(CLIMATE_COOL_AND_WET);
news_item_init_queue();
user_string_clear_all();
gInMapInitCode = false;
gNextGuestNumber = 1;
context_init();
scenery_set_default_placement_configuration();
auto intent = Intent(INTENT_ACTION_CLEAR_TILE_INSPECTOR_CLIPBOARD);
context_broadcast_intent(&intent);
load_palette();
}
void GameState::Update()
{
gInUpdateCode = true;
uint32 numUpdates;
// 0x006E3AEC // screen_game_process_mouse_input();
screenshot_check();
game_handle_keyboard_input();
if (game_is_not_paused() && gPreviewingTitleSequenceInGame)
{
title_sequence_player_update((ITitleSequencePlayer *) title_get_sequence_player());
}
// Determine how many times we need to update the game
if (gGameSpeed > 1)
{
numUpdates = 1 << (gGameSpeed - 1);
}
else
{
numUpdates = gTicksSinceLastUpdate / GAME_UPDATE_TIME_MS;
numUpdates = Math::Clamp<uint32>(1, numUpdates, GAME_MAX_UPDATES);
}
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED && network_get_authstatus() == NETWORK_AUTH_OK)
{
if (network_get_server_tick() - gCurrentTicks >= 10)
{
// Make sure client doesn't fall behind the server too much
numUpdates += 10;
}
}
if (game_is_paused())
{
numUpdates = 0;
// Update the animation list. Note this does not
// increment the map animation.
map_animation_invalidate_all();
// Special case because we set numUpdates to 0, otherwise in game_logic_update.
network_update();
network_process_game_commands();
}
// Update the game one or more times
for (uint32 i = 0; i < numUpdates; i++)
{
UpdateLogic();
if (gGameSpeed == 1)
{
if (input_get_state() == INPUT_STATE_RESET ||
input_get_state() == INPUT_STATE_NORMAL)
{
if (input_test_flag(INPUT_FLAG_VIEWPORT_SCROLLING))
{
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, false);
break;
}
}
else
{
break;
}
}
}
if (!gOpenRCT2Headless)
{
input_set_flag(INPUT_FLAG_VIEWPORT_SCROLLING, false);
// the flickering frequency is reduced by 4, compared to the original
// it was done due to inability to reproduce original frequency
// and decision that the original one looks too fast
if (gCurrentTicks % 4 == 0)
gWindowMapFlashingFlags ^= (1 << 15);
// Handle guest map flashing
gWindowMapFlashingFlags &= ~(1 << 1);
if (gWindowMapFlashingFlags & (1 << 0))
gWindowMapFlashingFlags |= (1 << 1);
gWindowMapFlashingFlags &= ~(1 << 0);
// Handle staff map flashing
gWindowMapFlashingFlags &= ~(1 << 3);
if (gWindowMapFlashingFlags & (1 << 2))
gWindowMapFlashingFlags |= (1 << 3);
gWindowMapFlashingFlags &= ~(1 << 2);
context_update_map_tooltip();
// Input
gUnk141F568 = gUnk13CA740;
context_handle_input();
}
// Always perform autosave check, even when paused
if (!(gScreenFlags & SCREEN_FLAGS_TITLE_DEMO) &&
!(gScreenFlags & SCREEN_FLAGS_TRACK_DESIGNER) &&
!(gScreenFlags & SCREEN_FLAGS_TRACK_MANAGER))
{
scenario_autosave_check();
}
window_dispatch_update_all();
gGameCommandNestLevel = 0;
gInUpdateCode = false;
}
void GameState::UpdateLogic()
{
gScreenAge++;
if (gScreenAge == 0)
gScreenAge--;
network_update();
if (network_get_mode() == NETWORK_MODE_CLIENT &&
network_get_status() == NETWORK_STATUS_CONNECTED &&
network_get_authstatus() == NETWORK_AUTH_OK)
{
// Can't be in sync with server, round trips won't work if we are at same level.
if (gCurrentTicks >= network_get_server_tick())
{
// Don't run past the server
return;
}
}
if (network_get_mode() == NETWORK_MODE_SERVER)
{
// Send current tick out.
network_send_tick();
}
else if (network_get_mode() == NETWORK_MODE_CLIENT)
{
// Check desync.
network_check_desynchronization();
}
sub_68B089();
date_update();
_date = Date(gDateMonthTicks, gDateMonthTicks);
scenario_update();
climate_update();
map_update_tiles();
// Temporarily remove provisional paths to prevent peep from interacting with them
map_remove_provisional_elements();
map_update_path_wide_flags();
peep_update_all();
map_restore_provisional_elements();
vehicle_update_all();
sprite_misc_update_all();
ride_update_all();
if (!(gScreenFlags & (SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)))
{
_park->Update(_date);
}
research_update();
ride_ratings_update_all();
ride_measurements_update();
news_item_update_current();
map_animation_invalidate_all();
vehicle_sounds_update();
peep_update_crowd_noise();
climate_update_sound();
editor_open_windows_for_current_step();
// Update windows
//window_dispatch_update_all();
if (gErrorType != ERROR_TYPE_NONE)
{
rct_string_id title_text = STR_UNABLE_TO_LOAD_FILE;
rct_string_id body_text = gErrorStringId;
if (gErrorType == ERROR_TYPE_GENERIC)
{
title_text = gErrorStringId;
body_text = 0xFFFF;
}
gErrorType = ERROR_TYPE_NONE;
context_show_error(title_text, body_text);
}
// Start autosave timer after update
if (gLastAutoSaveUpdate == AUTOSAVE_PAUSE)
{
gLastAutoSaveUpdate = Platform::GetTicks();
}
// Separated out processing commands in network_update which could call scenario_rand where gInUpdateCode is false.
// All commands that are received are first queued and then executed where gInUpdateCode is set to true.
network_process_game_commands();
network_flush();
gCurrentTicks++;
gScenarioTicks++;
gSavedAge++;
}

46
src/openrct2/GameState.h Normal file
View File

@ -0,0 +1,46 @@
#pragma region Copyright (c) 2014-2017 OpenRCT2 Developers
/*****************************************************************************
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
*
* OpenRCT2 is the work of many authors, a full list can be found in contributors.md
* For more information, visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 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, either version 3 of the License, or
* (at your option) any later version.
*
* A full copy of the GNU General Public License can be found in licence.txt
*****************************************************************************/
#pragma endregion
#pragma once
#include <memory>
#include "Date.h"
namespace OpenRCT2
{
class Park;
/**
* Class to update the state of the map and park.
*/
class GameState final
{
private:
std::unique_ptr<Park> _park;
Date _date;
public:
GameState();
GameState(const GameState&) = delete;
Date& GetDate() { return _date; }
Park& GetPark() { return *_park; }
void InitAll(sint32 mapSize);
void Update();
void UpdateLogic();
};
}

View File

@ -19,6 +19,7 @@
#include "../Cheats.h"
#include "../Context.h"
#include "../core/MemoryStream.h"
#include "../GameState.h"
#include "../interface/Window.h"
#include "../localisation/Localisation.h"
#include "../management/NewsItem.h"
@ -234,7 +235,7 @@ private:
user_string_free(ride->name);
ride->type = RIDE_TYPE_NULL;
gParkValue = GetContext()->GetPark()->CalculateParkValue();
gParkValue = GetContext()->GetGameState()->GetPark().CalculateParkValue();
auto res = std::make_unique<GameActionResult>();
res->ExpenditureType = RCT_EXPENDITURE_TYPE_RIDE_CONSTRUCTION;

View File

@ -27,6 +27,7 @@
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../core/Util.hpp"
#include "../GameState.h"
#include "../object/Object.h"
#include "../object/ObjectManager.h"
#include "../object/ObjectRepository.h"
@ -283,8 +284,8 @@ public:
{
// Use the ratio between the old and new park value to calcute the ratio to
// use for the park value history and the goal.
auto park = GetContext()->GetPark();
_parkValueConversionFactor = (park->CalculateParkValue() * 10) / _s4.park_value;
auto& park = GetContext()->GetGameState()->GetPark();
_parkValueConversionFactor = (park.CalculateParkValue() * 10) / _s4.park_value;
}
else
{
@ -340,8 +341,9 @@ private:
String::Set(gScenarioFileName, sizeof(gScenarioFileName), GetRCT1ScenarioName().c_str());
// Do map initialisation, same kind of stuff done when loading scenario editor
OpenRCT2::GetContext()->GetObjectManager()->UnloadAll();
game_init_all(mapSize);
auto context = OpenRCT2::GetContext();
context->GetObjectManager()->UnloadAll();
context->GetGameState()->InitAll(mapSize);
gS6Info.editor_step = EDITOR_STEP_OBJECT_SELECTION;
gParkFlags |= PARK_FLAGS_SHOW_REAL_GUEST_NAMES;
gS6Info.category = SCENARIO_CATEGORY_OTHER;

View File

@ -23,6 +23,7 @@
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../Game.h"
#include "../GameState.h"
#include "../interface/Viewport.h"
#include "../localisation/Date.h"
#include "../localisation/Localisation.h"
@ -771,7 +772,7 @@ public:
void Initialise()
{
game_init_all(_s6.map_size);
OpenRCT2::GetContext()->GetGameState()->InitAll(_s6.map_size);
}
/**

View File

@ -19,6 +19,7 @@
#include "../config/Config.h"
#include "../FileClassifier.h"
#include "../Game.h"
#include "../GameState.h"
#include "../interface/Viewport.h"
#include "../localisation/Date.h"
#include "../localisation/Localisation.h"
@ -110,10 +111,10 @@ void scenario_begin()
if (gScenarioObjectiveType != OBJECTIVE_NONE && !gLoadKeepWindowsOpen)
context_open_window_view(WV_PARK_OBJECTIVE);
auto park = GetContext()->GetPark();
gParkRating = park->CalculateParkRating();
gParkValue = park->CalculateParkValue();
gCompanyValue = park->CalculateCompanyValue();
auto& park = GetContext()->GetGameState()->GetPark();
gParkRating = park.CalculateParkRating();
gParkValue = park.CalculateParkValue();
gCompanyValue = park.CalculateCompanyValue();
gHistoricalProfit = gInitialCash - gBankLoan;
gCash = gInitialCash;
@ -172,7 +173,7 @@ void scenario_begin()
gTotalAdmissions = 0;
gTotalIncomeFromAdmissions = 0;
safe_strcpy(gScenarioCompletedBy, "?", sizeof(gScenarioCompletedBy));
park->ResetHistories();
park.ResetHistories();
finance_reset_history();
award_reset();
reset_all_ride_build_dates();
@ -397,7 +398,6 @@ void scenario_update()
{
if (gScreenFlags == SCREEN_FLAGS_PLAYING)
{
date_update();
if (date_is_day_start(gDateMonthTicks))
{
scenario_day_update();

View File

@ -17,6 +17,7 @@
#include "../config/Config.h"
#include "../Context.h"
#include "../core/Console.hpp"
#include "../GameState.h"
#include "../interface/Screenshot.h"
#include "../network/network.h"
#include "../OpenRCT2.h"
@ -35,10 +36,13 @@
#include "../interface/Window.h"
#include "../localisation/Localisation.h"
using namespace OpenRCT2;
// TODO Remove when no longer required.
static TitleScreen * _singleton = nullptr;
TitleScreen::TitleScreen()
TitleScreen::TitleScreen(GameState& gameState)
: _gameState(gameState)
{
_singleton = this;
}
@ -126,7 +130,7 @@ void TitleScreen::Load()
network_close();
audio_stop_all_music_and_sounds();
game_init_all(150);
GetContext()->GetGameState()->InitAll(150);
viewport_init_all();
context_open_window(WC_MAIN_WINDOW);
CreateWindows();
@ -170,7 +174,7 @@ void TitleScreen::Update()
}
for (sint32 i = 0; i < numUpdates; i++)
{
game_logic_update();
_gameState.UpdateLogic();
}
update_palette_effects();
// update_rain_animation();
@ -223,8 +227,8 @@ void TitleScreen::TitleInitialise()
{
if (_sequencePlayer == nullptr)
{
IScenarioRepository * scenarioRepository = GetScenarioRepository();
_sequencePlayer = CreateTitleSequencePlayer(scenarioRepository);
auto scenarioRepository = GetScenarioRepository();
_sequencePlayer = CreateTitleSequencePlayer(*scenarioRepository, _gameState);
}
size_t seqId = title_get_config_sequence();
if (seqId == SIZE_MAX)
@ -272,7 +276,7 @@ bool TitleScreen::TryLoadSequence(bool loadPreview)
_loadedTitleSequenceId = SIZE_MAX;
if (!loadPreview)
{
game_init_all(150);
GetContext()->GetGameState()->InitAll(150);
}
return false;
}

View File

@ -22,35 +22,42 @@
interface ITitleSequencePlayer;
class TitleScreen final
namespace OpenRCT2
{
public:
ITitleSequencePlayer * GetSequencePlayer();
size_t GetCurrentSequence();
bool PreviewSequence(size_t value);
void StopPreviewingSequence();
bool IsPreviewingSequence();
bool ShouldHideVersionInfo();
void SetHideVersionInfo(bool value);
class GameState;
TitleScreen();
~TitleScreen();
class TitleScreen final
{
public:
TitleScreen(GameState& gameState);
~TitleScreen();
void Load();
void Update();
void CreateWindows();
void ChangePresetSequence(size_t preset);
ITitleSequencePlayer * GetSequencePlayer();
size_t GetCurrentSequence();
bool PreviewSequence(size_t value);
void StopPreviewingSequence();
bool IsPreviewingSequence();
bool ShouldHideVersionInfo();
void SetHideVersionInfo(bool value);
private:
ITitleSequencePlayer * _sequencePlayer = nullptr;
size_t _loadedTitleSequenceId = SIZE_MAX;
size_t _currentSequence = SIZE_MAX;
bool _hideVersionInfo = false;
bool _previewingSequence = false;
void Load();
void Update();
void CreateWindows();
void ChangePresetSequence(size_t preset);
void TitleInitialise();
bool TryLoadSequence(bool loadPreview = false);
};
private:
GameState& _gameState;
ITitleSequencePlayer * _sequencePlayer = nullptr;
size_t _loadedTitleSequenceId = SIZE_MAX;
size_t _currentSequence = SIZE_MAX;
bool _hideVersionInfo = false;
bool _previewingSequence = false;
void TitleInitialise();
bool TryLoadSequence(bool loadPreview = false);
};
}
void title_load();
void title_create_windows();

View File

@ -24,6 +24,7 @@
#include "../core/String.hpp"
#include "../object/ObjectManager.h"
#include "../OpenRCT2.h"
#include "../GameState.h"
#include "../ParkImporter.h"
#include "../scenario/ScenarioRepository.h"
#include "../scenario/ScenarioSources.h"
@ -49,7 +50,8 @@ class TitleSequencePlayer final : public ITitleSequencePlayer
private:
static constexpr const char * SFMM_FILENAME = "Six Flags Magic Mountain.SC6";
IScenarioRepository * _scenarioRepository = nullptr;
IScenarioRepository& _scenarioRepository;
GameState& _gameState;
size_t _sequenceId = 0;
TitleSequence * _sequence = nullptr;
@ -61,11 +63,10 @@ private:
CoordsXY _viewCentreLocation = { 0 };
public:
explicit TitleSequencePlayer(IScenarioRepository * scenarioRepository)
explicit TitleSequencePlayer(IScenarioRepository& scenarioRepository, GameState& gameState)
: _scenarioRepository(scenarioRepository),
_gameState(gameState)
{
Guard::ArgumentNotNull(scenarioRepository);
_scenarioRepository = scenarioRepository;
}
~TitleSequencePlayer() override
@ -213,7 +214,7 @@ public:
{
if (Update())
{
game_logic_update();
_gameState.UpdateLogic();
}
else
{
@ -261,7 +262,7 @@ private:
break;
case TITLE_SCRIPT_LOADMM:
{
const scenario_index_entry * entry = _scenarioRepository->GetByFilename(SFMM_FILENAME);
const scenario_index_entry * entry = _scenarioRepository.GetByFilename(SFMM_FILENAME);
if (entry == nullptr)
{
Console::Error::WriteLine("%s not found.", SFMM_FILENAME);
@ -329,10 +330,10 @@ private:
}
const utf8 * path = nullptr;
size_t numScenarios = _scenarioRepository->GetCount();
size_t numScenarios = _scenarioRepository.GetCount();
for (size_t i = 0; i < numScenarios; i++)
{
const scenario_index_entry * scenario = _scenarioRepository->GetByIndex(i);
const scenario_index_entry * scenario = _scenarioRepository.GetByIndex(i);
if (scenario && scenario->source_index == sourceDesc.index)
{
path = scenario->path;
@ -588,9 +589,9 @@ private:
}
};
ITitleSequencePlayer * CreateTitleSequencePlayer(IScenarioRepository * scenarioRepository)
ITitleSequencePlayer * CreateTitleSequencePlayer(IScenarioRepository& scenarioRepository, GameState& gameState)
{
return new TitleSequencePlayer(scenarioRepository);
return new TitleSequencePlayer(scenarioRepository, gameState);
}
bool gPreviewingTitleSequenceInGame = false;

View File

@ -18,6 +18,11 @@
#include "../common.h"
namespace OpenRCT2
{
class GameState;
}
interface IScenarioRepository;
interface ITitleSequencePlayer
@ -33,7 +38,7 @@ interface ITitleSequencePlayer
virtual void Eject() abstract;
};
ITitleSequencePlayer * CreateTitleSequencePlayer(IScenarioRepository * scenarioRepository);
ITitleSequencePlayer * CreateTitleSequencePlayer(IScenarioRepository& scenarioRepository, OpenRCT2::GameState& gameState);
// When testing title sequences within a normal game
extern bool gPreviewingTitleSequenceInGame;

View File

@ -20,7 +20,9 @@
#include "../core/Math.hpp"
#include "../core/Memory.hpp"
#include "../core/Util.hpp"
#include "../Date.h"
#include "../Game.h"
#include "../GameState.h"
#include "../interface/Colour.h"
#include "../interface/Window.h"
#include "../localisation/Localisation.h"
@ -444,8 +446,8 @@ void game_command_buy_land_rights(
void set_forced_park_rating(sint32 rating)
{
_forcedParkRating = rating;
auto park = GetContext()->GetPark();
gParkRating = park->CalculateParkRating();
auto& park = GetContext()->GetGameState()->GetPark();
gParkRating = park.CalculateParkRating();
auto intent = Intent(INTENT_ACTION_UPDATE_PARK_RATING);
context_broadcast_intent(&intent);
}
@ -577,13 +579,9 @@ void Park::Initialise()
format_string(gS6Info.details, 256, STR_NO_DETAILS_YET, nullptr);
}
void Park::Update()
void Park::Update(const Date &date)
{
// TODO: move when GameState class is introduced.
if (gScreenFlags & (SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
return;
// Every 5 seconds approximately
// Every ~13 seconds
if (gCurrentTicks % 512 == 0)
{
gParkRating = CalculateParkRating();
@ -597,15 +595,17 @@ void Park::Update()
auto intent = Intent(INTENT_ACTION_UPDATE_PARK_RATING);
context_broadcast_intent(&intent);
}
// Every week
if (date_is_week_start(gDateMonthTicks))
// Every ~102 seconds
if (gCurrentTicks % 4096 == 0)
{
UpdateHistories();
gParkSize = CalculateParkSize();
window_invalidate_by_class(WC_PARK_INFORMATION);
}
// Every new week
if (date.IsWeekStart())
{
UpdateHistories();
}
GenerateGuests();
}
@ -1058,22 +1058,12 @@ void Park::UpdateHistories()
sint32 park_is_open()
{
return GetContext()->GetPark()->IsOpen();
}
void park_init()
{
auto park = GetContext()->GetPark();
if (park == nullptr)
{
return;
}
park->Initialise();
return GetContext()->GetGameState()->GetPark().IsOpen();
}
sint32 park_calculate_size()
{
auto tiles = GetContext()->GetPark()->CalculateParkSize();
auto tiles = GetContext()->GetGameState()->GetPark().CalculateParkSize();
if (tiles != gParkSize)
{
gParkSize = tiles;

View File

@ -55,9 +55,14 @@ struct rct_ride;
namespace OpenRCT2
{
class Date;
class Park final
{
public:
Park() = default;
Park(const Park&) = delete;
bool IsOpen() const;
uint16 GetParkRating() const;
@ -65,7 +70,7 @@ namespace OpenRCT2
money32 GetCompanyValue() const;
void Initialise();
void Update();
void Update(const Date &date);
sint32 CalculateParkSize() const;
sint32 CalculateParkRating() const;
@ -126,7 +131,6 @@ void set_forced_park_rating(sint32 rating);
sint32 get_forced_park_rating();
sint32 park_is_open();
void park_init();
sint32 park_calculate_size();
void reset_park_entry();

View File

@ -5,6 +5,7 @@
#include <openrct2/core/File.h>
#include <openrct2/core/Path.hpp>
#include <openrct2/core/String.hpp>
#include <openrct2/GameState.h>
#include <openrct2/OpenRCT2.h>
#include <openrct2/ParkImporter.h>
#include <openrct2/ride/Ride.h>
@ -15,6 +16,8 @@
using namespace OpenRCT2;
constexpr sint32 updatesToTest = 10;
TEST(MultiLaunchTest, all)
{
std::string path = TestData::GetParkPath("bpb.sv6");
@ -34,12 +37,18 @@ TEST(MultiLaunchTest, all)
// Check ride count to check load was successful
ASSERT_EQ(gRideCount, 134);
auto gs = context->GetGameState();
ASSERT_NE(gs, nullptr);
auto& date = gs->GetDate();
ASSERT_EQ(date.GetMonthTicks(), 0);
for (int j = 0; j < 10; j++)
for (int j = 0; j < updatesToTest; j++)
{
game_logic_update();
gs->UpdateLogic();
}
ASSERT_EQ(date.GetMonthTicks(), 7862 + updatesToTest);
// Check ride count again
ASSERT_EQ(gRideCount, 134);
}