R-Type
R-Type project
NetworkClient.hpp
1 #pragma once
2 
3 #include "Core/ArraySegment.hpp"
4 #include "Core/NetworkConnectionToServer.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  enum ConnectState {
17  None,
18  // connecting between Connect() and OnTransportConnected()
19  Connecting,
20  Connected,
21  // disconnecting between Disconnect() and OnTransportDisconnected()
22  Disconnecting,
23  Disconnected
24  };
25 
26  class NetworkManager;
27 
28  class NetworkClient {
29  private:
30  NetworkManager& manager;
31  KapEngine::KEngine& engine;
32 
33  ConnectState connectState;
34  std::shared_ptr<NetworkConnectionToServer> connection;
35 
36  KapEngine::Dictionary<ushort, std::shared_ptr<std::function<void(std::shared_ptr<NetworkConnectionToServer>, NetworkReader&)>>>
37  handlers;
39 
40  public:
41  explicit NetworkClient(NetworkManager& _manager, KapEngine::KEngine& _engine);
42  ~NetworkClient() = default;
43 
47  void connect(const std::string& ip, int port);
48 
52  void disconnect();
53 
58  void networkEarlyUpdate();
59 
64  bool isActive() const { return connectState == ConnectState::Connecting || connectState == ConnectState::Connected; }
65 
69  bool isConnecting() const { return connectState == ConnectState::Connecting; }
70 
74  bool isConnected() const { return connectState == ConnectState::Connected; }
75 
79  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
80  void send(T& message) {
81  if (connection != nullptr) {
82  if (connectState == ConnectState::Connected) {
83  connection->send(message);
84  } else {
85  KapEngine::Debug::error("NetworkClient: Send when not connected to a server");
86  }
87  } else {
88  KapEngine::Debug::error("NetworkClient: Send with no connection");
89  }
90  }
91 
95  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
96  void registerHandler(std::function<void(const std::shared_ptr<NetworkConnectionToServer>&, T&)> handler) {
97  ushort msgType = MessagePacking::getId<T>();
98  if (handlers.containsKey(msgType)) {
99  KapEngine::Debug::warning("NetworkClient.registerHandler replacing handler for {" + std::string(typeid(T).name()) +
100  "}, id={" + std::to_string(msgType) +
101  "}. If replacement is intentional, use replaceHandler instead to avoid this warning.");
102  }
103 
104  auto messageHandler = [handler](std::shared_ptr<NetworkConnectionToServer> conn, NetworkReader& reader) {
105  T message;
106  message.deserialize(reader);
107  handler(conn, message);
108  };
109  handlers[msgType] =
110  std::make_shared<std::function<void(std::shared_ptr<NetworkConnectionToServer>, NetworkReader&)>>(messageHandler);
111  }
112 
116  template <typename T, typename = std::enable_if<std::is_base_of<NetworkMessage, T>::value>>
117  void unregisterHandler(T& message) {
118  ushort msgType = MessagePacking::getId<T>();
119  handlers.remove(msgType);
120  }
121 
122 #pragma region KapEngine
123 
127  void updateObject(unsigned int id);
128 
133  bool getExistingObject(unsigned int networkId, std::shared_ptr<KapEngine::GameObject>& gameObject) {
134  return networkObjects.tryGetValue(networkId, gameObject);
135  }
136 
137 #pragma endregion
138 
139  private:
140  void addTransportHandlers();
141  void removeTransportHandlers();
142  void registerSystemHandlers();
143 
144  void onTransportConnect();
145  void onTransportDisconnect();
146  void onTransportData(const std::shared_ptr<ArraySegment<byte>>& data);
147 
148  bool unpackAndInvoke(const std::shared_ptr<ArraySegment<byte>>& data);
149 
150  // KapEngine
151  void onObjectSpawn(ObjectSpawnMessage& message);
152  void onObjectDestroy(ObjectDestroyMessage& message);
153  void onObjectTransformUpdate(ObjectTransformMessage& message);
154 
155  public:
156  Experimental::Action<void(std::shared_ptr<NetworkConnection>)> onConnectedEvent;
157  Experimental::Action<void(std::shared_ptr<NetworkConnection>)> onDisconnectedEvent;
158  };
159 } // namespace KapMirror
KapMirror::NetworkClient::send
void send(T &message)
Send a NetworkMessage to the server.
Definition: NetworkClient.hpp:80
KapMirror::NetworkClient::registerHandler
void registerHandler(std::function< void(const std::shared_ptr< NetworkConnectionToServer > &, T &)> handler)
Register a handler for a message type T.
Definition: NetworkClient.hpp:96
KapMirror::NetworkClient::connect
void connect(const std::string &ip, int port)
Connect client to a NetworkServer by ip and port.
Definition: NetworkClient.cpp:17
KapMirror::NetworkClient::isConnected
bool isConnected() const
Check if client is connected (after isConnecting).
Definition: NetworkClient.hpp:74
KapMirror::NetworkClient::getExistingObject
bool getExistingObject(unsigned int networkId, std::shared_ptr< KapEngine::GameObject > &gameObject)
Get existing GameObject with networkId. (Spawned by server)
Definition: NetworkClient.hpp:133
KapMirror::NetworkClient
Definition: NetworkClient.hpp:28
KapMirror::NetworkClient::disconnect
void disconnect()
Disconnect from server.
Definition: NetworkClient.cpp:34
KapMirror::NetworkClient::isConnecting
bool isConnecting() const
Check if client is connecting (before isConnected).
Definition: NetworkClient.hpp:69
KapMirror::NetworkClient::unregisterHandler
void unregisterHandler(T &message)
Unregister a message handler of type T.
Definition: NetworkClient.hpp:117
KapMirror::NetworkReader
Definition: NetworkReader.hpp:10
KapMirror::ObjectDestroyMessage
Definition: Messages.hpp:66
KapMirror::NetworkClient::updateObject
void updateObject(unsigned int id)
Update GameObject for all clients.
Definition: NetworkClient.cpp:225
KapMirror::ObjectSpawnMessage
Definition: Messages.hpp:8
KapEngine::Dictionary
Definition: Dictionary.hpp:16
KapMirror::NetworkClient::isActive
bool isActive() const
isActive is true while a client is isConnecting/isConnected. (= while the network is active)
Definition: NetworkClient.hpp:64
KapEngine::Debug::warning
static void warning(std::string _msg, std::string prefix="")
display a warning message
Definition: Debug.cpp:31
KapMirror::NetworkManager
Definition: NetworkManager.hpp:10
KapMirror::ObjectTransformMessage
Definition: Messages.hpp:75
KapEngine::Debug::error
static void error(std::string _msg, std::string prefix="")
display an error message
Definition: Debug.cpp:45
KapMirror::ArraySegment
Definition: ArraySegment.hpp:9
KapMirror::Experimental::Action
Definition: Action.hpp:10
KapMirror::NetworkClient::networkEarlyUpdate
void networkEarlyUpdate()
NetworkEarlyUpdate. (we add this to the KapEngine in OnFixedUpdate)
Definition: NetworkClient.cpp:47
KapEngine::KEngine
Class of engine.
Definition: Engine.hpp:60