Skip to content

Commit

Permalink
Optimize batch packets & RPCs using RakNet list commands.
Browse files Browse the repository at this point in the history
  • Loading branch information
Hual committed Jan 11, 2024
1 parent 25f8a91 commit 1824ce1
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 65 deletions.
9 changes: 9 additions & 0 deletions SDK/include/network.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,15 @@ struct INetwork : public IExtensible

/// Update server parameters
virtual void update() = 0;

/// Attempt to broadcast an RPC to a 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 exceptPeer send RPC to everyone except this peer
/// @param dispatchEvents dispatch RPC related events
virtual bool broadcastPacket(Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer = nullptr, bool dispatchEvents = true) = 0;

virtual bool broadcastRPC(int id, Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer, bool dispatchEvents) = 0;
};

/// A component interface which allows for writing a network component
Expand Down
13 changes: 13 additions & 0 deletions SDK/include/player.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1068,6 +1068,19 @@ struct IPlayerPool : public IExtensible, public IReadOnlyPool<IPlayer>
/// @param dispatchEvents dispatch RPC related events
virtual void broadcastRPC(int id, Span<uint8_t> data, int channel, const IPlayer* skipFrom = nullptr, bool dispatchEvents = true) = 0;

/// Attempt to broadcast an packet derived from NetworkPacketBase to all peers
/// @param data The data span with the length in BITS
/// @param skipFrom send packet to everyone except this player
/// @param dispatchEvents dispatch packet related events
virtual void broadcastPacket(Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* skipFrom = nullptr, bool dispatchEvents = true) = 0;

/// Attempt to broadcast an RPC derived from NetworkPacketBase to all peers
/// @param id The RPC ID for the current network
/// @param data The data span with the length in BITS
/// @param skipFrom send RPC to everyone except this peer
/// @param dispatchEvents dispatch RPC related events
virtual void broadcastRPC(int id, Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* skipFrom = nullptr, bool dispatchEvents = true) = 0;

/// Check if player name is valid.
virtual bool isNameValid(StringView name) const = 0;

Expand Down
12 changes: 7 additions & 5 deletions Server/Components/Actors/actor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
bool* validateAnimations_;
ICustomModelsComponent*& modelsComponent_;
IFixesComponent* fixesComponent_;
IPlayerPool& players_;

void restream()
{
Expand Down Expand Up @@ -103,7 +104,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
}
}

Actor(int skin, Vector3 pos, float angle, bool* allAnimationLibraries, bool* validateAnimations, ICustomModelsComponent*& modelsComponent, IFixesComponent* fixesComponent)
Actor(int skin, Vector3 pos, float angle, bool* allAnimationLibraries, bool* validateAnimations, ICustomModelsComponent*& modelsComponent, IFixesComponent* fixesComponent, IPlayerPool& players)
: virtualWorld_(0)
, skin_(skin)
, invulnerable_(true)
Expand All @@ -116,6 +117,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
, validateAnimations_(validateAnimations)
, modelsComponent_(modelsComponent)
, fixesComponent_(fixesComponent)
, players_(players)
{
}

Expand All @@ -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, players_, streamedFor_.entries());
}

float getHealth() const override
Expand Down Expand Up @@ -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, players_, streamedFor_.entries());
}

bool isStreamedInForPlayer(const IPlayer& player) const override
Expand Down Expand Up @@ -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, players_, streamedFor_.entries());
}

GTAQuat getRotation() const override
Expand All @@ -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, players_, streamedFor_.entries());
}

void setSkin(int id) override
Expand Down
2 changes: 1 addition & 1 deletion Server/Components/Actors/actors_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"), modelsComponent, fixesComponent_, core->getPlayers());
}

