Zappy GUI
C++ graphic client: renderer, camera, network
Loading...
Searching...
No Matches
GameState.cpp
Go to the documentation of this file.
1#include "GameState.hpp"
2
3#include <algorithm>
4#include <cmath>
5#include <iostream>
6#include <memory>
7
16
18{
19 std::visit(
20 [this](const auto& event) {
21 using T = std::decay_t<decltype(event)>;
22 if constexpr (std::is_same_v<T, MapSize>)
23 _applyMapSize(event);
24 else if constexpr (std::is_same_v<T, TileContent>)
25 _applyTileContent(event);
26 else if constexpr (std::is_same_v<T, TeamName>)
27 _applyTeamName(event);
28 else if constexpr (std::is_same_v<T, PlayerNew>)
29 _applyPlayerNew(event);
30 else if constexpr (std::is_same_v<T, PlayerPosition>)
32 else if constexpr (std::is_same_v<T, PlayerLevel>)
33 _applyPlayerLevel(event);
34 else if constexpr (std::is_same_v<T, PlayerInventory>)
36 else if constexpr (std::is_same_v<T, PlayerExpulsion>)
38 else if constexpr (std::is_same_v<T, PlayerBroadcast>)
40 else if constexpr (std::is_same_v<T, IncantationStart>)
42 else if constexpr (std::is_same_v<T, IncantationEnd>)
44 else if constexpr (std::is_same_v<T, PlayerFork>)
45 _applyPlayerFork(event);
46 else if constexpr (std::is_same_v<T, PlayerResourceDrop>)
48 else if constexpr (std::is_same_v<T, PlayerResourceTake>)
50 else if constexpr (std::is_same_v<T, PlayerDeath>)
51 _applyPlayerDeath(event);
52 else if constexpr (std::is_same_v<T, EggNew>)
53 _applyEggNew(event);
54 else if constexpr (std::is_same_v<T, EggHatch>)
55 _applyEggHatch(event);
56 else if constexpr (std::is_same_v<T, EggDeath>)
57 _applyEggDeath(event);
58 else if constexpr (std::is_same_v<T, TimeUnit>)
59 _applyTimeUnit(event);
60 else if constexpr (std::is_same_v<T, TimeUnitChange>)
62 else if constexpr (std::is_same_v<T, GameEnd>)
63 _applyGameEnd(event);
64 else if constexpr (std::is_same_v<T, ServerMessage>) {
65 // Likely temporary
66 std::cout << "[SERVER MESSAGE] " << event.message << std::endl;
67 } else if constexpr (std::is_same_v<T, ServerUptime>)
68 _applyServerUptime(event);
69 else if constexpr (std::is_same_v<T, ServerSpawnedEgg>)
71 else if constexpr (std::is_same_v<T, WinDuration>)
72 _applyWinDuration(event);
73 else {
74 // Is a UnknownCommand or BadParameters, we can ignore them for now
75 }
76 },
77 e);
78 dirty = true;
79}
80
82{
83 world.width = e.width;
85 world.tiles.resize(e.width * e.height);
86}
87
89
90void GameState::_applyTeamName(const TeamName& e) { world.teams.push_back(e.name); }
91
93{
94 auto [it, _] = world.players.emplace(e.id, Player{.id = e.id,
95 .x = e.x,
96 .y = e.y,
97 .orientation = e.orientation,
98 .level = e.level,
99 .team = e.team});
100 it->second.visual.pos =
102 it->second.visual.angle = toAngle(e.orientation);
103}
104
106{
107 auto it = world.players.find(e.id);
108 if (it != world.players.end()) {
109 Player& player = it->second;
110 int fromX = player.x;
111 int fromY = player.y;
112 player.x = e.x;
113 player.y = e.y;
114 player.orientation = e.orientation;
115
116 float duration = timeUnit > 0 ? 7.0f / timeUnit : 0.1f;
117 // remove only move/turn behaviors, preserve others (e.g. LevelUpBehavior)
118 auto& behaviors = player.visual.behaviors;
119 behaviors.erase(std::remove_if(behaviors.begin(), behaviors.end(),
120 [](const auto& b) {
121 return dynamic_cast<MoveBehavior*>(b.get()) ||
122 dynamic_cast<TurnBehavior*>(b.get());
123 }),
124 behaviors.end());
125 _pushBehavior(player.visual, std::make_unique<MoveBehavior>(
126 player.visual, fromX, fromY, e.x, e.y, world.width,
127 world.height, tileSize, duration));
128 _pushBehavior(player.visual,
129 std::make_unique<TurnBehavior>(player.visual, player.visual.angle,
130 toAngle(e.orientation), duration));
131 }
132}
133
135{
136 auto it = world.players.find(e.id);
137 if (it == world.players.end()) return;
138 it->second.level = e.level;
139 _pushBehavior(it->second.visual, std::make_unique<LevelUpBehavior>(
140 it->second.visual, static_cast<float>(timeUnit)));
141}
142
144{
145 auto it = world.players.find(e.id);
146 if (it != world.players.end()) {
147 it->second.inventory = e.inventory;
148 }
149}
150
152{
153 // Seemingly nothing tbd for now
154}
155
157{
158 auto it = world.players.find(e.id);
159 if (it == world.players.end()) return;
160 float mapRadius =
161 std::max(static_cast<float>(world.width), static_cast<float>(world.height)) / 2.0f;
162 _pushBehavior(it->second.visual,
163 std::make_unique<BroadcastBehavior>(
164 it->second.visual, static_cast<float>(timeUnit), mapRadius,
165 static_cast<float>(world.width), static_cast<float>(world.height)));
166}
167
169{
170 float offsetX = (world.width * tileSize) / 2.0f;
171 float offsetZ = (world.height * tileSize) / 2.0f;
172 float cx = e.x * tileSize - offsetX + tileSize / 2.0f;
173 float cz = e.y * tileSize - offsetZ + tileSize / 2.0f;
174
175 int total = static_cast<int>(e.playerIds.size());
176 for (int i = 0; i < total; i++) {
177 auto it = world.players.find(e.playerIds[i]);
178 if (it == world.players.end()) continue;
179 Player& p = it->second;
180 p.incanting = true;
181 p.incantationEnded = false;
182 p.incantationSuccess = false;
183 _pushBehavior(p.visual,
184 std::make_unique<IncantationBehavior>(p.visual, p, i, total, cx, cz, tileSize,
185 static_cast<float>(timeUnit)));
186 }
187}
188
190{
191 for (auto& [id, player] : world.players) {
192 if (player.x == e.x && player.y == e.y && player.incanting) {
193 player.incanting = false;
194 player.incantationEnded = true;
195 player.incantationSuccess = e.success;
196 }
197 }
198}
199
200void GameState::_applyPlayerFork([[maybe_unused]] const PlayerFork& e)
201{
202 // Seemingly nothing tbd for now
203}
204
206{
207 auto it = world.players.find(e.playerId);
208 if (it != world.players.end()) {
209 it->second.inventory[e.resourceId]--;
210 world.at(it->second.x, it->second.y)[e.resourceId]++;
211 }
212}
213
215{
216 auto it = world.players.find(e.playerId);
217 if (it != world.players.end()) {
218 world.at(it->second.x, it->second.y)[e.resourceId]--;
219 it->second.inventory[e.resourceId]++;
220 }
221}
222
224{
225 auto it = world.players.find(e.id);
226 if (it == world.players.end()) return;
227 Player dying = std::move(it->second);
228 world.players.erase(it);
229 dying.visual.behaviors.clear();
230 world.dyingPlayers[e.id] = std::move(dying);
231 Player& settled = world.dyingPlayers[e.id];
232 _pushBehavior(settled.visual,
233 std::make_unique<DeathBehavior>(settled.visual, static_cast<float>(timeUnit)));
234}
235
237{
238 auto it = world.players.find(e.playerId);
239 if (it == world.players.end()) {
240 return;
241 }
242 Egg egg{.id = e.eggId, .x = e.x, .y = e.y, .team = it->second.team};
244 world.eggs[e.eggId] = std::move(egg);
245 Egg& settled = world.eggs[e.eggId];
246 _pushBehavior(settled.visual,
247 std::make_unique<ForkBehavior>(settled.visual, static_cast<float>(timeUnit)));
248}
249
251{
252 world.eggs.erase(e.id);
253 // Spawning handled by PlayerNew event, so nothing else to do here
254}
255
256void GameState::_applyEggDeath(const EggDeath& e) { world.eggs.erase(e.id); }
257
259
261
263
269
271{
272 Egg egg{.id = e.eggId, .x = e.x, .y = e.y, .team = e.team};
274 world.eggs[e.eggId] = std::move(egg);
275 Egg& settled = world.eggs[e.eggId];
276 _pushBehavior(settled.visual,
277 std::make_unique<ForkBehavior>(settled.visual, static_cast<float>(timeUnit)));
278}
279
285
286void GameState::_pushBehavior(VisualState& visual, std::unique_ptr<IBehavior> b)
287{
288 if (b->getDuration() >= b->minDuration()) visual.behaviors.push_back(std::move(b));
289}
std::variant< MapSize, TileContent, TeamName, PlayerNew, PlayerPosition, PlayerLevel, PlayerInventory, PlayerExpulsion, PlayerBroadcast, IncantationStart, IncantationEnd, PlayerFork, PlayerResourceDrop, PlayerResourceTake, PlayerDeath, EggNew, EggHatch, EggDeath, TimeUnit, TimeUnitChange, GameEnd, ServerMessage, UnknownCommand, BadParameters, ServerUptime, ServerSpawnedEgg, WinDuration > Event
Represents an event received from the server. Is a variant of all possible events,...
Definition Event.hpp:188
float toAngle(Orientation orientation)
Returns the Y rotation angle (degrees) for a given orientation.
unsigned int serverUptimeSeconds
Definition GameState.hpp:23
WorldState world
Definition GameState.hpp:17
void _applyPlayerInventory(const PlayerInventory &e)
int64_t gameDurationTicks
Definition GameState.hpp:21
void _applyTimeUnitChange(const TimeUnitChange &e)
std::string winnerTeam
Definition GameState.hpp:19
void _applyIncantationStart(const IncantationStart &e)
static void _pushBehavior(VisualState &visual, std::unique_ptr< IBehavior > b)
void _applyServerUptime(const ServerUptime &e)
float tileSize
Definition GameState.hpp:22
void _applyTileContent(const TileContent &e)
Definition GameState.cpp:88
void _applyPlayerDeath(const PlayerDeath &e)
void _applyPlayerResourceDrop(const PlayerResourceDrop &e)
void _applyTeamName(const TeamName &e)
Definition GameState.cpp:90
void _applyPlayerBroadcast(const PlayerBroadcast &e)
void _applyPlayerExpulsion(const PlayerExpulsion &e)
void _applyMapSize(const MapSize &e)
Definition GameState.cpp:81
void _applyPlayerLevel(const PlayerLevel &e)
void _applyTimeUnit(const TimeUnit &e)
void _applyServerSpawnedEgg(const ServerSpawnedEgg &e)
void _applyEggNew(const EggNew &e)
void _applyEggDeath(const EggDeath &e)
void applyEvent(const Event &e)
Applies an event to the game state, modifying it accordingly and setting the dirty flag.
Definition GameState.cpp:17
void _applyPlayerResourceTake(const PlayerResourceTake &e)
void _applyEggHatch(const EggHatch &e)
bool receivedStuResponse
Definition GameState.hpp:24
void _applyIncantationEnd(const IncantationEnd &e)
void _applyPlayerNew(const PlayerNew &e)
Definition GameState.cpp:92
void _applyWinDuration(const WinDuration &e)
void _applyPlayerFork(const PlayerFork &e)
void _applyPlayerPosition(const PlayerPosition &e)
int gameDurationSeconds
Definition GameState.hpp:20
void _applyGameEnd(const GameEnd &e)
static Vector3 tileToWorld(int tileX, int tileY, int worldWidth, int worldHeight, float tileSize)
Converts tile coordinates to world coordinates (centered on tile).
Visual-only state for an entity, driven by behaviors each frame. Logical state (x,...
std::vector< std::unique_ptr< IBehavior > > behaviors
Resources & at(int x, int y)
Accesses the resources at a specific tile coordinate (x, y).
std::vector< std::string > teams
std::vector< Resources > tiles
std::unordered_map< int, Player > dyingPlayers
std::unordered_map< int, Egg > eggs
std::unordered_map< int, Player > players
int id
Definition Event.hpp:126
int id
Definition Event.hpp:121
int x
Definition Event.hpp:115
int playerId
Definition Event.hpp:114
int y
Definition Event.hpp:116
int eggId
Definition Event.hpp:113
int id
std::string winningTeam
Definition Event.hpp:141
std::vector< int > playerIds
Definition Event.hpp:79
int height
Definition Event.hpp:16
int width
Definition Event.hpp:15
Resources inventory
Definition Event.hpp:60
int level
Definition Event.hpp:52
int x
Definition Event.hpp:34
int y
Definition Event.hpp:35
int id
Definition Event.hpp:33
Orientation orientation
Definition Event.hpp:36
Orientation orientation
Definition Event.hpp:46
Orientation orientation
std::string team
Definition Event.hpp:174
int uptimeSeconds
Definition Event.hpp:166
std::string name
Definition Event.hpp:28
Resources resources
Definition Event.hpp:23
int timeUnit
Definition Event.hpp:131
int64_t ticks
Definition Event.hpp:149
int seconds
Definition Event.hpp:148