Skip to content

Commit

Permalink
feat(fivem/state): add ConVar to disallow server created entities being
Browse files Browse the repository at this point in the history
deleted by the client
  • Loading branch information
AvarianKnight committed Mar 18, 2024
1 parent 8b93ef2 commit 0969b57
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,7 @@ struct SyncEntityState
bool passedFilter = false;
bool wantsReassign = false;
bool firstOwnerDropped = false;
bool serverCreated = false;

std::list<std::function<void(const fx::ClientSharedPtr& ptr)>> onCreationRPC;

Expand Down Expand Up @@ -905,7 +906,7 @@ struct SyncEntityState

inline bool IsOwnedByServerScript()
{
return GetScriptHash() != 0 && creationToken != 0;
return (GetScriptHash() != 0 && creationToken != 0) || serverCreated;
}

// MAKE SURE YOU HAVE A LOCK BEFORE CALLING THIS
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ std::shared_ptr<ConVar<fx::OneSyncState>> g_oneSyncVar;
std::shared_ptr<ConVar<bool>> g_oneSyncPopulation;
std::shared_ptr<ConVar<bool>> g_oneSyncARQ;

// disallow client from deleting server side entities
std::shared_ptr<ConVar<bool>> g_disallowClientDeleteVar;
static bool g_disallowClientDelete;

static std::shared_ptr<ConVar<bool>> g_networkedSoundsEnabledVar;
static bool g_networkedSoundsEnabled;

Expand Down Expand Up @@ -3077,7 +3081,7 @@ void ServerGameState::ProcessCloneRemove(const fx::ClientSharedPtr& client, rl::

auto entity = GetEntity(0, objectId);

// ack remove no matter if we accept it
// ack remove as the calling client will have removed this entity anyways
ackPacket.Write(3, 3);
ackPacket.Write(13, objectId);
ackPacket.Write(16, uniqifier);
Expand All @@ -3101,6 +3105,21 @@ void ServerGameState::ProcessCloneRemove(const fx::ClientSharedPtr& client, rl::
return;
}

if (entity->serverCreated && g_disallowClientDelete)
{
const auto clientData = GetClientDataUnlocked(this, client);
const auto entIdentifier = MakeHandleUniqifierPair(objectId, uniqifier);
if (auto syncData = clientData->syncedEntities.find(entIdentifier); syncData != clientData->syncedEntities.end())
{
GS_LOG("%s: tried to delete server spawned entity setting entity id %d to be recreated for client %d\n", __func__, objectId, client->GetNetId());
// Reset the created state so they will get resent the entity data on the next server tick
syncData->second.hasCreated = false;
syncData->second.hasNAckedCreate = false;
}

return;
}

GS_LOG("%s: queueing remove (%d - %d)\n", __func__, objectId, uniqifier);
RemoveClone(client, objectId, uniqifier);
}
Expand Down Expand Up @@ -3213,6 +3232,7 @@ auto ServerGameState::CreateEntityFromTree(sync::NetObjEntityType type, const st
entity->creationToken = msec().count();
entity->createdAt = msec();
entity->passedFilter = true;
entity->serverCreated = true;

entity->syncTree = tree;

Expand Down Expand Up @@ -6949,6 +6969,7 @@ static InitFunction initFunction([]()

g_requestControlVar = instance->AddVariable<int>("sv_filterRequestControl", ConVar_None, (int)RequestControlFilterMode::NoFilter, (int*)&g_requestControlFilterState);
g_requestControlSettleVar = instance->AddVariable<int>("sv_filterRequestControlSettleTimer", ConVar_None, 30000, &g_requestControlSettleDelay);
g_disallowClientDeleteVar = instance->AddVariable<bool>("sv_disallowClientDelete", ConVar_None, false, &g_disallowClientDelete);

fx::SetOneSyncGetCallback([]()
{
Expand Down

0 comments on commit 0969b57

Please sign in to comment.