Skip to content

Commit

Permalink
tweak(gamestate/server): Parse SCRIPT_ENTITY_STATE_CHANGE_EVENT
Browse files Browse the repository at this point in the history
* This game event is sent when a client tries to change state values on a remotely owned entity.
* This event can be received and parsed in ScRTs using an event-handler for 'scriptEntityStateChangeEvent'.
  • Loading branch information
tens0rfl0w committed May 31, 2024
1 parent 0fc6406 commit 534d698
Showing 1 changed file with 151 additions and 0 deletions.
151 changes: 151 additions & 0 deletions code/components/citizen-server-impl/src/state/ServerGameState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5812,6 +5812,156 @@ struct CStopNetworkSyncedSceneEvent

MSGPACK_DEFINE_MAP(sceneId);
};

enum StateChangeType
{
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS,
SET_PED_RELATIONSHIP_GROUP_HASH,
SET_DRIVE_TASK_CRUISE_SPEED,
SET_LOOK_AT_ENTITY,
SET_PLANE_MIN_HEIGHT_ABOVE_TERRAIN,
SET_PED_RAGDOLL_BLOCKING_FLAGS,
SET_TASK_VEHICLE_TEMP_ACTION,
SET_PED_FACIAL_IDLE_ANIM_OVERRIDE,
SET_VEHICLE_LOCK_STATE,
SET_EXCLUSIVE_DRIVER
};

struct CScriptEntityStateChangeEvent
{
uint16_t objectId;
uint16_t stateChangeType;
uint32_t networkTimeOfChange;

std::unordered_map<std::string, msgpack::object> stateData;

std::string stateChangeName;

void Parse(rl::MessageBuffer& buffer)
{
objectId = buffer.Read<uint16_t>(13);
stateChangeType = buffer.Read<uint16_t>(4);
networkTimeOfChange = buffer.Read<uint32_t>(32);

switch (stateChangeType)
{
case SET_BLOCKING_OF_NON_TEMPORARY_EVENTS:
{
bool blockNonTemporaryEvents = buffer.ReadBit();

stateChangeName = "SetBlockingOfNonTemporaryEvents";
stateData["blockNonTemporaryEvents"] = msgpack::object(blockNonTemporaryEvents);
break;
}
case SET_PED_RELATIONSHIP_GROUP_HASH:
{
uint32_t relationshipGroupHash = buffer.Read<uint32_t>(32);

stateChangeName = "SetPedRelationshipGroupHash";
stateData["relationshipGroupHash"] = msgpack::object(relationshipGroupHash);
break;
}
case SET_DRIVE_TASK_CRUISE_SPEED:
{
float cruiseSpeed = buffer.ReadSignedFloat(8, 30.f);

stateChangeName = "SetDriveTaskCruiseSpeed";
stateData["cruiseSpeed"] = msgpack::object(cruiseSpeed);
break;
}
case SET_LOOK_AT_ENTITY:
{
uint16_t objectId = buffer.Read<uint16_t>(13);
uint32_t flags = buffer.Read<uint32_t>(17);
uint32_t timeCapped = buffer.Read<uint32_t>(10);
int time = static_cast<int>(timeCapped * 100) - 1;

stateChangeName = "SetLookAtEntity";
stateData["objectId"] = msgpack::object(objectId);
stateData["flags"] = msgpack::object(flags);
stateData["timeCapped"] = msgpack::object(timeCapped);
stateData["time"] = msgpack::object(time);
break;
}
case SET_PLANE_MIN_HEIGHT_ABOVE_TERRAIN:
{
uint32_t minHeightAboveTerrain = buffer.Read<uint32_t>(32);

stateChangeName = "SetPlaneMinHeightAboveTerrain";
stateData["minHeightAboveTerrain"] = msgpack::object(minHeightAboveTerrain);
break;
}
case SET_PED_RAGDOLL_BLOCKING_FLAGS:
{
uint32_t ragdollBlockFlags = buffer.Read<uint32_t>(32);

stateChangeName = "SetPedRagdollBlockingFlags";
stateData["ragdollBlockFlags"] = msgpack::object(ragdollBlockFlags);
break;
}
case SET_TASK_VEHICLE_TEMP_ACTION:
{
uint16_t objectId = buffer.Read<uint16_t>(13);
int action = buffer.Read<int>(8);
bool hasDuration = buffer.ReadBit();
int duration = hasDuration ? buffer.Read<int>(16) : -1;

stateChangeName = "SetTaskVehicleTempAction";
stateData["objectId"] = msgpack::object(objectId);
stateData["action"] = msgpack::object(action);
stateData["hasDuration"] = msgpack::object(hasDuration);
stateData["duration"] = msgpack::object(duration);
break;
}
case SET_PED_FACIAL_IDLE_ANIM_OVERRIDE:
{
bool clearOverride = buffer.ReadBit();
uint32_t idleClipNameHash = clearOverride ? 0 : buffer.Read<uint32_t>(32);
uint32_t idleClipDictNameHash = clearOverride ? 0 : buffer.Read<uint32_t>(32);

stateChangeName = "SetPedFacialIdleAnimOverride";
stateData["clearOverride"] = msgpack::object(clearOverride);
stateData["idleClipNameHash"] = msgpack::object(idleClipNameHash);
stateData["idleClipDictNameHash"] = msgpack::object(idleClipDictNameHash);
break;
}
case SET_VEHICLE_LOCK_STATE:
{
uint32_t playerLocks = buffer.Read<uint32_t>(32);
bool dontTryToEnterIfLocked = buffer.ReadBit();
uint8_t flags = buffer.Read<uint8_t>(2);

stateChangeName = "SetVehicleLockState";
stateData["playerLocks"] = msgpack::object(playerLocks);
stateData["dontTryToEnterIfLocked"] = msgpack::object(dontTryToEnterIfLocked);
stateData["flags"] = msgpack::object(flags);
break;
}
case SET_EXCLUSIVE_DRIVER:
{
uint16_t exclusiveDriverID = buffer.Read<uint16_t>(13);
uint32_t exclusiveDriverIndex = buffer.Read<uint32_t>(2);

stateChangeName = "SetExclusiveDriver";
stateData["exclusiveDriverID"] = msgpack::object(exclusiveDriverID);
stateData["exclusiveDriverIndex"] = msgpack::object(exclusiveDriverIndex);
break;
}
default:
{
stateChangeName = "Unknown";
break;
}
}
}

inline std::string GetName()
{
return "scriptEntityStateChangeEvent";
}

MSGPACK_DEFINE_MAP(objectId, stateChangeName, networkTimeOfChange, stateData);
};
#endif

#ifdef STATE_RDR3
Expand Down Expand Up @@ -7165,6 +7315,7 @@ std::function<bool()> fx::ServerGameState::GetGameEventHandler(const fx::ClientS
case NETWORK_START_SYNCED_SCENE_EVENT: return GetHandler<CStartNetworkSyncedSceneEvent>(instance, client, std::move(buffer));
case NETWORK_UPDATE_SYNCED_SCENE_EVENT: return GetHandler<CUpdateNetworkSyncedSceneEvent>(instance, client, std::move(buffer));
case NETWORK_STOP_SYNCED_SCENE_EVENT: return GetHandler<CStopNetworkSyncedSceneEvent>(instance, client, std::move(buffer));
case SCRIPT_ENTITY_STATE_CHANGE_EVENT: return GetHandler<CScriptEntityStateChangeEvent>(instance, client, std::move(buffer));
default:
break;
};
Expand Down

0 comments on commit 534d698

Please sign in to comment.