Skip to content

feat(server/state): expose attachment offset, bone and flags - #4094

Open
Github-Samuel wants to merge 1 commit into
citizenfx:masterfrom
Github-Samuel:feat/server-attachment-getters
Open

feat(server/state): expose attachment offset, bone and flags#4094
Github-Samuel wants to merge 1 commit into
citizenfx:masterfrom
Github-Samuel:feat/server-attachment-getters

Conversation

@Github-Samuel

Copy link
Copy Markdown

Goal of this PR

Let a server see how an entity is attached, not just what it is attached to. GET_ENTITY_ATTACHED_TO gives you the parent entity, but the offset, bone and flags are already parsed and there is currently no way to read them.

How is this PR achieving the goal

CBaseAttachNodeData already carries all of it, and both attach nodes fill it in. CPhysicalAttachDataNode::Parse:

data.hasOffset = state.buffer.ReadBit();
if (data.hasOffset) // Divisor 0x42200000
{
	data.x = state.buffer.ReadSignedFloat(15, 40.f);
	...
data.hasAttachBones = state.buffer.ReadBit();
if (data.hasAttachBones)
{
	data.otherAttachBone = state.buffer.Read<uint16_t>(8);
	data.attachBone = state.buffer.Read<uint16_t>(8);
}
else
{
	data.attachBone = 0xFFFF;
}

data.attachmentFlags = state.buffer.Read<uint32_t>(19);

with CPedAttachDataNode::Serialize writing the same base fields for peds and players. GetAttachment() already resolves whichever of the two the tree has, so this only adds the three getters on top:

native field
GET_ENTITY_ATTACHMENT_OFFSET x, y, z
GET_ENTITY_ATTACHMENT_BONE_INDEX attachBone
GET_ENTITY_ATTACHMENT_FLAGS attachmentFlags

Two details worth calling out, since the two parsers don't behave identically:

  • The offset is gated on hasOffset. CPedAttachDataNode zeroes x/y/z in its else branch but CPhysicalAttachDataNode leaves them untouched, so reading them unconditionally would hand back whatever was last there.
  • attachBone is returned as -1 when it is 0xFFFF, which is what CPhysicalAttachDataNode writes when there are no attach bones.

The flags are the same value the server already relies on for the parachute check in ServerGameState.cpp:

allowed |= (base && ((attachment->attachmentFlags & 130) == 130)); // Parachute attachment flags.

so this is not new data being trusted, just data that scripts couldn't see.

I left the orientation out. It is stored as a quaternion (qx/qy/qz/qw) and there is no four component return type here, so it would mean picking a euler convention and converting, which felt like it deserved its own change rather than being guessed at in this one.

Marked game: gta5 in the declarations: the natives are registered for both, but SyncTrees_RDR3.h returns nullptr from GetAttachment() and its attach nodes are empty stubs, so on RedM they would only ever return the defaults. GetEntityAttachedTo.md has no game line today even though it has the same limitation, so say the word if you would rather these matched it.

This PR applies to the following area(s)

FXServer, OneSync, Natives

Successfully tested on

Game builds: n/a, none of these fields are build gated

Platforms: Windows, Linux

Checklist

  • Code compiles and has been tested successfully.
  • Code explains itself well and/or is documented.
  • My commit message explains what the changes do and what they are for.
  • No extra compilation warnings are added by these changes.

I could not do a full server build locally so I left the first box unchecked. What I did check is that both attach parsers actually write these fields, which of them zero their outputs and which don't, that GetAttachment() resolves both node types, that RedM returns nullptr there so the null checks cover it, and that none of the three names collide with an existing native.

GET_ENTITY_ATTACHED_TO only reads attachedTo out of CBaseAttachNodeData,
even though the attach nodes parse the rest of it. Add getters for the
fields that describe how the entity is attached:

- GET_ENTITY_ATTACHMENT_OFFSET
- GET_ENTITY_ATTACHMENT_BONE_INDEX
- GET_ENTITY_ATTACHMENT_FLAGS

The offset is gated on hasOffset because CPhysicalAttachDataNode leaves
x/y/z alone when that bit is clear, and the bone index maps the 0xFFFF
sentinel that node writes for "no bone" onto -1.

Signed-off-by: Samuel Nicol <99494967+Github-Samuel@users.noreply.github.com>
@github-actions github-actions Bot added the invalid Requires changes before it's considered valid and can be (re)triaged label Jul 29, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

invalid Requires changes before it's considered valid and can be (re)triaged

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant