R-Type
R-Type project
NetworkServer.hpp
1 #pragma once
2 
3 #include "Core/ArraySegment.hpp"
4 #include "Core/NetworkConnectionToClient.hpp"
5 #include "Core/NetworkMessage.hpp"
6 #include "KapMirror/Experimental/Core/Action.hpp"
7 #include "Messages.hpp"
8 #include "KapEngine.hpp"
9 #include "Platform.hpp"
10 #include "Dictionary.hpp"
11 #include "Debug.hpp"
12 #include <memory>
13 #include <functional>
14 
15 namespace KapMirror {
16  class NetworkManager;
17 
18  class NetworkServer {
19  private:
20  NetworkManager& manager;
21  KapEngine::KEngine& engine;
22 
23  bool initialized;
24  bool active;
25 
26  int maxConnections = 10;
27 
29  KapEngine::Dictionary<ushort, std::shared_ptr<std::function<void(std::shared_ptr<NetworkConnectionToClient>, NetworkReader&)>>>
30  handlers;
32 
33  public:
34  explicit NetworkServer(NetworkManager& _manager, KapEngine::KEngine& _engine);
35  ~NetworkServer() = default;
36 
37  bool isActivated() const { return active; }
38 
42  void listen(int maxConnections, int port);
43 
47  void shutdown();
48 
53  void networkEarlyUpdate() const;
54 
58  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
59  void sendToAll(T& message) {
60  if (!active) {
61  KapEngine::Debug::warning("NetworkServer: Cannot send data, server not active");
62  return;
63  }
64 
65  for (auto const& [id, conn] : connections) {
66  conn->send(message);
67  }
68  }
69 
73  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
74  void sendToClient(T& message, unsigned int networkId) {
75  if (!active) {
76  KapEngine::Debug::warning("NetworkServer: Cannot send data, server not active");
77  return;
78  }
79 
80  std::shared_ptr<NetworkConnectionToClient> connection;
81  if (connections.tryGetValue(networkId, connection)) {
82  connection->send(message);
83  } else {
84  KapEngine::Debug::warning("NetworkServer: Cannot send data, client not found");
85  }
86  }
87 
91  void disconnectAll() {
92  for (auto const& [id, conn] : connections) {
93  conn->disconnect();
94  onTransportDisconnect(conn->getConnectionId());
95  }
96 
97  // cleanup
98  connections.clear();
99  }
100 
104  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
105  void registerHandler(std::function<void(const std::shared_ptr<NetworkConnectionToClient>&, T&)> handler) {
106  ushort msgType = MessagePacking::getId<T>();
107  if (handlers.containsKey(msgType)) {
108  KapEngine::Debug::warning("NetworkServer.registerHandler replacing handler for {" + std::string(typeid(T).name()) +
109  "}, id={" + std::to_string(msgType) +
110  "}. If replacement is intentional, use replaceHandler instead to avoid this warning.");
111  }
112 
113  auto messageHandler = [handler](std::shared_ptr<NetworkConnectionToClient> connection, NetworkReader& reader) {
114  T message;
115  message.deserialize(reader);
116  handler(connection, message);
117  };
118  handlers[msgType] =
119  std::make_shared<std::function<void(std::shared_ptr<NetworkConnectionToClient>, NetworkReader&)>>(messageHandler);
120  }
121 
125  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
126  void unregisterHandler(T& message) {
127  ushort id = MessagePacking::getId<T>();
128  handlers.remove(id);
129  }
130 
131 #pragma region KapEngine
132 
136  void spawnObject(const std::string& prefabName, KapEngine::SceneManagement::Scene& scene, const KapEngine::Tools::Vector3& position,
137  const std::function<void(const std::shared_ptr<KapEngine::GameObject>&)>& playload,
138  std::shared_ptr<KapEngine::GameObject>& gameObject);
139 
143  void spawnObject(const std::string& prefabName, std::size_t sceneId, const KapEngine::Tools::Vector3& position,
144  const std::function<void(const std::shared_ptr<KapEngine::GameObject>&)>& playload,
145  std::shared_ptr<KapEngine::GameObject>& gameObject) {
146  auto& scene = engine.getSceneManager()->getScene(sceneId);
147  spawnObject(prefabName, scene, position, playload, gameObject);
148  }
149 
153  void spawnObject(const std::string& prefabName, const KapEngine::Tools::Vector3& position,
154  const std::function<void(const std::shared_ptr<KapEngine::GameObject>&)>& playload,
155  std::shared_ptr<KapEngine::GameObject>& gameObject) {
156  auto& scene = engine.getSceneManager()->getCurrentScene();
157  spawnObject(prefabName, scene, position, playload, gameObject);
158  }
159 
163  void spawnObject(const std::string& prefabName, const KapEngine::Tools::Vector3& position,
164  std::shared_ptr<KapEngine::GameObject>& gameObject) {
165  auto& scene = engine.getSceneManager()->getCurrentScene();
166  spawnObject(prefabName, scene, position, nullptr, gameObject);
167  }
168 
173  void unSpawn(const std::shared_ptr<KapEngine::GameObject>& gameObject);
174 
178  void destroyObject(unsigned int networkId);
179 
183  void destroyObject(const std::shared_ptr<KapEngine::GameObject>& gameObject) { unSpawn(gameObject); }
184 
188  void updateObject(unsigned int id);
189 
193  bool getExistingObject(unsigned int id, std::shared_ptr<KapEngine::GameObject>& gameObject) {
194  return networkObjects.tryGetValue(id, gameObject);
195  }
196 
197 #pragma endregion
198 
199  private:
200  void initialize();
201 
202  void addTransportHandlers();
203  void removeTransportHandlers();
204  void registerSystemHandlers();
205 
206  void onTransportConnect(int connectionId);
207  void onTransportDisconnect(int connectionId);
208  void onTransportData(int connectionId, const std::shared_ptr<ArraySegment<byte>>& data);
209 
210  bool addConnection(const std::shared_ptr<NetworkConnectionToClient>& connection);
211  bool removeConnection(int connectionId);
212 
213  bool unpackAndInvoke(const std::shared_ptr<NetworkConnectionToClient>& connection, const std::shared_ptr<ArraySegment<byte>>& data);
214 
215  void sendObject(const std::shared_ptr<KapEngine::GameObject>& gameObject,
216  const std::shared_ptr<NetworkConnectionToClient>& connection);
217 
218  // KapEngine
219  void onObjectSpawn(ObjectSpawnMessage& message);
220  void onObjectTransformUpdate(ObjectTransformMessage& message);
221 
222  public:
223  Experimental::Action<void(std::shared_ptr<NetworkConnection>)> onConnectedEvent;
224  Experimental::Action<void(std::shared_ptr<NetworkConnection>)> onDisconnectedEvent;
225  };
226 } // namespace KapMirror
KapMirror::NetworkServer::destroyObject
void destroyObject(unsigned int networkId)
Destroy GameObject corresponding of networkId for all clients.
Definition: NetworkServer.cpp:322
KapMirror::NetworkServer::getExistingObject
bool getExistingObject(unsigned int id, std::shared_ptr< KapEngine::GameObject > &gameObject)
Get existing GameObject with networkId.
Definition: NetworkServer.hpp:193
KapMirror::NetworkServer::listen
void listen(int maxConnections, int port)
Starts server and listens to incoming connections with max connections limit.
Definition: NetworkServer.cpp:33
KapMirror::NetworkServer::registerHandler
void registerHandler(std::function< void(const std::shared_ptr< NetworkConnectionToClient > &, T &)> handler)
Register a handler for a message type T.
Definition: NetworkServer.hpp:105
KapMirror::NetworkReader
Definition: NetworkReader.hpp:10
KapMirror::NetworkServer::spawnObject
void spawnObject(const std::string &prefabName, std::size_t sceneId, const KapEngine::Tools::Vector3 &position, const std::function< void(const std::shared_ptr< KapEngine::GameObject > &)> &playload, std::shared_ptr< KapEngine::GameObject > &gameObject)
Spawn new GameObject on specifics Scene for all clients. (only Prefab)
Definition: NetworkServer.hpp:143
KapMirror::NetworkServer::sendToAll
void sendToAll(T &message)
Send a message to all clients which have joined the world (are ready).
Definition: NetworkServer.hpp:59
KapMirror::NetworkServer::spawnObject
void spawnObject(const std::string &prefabName, const KapEngine::Tools::Vector3 &position, std::shared_ptr< KapEngine::GameObject > &gameObject)
Spawn new GameObject on current Scene for all clients. (only Prefab)
Definition: NetworkServer.hpp:163
KapMirror::NetworkServer::sendToClient
void sendToClient(T &message, unsigned int networkId)
Send a message to a specific client.
Definition: NetworkServer.hpp:74
KapMirror::NetworkServer::unregisterHandler
void unregisterHandler(T &message)
Unregister a message handler of type T.
Definition: NetworkServer.hpp:126
KapMirror::NetworkServer::spawnObject
void spawnObject(const std::string &prefabName, const KapEngine::Tools::Vector3 &position, const std::function< void(const std::shared_ptr< KapEngine::GameObject > &)> &playload, std::shared_ptr< KapEngine::GameObject > &gameObject)
Spawn new GameObject on current Scene for all clients. (only Prefab)
Definition: NetworkServer.hpp:153
KapEngine::KEngine::getSceneManager
std::shared_ptr< SceneManagement::SceneManager > getSceneManager() const
Get the Scene Manager of game.
Definition: Engine.hpp:200
KapMirror::ObjectSpawnMessage
Definition: Messages.hpp:8
KapMirror::NetworkServer
Definition: NetworkServer.hpp:18
KapEngine::Dictionary
Definition: Dictionary.hpp:16
KapEngine::Debug::warning
static void warning(std::string _msg, std::string prefix="")
display a warning message
Definition: Debug.cpp:31
KapMirror::NetworkServer::networkEarlyUpdate
void networkEarlyUpdate() const
NetworkEarlyUpdate. (we add this to the KapEngine in OnFixedUpdate)
Definition: NetworkServer.cpp:59
KapMirror::NetworkServer::updateObject
void updateObject(unsigned int id)
Update GameObject for all clients.
Definition: NetworkServer.cpp:347
KapMirror::NetworkServer::shutdown
void shutdown()
Shuts down the server and disconnects all clients.
Definition: NetworkServer.cpp:42
KapMirror::NetworkServer::spawnObject
void spawnObject(const std::string &prefabName, KapEngine::SceneManagement::Scene &scene, const KapEngine::Tools::Vector3 &position, const std::function< void(const std::shared_ptr< KapEngine::GameObject > &)> &playload, std::shared_ptr< KapEngine::GameObject > &gameObject)
Spawn new GameObject on specifics Scene for all clients. (only Prefab)
Definition: NetworkServer.cpp:224
KapEngine::Tools::Vector3
Definition: Vectors.hpp:251
KapMirror::NetworkServer::destroyObject
void destroyObject(const std::shared_ptr< KapEngine::GameObject > &gameObject)
Destroy GameObject for all clients.
Definition: NetworkServer.hpp:183
KapMirror::NetworkManager
Definition: NetworkManager.hpp:10
KapMirror::ObjectTransformMessage
Definition: Messages.hpp:75
KapEngine::SceneManagement::Scene
Definition: Scene.hpp:37
KapMirror::ArraySegment
Definition: ArraySegment.hpp:9
KapMirror::Experimental::Action
Definition: Action.hpp:10
KapMirror::NetworkServer::unSpawn
void unSpawn(const std::shared_ptr< KapEngine::GameObject > &gameObject)
This takes an object that has been spawned and un-spawns it. The object will be removed from clients.
Definition: NetworkServer.cpp:308
KapEngine::KEngine
Class of engine.
Definition: Engine.hpp:60
KapMirror::NetworkServer::disconnectAll
void disconnectAll()
Disconnect all connections.
Definition: NetworkServer.hpp:91