Skip to content

Commit 22270db

Browse files
committed
player attached objects
1 parent 73c6ed6 commit 22270db

7 files changed

Lines changed: 221 additions & 77 deletions

File tree

SDK/include/Server/Components/Objects/objects.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ struct IObject : public IBaseObject
216216
struct IPlayerObject : public IBaseObject
217217
{
218218
virtual void attachToObject(IPlayerObject& object, Vector3 offset, Vector3 rotation) = 0;
219+
220+
/// Attach the object to a player
221+
virtual void attachToPlayer(IPlayer& player, Vector3 offset, Vector3 rotation) = 0;
219222
};
220223

221224
struct ObjectEventHandler;

Server/Components/Objects/object.cpp

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
Object::~Object()
1313
{
1414
eraseFromProcessed(true /* force */);
15+
objects_.getAttachedToPlayers().erase(this);
1516
}
1617

1718
void Object::destream()
@@ -143,6 +144,27 @@ void Object::setRotation(GTAQuat rotation)
143144
PacketHelper::broadcast(setObjectRotationRPC, objects_.getPlayers());
144145
}
145146

147+
void Object::attachToPlayer(IPlayer& player, Vector3 offset, Vector3 rotation)
148+
{
149+
const int id = player.getID();
150+
setAttachmentData(ObjectAttachmentData::Type::Player, id, offset, rotation, true);
151+
NetCode::RPC::AttachObjectToPlayer attachObjectToPlayerRPC;
152+
attachObjectToPlayerRPC.ObjectID = poolID;
153+
attachObjectToPlayerRPC.PlayerID = id;
154+
attachObjectToPlayerRPC.Offset = offset;
155+
attachObjectToPlayerRPC.Rotation = rotation;
156+
PacketHelper::broadcastToStreamed(attachObjectToPlayerRPC, player);
157+
158+
objects_.getAttachedToPlayers().insert(this);
159+
}
160+
161+
void Object::resetAttachment()
162+
{
163+
objects_.getAttachedToPlayers().erase(this);
164+
this->BaseObject<IObject>::resetAttachment();
165+
restream();
166+
}
167+
146168
void PlayerObject::restream()
147169
{
148170
createObjectForClient(objects_.getPlayer());
@@ -241,7 +263,7 @@ void PlayerObject::createForPlayer()
241263
{
242264
createObjectForClient(objects_.getPlayer());
243265

244-
if (isMoving() || getAttachmentData().type == ObjectAttachmentData::Type::Player)
266+
if (isMoving())
245267
{
246268
delayedProcessingTime_ = Time::now() + Seconds(1);
247269
enableDelayedProcessing();
@@ -278,9 +300,58 @@ void PlayerObject::setRotation(GTAQuat rotation)
278300
PlayerObject::~PlayerObject()
279301
{
280302
eraseFromProcessed(true /* force*/);
303+
this->objects_.getAttachedToPlayerObjects().erase(this);
281304
}
282305

283306
void PlayerObject::destream()
284307
{
285308
destroyForPlayer();
286309
}
310+
311+
void PlayerObject::resetAttachment()
312+
{
313+
this->objects_.getAttachedToPlayerObjects().erase(this);
314+
this->BaseObject<IPlayerObject>::resetAttachment();
315+
restream();
316+
}
317+
318+
void PlayerObject::attachToPlayer(IPlayer& player, Vector3 offset, Vector3 rotation)
319+
{
320+
this->objects_.getAttachedToPlayerObjects().insert(this);
321+
setAttachmentData(ObjectAttachmentData::Type::Player, player.getID(), offset, rotation, true);
322+
restream();
323+
}
324+
325+
void PlayerObject::createObjectForClient(IPlayer& player)
326+
{
327+
auto& attach = getAttachmentData();
328+
329+
// Object attached to player.
330+
if (attach.type == ObjectAttachmentData::Type::Player)
331+
{
332+
auto attachTo = objects_.getComponent().getPlayers().get(attach.ID);
333+
334+
// Invalid player or player is not streamed.
335+
// Object won't be created on client.
336+
if (!attachTo || !attachTo->isStreamedInForPlayer(player))
337+
{
338+
destream();
339+
return;
340+
}
341+
342+
// Create object.
343+
this->BaseObject<IPlayerObject>::createObjectForClient(player);
344+
345+
// Attach object.
346+
NetCode::RPC::AttachObjectToPlayer attachObjectToPlayerRPC;
347+
attachObjectToPlayerRPC.ObjectID = poolID;
348+
attachObjectToPlayerRPC.PlayerID = attach.ID;
349+
attachObjectToPlayerRPC.Offset = attach.offset;
350+
attachObjectToPlayerRPC.Rotation = attach.rotation;
351+
PacketHelper::send(attachObjectToPlayerRPC, player);
352+
return;
353+
}
354+
355+
// Create object.
356+
this->BaseObject<IPlayerObject>::createObjectForClient(player);
357+
}

Server/Components/Objects/object.hpp

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -367,11 +367,7 @@ class Object final : public BaseObject<IObject>
367367

368368
void stop() override;
369369

370-
void resetAttachment() override
371-
{
372-
this->BaseObject<IObject>::resetAttachment();
373-
restream();
374-
}
370+
void resetAttachment() override;
375371

376372
void setPosition(Vector3 position) override;
377373

@@ -407,17 +403,7 @@ class Object final : public BaseObject<IObject>
407403
restream();
408404
}
409405

410-
void attachToPlayer(IPlayer& player, Vector3 offset, Vector3 rotation) override
411-
{
412-
const int id = player.getID();
413-
setAttachmentData(ObjectAttachmentData::Type::Player, id, offset, rotation, true);
414-
NetCode::RPC::AttachObjectToPlayer attachObjectToPlayerRPC;
415-
attachObjectToPlayerRPC.ObjectID = poolID;
416-
attachObjectToPlayerRPC.PlayerID = id;
417-
attachObjectToPlayerRPC.Offset = offset;
418-
attachObjectToPlayerRPC.Rotation = rotation;
419-
PacketHelper::broadcastToStreamed(attachObjectToPlayerRPC, player);
420-
}
406+
void attachToPlayer(IPlayer& player, Vector3 offset, Vector3 rotation) override;
421407

422408
~Object();
423409
void destream();
@@ -451,6 +437,8 @@ class PlayerObject final : public BaseObject<IPlayerObject>
451437
{
452438
}
453439

440+
void createObjectForClient(IPlayer& player);
441+
454442
void setMaterial(uint32_t materialIndex, int model, StringView textureLibrary, StringView textureName, Colour colour) override;
455443

456444
void setMaterialText(uint32_t materialIndex, StringView text, ObjectMaterialSize materialSize, StringView fontFace, int fontSize, bool bold, Colour fontColour, Colour backgroundColour, ObjectMaterialTextAlign align) override;
@@ -461,11 +449,7 @@ class PlayerObject final : public BaseObject<IPlayerObject>
461449

462450
bool advance(Microseconds elapsed, TimePoint now);
463451

464-
void resetAttachment() override
465-
{
466-
this->BaseObject<IPlayerObject>::resetAttachment();
467-
restream();
468-
}
452+
void resetAttachment() override;
469453

470454
void setPosition(Vector3 position) override;
471455

@@ -501,6 +485,8 @@ class PlayerObject final : public BaseObject<IPlayerObject>
501485
restream();
502486
}
503487

488+
void attachToPlayer(IPlayer& player, Vector3 offset, Vector3 rotation) override;
489+
504490
~PlayerObject();
505491
void destream();
506492
};

