Skip to content

Commit 1824ce1

Browse files
committed
Optimize batch packets & RPCs using RakNet list commands.
1 parent 25f8a91 commit 1824ce1

File tree

12 files changed

+254
-65
lines changed

12 files changed

+254
-65
lines changed

SDK/include/network.hpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,15 @@ struct INetwork : public IExtensible
348348

349349
/// Update server parameters
350350
virtual void update() = 0;
351+
352+
/// Attempt to broadcast an RPC to a list of players on this network
353+
/// @param id The RPC ID for the current network
354+
/// @param data The data span with the length in BITS
355+
/// @param exceptPeer send RPC to everyone except this peer
356+
/// @param dispatchEvents dispatch RPC related events
357+
virtual bool broadcastPacket(Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer = nullptr, bool dispatchEvents = true) = 0;
358+
359+
virtual bool broadcastRPC(int id, Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer, bool dispatchEvents) = 0;
351360
};
352361

353362
/// A component interface which allows for writing a network component

SDK/include/player.hpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1068,6 +1068,19 @@ struct IPlayerPool : public IExtensible, public IReadOnlyPool<IPlayer>
10681068
/// @param dispatchEvents dispatch RPC related events
10691069
virtual void broadcastRPC(int id, Span<uint8_t> data, int channel, const IPlayer* skipFrom = nullptr, bool dispatchEvents = true) = 0;
10701070

1071+
/// Attempt to broadcast an packet derived from NetworkPacketBase to all peers
1072+
/// @param data The data span with the length in BITS
1073+
/// @param skipFrom send packet to everyone except this player
1074+
/// @param dispatchEvents dispatch packet related events
1075+
virtual void broadcastPacket(Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* skipFrom = nullptr, bool dispatchEvents = true) = 0;
1076+
1077+
/// Attempt to broadcast an RPC derived from NetworkPacketBase to all peers
1078+
/// @param id The RPC ID for the current network
1079+
/// @param data The data span with the length in BITS
1080+
/// @param skipFrom send RPC to everyone except this peer
1081+
/// @param dispatchEvents dispatch RPC related events
1082+
virtual void broadcastRPC(int id, Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* skipFrom = nullptr, bool dispatchEvents = true) = 0;
1083+
10711084
/// Check if player name is valid.
10721085
virtual bool isNameValid(StringView name) const = 0;
10731086

Server/Components/Actors/actor.hpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
4848
bool* validateAnimations_;
4949
ICustomModelsComponent*& modelsComponent_;
5050
IFixesComponent* fixesComponent_;
51+
IPlayerPool& players_;
5152

5253
void restream()
5354
{
@@ -103,7 +104,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
103104
}
104105
}
105106

106-
Actor(int skin, Vector3 pos, float angle, bool* allAnimationLibraries, bool* validateAnimations, ICustomModelsComponent*& modelsComponent, IFixesComponent* fixesComponent)
107+
Actor(int skin, Vector3 pos, float angle, bool* allAnimationLibraries, bool* validateAnimations, ICustomModelsComponent*& modelsComponent, IFixesComponent* fixesComponent, IPlayerPool& players)
107108
: virtualWorld_(0)
108109
, skin_(skin)
109110
, invulnerable_(true)
@@ -116,6 +117,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
116117
, validateAnimations_(validateAnimations)
117118
, modelsComponent_(modelsComponent)
118119
, fixesComponent_(fixesComponent)
120+
, players_(players)
119121
{
120122
}
121123

@@ -125,7 +127,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
125127
NetCode::RPC::SetActorHealthForPlayer RPC;
126128
RPC.ActorID = poolID;
127129
RPC.Health = health_;
128-
PacketHelper::broadcastToSome(RPC, streamedFor_.entries());
130+
PacketHelper::broadcastToSome(RPC, players_, streamedFor_.entries());
129131
}
130132

131133
float getHealth() const override
@@ -196,7 +198,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
196198

