Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Permissions/Permissions/Permissions.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
<Filter Include="Private\Sqlite">
<UniqueIdentifier>{b090c175-c079-441f-bf0c-01d206683d33}</UniqueIdentifier>
</Filter>
<Filter Include="Private\Cache">
<UniqueIdentifier>{c048ee96-81a8-4d9f-846e-4fbea9158926}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Private\Main.h">
Expand Down Expand Up @@ -45,6 +48,9 @@
<ClInclude Include="Public\AtlasPermissions.h">
<Filter>Public</Filter>
</ClInclude>
<ClInclude Include="Private\Cache\Cache.h">
<Filter>Private\Cache</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="Private\Permissions.cpp">
Expand Down
109 changes: 109 additions & 0 deletions Permissions/Permissions/Private/Cache/Cache.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#pragma once

namespace Permissions::Cache
{
struct permissions_cache_player_permissions
{
size_t permission_hash;
bool active;

permissions_cache_player_permissions(size_t _permission_hash, bool _active)
{
permission_hash = _permission_hash;
active = _active;
}
};

struct permission_cache_player_groups
{
size_t group_hash;
bool active;

permission_cache_player_groups(size_t _group_hash, bool _active)
{
group_hash = _group_hash;
active = _active;
}
};

struct permission_cache_player
{
std::vector<permission_cache_player_groups> groups;
std::vector<permissions_cache_player_permissions> permissions;

permission_cache_player(permission_cache_player_groups group)
{
groups.push_back(group);
}

permission_cache_player(permissions_cache_player_permissions permission)
{
permissions.push_back(permission);
}
};

inline std::hash<std::string> hasher;
inline std::unordered_map<uint64, std::unique_ptr<permission_cache_player>> player_cache;

inline void AddPlayerToGroup(const uint64& steam_id, const FString& group, const bool active)
{
const size_t group_hash = hasher(group.ToString());

auto cache_info = std::find_if(player_cache.begin(), player_cache.end(), [&steam_id](const auto& perm_info) { return perm_info.first == steam_id; });
if (cache_info != player_cache.end())
cache_info->second->groups.push_back(permission_cache_player_groups(group_hash, active));
else
player_cache[steam_id] = std::make_unique<permission_cache_player>(permission_cache_player(permission_cache_player_groups(group_hash, active)));
}

inline void AddPlayerToPermission(const uint64& steam_id, const FString& permission, const bool active)
{
const size_t permission_hash = hasher(permission.ToString());

auto cache_info = std::find_if(player_cache.begin(), player_cache.end(), [&steam_id](const auto& perm_info) { return perm_info.first == steam_id; });
if (cache_info != player_cache.end())
cache_info->second->permissions.push_back(permissions_cache_player_permissions(permission_hash, active));
else
player_cache[steam_id] = std::make_unique<permission_cache_player>(permission_cache_player(permissions_cache_player_permissions(permission_hash, active)));
}

inline void RemovePlayer(const uint64& steam_id)
{
player_cache.erase(steam_id);
}

inline void ClearAll()
{
player_cache.clear();
}

inline const int IsPlayerInGroup(const uint64& steam_id, const FString& group)
{
const auto& cache_info = std::find_if(player_cache.begin(), player_cache.end(), [&steam_id](const auto& perm_info) { return perm_info.first == steam_id; });
if (cache_info == player_cache.end())
return -1;

const size_t group_hash = hasher(group.ToString());

const auto& cache_group_perm = std::find_if(cache_info->second->groups.begin(), cache_info->second->groups.end(), [&group_hash](const auto& group_info) { return group_info.group_hash == group_hash; });
if (cache_group_perm != cache_info->second->groups.end())
return cache_group_perm->active ? 1 : 0;

return -1;
}

inline const int IsPlayerHasPermission(const uint64& steam_id, const FString& permission)
{
const auto& cache_info = std::find_if(player_cache.begin(), player_cache.end(), [&steam_id](const auto& perm_info) { return perm_info.first == steam_id; });
if (cache_info == player_cache.end())
return -1;

const size_t permission_hash = hasher(permission.ToString());

const auto& cache_perm = std::find_if(cache_info->second->permissions.begin(), cache_info->second->permissions.end(), [&permission_hash](const auto& perm_info) { return perm_info.permission_hash == permission_hash; });
if (cache_perm != cache_info->second->permissions.end())
return cache_perm->active ? 1 : 0;

return -1;
}
}
4 changes: 2 additions & 2 deletions Permissions/Permissions/Private/Database/MysqlDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ class MySql : public IDatabase
"WHERE NOT EXISTS(SELECT 1 FROM {} WHERE GroupName = 'Admins');",
table_groups_,
table_groups_));
result |= db_.query(fmt::format("INSERT INTO {} (GroupName)"
"SELECT 'Default'"
result |= db_.query(fmt::format("INSERT INTO {} (GroupName, Permissions)"
"SELECT 'Default', 'Default,'"
"WHERE NOT EXISTS(SELECT 1 FROM {} WHERE GroupName = 'Default');",
table_groups_,
table_groups_));
Expand Down
4 changes: 2 additions & 2 deletions Permissions/Permissions/Private/Database/SqlLiteDB.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ class SqlLite : public IDatabase
db_.exec("INSERT INTO Groups(GroupName, Permissions)"
"SELECT 'Admins', '*,'"
"WHERE NOT EXISTS(SELECT 1 FROM Groups WHERE GroupName = 'Admins');");
db_.exec("INSERT INTO Groups(GroupName)"
"SELECT 'Default'"
db_.exec("INSERT INTO Groups(GroupName, Permissions)"
"SELECT 'Default', 'Default,'"
"WHERE NOT EXISTS(SELECT 1 FROM Groups WHERE GroupName = 'Default');");
}
catch (const std::exception& exception)
Expand Down
39 changes: 32 additions & 7 deletions Permissions/Permissions/Private/Hooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,20 @@ namespace Permissions::Hooks
DECLARE_HOOK(AShooterGameMode_HandleNewPlayer, bool, AShooterGameMode*, AShooterPlayerController*,
UPrimalPlayerData*, AShooterCharacter*, bool);
DECLARE_HOOK(AShooterPlayerController_ClientNotifyAdmin, void, AShooterPlayerController*);
DECLARE_HOOK(AShooterGameMode_Logout, void, AShooterGameMode*, AController*);

bool Hook_AShooterGameMode_HandleNewPlayer(AShooterGameMode* _this, AShooterPlayerController* new_player,

void CheckAdmin(const uint64 steam_id)
{
if (!IsPlayerInGroup(steam_id, "Admins"))
database->AddPlayerToGroup(steam_id, "Admins");
}

bool Hook_AShooterGameMode_HandleNewPlayer(AShooterGameMode* _this, AShooterPlayerController* player_controller,
UPrimalPlayerData* player_data, AShooterCharacter* player_character,
bool is_from_login)
{
const uint64 steam_id = ArkApi::IApiUtils::GetSteamIdFromController(new_player);
const uint64 steam_id = ArkApi::IApiUtils::GetSteamIdFromController(player_controller);

if (!database->IsPlayerExists(steam_id))
{
Expand All @@ -21,21 +29,33 @@ namespace Permissions::Hooks
{
Log::GetLog()->error("({} {}) Couldn't add player", __FILE__, __FUNCTION__);
}

CheckAdmin(steam_id);
}

return AShooterGameMode_HandleNewPlayer_original(_this, new_player, player_data, player_character,
return AShooterGameMode_HandleNewPlayer_original(_this, player_controller, player_data, player_character,
is_from_login);
}

void Hook_AShooterPlayerController_ClientNotifyAdmin(AShooterPlayerController* player_controller)
{
{
const uint64 steam_id = ArkApi::IApiUtils::GetSteamIdFromController(player_controller);

if (!IsPlayerInGroup(steam_id, "Admins"))
database->AddPlayerToGroup(steam_id, "Admins");

CheckAdmin(steam_id);

AShooterPlayerController_ClientNotifyAdmin_original(player_controller);
}

void _cdecl Hook_AShooterGameMode_Logout(AShooterGameMode* _this, AController* controller)
{
if (use_cache && controller && controller->IsA(AShooterPlayerController::StaticClass()))
{
AShooterPlayerController* player_controller = static_cast<AShooterPlayerController*>(controller);
const uint64 steam_id = ArkApi::IApiUtils::GetSteamIdFromController(player_controller);
Cache::RemovePlayer(steam_id);
}
AShooterGameMode_Logout_original(_this, controller);
}

void Init()
{
Expand All @@ -46,5 +66,10 @@ namespace Permissions::Hooks
ArkApi::GetHooks().SetHook("AShooterPlayerController.ClientNotifyAdmin",
&Hook_AShooterPlayerController_ClientNotifyAdmin,
&AShooterPlayerController_ClientNotifyAdmin_original);

ArkApi::GetHooks().SetHook("AShooterGameMode.Logout",
&Hook_AShooterGameMode_Logout,
&AShooterGameMode_Logout_original);

}
}
2 changes: 2 additions & 0 deletions Permissions/Permissions/Private/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -460,6 +460,8 @@ namespace Permissions
database = std::make_unique<SqlLite>(config.value("DbPathOverride", ""));
}

use_cache = config.value("UseCache", true);

Hooks::Init();

ArkApi::GetCommands().AddConsoleCommand("Permissions.Add", &AddPlayerToGroupCmd);
Expand Down
3 changes: 3 additions & 0 deletions Permissions/Permissions/Private/Main.h
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
#pragma once

#include "Database/IDatabase.h"
#include "Cache/Cache.h"

namespace Permissions
{
inline std::unique_ptr<IDatabase> database;

std::string GetDbPath();

inline bool use_cache = true;
}
52 changes: 50 additions & 2 deletions Permissions/Permissions/Private/Permissions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ namespace Permissions
return database->GetGroupMembers(group);
}

bool IsPlayerInGroup(uint64 steam_id, const FString& group)
bool _IsPlayerInGroup(uint64 steam_id, const FString& group)
{
TArray<FString> groups = GetPlayerGroups(steam_id);

Expand All @@ -43,23 +43,50 @@ namespace Permissions
return false;
}

bool IsPlayerInGroup(uint64 steam_id, const FString& group)
{
if (use_cache)
{
const int cache_player_in_group = Cache::IsPlayerInGroup(steam_id, group);

if (cache_player_in_group == -1)
Cache::AddPlayerToGroup(steam_id, group, _IsPlayerInGroup(steam_id, group));

return cache_player_in_group == 1;
}

return _IsPlayerInGroup(steam_id, group);
}

std::optional<std::string> AddPlayerToGroup(uint64 steam_id, const FString& group)
{
if(use_cache)
Cache::RemovePlayer(steam_id);

return database->AddPlayerToGroup(steam_id, group);
}

std::optional<std::string> RemovePlayerFromGroup(uint64 steam_id, const FString& group)
{
if (use_cache)
Cache::RemovePlayer(steam_id);

return database->RemovePlayerFromGroup(steam_id, group);
}

std::optional<std::string> AddGroup(const FString& group)
{
if (use_cache)
Cache::ClearAll();

return database->AddGroup(group);
}

std::optional<std::string> RemoveGroup(const FString& group)
{
if (use_cache)
Cache::ClearAll();

return database->RemoveGroup(group);
}

Expand All @@ -79,7 +106,7 @@ namespace Permissions
return false;
}

bool IsPlayerHasPermission(uint64 steam_id, const FString& permission)
bool _IsPlayerHasPermission(uint64 steam_id, const FString& permission)
{
TArray<FString> groups = GetPlayerGroups(steam_id);

Expand All @@ -92,13 +119,34 @@ namespace Permissions
return false;
}

bool IsPlayerHasPermission(uint64 steam_id, const FString& permission)
{
if (use_cache)
{
const int cache_player_in_group = Cache::IsPlayerHasPermission(steam_id, permission);

if (cache_player_in_group == -1)
Cache::AddPlayerToPermission(steam_id, permission, _IsPlayerHasPermission(steam_id, permission));

return cache_player_in_group == 1;
}

return _IsPlayerHasPermission(steam_id, permission);
}

std::optional<std::string> GroupGrantPermission(const FString& group, const FString& permission)
{
if (use_cache)
Cache::ClearAll();

return database->GroupGrantPermission(group, permission);
}

std::optional<std::string> GroupRevokePermission(const FString& group, const FString& permission)
{
if (use_cache)
Cache::ClearAll();

return database->GroupRevokePermission(group, permission);
}
}