Server/Components/Objects/objects_impl.hpp

Lines changed: 20 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class ObjectComponent final : public IObjectsComponent, public CoreEventHandler,
2424
std::list<uint16_t> slotsUsedByPlayerObjects;
2525
FlatPtrHashSet<PlayerObject> processedPlayerObjects;
2626
FlatPtrHashSet<Object> processedObjects;
27+
FlatPtrHashSet<Object> attachedToPlayer;
2728
bool defCameraCollision = true;
2829

2930
ICustomModelsComponent* models = nullptr;
@@ -414,54 +415,9 @@ class ObjectComponent final : public IObjectsComponent, public CoreEventHandler,
414415
return storage._entries();
415416
}
416417

417-
void onPoolEntryDestroyed(IPlayer& player) override
418-
{
419-
const int pid = player.getID();
420-
for (IObject* obj : storage)
421-
{
422-
const ObjectAttachmentData& data = obj->getAttachmentData();
423-
if (data.type == ObjectAttachmentData::Type::Player && data.ID == pid)
424-
{
425-
obj->resetAttachment();
426-
}
427-
}
428-
}
418+
void onPoolEntryDestroyed(IPlayer& player) override;
429419

430-
void onPlayerStreamIn(IPlayer& player, IPlayer& forPlayer) override
431-
{
432-
const int pid = player.getID();
433-
for (IObject* object : storage)
434-
{
435-
Object* obj = static_cast<Object*>(object);
436-
const ObjectAttachmentData& attachment = obj->getAttachmentData();
437-
if (attachment.type == ObjectAttachmentData::Type::Player && attachment.ID == pid)
438-
{
439-
NetCode::RPC::AttachObjectToPlayer attachObjectToPlayerRPC;
440-
attachObjectToPlayerRPC.ObjectID = obj->poolID;
441-
attachObjectToPlayerRPC.PlayerID = attachment.ID;
442-
attachObjectToPlayerRPC.Offset = attachment.offset;
443-
attachObjectToPlayerRPC.Rotation = attachment.rotation;
444-
PacketHelper::send(attachObjectToPlayerRPC, forPlayer);
445-
}
446-
}
447-
448-
IPlayerObjectData* objectData = queryExtension<IPlayerObjectData>(player);
449-
if (objectData)
450-
{
451-
for (int i = 0; i < MAX_ATTACHED_OBJECT_SLOTS; ++i)
452-
{
453-
if (objectData->hasAttachedObject(i))
454-
{
455-
NetCode::RPC::SetPlayerAttachedObject setPlayerAttachedObjectRPC;
456-
setPlayerAttachedObjectRPC.PlayerID = player.getID();
457-
setPlayerAttachedObjectRPC.Index = i;
458-
setPlayerAttachedObjectRPC.Create = true;
459-
setPlayerAttachedObjectRPC.AttachmentData = objectData->getAttachedObject(i);
460-
PacketHelper::send(setPlayerAttachedObjectRPC, forPlayer);
461-
}
462-
}
463-
}
464-
}
420+
void onPlayerStreamIn(IPlayer& player, IPlayer& forPlayer) override;
465421