197199
NetCode::RPC::ClearActorAnimationsForPlayer RPC;
198200
RPC.ActorID = poolID;
199-
PacketHelper::broadcastToSome(RPC, streamedFor_.entries());
201+
PacketHelper::broadcastToSome(RPC, players_, streamedFor_.entries());
200202
}
201203

202204
bool isStreamedInForPlayer(const IPlayer& player) const override
@@ -264,7 +266,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
264266
NetCode::RPC::SetActorPosForPlayer RPC;
265267
RPC.ActorID = poolID;
266268
RPC.Pos = position;
267-
PacketHelper::broadcastToSome(RPC, streamedFor_.entries());
269+
PacketHelper::broadcastToSome(RPC, players_, streamedFor_.entries());
268270
}
269271

270272
GTAQuat getRotation() const override
@@ -279,7 +281,7 @@ class Actor final : public IActor, public PoolIDProvider, public NoCopy
279281
NetCode::RPC::SetActorFacingAngleForPlayer RPC;
280282
RPC.ActorID = poolID;
281283
RPC.Angle = angle_;
282-
PacketHelper::broadcastToSome(RPC, streamedFor_.entries());
284+
PacketHelper::broadcastToSome(RPC, players_, streamedFor_.entries());
283285
}
284286

285287
void setSkin(int id) override

Server/Components/Actors/actors_main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,7 @@ class ActorsComponent final : public IActorsComponent, public PlayerConnectEvent
145145

146146
IActor* create(int skin, Vector3 pos, float angle) override
147147
{
148-
return storage.emplace(skin, pos, angle, core->getConfig().getBool("game.use_all_animations"), core->getConfig().getBool("game.validate_animations"), modelsComponent, fixesComponent_);
148+
return storage.emplace(skin, pos, angle, core->getConfig().getBool("game.use_all_animations"), core->getConfig().getBool("game.validate_animations"), modelsComponent, fixesComponent_, core->getPlayers());
149149
}
150150

151151
void free() override

Server/Components/LegacyNetwork/legacy_network_impl.hpp

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,85 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi
137137
return rakNetServer.Send((const char*)bs.GetData(), bs.GetNumberOfUnreadBits(), RakNet::HIGH_PRIORITY, reliability, channel, RakNet::UNASSIGNED_PLAYER_ID, true);
138138
}
139139

