diff --git a/include/Engine/Network/Server.h b/include/Engine/Network/Server.h index e0ef9fcf..f16c6c16 100644 --- a/include/Engine/Network/Server.h +++ b/include/Engine/Network/Server.h @@ -48,6 +48,7 @@ private: float snapshotInterval; int checkTimeOutInterval = 100; int m_NextPlayerID = 0; + std::vector m_InputCommandsToBroadcast; //Timers std::clock_t m_StartPingTime; @@ -64,6 +65,7 @@ private: void broadcast(Packet& packet); void sendSnapshot(); void addChildrenToPacket(Packet& packet, EntityID entityID); + void addInputCommandsToPacket(Packet& packet); void sendPing(); void checkForTimeOuts(); void disconnect(PlayerID playerID); diff --git a/include/Game/Systems/WeaponSystem.h b/include/Game/Systems/WeaponSystem.h index 59048ee0..d6525377 100644 --- a/include/Game/Systems/WeaponSystem.h +++ b/include/Game/Systems/WeaponSystem.h @@ -9,7 +9,6 @@ #include "Core/System.h" #include "Core/EPlayerDamage.h" #include "Core/EShoot.h" -#include "Core/EPlayerSpawned.h" #include "Input/EInputCommand.h" #include "Core/EntityFile.h" #include "Core/EntityFileParser.h" @@ -28,16 +27,11 @@ public: private: IRenderer* m_Renderer; - // State - EntityWrapper m_LocalPlayer = EntityWrapper::Invalid; - // Events - EventRelay m_EPlayerSpawned; - bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e); EventRelay m_EShoot; bool WeaponSystem::OnShoot(Events::Shoot& e); EventRelay m_EInputCommand; - bool WeaponSystem::OnInputCommand(const Events::InputCommand& e); + bool WeaponSystem::OnInputCommand(Events::InputCommand& e); }; #endif \ No newline at end of file diff --git a/src/Engine/Network/Client.cpp b/src/Engine/Network/Client.cpp index b3fa227a..7d2c8f92 100644 --- a/src/Engine/Network/Client.cpp +++ b/src/Engine/Network/Client.cpp @@ -230,6 +230,18 @@ void Client::ignoreFields(Packet& packet, const ComponentInfo& componentInfo) void Client::parseSnapshot(Packet& packet) { + // Read input commands + std::size_t numInputCommands = packet.ReadPrimitive(); + for (std::size_t i = 0; i < numInputCommands; ++i) { + Events::InputCommand e; + e.PlayerID = packet.ReadPrimitive(); + e.Player = EntityWrapper(m_World, m_ServerIDToClientID.at(packet.ReadPrimitive())); + e.Command = packet.ReadString(); + e.Value = packet.ReadPrimitive(); + m_EventBroker->Publish(e); + } + + // Read world state while (packet.DataReadSize() < packet.Size()) { EntityID serverEntityID = packet.ReadPrimitive(); EntityID serverParentID = packet.ReadPrimitive(); @@ -339,6 +351,10 @@ void Client::disconnect() bool Client::OnInputCommand(const Events::InputCommand & e) { + if (e.PlayerID != -1) { + return false; + } + if (e.Command == "ConnectToServer") { // Connect for now if (e.Value > 0) { connect(); diff --git a/src/Engine/Network/Server.cpp b/src/Engine/Network/Server.cpp index b0003539..7ad1cc76 100644 --- a/src/Engine/Network/Server.cpp +++ b/src/Engine/Network/Server.cpp @@ -165,10 +165,24 @@ void Server::broadcast(Packet& packet) void Server::sendSnapshot() { Packet packet(MessageType::Snapshot); + addInputCommandsToPacket(packet); addChildrenToPacket(packet, EntityID_Invalid); broadcast(packet); } +void Server::addInputCommandsToPacket(Packet& packet) +{ + // Number of input commands + packet.WritePrimitive(m_InputCommandsToBroadcast.size()); + for (auto& command : m_InputCommandsToBroadcast) { + packet.WritePrimitive(command.PlayerID); + packet.WritePrimitive(m_ConnectedPlayers.at(command.PlayerID).EntityID); + packet.WriteString(command.Command); + packet.WritePrimitive(command.Value); + } + m_InputCommandsToBroadcast.clear(); +} + void Server::addChildrenToPacket(Packet & packet, EntityID entityID) { auto itPair = m_World->GetChildren(entityID); @@ -273,6 +287,10 @@ void Server::parseOnInputCommand(Packet& packet) e.Player = EntityWrapper(m_World, m_ConnectedPlayers.at(player).EntityID); e.Value = packet.ReadPrimitive(); m_EventBroker->Publish(e); + + if (e.Command == "PrimaryFire") { + m_InputCommandsToBroadcast.push_back(e); + } //LOG_INFO("Server::parseOnInputCommand: Command is %s. Value is %f. PlayerID is %i.", e.Command.c_str(), e.Value, e.PlayerID); } } diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 38468e47..ce782ece 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -218,5 +218,10 @@ int Game::parseArgs(int argc, char* argv[]) m_IsClient = true; } + // HACK: Right now, client and server are mutually exclusive + if (m_IsServer) { + m_IsClient = false; + } + return 0; } diff --git a/src/Game/Systems/WeaponSystem.cpp b/src/Game/Systems/WeaponSystem.cpp index 22cd173a..a650a6b7 100644 --- a/src/Game/Systems/WeaponSystem.cpp +++ b/src/Game/Systems/WeaponSystem.cpp @@ -5,7 +5,6 @@ WeaponSystem::WeaponSystem(SystemParams params, IRenderer* renderer) , ImpureSystem() , m_Renderer(renderer) { - EVENT_SUBSCRIBE_MEMBER(m_EPlayerSpawned, &WeaponSystem::OnPlayerSpawned); EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &WeaponSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EShoot, &WeaponSystem::OnShoot); } @@ -15,30 +14,22 @@ void WeaponSystem::Update(double dt) } -bool WeaponSystem::OnPlayerSpawned(const Events::PlayerSpawned& e) -{ - if (e.PlayerID == -1) { - m_LocalPlayer = e.Player; - } - return true; -} - -bool WeaponSystem::OnInputCommand(const Events::InputCommand& e) +bool WeaponSystem::OnInputCommand(Events::InputCommand& e) { // Only shoot client-side! - if (e.PlayerID != -1) { + if (!IsClient) { return false; } // Only shoot if the player is alive - if (!m_LocalPlayer.Valid()) { + if (!e.Player.Valid()) { return false; } if (e.Command == "PrimaryFire" && e.Value > 0) { Events::Shoot eShoot; if (e.PlayerID == -1) { - eShoot.Player = m_LocalPlayer; + eShoot.Player = LocalPlayer; } else { eShoot.Player = e.Player; } @@ -97,8 +88,8 @@ bool WeaponSystem::OnShoot(Events::Shoot& eShoot) //(glm::vec3&)ray["Transform"]["Orientation"] = Transform::AbsoluteOrientationEuler(weapon); } - // Only run further picking code client-side! - if (eShoot.Player != m_LocalPlayer) { + // Only run further picking code for the local player! + if (eShoot.Player != LocalPlayer) { return false; }