466422
// Pre-spawn so you can safely attach onPlayerSpawn
467423
void onPlayerSpawn(IPlayer& player) override
@@ -499,13 +455,17 @@ class ObjectComponent final : public IObjectsComponent, public CoreEventHandler,
499455
storage.clear();
500456
isPlayerObject.fill(0);
501457
defCameraCollision = true;
458+
attachedToPlayer.clear();
502459
}
503460

504461
bool is037CompatModeEnabled() const { return compatModeEnabled; }
505462
void onPlayerFinishedDownloading(IPlayer& player) override;
506463

507464
inline const std::list<uint16_t>& getSlotsUsedByPlayerObjects() const { return slotsUsedByPlayerObjects; }
508465
bool isGroupPlayerObjects() const { return groupPlayerObjects ? *groupPlayerObjects : false; }
466+
467+
void onPlayerStreamOut(IPlayer& player, IPlayer& forPlayer) override;
468+
inline FlatPtrHashSet<Object>& getAttachedToPlayers() { return attachedToPlayer; }
509469
};
510470

511471
class PlayerObjectData final : public IPlayerObjectData
@@ -516,6 +476,7 @@ class PlayerObjectData final : public IPlayerObjectData
516476
StaticBitset<MAX_ATTACHED_OBJECT_SLOTS> slotsOccupied_;
517477
StaticArray<ObjectAttachmentSlotData, MAX_ATTACHED_OBJECT_SLOTS> slots_;
518478
MarkedDynamicPoolStorage<PlayerObject, IPlayerObject, 1, OBJECT_POOL_SIZE> storage;
479+
FlatPtrHashSet<PlayerObject> attachedToPlayer_;
519480
bool inObjectSelection_;
520481
bool inObjectEdit_;
521482
bool streamedGlobalObjects_;
@@ -635,6 +596,7 @@ class PlayerObjectData final : public IPlayerObjectData
635596
component_.decrementPlayerCounter(index);
636597
obj->destream();
637598
storage.release(index, false);
599+
attachedToPlayer_.erase(obj);
638600
}
639601
}
640602

@@ -677,6 +639,7 @@ class PlayerObjectData final : public IPlayerObjectData
677639
streamedGlobalObjects_ = false;
678640
slotsOccupied_.reset();
679641
storage.clear();
642+
attachedToPlayer_.clear();
680643
}
681644