140+
bool broadcastPacket(Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer, bool dispatchEvents) override
141+
{
142+
{
143+
int playersSize = players.size();
144+
if (players.size() == 2)
145+
{
146+
IPlayer* first = *players.begin();
147+
IPlayer* second = *(players.begin()++);
148+
if (first == exceptPeer || second == exceptPeer)
149+
{
150+
--playersSize;
151+
}
152+
}
153+
if (playersSize == 1)
154+
{
155+
IPlayer* player = *players.begin();
156+
if (player == exceptPeer)
157+
{
158+
return false;
159+
}
160+
}
161+
}
162+
163+
// Don't use constructor because it takes bytes; we want bits
164+
NetworkBitStream bs;
165+
bs.SetData(data.data());
166+
bs.SetWriteOffset(data.size());
167+
bs.SetReadOffset(0);
168+
169+
if (dispatchEvents)
170+
{
171+
uint8_t type;
172+
if (bs.readUINT8(type))
173+
{
174+
if (!outEventDispatcher.stopAtFalse([type, &bs](NetworkOutEventHandler* handler)
175+
{
176+
bs.SetReadOffset(8); // Ignore packet ID
177+
return handler->onSendPacket(nullptr, type, bs);
178+
}))
179+
{
180+
return false;
181+
}
182+
183+
if (!packetOutEventDispatcher.stopAtFalse(type, [&bs](SingleNetworkOutEventHandler* handler)
184+
{
185+
bs.SetReadOffset(8); // Ignore packet ID
186+
return handler->onSend(nullptr, bs);
187+
}))
188+
{
189+
return false;
190+
}
191+
}
192+
}
193+
194+
RakNet::PlayerID* playerIds = new RakNet::PlayerID[players.size()];
195+
int currentId = 0;
196+
for (IPlayer* player : players)
197+
{
198+
if (player != exceptPeer)
199+
{
200+
const PeerNetworkData& netData = player->getNetworkData();
201+
if (netData.network == this)
202+
{
203+
const PeerNetworkData::NetworkID& nid = netData.networkID;
204+
const RakNet::PlayerID rid { unsigned(nid.address.v4), nid.port };
205+
playerIds[currentId++] = rid;
206+
}
207+
}
208+
}
209+
210+
const RakNet::PacketReliability reliability = (channel == OrderingChannel_Reliable) ? RakNet::RELIABLE : ((channel == OrderingChannel_Unordered) ? RakNet::UNRELIABLE : RakNet::UNRELIABLE_SEQUENCED);
211+
const bool res = rakNetServer.SendToList((const char*)bs.GetData(), bs.GetNumberOfBytesUsed(), RakNet::HIGH_PRIORITY, reliability, channel, playerIds, currentId);
212+
if (!res)
213+
{
214+
delete[] playerIds;
215+
}
216+
return res;
217+
}
218+
140219
bool sendPacket(IPlayer& peer, Span<uint8_t> data, int channel, bool dispatchEvents) override
141220
{
142221
const PeerNetworkData& netData = peer.getNetworkData();
@@ -232,6 +311,86 @@ class RakNetLegacyNetwork final : public Network, public CoreEventHandler, publi
232311
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);
233312
}
234313

314+
bool broadcastRPC(int id, Span<uint8_t> data, int channel, const FlatPtrHashSet<IPlayer>& players, const IPlayer* exceptPeer, bool dispatchEvents) override
315+
{
316+
if (id == INVALID_PACKET_ID)
317+
{
318+
return false;
319+
}
320+
321+
{
322+
int playersSize = players.size();
323+
if (players.size() == 2)
324+
{
325+
IPlayer* first = *players.begin();
326+
IPlayer* second = *(players.begin()++);
327+
if (first == exceptPeer || second == exceptPeer)
328+
{
329+
--playersSize;
330+
}
331+
}
332+
if (playersSize == 1)
333+
{
334+
IPlayer* player = *players.begin();
335+
if (player == exceptPeer)
336+
{
337+
return false;
338+
}
339+
}
340+
}
341+
342+
// Don't use constructor because it takes bytes; we want bits
343+
NetworkBitStream bs;
344+
bs.SetData(data.data());
345+
bs.SetWriteOffset(data.size());
346+
bs.SetReadOffset(0);
347+
348+
if (dispatchEvents)
349+
{
350+
if (!outEventDispatcher.stopAtFalse([id, &bs](NetworkOutEventHandler* handler)
351+
{
352+
bs.resetReadPointer();
353+
return handler->onSendRPC(nullptr, id, bs);
354+
}))
355+
{
356+
return false;
357+
}
358+
359+
if (!rpcOutEventDispatcher.stopAtFalse(id, [&bs](SingleNetworkOutEventHandler* handler)
360+
{
361+
bs.resetReadPointer();
362+
return handler->onSend(nullptr, bs);
363+
}))
364+
{
365+
return false;
366+
}
367+
}
368+
369+
RakNet::PlayerID* playerIds = new RakNet::PlayerID[players.size()];
370+
int currentId = 0;
371+
for (IPlayer* player : players)
372+
{
373+
if (player != exceptPeer)
374+
{
375+
const PeerNetworkData& netData = player->getNetworkData();
376+
if (netData.network == this)
377+
{
378+
const PeerNetworkData::NetworkID& nid = netData.networkID;
379+
const RakNet::PlayerID rid { unsigned(nid.address.v4), nid.port };
380+
playerIds[currentId++] = rid;
381+
}
382+
}
383+
}
384+
385+
const RakNet::PacketReliability reliability = (channel == OrderingChannel_Unordered) ? RakNet::RELIABLE : RakNet::RELIABLE_ORDERED;
386+
const bool res = rakNetServer.RPC(id, (const char*)bs.GetData(), bs.GetNumberOfBitsUsed(), RakNet::HIGH_PRIORITY, reliability, channel, playerIds, currentId, false, RakNet::UNASSIGNED_NETWORK_ID);
387+
if (!res)
388+
{
389+
delete[] playerIds;
390+
}
391+
return res;
392+
}
393+
235394
bool sendRPC(IPlayer& peer, int id, Span<uint8_t> data, int channel, bool dispatchEvents) override
236395
{
237396
if (id == INVALID_PACKET_ID)

Server/Components/Vehicles/vehicle.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,7 @@ void Vehicle::setPlate(StringView plate)
415415
NetCode::RPC::SetVehiclePlate plateRPC;
416416
plateRPC.VehicleID = poolID;
417417
plateRPC.plate = numberPlate;
418-
PacketHelper::broadcastToSome(plateRPC, streamedFor_.entries());
418+
PacketHelper::broadcastToSome(plateRPC, pool->getPlayers(), streamedFor_.entries());
419419
}
420420

