1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
|
//-----------------------------------------------------------------------------
// Name: online.h
// Developer: Wolfire Games LLC
// Description:
// License: Read below
//-----------------------------------------------------------------------------
//
// Copyright 2022 Wolfire Games LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//-----------------------------------------------------------------------------
#pragma once
#include <Online/online_datastructures.h>
#include <Online/online_session.h>
#include <Online/online_peer.h>
#include <Online/online_file_transfer_handler.h>
#include <Online/online_message_handler.h>
#include <Online/state_machine.h>
#include <Online/Message/audio_play_sound_group_relative_gain_message.h>
#include <Online/Message/audio_play_sound_group_gain_message.h>
#include <Online/Message/audio_play_sound_loop_message.h>
#include <Online/Message/audio_play_sound_loop_at_location_message.h>
#include <Online/Message/whoosh_sound_message.h>
#include <Online/Message/audio_play_group_priority_message.h>
#include <Online/Message/audio_play_sound_message.h>
#include <Online/Message/audio_play_sound_location_message.h>
#include <Online/Message/audio_play_sound_group_relative_message.h>
#include <Online/Message/audio_play_sound_group_message.h>
#include <Online/Message/audio_play_sound_group_voice_message.h>
#include <Online/Message/audio_play_sound_impact_item_message.h>
#include <Online/Message/pcs_build_version_request_message.h>
#include <Online/Message/pcs_build_version_message.h>
#include <Online/Message/pcs_loading_completed_message.h>
#include <Online/Message/pcs_client_parameters_message.h>
#include <Online/Message/pcs_session_parameters_message.h>
#include <Online/Message/pcs_assign_player_id.h>
#include <Online/Message/pcs_file_transfer_metadata_message.h>
#include <Online/Message/set_player_state.h>
#include <Online/Message/remove_player_state.h>
#include <Online/Message/sp_string_message.h>
#include <Online/Message/sp_union_message.h>
#include <Online/Message/sp_remove_message.h>
#include <Online/Message/sp_rename_message.h>
#include <Online/Message/chat_entry_message.h>
#include <Online/Message/set_object_enabled_message.h>
#include <Online/Message/player_input_message.h>
#include <Online/Message/attach_to_message.h>
#include <Online/Message/camera_transform_message.h>
#include <Online/Message/test_message.h>
#include <Online/Message/movement_object_update.h>
#include <Online/Message/morph_target_update.h>
#include <Online/Message/item_update.h>
#include <Online/Message/env_object_update.h>
#include <Online/Message/cut_line.h>
#include <Online/Message/angelscript_data.h>
#include <Online/Message/angelscript_object_data.h>
#include <Online/Message/material_sound_event.h>
#include <Online/Message/host_session_flag.h>
#include <Online/Message/timed_slow_motion.h>
#include <Online/Message/create_entity.h>
#include <Online/Message/remove_object.h>
#include <Online/Message/set_avatar_palette.h>
#include <Online/Message/send_level_message.h>
#include <Online/Message/editor_transform_change.h>
#include <Online/Message/ping.h>
#include <Online/Message/pong.h>
#include <Math/vec3.h>
#include <Math/mat4.h>
#include <Game/connection_closed_reason.h>
#include <Game/levelinfo.h>
#include <UserInput/input.h>
#include <Math/quaternions.h>
#include <Utility/block_allocator.h>
#include <Internal/filesystem.h>
#include <Network/net_framework.h>
#include <cstdint>
#include <list>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <queue>
#include <array>
#include <list>
#include <thread>
#include <mutex>
class MovementObject;
class SceneGraph;
class EnvObject;
class Object;
class ItemObject;
class Engine;
struct PlayerInput;
struct ZSTD_CCtx_s;
typedef struct ZSTD_CCtx_s ZSTD_CCtx;
struct ZSTD_DCtx_s;
typedef struct ZSTD_DCtx_s ZSTD_DCtx;
using std::array;
using std::unordered_map;
using std::string;
using std::list;
using std::vector;
using std::thread;
using std::mutex;
using std::unordered_set;
using std::numeric_limits;
using std::lock_guard;
using std::pair;
using std::endl;
using std::to_string;
using std::stringstream;
using std::runtime_error;
using std::map;
using namespace OnlineMessages;
typedef OnlineMessageHandlerTemplate<
TestMessage,
AudioPlayGroupPriorityMessage,
AudioPlaySoundLoopMessage,
AudioPlaySoundGroupGainMessage,
AudioPlaySoundLocationMessage,
AudioPlaySoundMessage,
AudioPlaySoundLoopAtLocationMessage,
AudioPlaySoundGroupRelativeMessage,
AudioPlaySoundGroupMessage,
AudioPlaySoundGroupVoiceMessage,
AudioPlaySoundImpactItemMessage,
AudioPlaySoundGroupRelativeGainMessage,
WhooshSoundMessage,
ChatEntryMessage,
SetObjectEnabledMessage,
PlayerInputMessage,
AttachToMessage,
CameraTransformMessage,
MovementObjectUpdate,
PCSBuildVersionRequestMessage,
PCSBuildVersionMessage,
PCSLoadingCompletedMessage,
PCSSessionParametersMessage,
PCSClientParametersMessage,
PCSAssignPlayerID,
PCSFileTransferMetadataMessage,
SetPlayerState,
RemovePlayerState,
SPStringMessage,
SPUnionMessage,
SPRemoveMessage,
SPRenameMessage,
MorphTargetUpdate,
ItemUpdate,
EnvObjectUpdate,
CutLine,
AngelscriptData,
AngelscriptObjectData,
MaterialSoundEvent,
HostSessionFlag,
TimedSlowMotion,
CreateEntity,
RemoveObject,
SetAvatarPalette,
SendLevelMessage,
EditorTransformChange,
Ping,
Pong
> OnlineMessageHandler;
extern OnlineMessageHandler message_handler;
class Online {
public:
int compression_level;
string level_name;
string campaign_id;
bool host_started_level;
OnlineSession* online_session;
private:
NetFramework net;
OnlineFileTransferHandler online_file_transfer_handler;
vector<char> compressed_serialization_buffer;
thread socket_thread;
unordered_map<string, uint32_t> states; // This is angelscript states, these need to exist independent of Multiplayer to allow for states to be set while not hosting to transfer when starting to host
unordered_map<CommonObjectID, ObjectID> to_object_id;
unordered_map<ObjectID, CommonObjectID> to_common_id;
bool attach_avatar_camera;
MultiplayerMode mode;
uint64_t initial_ts;
uint32_t next_available_state_id;
bool loading;
PeerID next_free_peer_id;
uint32_t tick_period;
bool p2p_sockets_active = false;
unordered_set<NetListenSocketID> listen_sockets;
float no_data_interpstep_override = 0.5f;
uint32_t last_update_wall_ticks = 0;
uint32_t last_quarter_update_wall_ticks = 0;
string default_hot_join_characte_path;
ZSTD_CCtx *zstdCContext;
ZSTD_DCtx *zstdDContext;
map<string, KeyState> client_key_down_map_state;
public:
static Online* Instance() {
static Online online;
return &online;
}
Online();
void Dispose();
bool IsClient() const;
bool IsActive() const;
bool IsHosting() const;
bool IsAwaitingShutdown() const;
uint32_t GetPlayerCount();
void StartMultiplayer(MultiplayerMode multiplayerMode);
void StartHostingMultiplayer();
void QueueStopMultiplayer();
void StopMultiplayer();
void StopListening();
vector<PlayerState> GetPlayerStates();
void CloseConnection(NetConnectionID conn_id, ConnectionClosedReason reason);
bool TryGetPlayerState(PlayerState& player_state, ObjectID object_id) const;
void AssignNewControllerForPlayer(PlayerID player_id);
void ClearOnlineSession();
template<typename Message, typename... Args>
OnlineMessageRef& CreateMessage(Args... args);
void Send(const OnlineMessageRef& message);
void SendTo(NetConnectionID target, const OnlineMessageRef& message);
template<typename Message, typename... Args>
void Send(Args... args);
template<typename Message, typename... Args>
void SendTo(NetConnectionID target, Args... args);
void SendIntFloatScriptParam(uint32_t i, const string& key, const ScriptParam& param);
void SendStringScriptParam(uint32_t i, const string& key, const ScriptParam& param);
void SendScriptParam(uint32_t id, const string& key, const ScriptParam& param);
void SendScriptParamMap(uint32_t id, const ScriptParamMap& param);
bool GetHostAllowsClientEditor() const;
void SetIfHostAllowsClientEditor(bool mode);
void SetDefaultHotJoinCharacter(const string& path);
string GetDefaultHotJoinCharacter() const;
void SessionStarted(bool host_started_the_level);
bool ForceMapStartOnLoad() const;
bool AllClientsReady();
ScriptParams* GetScriptParamsFromID(ObjectID id);
void UpdateMovementObjectFromID(uint32_t id);
void SocketMessageApplyLevelChange();
bool SetAvatarCameraAttachedMode(bool mode);
bool IsAvatarCameraAttached() const;
void SendLevelMessage(const string& msg);
void SendAvatarPaletteChange(const OGPalette& palette, ObjectID object_id);
bool IsAvatarPossessed(ObjectID avatar_id);
void PossessAvatar(PlayerID player_id, ObjectID object_id);
ObjectID CreateCharacter();
void SetNoDataInterpStepOverRide(float override);
float GetNoDataInterpStepOverRide() const;
void LateUpdate(SceneGraph * scenegraph);
void SyncHostSessionFlags();
void GenerateEnvObjectSyncPackages(NetConnectionID conn, SceneGraph* graph);
void GenerateMovementSyncPackages(NetConnectionID conn, SceneGraph * graph);
void GenerateStateForNewConnection(NetConnectionID conn);
bool CheckLoadedMapAndCampaignState(const string& campagin, const string& level_name);
void SetLevelLoaded();
uint32_t IncomingMessageCount() const;
uint32_t OutgoingMessageCount() const;
bool GetIfPendingAngelScriptUpdates();
bool GetIfPendingAngelScriptStates();
AngelScriptUpdate GetAngelScriptUpdate();
void MoveAngelScriptQueueForward();
void MoveAngelStateQueueForward();
AngelScriptUpdate GetAngelScriptStates();
uint32_t AddSyncState(uint32_t state, const vector<char>& data);
uint32_t RegisterMPState(const string& state);
void SetTickperiod(const uint32_t& tickperiod);
void GetConnectionStatus(const Peer& peer, ConnectionStatus* status) const;
void RegisterHostObjectID(CommonObjectID hostid, ObjectID clientid);
void DeRegisterHostClientIDTranslation(ObjectID clientid);
ObjectID GetObjectID(CommonObjectID hostid) const;
CommonObjectID GetOriginalID(ObjectID clientid) const;
void ClearIDTranslations();
bool SendingRemovePackages() const;
void RemoveObject(Object * o, ObjectID my_id);
bool NetworkRemoveableType(Object* o) const;
void ChangeLevel(const string& id);
void PerformLevelChangeCleanUp();
const vector<Peer> GetPeers();
vector<Peer>::iterator GetPeerIt(NetConnectionID conn_id);
bool IsLocalAvatar(const ObjectID avatar) const;
vector<ObjectID> GetLocalAvatarIDs() const;
PlayerState GenerateHostPlayerState() const;
void OnConnectionChange(NetFrameworkConnectionStatusChanged *data);
void BroadcastChatMessage(const string& chat_message);
void SendRawChatMessage(const string& raw_chat_entry);
void AddLocalChatMessage(string chat_message);
void RemoveOldChatMessages(float threshold);
const vector<ChatMessage>& GetChatMessages() const;
void AddPeer(NetFrameworkConnectionStatusChanged *data);
Peer* GetPeerFromConnection(NetConnectionID conn_id);
Peer* GetPeerFromID(PeerID peer_id);
bool HasFreeAvatars() const;
void UpdateObjects(SceneGraph *scenegraph_);
uint32_t GetNumberOfFreeAvatars() const;
uint8_t GetPlayerLimit();
bool IsLobbyFull();
void AddFreeAvatarsIds();
void RemoveAllAvatarIds();
void RemoveFreeAvatarId(uint32_t id);
ObjectID GetFreeAvatarID();
void AddFreeAvatarId(uint32_t id);
void CreateListenSocketIP(const string &localAddress);
void ConnectByIPAddress(const string &address);
bool NetFrameworkHasFriendInviteOverlay() const;
void ActivateGameOverlayInviteDialog();
void CheckPendingMessages();
void ApplyPlayerInput();
PlayerState GetOwnPlayerState();
//Host and Client use, used to convert a PlayerInput binding name to a shared integer representation.
uint8_t GetBindID(string bind_name);
private:
//Explicitally disable copy constructors and assignment to prevent misuse.
Online(const Online&) = delete;
Online &operator=(const Online &) = delete;
Online(Online &&) = delete;
Online &operator=(Online &&) = delete;
//Host only function, clients get their bindings from the host.
void AssignBindID(string bind_name);
//Client side cache, not used on the server.
void SendPlayerInputState();
void SendPlayerCameraState();
void CloseConnectionImmediate(NetConnectionID conn, ConnectionClosedReason reason);
//Functions run inside a separate socket communication thread.
void NetworkDataThread();
void SendMessages();
void SendMessageObjects();
void HandleConnectionsToBeClosed();
void SendMessageToConnection(NetConnectionID conn_id, char * buffer, uint32_t bytes, bool reliable, bool flush);
void SendStateMessages();
void CheckNewMessages();
size_t CompressData(vector<char>& target_buffer, const void* source_buffer, uint32_t source_size);
size_t DecompressData(vector<char>& target_buffer, const void* source_buffer, size_t source_size);
};
template<typename Message, typename... Args>
void Online::Send(Args... args) {
Send(message_handler.Create<Message>(args...));
}
template<typename Message, typename... Args>
void Online::SendTo(NetConnectionID target, Args... args) {
SendTo(target, message_handler.Create<Message>(args...));
}
template<typename Message, typename... Args>
OnlineMessageRef& Online::CreateMessage(Args... args) {
return message_handler.Create<Message>(args...);
}
|