682645
void beginSelecting() override
@@ -795,4 +758,14 @@ class PlayerObjectData final : public IPlayerObjectData
795758
{
796759
streamedGlobalObjects_ = value;
797760
}
761+
762+
ObjectComponent& getComponent()
763+
{
764+
return component_;
765+
}
766+
767+
inline FlatPtrHashSet<PlayerObject>& getAttachedToPlayerObjects()
768+
{
769+
return attachedToPlayer_;
770+
}
798771
};

Server/Components/Objects/objects_main.cpp

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,97 @@ void ObjectComponent::onPlayerFinishedDownloading(IPlayer& player)
7272
}
7373
}
7474

75+
void ObjectComponent::onPlayerStreamIn(IPlayer& player, IPlayer& forPlayer)
76+
{
77+
const int pid = player.getID();
78+
for (Object* object : attachedToPlayer)
79+
{
80+
const ObjectAttachmentData& attachment = object->getAttachmentData();
81+
if (attachment.type == ObjectAttachmentData::Type::Player && attachment.ID == pid)
82+
{
83+
NetCode::RPC::AttachObjectToPlayer attachObjectToPlayerRPC;
84+
attachObjectToPlayerRPC.ObjectID = object->poolID;
85+
attachObjectToPlayerRPC.PlayerID = attachment.ID;
86+
attachObjectToPlayerRPC.Offset = attachment.offset;
87+
attachObjectToPlayerRPC.Rotation = attachment.rotation;
88+
PacketHelper::send(attachObjectToPlayerRPC, forPlayer);
89+
}
90+
}
91+
92+
if (PlayerObjectData* objectData = queryExtension<PlayerObjectData>(forPlayer); objectData != nullptr)
93+
{
94+
95+
for (int i = 0; i != MAX_ATTACHED_OBJECT_SLOTS; ++i)
96+
{
97+
if (objectData->hasAttachedObject(i))
98+
{
99+
NetCode::RPC::SetPlayerAttachedObject setPlayerAttachedObjectRPC;
100+
setPlayerAttachedObjectRPC.PlayerID = player.getID();
101+
setPlayerAttachedObjectRPC.Index = i;
102+
setPlayerAttachedObjectRPC.Create = true;
103+
setPlayerAttachedObjectRPC.AttachmentData = objectData->getAttachedObject(i);
104+
PacketHelper::send(setPlayerAttachedObjectRPC, forPlayer);
105+
}
106+
}
107+
108+
for (PlayerObject* object : objectData->getAttachedToPlayerObjects())
109+
{
110+
if (object->getAttachmentData().ID == pid)
111+
{
112+
object->createForPlayer();
113+
}
114+
}
115+
}
116+
}
117+
118+
void ObjectComponent::onPlayerStreamOut(IPlayer& player, IPlayer& forPlayer)
119+
{
120+
const int pid = player.getID();
121+
if (PlayerObjectData* objectData = queryExtension<PlayerObjectData>(forPlayer); objectData != nullptr)
122+
{
123+
for (PlayerObject* object : objectData->getAttachedToPlayerObjects())
124+
{
125+
if (object->getAttachmentData().ID == pid)
126+
{
127+
object->destream();
128+
}
129+
}
130+
}
131+
}
132+
133+
void ObjectComponent::onPoolEntryDestroyed(IPlayer& player)
134+
{
135+
const int pid = player.getID();
136+
for (IObject* obj : attachedToPlayer)
137+
{
138+
if (obj->getAttachmentData().ID == pid)
139+
{
140+
obj->resetAttachment();
141+
}
142+
}
143+
144+
for (IPlayer* other : players->entries())
145+
{
146+
if (other == &player)
147+
{
148+
continue;
149+
}
150+
151+
if (PlayerObjectData* objectData = queryExtension<PlayerObjectData>(other); objectData != nullptr)
152+
{
153+
for (PlayerObject* object : objectData->getAttachedToPlayerObjects())
154+
{
155+
const auto& attach = object->getAttachmentData();
156+
if (attach.ID == pid)
157+
{
158+
object->resetAttachment();
159+
}
160+
}
161+
}
162+
}
163+
}
164+
75165
COMPONENT_ENTRY_POINT()
76166
{
77167
return new ObjectComponent();
78-
}
168+
}

0 commit comments

Comments
 (0)