421421
const StringView Vehicle::getPlate()
@@ -434,7 +434,7 @@ void Vehicle::setColour(int col1, int col2)
434434
colourRPC.EventType = VehicleSCMEvent_SetColour;
435435
colourRPC.Arg1 = col1;
436436
colourRPC.Arg2 = col2;
437-
PacketHelper::broadcastToSome(colourRPC, streamedFor_.entries());
437+
PacketHelper::broadcastToSome(colourRPC, pool->getPlayers(), streamedFor_.entries());
438438
}
439439

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

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

468468
void Vehicle::getDamageStatus(int& PanelStatus, int& DoorStatus, int& LightStatus, int& TyreStatus)
@@ -481,7 +481,7 @@ void Vehicle::setPaintJob(int paintjob)
481481
paintRPC.EventType = VehicleSCMEvent_SetPaintjob;
482482
paintRPC.VehicleID = poolID;
483483
paintRPC.Arg1 = paintjob;
484-
PacketHelper::broadcastToSome(paintRPC, streamedFor_.entries());
484+
PacketHelper::broadcastToSome(paintRPC, pool->getPlayers(), streamedFor_.entries());
485485
}
486486

487487
int Vehicle::getPaintJob()
@@ -510,7 +510,7 @@ void Vehicle::addComponent(int component)
510510
modRPC.EventType = VehicleSCMEvent_AddComponent;
511511
modRPC.VehicleID = poolID;
512512
modRPC.Arg1 = component;
513-
PacketHelper::broadcastToSome(modRPC, streamedFor_.entries());
513+
PacketHelper::broadcastToSome(modRPC, pool->getPlayers(), streamedFor_.entries());
514514
}
515515

516516
int Vehicle::getComponentInSlot(int slot)
@@ -538,7 +538,7 @@ void Vehicle::removeComponent(int component)
538538
NetCode::RPC::RemoveVehicleComponent modRPC;
539539
modRPC.VehicleID = poolID;
540540
modRPC.Component = component;
541-
PacketHelper::broadcastToSome(modRPC, streamedFor_.entries());
541+
PacketHelper::broadcastToSome(modRPC, pool->getPlayers(), streamedFor_.entries());
542542
}
543543

