vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
net_client.h
1#pragma once
2
3#include <cstddef>
4#include <cstdint>
5#include <memory>
6#include <string>
7#include <vector>
8
9#include <glm/glm.hpp>
10
11#include "ecs/component/core/transform.h"
12#include "ecs/component/physics/rigidbody.h"
13#include "ecs/entity.h"
14#include "net/prediction/command.h"
15#include "net/prediction/interpolation.h"
16#include "net/prediction/pacing.h"
17#include "net/transport/connection.h"
18#include "net/wire/bit_stream.h"
19#include "net/wire/protocol.h"
20
21namespace Vkm::Engine {
22
23class Scene;
24class ResourceManager;
25struct NetCore;
26struct NetSpawn;
27
34constexpr uint32_t NET_SPAWN_BUILDS_PER_FRAME = 8;
35
42class NetClient {
43 public:
44 explicit NetClient(NetCore& core);
45 ~NetClient();
46
47 NetClient(const NetClient& other) = delete;
48 NetClient& operator=(const NetClient& other) = delete;
49
50 NetClient(NetClient && other) = delete;
51 NetClient& operator=(NetClient && other) = delete;
52
53 public:
55 void open(const NetAddress& server);
56
58 void close();
59
60 void advance(float seconds);
61
70 bool receive(Scene& scene, ResourceManager& resources);
71
73 void send();
74
76 bool simulates(EntityId entity) const;
77
79 void lease(const std::vector<EntityId>& entities);
80
82 void ageLeases();
83
85 void beginTick(const InputCommand& command);
86
88 void endTick(const Scene& scene, uint32_t tick);
89
90 void beginReplayTick() { m_prediction.replaying = true; }
91
93 void endReplay(const Scene& scene);
94
95 void interpolate(Scene& scene, float deltaTime);
96
98 void applyDrawCorrection(Scene& scene, float deltaTime);
99
102
105
106 std::string describe() const;
107
108 public:
109 PlayerId localPlayer() const { return m_localPlayer; }
110 EntityId localEntity() const { return m_localEntity; }
111
113 bool isPlaying() const { return m_localPlayer != NO_PLAYER; }
114
115 float roundTrip() const { return m_connection ? m_connection->roundTrip() : 0.0f; }
116
117 size_t leaseCount() const { return m_prediction.leases.size(); }
118
119 const std::vector<InputCommand>& replayCommands() const { return m_prediction.replay; }
120
121 bool replaying() const { return m_prediction.replaying; }
122
123 float predictionError() const { return m_prediction.error; }
124
125 float renderDelay() const { return m_interpolation.behindTicks(); }
126
127 float pacing() const { return m_prediction.pacing.scale(); }
128
129 private:
133 struct Predicted {
134 uint32_t tick = 0;
135 glm::vec3 position{0.0f};
136 };
137
142 struct Lease {
143 EntityId entity;
144 uint32_t ticks = 0;
145 };
146
153 struct DrawCorrection {
154 EntityId entity;
155 glm::vec3 offset;
156 };
157
165 struct Held {
166 EntityId entity;
167 Transform transform;
168 Rigidbody body;
169 bool hasBody = false;
170 };
171
177 struct Prediction {
178 std::vector<Predicted> predicted;
179 float error = 0.0f;
180 std::vector<InputCommand> unacknowledged;
181 std::vector<InputCommand> replay;
182 bool replaying = false;
183
184 uint32_t heard = 0;
185 uint32_t sent = 0;
186
188 NetPacing pacing;
189
194 std::vector<Lease> leases;
195 std::vector<EntityId> acquired;
196 std::vector<EntityId> released;
197
199 std::vector<Held> held;
200 std::vector<DrawCorrection> corrections;
201
202 bool warnedNoReplay = false;
203
204 void clear() { *this = Prediction{}; }
205 };
206
211 struct DrawnFrom {
212 EntityId entity;
213 glm::vec3 drawn{0.0f};
214 };
215
216 private:
217 bool onWelcome(Scene& scene, BitReader& reader);
218 bool onRefuse(BitReader& reader);
219 bool onGoodbye();
220 void onSnapshot(Scene& scene, BitReader& reader);
221
232 void holdPredicted(Scene& scene, std::vector<DrawnFrom>& takenFrom);
233
244 void buildSpawned(Scene& scene, ResourceManager& resources);
245
257 void buildInto(Scene& scene, ResourceManager& resources, EntityId root, const NetSpawn& spawn);
258
268 void reconcile(Scene& scene, uint32_t confirmedTick);
269
279 void restoreHeld(Scene& scene);
280 void correctDraw(EntityId entity, const glm::vec3& drawn, const glm::vec3& simulated);
281 void offsetDrawn(Scene& scene, EntityId entity, const glm::vec3& by);
282 glm::vec3 drawOffsetFor(EntityId entity) const;
283
290 bool adoptServerTick(uint32_t serverTick);
291
292 private:
293 NetCore& m_core;
294
295 std::unique_ptr<NetConnection> m_connection;
296
297 PlayerId m_localPlayer = NO_PLAYER;
298 EntityId m_localEntity;
299 uint64_t m_token = 0;
300
301 bool m_warnedTickJump = false;
302
304 Prediction m_prediction;
305
306 NetInterpolation m_interpolation;
307 std::vector<uint32_t> m_touched;
308};
309
310} // namespace Vkm::Engine
bool isPlaying() const
From the Welcome until the session ends.
Definition net_client.h:113
void ageLeases()
Count every lease down a tick, outside a replay, and hand back the lapsed.
void close()
Tell the server goodbye and forget everything this session held.
void endReplay(const Scene &scene)
Finish the replay and measure what the picture owes for it.
void endTick(const Scene &scene, uint32_t tick)
Record where this end's own entity ended tick.
void removeDrawCorrection(Scene &scene)
Take back what applyDrawCorrection applied.
void beginTick(const InputCommand &command)
Keep command until the server says it ran it.
bool simulates(EntityId entity) const
Whether this end decides entity: its own, or one it leases.
void forgetWorld()
Drop everything naming an entity; see NetSession::forgetWorld.
bool receive(Scene &scene, ResourceManager &resources)
Take what has arrived, one datagram at a time, then build what was spawned.
void open(const NetAddress &server)
Start talking to server. Nothing is sent until the first tick has run.
void send()
Send a Hello until welcomed, then the commands the server has not heard.
void applyDrawCorrection(Scene &scene, float deltaTime)
Work a little of every outstanding correction off, and apply the rest.
void lease(const std::vector< EntityId > &entities)
See NetSession::lease.
Open type-erased resource registry with typed handles and generational lifetimes.
Definition resource_manager.h:46
Central registry managing entities and an open set of component types.
Definition scene.h:29
Names one entity of one Scene, for as long as that slot holds it.
Definition entity.h:23
Everything one simulation tick was told to do, as a value.
Definition input_command.h:25
Where a datagram came from, or is going to: an IPv4 host and a port.
Definition net_address.h:13
What a session's server and client halves share: the socket, what the two ends agreed,...
Definition net_session.h:53
What a server built at this root after the scene loaded, so every client can build the same.
Definition net_spawn.h:19