From 15042f1253caae9acd1ac3257d328ecc7455445b Mon Sep 17 00:00:00 2001 From: iAmir Date: Wed, 24 Apr 2024 18:14:33 +0330 Subject: [PATCH 1/3] improve and optimize semi-broadcast behavior --- SDK/include/network.hpp | 15 ++ Server/Components/Actors/actor.hpp | 14 +- Server/Components/Actors/actors_main.cpp | 2 +- .../LegacyNetwork/legacy_network_impl.hpp | 118 ++++++++++ Server/Components/Vehicles/vehicle.cpp | 26 +-- Server/Components/Vehicles/vehicles_impl.hpp | 12 +- Server/Source/player.cpp | 48 ++++ Server/Source/player_impl.hpp | 47 +--- Server/Source/player_pool.hpp | 4 +- Shared/Network/packet.hpp | 216 ++++++++++-------- lib/RakNet | 2 +- 11 files changed, 345 insertions(+), 159 deletions(-) diff --git a/SDK/include/network.hpp b/SDK/include/network.hpp index 42583cee5..ef4b5d299 100644 --- a/SDK/include/network.hpp +++ b/SDK/include/network.hpp @@ -344,6 +344,21 @@ struct INetwork : public IExtensible /// Update server parameters virtual void update() = 0; + + /// Attempt to broadcast a packet to everyone on this network + /// @param data The data span with the length in BITS + /// @param players list of players to send packet to + /// @param exceptPeer send RPC to everyone except this peer + /// @param dispatchEvents dispatch packet related events + virtual bool broadcastPacket(Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents = true) = 0; + + /// Attempt to broadcast an RPC to everyone on this network + /// @param id The RPC ID for the current network + /// @param data The data span with the length in BITS + /// @param players list of players to send RPC to + /// @param exceptPeer send RPC to everyone except this peer + /// @param dispatchEvents dispatch RPC related events + virtual bool broadcastRPC(int id, Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents = true) = 0; }; /// A component interface which allows for writing a network component diff --git a/Server/Components/Actors/actor.hpp b/Server/Components/Actors/actor.hpp index 78357c8a9..ec9e29fa3 100644 --- a/Server/Components/Actors/actor.hpp +++ b/Server/Components/Actors/actor.hpp @@ -34,6 +34,7 @@ struct PlayerActorData final : IExtension class Actor final : public IActor, public PoolIDProvider, public NoCopy { private: + ICore& core_; int virtualWorld_; int16_t skin_; bool invulnerable_; @@ -103,8 +104,9 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy } } - Actor(int skin, Vector3 pos, float angle, bool* allAnimationLibraries, bool* validateAnimations, ICustomModelsComponent*& modelsComponent, IFixesComponent* fixesComponent) - : virtualWorld_(0) + Actor(int skin, Vector3 pos, float angle, bool* allAnimationLibraries, bool* validateAnimations, ICore& core, ICustomModelsComponent*& modelsComponent, IFixesComponent* fixesComponent) + : core_(core) + , virtualWorld_(0) , skin_(skin) , invulnerable_(true) , animationLoop_(false) @@ -125,7 +127,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy NetCode::RPC::SetActorHealthForPlayer RPC; RPC.ActorID = poolID; RPC.Health = health_; - PacketHelper::broadcastToSome(RPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(RPC, core_.getNetworks(), streamedFor_.entries()); } float getHealth() const override @@ -196,7 +198,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy NetCode::RPC::ClearActorAnimationsForPlayer RPC; RPC.ActorID = poolID; - PacketHelper::broadcastToSome(RPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(RPC, core_.getNetworks(), streamedFor_.entries()); } bool isStreamedInForPlayer(const IPlayer& player) const override @@ -264,7 +266,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy NetCode::RPC::SetActorPosForPlayer RPC; RPC.ActorID = poolID; RPC.Pos = position; - PacketHelper::broadcastToSome(RPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(RPC, core_.getNetworks(), streamedFor_.entries()); } GTAQuat getRotation() const override @@ -279,7 +281,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy NetCode::RPC::SetActorFacingAngleForPlayer RPC; RPC.ActorID = poolID; RPC.Angle = angle_; - PacketHelper::broadcastToSome(RPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(RPC, core_.getNetworks(), streamedFor_.entries()); } void setSkin(int id) override diff --git a/Server/Components/Actors/actors_main.cpp b/Server/Components/Actors/actors_main.cpp index 474d75f90..fbc3a1da8 100644 --- a/Server/Components/Actors/actors_main.cpp +++ b/Server/Components/Actors/actors_main.cpp @@ -145,7 +145,7 @@ class ActorsComponent final : public IActorsComponent, public PlayerConnectEvent IActor* create(int skin, Vector3 pos, float angle) override { - return storage.emplace(skin, pos, angle, core->getConfig().getBool("game.use_all_animations"), core->getConfig().getBool("game.validate_animations"), modelsComponent, fixesComponent_); + return storage.emplace(skin, pos, angle, core->getConfig().getBool("game.use_all_animations"), core->getConfig().getBool("game.validate_animations"), *core, modelsComponent, fixesComponent_); } void free() override diff --git a/Server/Components/LegacyNetwork/legacy_network_impl.hpp b/Server/Components/LegacyNetwork/legacy_network_impl.hpp index 311614c7d..6c49c2dc3 100644 --- a/Server/Components/LegacyNetwork/legacy_network_impl.hpp +++ b/Server/Components/LegacyNetwork/legacy_network_impl.hpp @@ -138,6 +138,65 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi return rakNetServer.Send((const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, RakNet::UNASSIGNED_PLAYER_ID, true); } + bool broadcastPacket(Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents) override + { + // Don't use constructor because it takes bytes; we want bits + NetworkBitStream bs; + bs.SetData(data.data()); + bs.SetWriteOffset(data.size()); + bs.SetReadOffset(0); + + // Store packet type here, we're gonna use it later + uint8_t type; + bs.readUINT8(type); + bs.SetReadOffset(0); + + // Now go through all players to see if we need to send packet to, based on various checks and event results. + RakNet::PlayerIndex* broadcastList = new RakNet::PlayerIndex[players.size()]; + int broadcastListSize = 0; + for (auto player : players) + { + if (player && player != exceptPeer && player->getNetworkData().network == this) + { + auto remoteSystem = playerRemoteSystem[player->getID()]; + if (remoteSystem && remoteSystem->isActive) + { + int index = rakNetServer.GetIndexFromPlayerID(remoteSystem->playerId); + if (index != -1) + { + bool mustSend = true; + if (dispatchEvents) + { + mustSend = outEventDispatcher.stopAtFalse([type, &bs, player](NetworkOutEventHandler* handler) + { + bs.SetReadOffset(8); // Ignore packet ID + return handler->onSendPacket(player, type, bs); + }); + + if (mustSend) + { + mustSend = packetOutEventDispatcher.stopAtFalse(type, [&bs, player](SingleNetworkOutEventHandler* handler) + { + bs.SetReadOffset(8); // Ignore packet ID + return handler->onSend(player, bs); + }); + } + } + + if (mustSend) + { + broadcastList[broadcastListSize] = index; + broadcastListSize++; + } + } + } + } + } + + const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED; + return rakNetServer.Send((const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, Span(broadcastList, broadcastListSize)); + } + bool sendPacket(IPlayer& peer, Span data, int channel, bool dispatchEvents) override { const PeerNetworkData& netData = peer.getNetworkData(); @@ -233,6 +292,65 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi return rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, RakNet::UNASSIGNED_PLAYER_ID, true, false, RakNet::UNASSIGNED_NETWORK_ID, nullptr); } + bool broadcastRPC(int id, Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents) override + { + if (id == INVALID_PACKET_ID) + { + return false; + } + + // Don't use constructor because it takes bytes; we want bits + NetworkBitStream bs; + bs.SetData(data.data()); + bs.SetWriteOffset(data.size()); + bs.SetReadOffset(0); + + // Now go through all players to see if we need to send RPC to, based on various checks and event results. + RakNet::PlayerIndex* broadcastList = new RakNet::PlayerIndex[players.size()]; + int broadcastListSize = 0; + for (auto player : players) + { + if (player && player != exceptPeer && player->getNetworkData().network == this) + { + auto remoteSystem = playerRemoteSystem[player->getID()]; + if (remoteSystem && remoteSystem->isActive) + { + int index = rakNetServer.GetIndexFromPlayerID(remoteSystem->playerId); + if (index != -1) + { + bool mustSend = true; + if (dispatchEvents) + { + mustSend = outEventDispatcher.stopAtFalse([id, &bs, player](NetworkOutEventHandler* handler) + { + bs.resetReadPointer(); + return handler->onSendRPC(player, id, bs); + }); + + if (mustSend) + { + mustSend = rpcOutEventDispatcher.stopAtFalse(id, [&bs, player](SingleNetworkOutEventHandler* handler) + { + bs.resetReadPointer(); + return handler->onSend(player, bs); + }); + } + } + + if (mustSend) + { + broadcastList[broadcastListSize] = index; + broadcastListSize++; + } + } + } + } + } + + const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED; + return rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, Span(broadcastList, broadcastListSize)); + } + bool sendRPC(IPlayer& peer, int id, Span data, int channel, bool dispatchEvents) override { if (id == INVALID_PACKET_ID) diff --git a/Server/Components/Vehicles/vehicle.cpp b/Server/Components/Vehicles/vehicle.cpp index b39c7f74d..74ad4d698 100644 --- a/Server/Components/Vehicles/vehicle.cpp +++ b/Server/Components/Vehicles/vehicle.cpp @@ -415,7 +415,7 @@ void Vehicle::setPlate(StringView plate) NetCode::RPC::SetVehiclePlate plateRPC; plateRPC.VehicleID = poolID; plateRPC.plate = numberPlate; - PacketHelper::broadcastToSome(plateRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(plateRPC, pool->getNetworks(), streamedFor_.entries()); } const StringView Vehicle::getPlate() @@ -434,7 +434,7 @@ void Vehicle::setColour(int col1, int col2) colourRPC.EventType = VehicleSCMEvent_SetColour; colourRPC.Arg1 = col1; colourRPC.Arg2 = col2; - PacketHelper::broadcastToSome(colourRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(colourRPC, pool->getNetworks(), streamedFor_.entries()); } Pair Vehicle::getColour() const @@ -462,7 +462,7 @@ void Vehicle::setDamageStatus(int PanelStatus, int DoorStatus, uint8_t LightStat static_cast&>(pool->getEventDispatcher()).dispatch(&VehicleEventHandler::onVehicleDamageStatusUpdate, *lock.entry, *vehicleUpdater); } - PacketHelper::broadcastToSome(damageStatus, streamedFor_.entries(), vehicleUpdater); + PacketHelper::broadcastToSome(damageStatus, pool->getNetworks(), streamedFor_.entries(), vehicleUpdater); } void Vehicle::getDamageStatus(int& PanelStatus, int& DoorStatus, int& LightStatus, int& TyreStatus) @@ -481,7 +481,7 @@ void Vehicle::setPaintJob(int paintjob) paintRPC.EventType = VehicleSCMEvent_SetPaintjob; paintRPC.VehicleID = poolID; paintRPC.Arg1 = paintjob; - PacketHelper::broadcastToSome(paintRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(paintRPC, pool->getNetworks(), streamedFor_.entries()); } int Vehicle::getPaintJob() @@ -510,7 +510,7 @@ void Vehicle::addComponent(int component) modRPC.EventType = VehicleSCMEvent_AddComponent; modRPC.VehicleID = poolID; modRPC.Arg1 = component; - PacketHelper::broadcastToSome(modRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(modRPC, pool->getNetworks(), streamedFor_.entries()); } int Vehicle::getComponentInSlot(int slot) @@ -538,7 +538,7 @@ void Vehicle::removeComponent(int component) NetCode::RPC::RemoveVehicleComponent modRPC; modRPC.VehicleID = poolID; modRPC.Component = component; - PacketHelper::broadcastToSome(modRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(modRPC, pool->getNetworks(), streamedFor_.entries()); } void Vehicle::putPlayer(IPlayer& player, int SeatID) @@ -588,7 +588,7 @@ void Vehicle::setHealth(float Health) NetCode::RPC::SetVehicleHealth setVehicleHealthRPC; setVehicleHealthRPC.VehicleID = poolID; setVehicleHealthRPC.health = Health; - PacketHelper::broadcastToSome(setVehicleHealthRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(setVehicleHealthRPC, pool->getNetworks(), streamedFor_.entries()); } void Vehicle::setInterior(int InteriorID) @@ -597,7 +597,7 @@ void Vehicle::setInterior(int InteriorID) NetCode::RPC::LinkVehicleToInterior linkVehicleToInteriorRPC; linkVehicleToInteriorRPC.VehicleID = poolID; linkVehicleToInteriorRPC.InteriorID = InteriorID; - PacketHelper::broadcastToSome(linkVehicleToInteriorRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(linkVehicleToInteriorRPC, pool->getNetworks(), streamedFor_.entries()); } int Vehicle::getInterior() @@ -612,7 +612,7 @@ void Vehicle::setZAngle(float angle) NetCode::RPC::SetVehicleZAngle setVehicleZAngleRPC; setVehicleZAngleRPC.VehicleID = poolID; setVehicleZAngleRPC.angle = angle; - PacketHelper::broadcastToSome(setVehicleZAngleRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(setVehicleZAngleRPC, pool->getNetworks(), streamedFor_.entries()); } float Vehicle::getZAngle() @@ -627,7 +627,7 @@ void Vehicle::setParams(const VehicleParams& params) NetCode::RPC::SetVehicleParams vehicleRPC; vehicleRPC.VehicleID = poolID; vehicleRPC.params = params; - PacketHelper::broadcastToSome(vehicleRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(vehicleRPC, pool->getNetworks(), streamedFor_.entries()); } // Set the vehicle's parameters for a specific player. @@ -655,7 +655,7 @@ void Vehicle::setPosition(Vector3 position) NetCode::RPC::SetVehiclePosition setVehiclePosition; setVehiclePosition.VehicleID = poolID; setVehiclePosition.position = position; - PacketHelper::broadcastToSome(setVehiclePosition, streamedFor_.entries()); + PacketHelper::broadcastToSome(setVehiclePosition, pool->getNetworks(), streamedFor_.entries()); } Vector3 Vehicle::getPosition() const @@ -741,7 +741,7 @@ void Vehicle::attachTrailer(IVehicle& trailer) NetCode::RPC::AttachTrailer trailerRPC; trailerRPC.TrailerID = this->trailer->poolID; trailerRPC.VehicleID = poolID; - PacketHelper::broadcastToSome(trailerRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(trailerRPC, pool->getNetworks(), streamedFor_.entries()); } void Vehicle::detachTrailer() @@ -750,7 +750,7 @@ void Vehicle::detachTrailer() { NetCode::RPC::DetachTrailer trailerRPC; trailerRPC.VehicleID = poolID; - PacketHelper::broadcastToSome(trailerRPC, streamedFor_.entries()); + PacketHelper::broadcastToSome(trailerRPC, pool->getNetworks(), streamedFor_.entries()); trailer->setCab(nullptr); trailer = nullptr; detaching = true; diff --git a/Server/Components/Vehicles/vehicles_impl.hpp b/Server/Components/Vehicles/vehicles_impl.hpp index 492e3378d..f2b6b976f 100644 --- a/Server/Components/Vehicles/vehicles_impl.hpp +++ b/Server/Components/Vehicles/vehicles_impl.hpp @@ -246,7 +246,7 @@ class VehiclesComponent final : public IVehiclesComponent, public CoreEventHandl enterExitRPC.EventType = VehicleSCMEvent_EnterExitModShop; enterExitRPC.Arg1 = scmEvent.Arg1; enterExitRPC.Arg2 = scmEvent.Arg2; - PacketHelper::broadcastToSome(enterExitRPC, vehicle.streamedForPlayers(), &peer); + PacketHelper::broadcastToSome(enterExitRPC, self.getNetworks(), vehicle.streamedForPlayers(), &peer); break; } } @@ -292,6 +292,16 @@ class VehiclesComponent final : public IVehiclesComponent, public CoreEventHandl } vehicleDeathHandler; public: + ICore* getCore() + { + return core; + } + + const FlatPtrHashSet& getNetworks() + { + return core->getNetworks(); + } + IPlayerPool& getPlayers() { return core->getPlayers(); diff --git a/Server/Source/player.cpp b/Server/Source/player.cpp index 76eaeeb81..1e7e99afc 100644 --- a/Server/Source/player.cpp +++ b/Server/Source/player.cpp @@ -374,3 +374,51 @@ void Player::ban(StringView reason) pool_.core.getConfig().writeBans(); kick(); } + +void Player::broadcastRPCToStreamed(int id, Span data, int channel, bool skipFrom) const +{ + for (auto network : pool_.core.getNetworks()) + { + if (network) + { + network->broadcastRPC(id, data, channel, streamedFor_.entries(), skipFrom ? this : nullptr, true); + } + } +} + +void Player::broadcastPacketToStreamed(Span data, int channel, bool skipFrom) const +{ + for (auto network : pool_.core.getNetworks()) + { + if (network) + { + network->broadcastPacket(data, channel, streamedFor_.entries(), skipFrom ? this : nullptr, true); + } + } +} + +void Player::broadcastSyncPacket(Span data, int channel) const +{ + FlatPtrHashSet broadcastList; + for (IPlayer* p : streamedFor_.entries()) + { + Player* player = static_cast(p); + if (player == this) + { + continue; + } + + if (shouldSendSyncPacket(player)) + { + broadcastList.emplace(p); + } + } + + for (auto network : pool_.core.getNetworks()) + { + if (network) + { + network->broadcastPacket(data, channel, broadcastList, nullptr, true); + } + } +} diff --git a/Server/Source/player_impl.hpp b/Server/Source/player_impl.hpp index f7b728652..ef5d121f0 100644 --- a/Server/Source/player_impl.hpp +++ b/Server/Source/player_impl.hpp @@ -386,32 +386,7 @@ struct Player final : public IPlayer, public PoolIDProvider, public NoCopy /// Attempt to broadcast an RPC derived from NetworkPacketBase to the player's streamed peers /// @param packet The packet to send - void broadcastRPCToStreamed(int id, Span data, int channel, bool skipFrom = false) const override - { - for (IPlayer* player : streamedForPlayers()) - { - if (skipFrom && player == this) - { - continue; - } - player->sendRPC(id, data, channel); - } - } - - /// Attempt to broadcast a packet derived from NetworkPacketBase to the player's streamed peers - /// @param packet The packet to send - void broadcastPacketToStreamed(Span data, int channel, bool skipFrom = true) const override - { - for (IPlayer* p : streamedFor_.entries()) - { - Player* player = static_cast(p); - if (skipFrom && player == this) - { - continue; - } - player->sendPacket(data, channel); - } - } + void broadcastRPCToStreamed(int id, Span data, int channel, bool skipFrom = false) const override; inline bool shouldSendSyncPacket(Player* other) const { @@ -430,21 +405,11 @@ struct Player final : public IPlayer, public PoolIDProvider, public NoCopy /// Attempt to broadcast a packet derived from NetworkPacketBase to the player's streamed peers /// @param packet The packet to send - void broadcastSyncPacket(Span data, int channel) const override - { - for (IPlayer* p : streamedFor_.entries()) - { - Player* player = static_cast(p); - if (player == this) - { - continue; - } - if (shouldSendSyncPacket(player)) - { - player->sendPacket(data, channel); - } - } - } + void broadcastPacketToStreamed(Span data, int channel, bool skipFrom = true) const override; + + /// Attempt to broadcast a packet derived from NetworkPacketBase to the player's streamed peers + /// @param packet The packet to send + void broadcastSyncPacket(Span data, int channel) const override; void createExplosion(Vector3 vec, int type, float radius) override { diff --git a/Server/Source/player_pool.hpp b/Server/Source/player_pool.hpp index 8b229a5bd..291b7e0b4 100644 --- a/Server/Source/player_pool.hpp +++ b/Server/Source/player_pool.hpp @@ -1708,7 +1708,7 @@ struct PlayerPool final : public IPlayerPool, public NetworkEventHandler, public playerJoinPacket.Col = player.colour_; playerJoinPacket.IsNPC = player.isBot_; playerJoinPacket.Name = StringView(player.name_); - PacketHelper::broadcastToSome(playerJoinPacket, storage.entries(), &peer); + PacketHelper::broadcastToSome(playerJoinPacket, core.getNetworks(), storage.entries(), &peer); for (IPlayer* other : storage.entries()) { @@ -2187,7 +2187,7 @@ struct PlayerPool final : public IPlayerPool, public NetworkEventHandler, public IVehicle* vehicle = vehiclesComponent->get(player->unoccupiedSync_.VehicleID); if (vehicle) { - PacketHelper::broadcastToSome(player->unoccupiedSync_, vehicle->streamedForPlayers(), player); + PacketHelper::broadcastToSome(player->unoccupiedSync_, core.getNetworks(), vehicle->streamedForPlayers(), player); } } } diff --git a/Shared/Network/packet.hpp b/Shared/Network/packet.hpp index ef601ee03..6efadb8dc 100644 --- a/Shared/Network/packet.hpp +++ b/Shared/Network/packet.hpp @@ -5,37 +5,45 @@ #include #include -enum class NetworkPacketType { - Packet, - RPC, +enum class NetworkPacketType +{ + Packet, + RPC, }; /// Class used for declaring netcode packets /// Provides an array of packet IDs /// @typeparam PacketIDs A list of packet IDs for each network in the ENetworkType enum template -struct NetworkPacketBase { - static constexpr const int PacketID = PktID; - static constexpr const NetworkPacketType PacketType = PktType; - static constexpr const int PacketChannel = PktChannel; +struct NetworkPacketBase +{ + static constexpr const int PacketID = PktID; + static constexpr const NetworkPacketType PacketType = PktType; + static constexpr const int PacketChannel = PktChannel; - constexpr static void addEventHandler(ICore& core, SingleNetworkInEventHandler* handler, event_order_t priority = EventPriority_Default) - { - if (PacketType == NetworkPacketType::RPC) { - core.addPerRPCInEventHandler(handler, priority); - } else if (PacketType == NetworkPacketType::Packet) { - core.addPerPacketInEventHandler(handler, priority); - } - } + constexpr static void addEventHandler(ICore& core, SingleNetworkInEventHandler* handler, event_order_t priority = EventPriority_Default) + { + if (PacketType == NetworkPacketType::RPC) + { + core.addPerRPCInEventHandler(handler, priority); + } + else if (PacketType == NetworkPacketType::Packet) + { + core.addPerPacketInEventHandler(handler, priority); + } + } - constexpr static void removeEventHandler(ICore& core, SingleNetworkInEventHandler* handler, event_order_t priority = EventPriority_Default) - { - if (PacketType == NetworkPacketType::RPC) { - core.removePerRPCInEventHandler(handler); - } else if (PacketType == NetworkPacketType::Packet) { - core.removePerPacketInEventHandler(handler); - } - } + constexpr static void removeEventHandler(ICore& core, SingleNetworkInEventHandler* handler, event_order_t priority = EventPriority_Default) + { + if (PacketType == NetworkPacketType::RPC) + { + core.removePerRPCInEventHandler(handler); + } + else if (PacketType == NetworkPacketType::Packet) + { + core.removePerPacketInEventHandler(handler); + } + } }; std::false_type is_network_packet_impl(...); @@ -46,79 +54,99 @@ std::true_type is_network_packet_impl(NetworkPacketBase using is_network_packet = decltype(is_network_packet_impl(std::declval())); -struct PacketHelper { - /// Attempt to send a packet derived from NetworkPacketBase to the peer - /// @param packet The packet to send - /// @param peer The peer to send the packet to - template ::value>> - static bool send(const Packet& packet, IPlayer& peer) - { - NetworkBitStream bs; - packet.write(bs); - if constexpr (Packet::PacketType == NetworkPacketType::RPC) { - return peer.sendRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); - } else if constexpr (Packet::PacketType == NetworkPacketType::Packet) { - return peer.sendPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); - } - } +struct PacketHelper +{ + /// Attempt to send a packet derived from NetworkPacketBase to the peer + /// @param packet The packet to send + /// @param peer The peer to send the packet to + template ::value>> + static bool send(const Packet& packet, IPlayer& peer) + { + NetworkBitStream bs; + packet.write(bs); + if constexpr (Packet::PacketType == NetworkPacketType::RPC) + { + return peer.sendRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); + } + else if constexpr (Packet::PacketType == NetworkPacketType::Packet) + { + return peer.sendPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); + } + } - /// Attempt to send a packet derived from NetworkPacketBase to the list of peers - /// @param packet The packet to send - /// @param players The list of peers to send the packet to - /// @param skipFrom The player to skip in the list of peers - template ::value>> - static void broadcastToSome(const Packet& packet, const FlatPtrHashSet& players, const IPlayer* skipFrom = nullptr) - { - NetworkBitStream bs; - packet.write(bs); - for (IPlayer* peer : players) { - if (peer != skipFrom) { - if constexpr (Packet::PacketType == NetworkPacketType::RPC) { - peer->sendRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); - } else if constexpr (Packet::PacketType == NetworkPacketType::Packet) { - peer->sendPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); - } - } - } - } + /// Attempt to send a packet derived from NetworkPacketBase to the list of peers + /// @param packet The packet to send + /// @param players The list of peers to send the packet to + /// @param skipFrom The player to skip in the list of peers + template ::value>> + static void broadcastToSome(const Packet& packet, const FlatPtrHashSet& networks, const FlatPtrHashSet& players, const IPlayer* skipFrom = nullptr) + { + NetworkBitStream bs; + packet.write(bs); - /// Attempt to send a packet derived from NetworkPacketBase to the players that a player is streamed for - /// @param packet The packet to send - /// @param player The player whose streamed players to send to - /// @param skipFrom Whether to skip the player when sending the packet - template ::value>> - static void broadcastToStreamed(const Packet& packet, IPlayer& player, bool skipFrom = false) - { - NetworkBitStream bs; - packet.write(bs); - if constexpr (Packet::PacketType == NetworkPacketType::RPC) { - return player.broadcastRPCToStreamed(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, skipFrom); - } else if constexpr (Packet::PacketType == NetworkPacketType::Packet) { - return player.broadcastPacketToStreamed(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, skipFrom); - } - } + if constexpr (Packet::PacketType == NetworkPacketType::RPC) + { + for (auto network : networks) + { + if (network) + { + network->broadcastRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, players, skipFrom, true); + } + } + } + else if constexpr (Packet::PacketType == NetworkPacketType::Packet) + { + for (auto network : networks) + { + if (network) + { + network->broadcastPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, players, skipFrom, true); + } + } + } + } - /// Broadcast a sync packet - template ::value>> - static void broadcastSyncPacket(const Packet& packet, IPlayer& player) - { - static_assert(Packet::PacketType == NetworkPacketType::Packet, "broadcastSyncPacket can only be used with NetworkPacketType::Packet"); - NetworkBitStream bs; - packet.write(bs); - return player.broadcastSyncPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); - } + /// Attempt to send a packet derived from NetworkPacketBase to the players that a player is streamed for + /// @param packet The packet to send + /// @param player The player whose streamed players to send to + /// @param skipFrom Whether to skip the player when sending the packet + template ::value>> + static void broadcastToStreamed(const Packet& packet, IPlayer& player, bool skipFrom = false) + { + NetworkBitStream bs; + packet.write(bs); + if constexpr (Packet::PacketType == NetworkPacketType::RPC) + { + return player.broadcastRPCToStreamed(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, skipFrom); + } + else if constexpr (Packet::PacketType == NetworkPacketType::Packet) + { + return player.broadcastPacketToStreamed(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, skipFrom); + } + } - /// Attempt to send a packet derived from NetworkPacketBase to all players in the player pool - /// @param packet The packet to send - /// @param players The player pool - /// @param skipFrom The player to skip in the list of peers - template ::value, Packet>> - static void broadcast(const Packet& packet, IPlayerPool& players, const IPlayer* skipFrom = nullptr) - { - NetworkBitStream bs; - packet.write(bs); - if constexpr (Packet::PacketType == NetworkPacketType::RPC) { - players.broadcastRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, skipFrom); - } - } + /// Broadcast a sync packet + template ::value>> + static void broadcastSyncPacket(const Packet& packet, IPlayer& player) + { + static_assert(Packet::PacketType == NetworkPacketType::Packet, "broadcastSyncPacket can only be used with NetworkPacketType::Packet"); + NetworkBitStream bs; + packet.write(bs); + return player.broadcastSyncPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel); + } + + /// Attempt to send a packet derived from NetworkPacketBase to all players in the player pool + /// @param packet The packet to send + /// @param players The player pool + /// @param skipFrom The player to skip in the list of peers + template ::value, Packet>> + static void broadcast(const Packet& packet, IPlayerPool& players, const IPlayer* skipFrom = nullptr) + { + NetworkBitStream bs; + packet.write(bs); + if constexpr (Packet::PacketType == NetworkPacketType::RPC) + { + players.broadcastRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, skipFrom); + } + } }; diff --git a/lib/RakNet b/lib/RakNet index a3bbcd613..51eaf8ccd 160000 --- a/lib/RakNet +++ b/lib/RakNet @@ -1 +1 @@ -Subproject commit a3bbcd613dceaa58386f1bb9be944e0d555d40e7 +Subproject commit 51eaf8ccdb8967946662787cb64a953b8093be12 From b9f9661a68fa0838009a64037c36ef6be012748b Mon Sep 17 00:00:00 2001 From: iAmir Date: Wed, 24 Apr 2024 18:24:28 +0330 Subject: [PATCH 2/3] rename list based broadcast functions --- SDK/include/network.hpp | 8 ++++---- Server/Components/LegacyNetwork/legacy_network_impl.hpp | 4 ++-- Server/Source/player.cpp | 6 +++--- Shared/Network/packet.hpp | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/SDK/include/network.hpp b/SDK/include/network.hpp index ef4b5d299..bf563321d 100644 --- a/SDK/include/network.hpp +++ b/SDK/include/network.hpp @@ -345,20 +345,20 @@ struct INetwork : public IExtensible /// Update server parameters virtual void update() = 0; - /// Attempt to broadcast a packet to everyone on this network + /// Attempt to broadcast a packet to a specific list of players on this network /// @param data The data span with the length in BITS /// @param players list of players to send packet to /// @param exceptPeer send RPC to everyone except this peer /// @param dispatchEvents dispatch packet related events - virtual bool broadcastPacket(Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents = true) = 0; + virtual bool broadcastPacketToSome(Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents = true) = 0; - /// Attempt to broadcast an RPC to everyone on this network + /// Attempt to broadcast an RPC to a specific list of players on this network /// @param id The RPC ID for the current network /// @param data The data span with the length in BITS /// @param players list of players to send RPC to /// @param exceptPeer send RPC to everyone except this peer /// @param dispatchEvents dispatch RPC related events - virtual bool broadcastRPC(int id, Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents = true) = 0; + virtual bool broadcastRPCToSome(int id, Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents = true) = 0; }; /// A component interface which allows for writing a network component diff --git a/Server/Components/LegacyNetwork/legacy_network_impl.hpp b/Server/Components/LegacyNetwork/legacy_network_impl.hpp index 6c49c2dc3..ed1ebf224 100644 --- a/Server/Components/LegacyNetwork/legacy_network_impl.hpp +++ b/Server/Components/LegacyNetwork/legacy_network_impl.hpp @@ -138,7 +138,7 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi return rakNetServer.Send((const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, RakNet::UNASSIGNED_PLAYER_ID, true); } - bool broadcastPacket(Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents) override + bool broadcastPacketToSome(Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents) override { // Don't use constructor because it takes bytes; we want bits NetworkBitStream bs; @@ -292,7 +292,7 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi return rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, RakNet::UNASSIGNED_PLAYER_ID, true, false, RakNet::UNASSIGNED_NETWORK_ID, nullptr); } - bool broadcastRPC(int id, Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents) override + bool broadcastRPCToSome(int id, Span data, int channel, const FlatPtrHashSet& players, const IPlayer* exceptPeer, bool dispatchEvents) override { if (id == INVALID_PACKET_ID) { diff --git a/Server/Source/player.cpp b/Server/Source/player.cpp index 1e7e99afc..a148a12be 100644 --- a/Server/Source/player.cpp +++ b/Server/Source/player.cpp @@ -381,7 +381,7 @@ void Player::broadcastRPCToStreamed(int id, Span data, int channel, boo { if (network) { - network->broadcastRPC(id, data, channel, streamedFor_.entries(), skipFrom ? this : nullptr, true); + network->broadcastRPCToSome(id, data, channel, streamedFor_.entries(), skipFrom ? this : nullptr, true); } } } @@ -392,7 +392,7 @@ void Player::broadcastPacketToStreamed(Span data, int channel, bool ski { if (network) { - network->broadcastPacket(data, channel, streamedFor_.entries(), skipFrom ? this : nullptr, true); + network->broadcastPacketToSome(data, channel, streamedFor_.entries(), skipFrom ? this : nullptr, true); } } } @@ -418,7 +418,7 @@ void Player::broadcastSyncPacket(Span data, int channel) const { if (network) { - network->broadcastPacket(data, channel, broadcastList, nullptr, true); + network->broadcastPacketToSome(data, channel, broadcastList, nullptr, true); } } } diff --git a/Shared/Network/packet.hpp b/Shared/Network/packet.hpp index 6efadb8dc..514526cfb 100644 --- a/Shared/Network/packet.hpp +++ b/Shared/Network/packet.hpp @@ -90,7 +90,7 @@ struct PacketHelper { if (network) { - network->broadcastRPC(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, players, skipFrom, true); + network->broadcastRPCToSome(Packet::PacketID, Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, players, skipFrom, true); } } } @@ -100,7 +100,7 @@ struct PacketHelper { if (network) { - network->broadcastPacket(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, players, skipFrom, true); + network->broadcastPacketToSome(Span(bs.GetData(), bs.GetNumberOfBitsUsed()), Packet::PacketChannel, players, skipFrom, true); } } } From e286b32198b80a546cf00ee13b576314cac470c1 Mon Sep 17 00:00:00 2001 From: iAmir Date: Sun, 28 Apr 2024 13:19:07 +0330 Subject: [PATCH 3/3] sync raknet & delete broadcastList if size is 0 --- .../LegacyNetwork/legacy_network_impl.hpp | 26 ++++++++++++++++--- lib/RakNet | 2 +- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/Server/Components/LegacyNetwork/legacy_network_impl.hpp b/Server/Components/LegacyNetwork/legacy_network_impl.hpp index ed1ebf224..cd2e55516 100644 --- a/Server/Components/LegacyNetwork/legacy_network_impl.hpp +++ b/Server/Components/LegacyNetwork/legacy_network_impl.hpp @@ -193,8 +193,17 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi } } - const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED; - return rakNetServer.Send((const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, Span(broadcastList, broadcastListSize)); + if (broadcastListSize) + { + const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED; + return rakNetServer.Send((const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, broadcastList, broadcastListSize); + } + else + { + delete[] broadcastList; + } + + return true; } bool sendPacket(IPlayer& peer, Span data, int channel, bool dispatchEvents) override @@ -347,8 +356,17 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi } } - const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED; - return rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, Span(broadcastList, broadcastListSize)); + if (broadcastListSize) + { + const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED; + return rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, broadcastList, broadcastListSize); + } + else + { + delete[] broadcastList; + } + + return true; } bool sendRPC(IPlayer& peer, int id, Span data, int channel, bool dispatchEvents) override diff --git a/lib/RakNet b/lib/RakNet index 51eaf8ccd..43495d709 160000 --- a/lib/RakNet +++ b/lib/RakNet @@ -1 +1 @@ -Subproject commit 51eaf8ccdb8967946662787cb64a953b8093be12 +Subproject commit 43495d709b51d509a3c869eed834f79e94c9ee7c