void free() override
Expand Down
159 changes: 159 additions & 0 deletions Server/Components/LegacyNetwork/legacy_network_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,85 @@ 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<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer, bool dispatchEvents) override
{
{
int playersSize = players.size();
if (players.size() == 2)
{
IPlayer* first = *players.begin();
IPlayer* second = *(players.begin()++);
if (first == exceptPeer || second == exceptPeer)
{
--playersSize;
}
}
if (playersSize == 1)
{
IPlayer* player = *players.begin();
if (player == exceptPeer)
{
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);

if (dispatchEvents)
{
uint8_t type;
if (bs.readUINT8(type))
{
if (!outEventDispatcher.stopAtFalse([type, &bs](NetworkOutEventHandler* handler)
{
bs.SetReadOffset(8); // Ignore packet ID
return handler->onSendPacket(nullptr, type, bs);
}))
{
return false;
}

if (!packetOutEventDispatcher.stopAtFalse(type, [&bs](SingleNetworkOutEventHandler* handler)
{
bs.SetReadOffset(8); // Ignore packet ID
return handler->onSend(nullptr, bs);
}))
{
return false;
}
}
}

RakNet::PlayerID* playerIds = new RakNet::PlayerID[players.size()];
int currentId = 0;
for (IPlayer* player : players)
{
if (player != exceptPeer)
{
const PeerNetworkData& netData = player->getNetworkData();
if (netData.network == this)
{
const PeerNetworkData::NetworkID& nid = netData.networkID;
const RakNet::PlayerID rid { unsigned(nid.address.v4), nid.port };
playerIds[currentId++] = rid;
}
}
}

const RakNet::PacketReliability reliability = (channel == OrderingChannel_Reliable) ? RakNet::RELIABLE : ((channel == OrderingChannel_Unordered) ? RakNet::UNRELIABLE : RakNet::UNRELIABLE_SEQUENCED);
const bool res = rakNetServer.SendToList((const char*)bs.GetData(), bs.GetNumberOfBytesUsed(), RakNet::HIGH_PRIORITY, reliability, channel, playerIds, currentId);
if (!res)
{
delete[] playerIds;
}
return res;
}

bool sendPacket(IPlayer& peer, Span<uint8_t> data, int channel, bool dispatchEvents) override
{
const PeerNetworkData& netData = peer.getNetworkData();
Expand Down Expand Up @@ -232,6 +311,86 @@ 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<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer, bool dispatchEvents) override
{
if (id == INVALID_PACKET_ID)
{
return false;
}

{
int playersSize = players.size();
if (players.size() == 2)
{
IPlayer* first = *players.begin();
IPlayer* second = *(players.begin()++);
if (first == exceptPeer || second == exceptPeer)
{
--playersSize;
}
}
if (playersSize == 1)
{
IPlayer* player = *players.begin();
if (player == exceptPeer)
{
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);

if (dispatchEvents)
{
if (!outEventDispatcher.stopAtFalse([id, &bs](NetworkOutEventHandler* handler)
{
bs.resetReadPointer();
return handler->onSendRPC(nullptr, id, bs);
}))
{
return false;
}

if (!rpcOutEventDispatcher.stopAtFalse(id, [&bs](SingleNetworkOutEventHandler* handler)
{
bs.resetReadPointer();
return handler->onSend(nullptr, bs);
}))
{
return false;
}
}

RakNet::PlayerID* playerIds = new RakNet::PlayerID[players.size()];
int currentId = 0;
for (IPlayer* player : players)
{
if (player != exceptPeer)
{
const PeerNetworkData& netData = player->getNetworkData();
if (netData.network == this)
{
const PeerNetworkData::NetworkID& nid = netData.networkID;
const RakNet::PlayerID rid { unsigned(nid.address.v4), nid.port };
playerIds[currentId++] = rid;
}
}
}

const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED;
const bool res = rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfBitsUsed(), RakNet::HIGH_PRIORITY, reliability, channel, playerIds, currentId, false, RakNet::UNASSIGNED_NETWORK_ID);
if (!res)
{
delete[] playerIds;
}
return res;
}

bool sendRPC(IPlayer& peer, int id, Span<uint8_t> data, int channel, bool dispatchEvents) override
{
if (id == INVALID_PACKET_ID)
Expand Down
26 changes: 13 additions & 13 deletions Server/Components/Vehicles/vehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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->getPlayers(), streamedFor_.entries());
}

const StringView Vehicle::getPlate()
Expand All @@ -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->getPlayers(), streamedFor_.entries());
}

Pair<int, int> Vehicle::getColour() const
Expand Down Expand Up @@ -462,7 +462,7 @@ void Vehicle::setDamageStatus(int PanelStatus, int DoorStatus, uint8_t LightStat
static_cast<DefaultEventDispatcher<VehicleEventHandler>&>(pool->getEventDispatcher()).dispatch(&VehicleEventHandler::onVehicleDamageStatusUpdate, *lock.entry, *vehicleUpdater);
}

PacketHelper::broadcastToSome(damageStatus, streamedFor_.entries(), vehicleUpdater);
PacketHelper::broadcastToSome(damageStatus, pool->getPlayers(), streamedFor_.entries(), vehicleUpdater);
}

void Vehicle::getDamageStatus(int& PanelStatus, int& DoorStatus, int& LightStatus, int& TyreStatus)
Expand All @@ -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->getPlayers(), streamedFor_.entries());
}

int Vehicle::getPaintJob()
Expand Down Expand Up @@ -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->getPlayers(), streamedFor_.entries());
}

int Vehicle::getComponentInSlot(int slot)
Expand Down Expand Up @@ -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->getPlayers(), streamedFor_.entries());
}

void Vehicle::putPlayer(IPlayer& player, int SeatID)
Expand Down Expand Up @@ -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->getPlayers(), streamedFor_.entries());
}

void Vehicle::setInterior(int InteriorID)
Expand All @@ -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->getPlayers(), streamedFor_.entries());
}

int Vehicle::getInterior()
Expand All @@ -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->getPlayers(), streamedFor_.entries());
}

float Vehicle::getZAngle()
Expand All @@ -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->getPlayers(), streamedFor_.entries());
}

// Set the vehicle's parameters for a specific player.
Expand Down Expand Up @@ -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->getPlayers(), streamedFor_.entries());
}

Vector3 Vehicle::getPosition() const
Expand Down Expand Up @@ -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->getPlayers(), streamedFor_.entries());
}

void Vehicle::detachTrailer()
Expand All @@ -750,7 +750,7 @@ void Vehicle::detachTrailer()
{
NetCode::RPC::DetachTrailer trailerRPC;
trailerRPC.VehicleID = poolID;
PacketHelper::broadcastToSome(trailerRPC, streamedFor_.entries());
PacketHelper::broadcastToSome(trailerRPC, pool->getPlayers(), streamedFor_.entries());
trailer->setCab(nullptr);
trailer = nullptr;
detaching = true;
Expand Down
Loading

0 comments on commit 1824ce1

Please sign in to comment.