1 /*****************************************************************************
2  * Copyright (c) 2014-2020 OpenRCT2 developers
3  *
4  * For a complete list of all authors, please refer to contributors.md
5  * Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
6  *
7  * OpenRCT2 is licensed under the GNU General Public License version 3.
8  *****************************************************************************/
9 
10 #pragma once
11 
12 #include "common.h"
13 #include "core/DataSerialiser.h"
14 
15 #include <memory>
16 #include <set>
17 #include <string>
18 
19 struct GameStateSnapshot_t;
20 
21 struct GameStateSpriteChange_t
22 {
23     enum
24     {
25         REMOVED,
26         ADDED,
27         MODIFIED,
28         EQUAL
29     };
30 
31     struct Diff_t
32     {
33         size_t offset;
34         size_t length;
35         const char* structname;
36         const char* fieldname;
37         uint64_t valueA;
38         uint64_t valueB;
39     };
40 
41     uint8_t changeType;
42     EntityType entityType;
43     uint32_t spriteIndex;
44 
45     std::vector<Diff_t> diffs;
46 };
47 
48 struct GameStateCompareData_t
49 {
50     uint32_t tickLeft;
51     uint32_t tickRight;
52     uint32_t srand0Left;
53     uint32_t srand0Right;
54     std::vector<GameStateSpriteChange_t> spriteChanges;
55 };
56 
57 /*
58  * Interface to create and capture game states. It only allows one to have 32 active snapshots
59  * the oldest snapshot will be removed from the buffer. Never store the snapshot pointer
60  * as it may become invalid at any time when a snapshot is created, rather Link the snapshot
61  * to a specific tick which can be obtained by that later again assuming its still valid.
62  */
63 struct IGameStateSnapshots
64 {
65     virtual ~IGameStateSnapshots() = default;
66 
67     /*
68      * Removes all existing entries and starts over.
69      */
70     virtual void Reset() = 0;
71 
72     /*
73      * Creates a new empty snapshot, oldest snapshot will be removed.
74      */
75     virtual GameStateSnapshot_t& CreateSnapshot() = 0;
76 
77     /*
78      * Links the snapshot to a specific game tick.
79      */
80     virtual void LinkSnapshot(GameStateSnapshot_t& snapshot, uint32_t tick, uint32_t srand0) = 0;
81 
82     /*
83      * This will fill the snapshot with the current game state in a compact form.
84      */
85     virtual void Capture(GameStateSnapshot_t& snapshot) = 0;
86 
87     /*
88      * Returns the snapshot for a given tick in the history, nullptr if not found.
89      */
90     virtual const GameStateSnapshot_t* GetLinkedSnapshot(uint32_t tick) const = 0;
91 
92     /*
93      * Serialisation of GameStateSnapshot_t
94      */
95     virtual void SerialiseSnapshot(GameStateSnapshot_t& snapshot, DataSerialiser& serialiser) const = 0;
96 
97     /*
98      * Compares two states resulting GameStateCompareData_t with all mismatches stored.
99      */
100     virtual GameStateCompareData_t Compare(const GameStateSnapshot_t& base, const GameStateSnapshot_t& cmp) const = 0;
101 
102     /*
103      * Writes the GameStateCompareData_t into the specified file as readable text.
104      */
105     virtual bool LogCompareDataToFile(const std::string& fileName, const GameStateCompareData_t& cmpData) const = 0;
106 
107     /*
108      * Generates a string of readable text from GameStateCompareData_t
109      */
110     virtual std::string GetCompareDataText(const GameStateCompareData_t& cmpData) const = 0;
111 };
112 
113 [[nodiscard]] std::unique_ptr<IGameStateSnapshots> CreateGameStateSnapshots();
114