544544
void Vehicle::putPlayer(IPlayer& player, int SeatID)
@@ -588,7 +588,7 @@ void Vehicle::setHealth(float Health)
588588
NetCode::RPC::SetVehicleHealth setVehicleHealthRPC;
589589
setVehicleHealthRPC.VehicleID = poolID;
590590
setVehicleHealthRPC.health = Health;
591-
PacketHelper::broadcastToSome(setVehicleHealthRPC, streamedFor_.entries());
591+
PacketHelper::broadcastToSome(setVehicleHealthRPC, pool->getPlayers(), streamedFor_.entries());
592592
}
593593

594594
void Vehicle::setInterior(int InteriorID)
@@ -597,7 +597,7 @@ void Vehicle::setInterior(int InteriorID)
597597
NetCode::RPC::LinkVehicleToInterior linkVehicleToInteriorRPC;
598598
linkVehicleToInteriorRPC.VehicleID = poolID;
599599
linkVehicleToInteriorRPC.InteriorID = InteriorID;
600-
PacketHelper::broadcastToSome(linkVehicleToInteriorRPC, streamedFor_.entries());
600+
PacketHelper::broadcastToSome(linkVehicleToInteriorRPC, pool->getPlayers(), streamedFor_.entries());
601601
}
602602

603603
int Vehicle::getInterior()
@@ -612,7 +612,7 @@ void Vehicle::setZAngle(float angle)
612612
NetCode::RPC::SetVehicleZAngle setVehicleZAngleRPC;
613613
setVehicleZAngleRPC.VehicleID = poolID;
614614
setVehicleZAngleRPC.angle = angle;
615-
PacketHelper::broadcastToSome(setVehicleZAngleRPC, streamedFor_.entries());
615+
PacketHelper::broadcastToSome(setVehicleZAngleRPC, pool->getPlayers(), streamedFor_.entries());
616616
}
617617

618618
float Vehicle::getZAngle()
@@ -627,7 +627,7 @@ void Vehicle::setParams(const VehicleParams& params)
627627
NetCode::RPC::SetVehicleParams vehicleRPC;
628628
vehicleRPC.VehicleID = poolID;
629629
vehicleRPC.params = params;
630-
PacketHelper::broadcastToSome(vehicleRPC, streamedFor_.entries());
630+
PacketHelper::broadcastToSome(vehicleRPC, pool->getPlayers(), streamedFor_.entries());
631631
}
632632

633633
// Set the vehicle's parameters for a specific player.
@@ -655,7 +655,7 @@ void Vehicle::setPosition(Vector3 position)
655655
NetCode::RPC::SetVehiclePosition setVehiclePosition;
656656
setVehiclePosition.VehicleID = poolID;
657657
setVehiclePosition.position = position;
658-
PacketHelper::broadcastToSome(setVehiclePosition, streamedFor_.entries());
658+
PacketHelper::broadcastToSome(setVehiclePosition, pool->getPlayers(), streamedFor_.entries());
659659
}
660660

661661
Vector3 Vehicle::getPosition() const
@@ -741,7 +741,7 @@ void Vehicle::attachTrailer(IVehicle& trailer)
741741
NetCode::RPC::AttachTrailer trailerRPC;
742742
trailerRPC.TrailerID = this->trailer->poolID;
743743
trailerRPC.VehicleID = poolID;
744-
PacketHelper::broadcastToSome(trailerRPC, streamedFor_.entries());
744+
PacketHelper::broadcastToSome(trailerRPC, pool->getPlayers(), streamedFor_.entries());
745745
}
746746

747747
void Vehicle::detachTrailer()
@@ -750,7 +750,7 @@ void Vehicle::detachTrailer()
750750
{
751751
NetCode::RPC::DetachTrailer trailerRPC;
752752
trailerRPC.VehicleID = poolID;
753-
PacketHelper::broadcastToSome(trailerRPC, streamedFor_.entries());
753+
PacketHelper::broadcastToSome(trailerRPC, pool->getPlayers(), streamedFor_.entries());
754754
trailer->setCab(nullptr);
755755
trailer = nullptr;
756756
detaching = true;

0 commit comments

Comments
 (0)