Skip to content

Commit de26f64

Browse files
authored
Merge pull request #565 from openmultiplayer/kseny/attach_obj
Player attached objects.
2 parents 9c30825 + c1fae22 commit de26f64

9 files changed

Lines changed: 223 additions & 87 deletions

File tree

.github/workflows/build.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,6 @@ jobs:
4747
run: |
4848
echo "build_version=$(git describe --always --tags "refs/remotes/origin/${HEAD_REF}")" >> $GITHUB_OUTPUT
4949
echo "build_config=RelWithDebInfo" >> $GITHUB_OUTPUT
50-
echo "build_ubuntu_version=18.04" >> $GITHUB_OUTPUT
51-
echo "build_shared=0" >> $GITHUB_OUTPUT
52-
echo "build_server=1" >> $GITHUB_OUTPUT
53-
echo "build_tools=0" >> $GITHUB_OUTPUT
5450
5551
- name: Setup Python
5652
uses: actions/setup-python@v2
@@ -69,7 +65,7 @@ jobs:
6965
$env:OMP_BUILD_COMMIT=$(git rev-parse HEAD)
7066
mkdir build
7167
cd build
72-
cmake .. -A Win32 -T "ClangCL"
68+
cmake -DCMAKE_BUILD_TYPE=${{ steps.vars.outputs.build_config }} .. -A Win32 -T "ClangCL"
7369
7470
- name: Build
7571
run: |

.github/workflows/release.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,6 @@ jobs:
2727
run: |
2828
echo "build_version=$(git describe --always --tags "refs/remotes/origin/${HEAD_REF}")" >> $GITHUB_OUTPUT
2929
echo "build_config=RelWithDebInfo" >> $GITHUB_OUTPUT
30-
echo "build_ubuntu_version=18.04" >> $GITHUB_OUTPUT
31-
echo "build_shared=0" >> $GITHUB_OUTPUT
32-
echo "build_server=1" >> $GITHUB_OUTPUT
33-
echo "build_tools=0" >> $GITHUB_OUTPUT
3430
3531
- name: Setup Python
3632
uses: actions/setup-python@v2
@@ -49,7 +45,7 @@ jobs:
4945
$env:OMP_BUILD_COMMIT=$(git rev-parse HEAD)
5046
mkdir build
5147
cd build
52-
cmake .. -A Win32 -T "ClangCL"
48+
cmake -DCMAKE_BUILD_TYPE=${{ steps.vars.outputs.build_config }} .. -A Win32 -T "ClangCL"
5349
5450
- name: Build
5551
run: |

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
};

0 commit comments

Comments
 (0)