423 lines
12 KiB
Lua
423 lines
12 KiB
Lua
--[[
|
|
© 2017 Thriving Ventures Limited do not share, re-distribute or modify
|
|
|
|
without permission of its author (gustaf@thrivingventures.com).
|
|
]]
|
|
|
|
--- ## Shared
|
|
-- Player manipulation.
|
|
-- @module serverguard.player
|
|
|
|
serverguard.player = serverguard.player or {};
|
|
|
|
--- Sets a player's rank.
|
|
-- @player player The player to set the rank of.
|
|
-- @string rank The unique ID of the rank to set as.
|
|
-- @bool[opt] length Amount of time (in seconds) after which the rank will be taken away from the player.
|
|
-- @bool[opt] bSaveless Whether or not to save the player's rank. Defaults to false;
|
|
-- @treturn bool Whether or not the operation was successful.
|
|
function serverguard.player:SetRank(player, rank, length, bSaveless)
|
|
local rankData = serverguard.ranks:GetRank(rank);
|
|
|
|
if (!rankData) then
|
|
ErrorNoHalt("Error: (SetRank) Attempted to set non-existent rank to player '"..tostring(rank).."'.\n"..debug.traceback().."\n");
|
|
return false;
|
|
end;
|
|
|
|
if (isstring(player) and string.SteamID(player)) then
|
|
local queryObj = serverguard.mysql:Select("serverguard_users");
|
|
queryObj:Where("steam_id", player);
|
|
queryObj:Limit(1);
|
|
queryObj:Callback(function(result, status, lastID)
|
|
if (istable(result) and #result > 0) then
|
|
local updateObj = serverguard.mysql:Update("serverguard_users");
|
|
updateObj:Update("rank", rank);
|
|
updateObj:Where("steam_id", player);
|
|
updateObj:Execute();
|
|
else
|
|
local insertObj = serverguard.mysql:Insert("serverguard_users");
|
|
insertObj:Insert("name", "Unknown");
|
|
insertObj:Insert("rank", rank);
|
|
insertObj:Insert("steam_id", player);
|
|
insertObj:Insert("last_played", os.time());
|
|
insertObj:Insert("data",
|
|
serverguard.von.serialize(
|
|
{
|
|
groupExpire = ((length != nil and tonumber(length) != nil and length > 0) and os.time() + math.ceil(tonumber(length))) or 0
|
|
}
|
|
)
|
|
);
|
|
insertObj:Execute();
|
|
end;
|
|
end);
|
|
queryObj:Execute();
|
|
|
|
return true;
|
|
end;
|
|
|
|
if (!IsValid(player)) then
|
|
ErrorNoHalt("Error: (SetRank) Attempted to set rank to non-existent player.\n"..debug.traceback().."\n");
|
|
return false;
|
|
end;
|
|
|
|
player.sg_incognito = nil;
|
|
player:SetNetVar("serverguard_rank", rank);
|
|
player:SetUserGroup(rank);
|
|
|
|
if timer.Exists("serverguard.timer.RemoveRank_" .. player:UniqueID()) then
|
|
timer.Remove("serverguard.timer.RemoveRank_" .. player:UniqueID());
|
|
end;
|
|
|
|
if (length != nil and tonumber(length) != nil and length > 0) then
|
|
serverguard.player:SetData(player, "groupExpire", os.time() + math.ceil(tonumber(length)));
|
|
timer.Create("serverguard.timer.RemoveRank_" .. player:UniqueID(), math.ceil(tonumber(length)), 1, function()
|
|
if (IsValid(player)) then
|
|
serverguard.player:SetRank(player, "user", 0);
|
|
end;
|
|
end);
|
|
else
|
|
serverguard.player:SetData(player, "groupExpire", false);
|
|
end
|
|
|
|
if (!bSaveless) then
|
|
serverguard.ranks:SavePlayerRank(player, rankData.unique);
|
|
end;
|
|
|
|
if (SERVER) then
|
|
timer.Simple(FrameTime() * 32, function()
|
|
hook.Run('octolib.updateNetVars', player)
|
|
serverguard.netstream.Start(player, "sgSetPlayerRank", true);
|
|
end);
|
|
end;
|
|
|
|
return true;
|
|
end;
|
|
|
|
--- Gets the player's rank unique ID. Defaults to "user" if it doesn't exist.
|
|
-- @player player The player to get the rank of.
|
|
-- @treturn string The rank's unique ID.
|
|
function serverguard.player:GetRank(player)
|
|
result = "user";
|
|
|
|
if (IsValid(player) and player:IsPlayer()) then
|
|
result = player:GetNetVar("serverguard_rank", "user");
|
|
elseif (util.IsConsole(player)) then
|
|
result = "founder";
|
|
end;
|
|
|
|
return result;
|
|
end;
|
|
|
|
--- Sets a player's immunity level.
|
|
-- @player player The player to set the immunity of.
|
|
-- @number immunity The new immunity level to set.
|
|
function serverguard.player:SetImmunity(player, immunity)
|
|
player:SetNetVar("serverguard_immunity", immunity);
|
|
end;
|
|
|
|
--- Sets a player's ban limit.
|
|
-- @player player The player to set the ban limit of.
|
|
-- @number limit The new ban limit to set.
|
|
function serverguard.player:SetBanLimit(player, limit)
|
|
player:SetNetVar("serverguard_banlimit", limit);
|
|
end;
|
|
|
|
--- Sets a player's targetable rank.
|
|
-- @player player The player to set the targetable rank of.
|
|
-- @number immunity The new targetable rank to set.
|
|
function serverguard.player:SetTargetableRank(player, immunity)
|
|
player:SetNetVar("serverguard_targetable_rank", immunity);
|
|
end;
|
|
|
|
--- Gets a player's immunity level. Defaults to 0 if the immunity is not set.
|
|
-- @player player The player to get the immunity of.
|
|
-- @treturn number The immunity level of the player.
|
|
function serverguard.player:GetImmunity(player)
|
|
if (IsValid(player)) then
|
|
return player:GetNetVar("serverguard_immunity", 0);
|
|
else
|
|
return 100;
|
|
end;
|
|
end;
|
|
|
|
--- Gets a player's ban length.
|
|
-- @player player The player to get the banlimit of.
|
|
-- @number length The ban limit to get.
|
|
function serverguard.player:GetBanLimit(player)
|
|
if (IsValid(player)) then
|
|
return player:GetNetVar("serverguard_banlimit", 0);
|
|
end
|
|
end;
|
|
|
|
--- Gets a player's targetable rank. Defaults to 0 if the immunity is not set.
|
|
-- @player player The player to get the targetable rank of.
|
|
-- @treturn number The targetable rank of the player.
|
|
function serverguard.player:GetTargetableRank(player)
|
|
if (IsValid(player)) then
|
|
return player:GetNetVar("serverguard_targetable_rank", 0);
|
|
else
|
|
return 100;
|
|
end;
|
|
end;
|
|
|
|
--- Returns whether or not the player has a better targetable level than the immunity specified.
|
|
-- @player player The player to check the targetable rank of.
|
|
-- @number immunity The immunity level to check with.
|
|
-- @treturn bool Whether or not the player has a better immunity.
|
|
function serverguard.player:HasBetterImmunity(player, immunity)
|
|
return self:GetTargetableRank(player) >= immunity;
|
|
end;
|
|
--- Returns whether or not the player has a better targetable level than the target's immunity level.
|
|
-- @player player The player to check the targetable rank of.
|
|
-- @player target The target to check with.
|
|
-- @treturn bool Whether or not the player has a better immunity.
|
|
function serverguard.player:CanTarget(player, target)
|
|
return self:GetTargetableRank(player) >= serverguard.player:GetImmunity(target);
|
|
end;
|
|
|
|
--- Gets a player's name. Will return with the orignal name in if player.SteamName is defined.
|
|
function serverguard.player:GetName(pPlayer)
|
|
if (util.IsConsole(pPlayer)) then
|
|
return "Console";
|
|
elseif (isplayer(pPlayer)) then
|
|
local playerName = pPlayer:Name();
|
|
|
|
if (pPlayer.SteamName) then
|
|
playerName = "(" .. pPlayer:SteamName() .. ") " .. playerName;
|
|
end;
|
|
|
|
return playerName;
|
|
else
|
|
return "Unknown";
|
|
end;
|
|
end;
|
|
|
|
--- Sets up the spectate routine for the given player. Strips weapons, makes invisible,
|
|
-- disables collision, etc.
|
|
-- @player player The player to set up the spectate mode for.
|
|
-- @number mode The spectate mode to use.
|
|
function serverguard.player:SetupSpectate(player, mode)
|
|
if (!player.sg_spectateData) then
|
|
local weapons = player:GetWeapons();
|
|
|
|
player.sg_spectateData = {};
|
|
player.sg_spectateData.weapons = {};
|
|
player.sg_spectateData.position = player:GetPos();
|
|
player.sg_spectateData.team = player:Team();
|
|
|
|
for k, v in pairs(weapons) do
|
|
table.insert(player.sg_spectateData.weapons, v:GetClass());
|
|
end;
|
|
end;
|
|
|
|
player:StripWeapons();
|
|
player:SetTeam(TEAM_SPECTATOR);
|
|
player:Spectate(mode);
|
|
player:SpectateEntity(NULL);
|
|
player:SetCollisionGroup(COLLISION_GROUP_WORLD);
|
|
|
|
if (mode == OBS_MODE_ROAMING) then
|
|
player:SetMoveType(MOVETYPE_NOCLIP);
|
|
else
|
|
player:SetMoveType(MOVETYPE_OBSERVER);
|
|
|
|
if (IsValid(player.spectateTarget)) then
|
|
player:SpectateEntity(player.spectateTarget);
|
|
end;
|
|
end;
|
|
|
|
if (!player.spectatorMode) then
|
|
player.spectatorMode = 1;
|
|
end;
|
|
|
|
player.sg_spectating = true;
|
|
end;
|
|
|
|
--- Stops a player from spectating. Returns all of their stuff to normal; weapons,
|
|
-- collision, etc.
|
|
-- @player player The player to make stop spectating.
|
|
function serverguard.player:StopSpectate(player)
|
|
player:SetTeam(player.sg_spectateData.team);
|
|
player:Spectate(OBS_MODE_NONE);
|
|
player:SetMoveType(MOVETYPE_WALK);
|
|
player:SpectateEntity(NULL);
|
|
player:SetCollisionGroup(COLLISION_GROUP_PLAYER);
|
|
|
|
player:Spawn();
|
|
|
|
player:SetPos(player.sg_spectateData.position);
|
|
|
|
for k, v in pairs(player.sg_spectateData.weapons) do
|
|
player:Give(v);
|
|
end;
|
|
|
|
player.sg_spectating = nil;
|
|
player.sg_spectateData = nil;
|
|
end;
|
|
|
|
--- Gets the target player that the given player is spectating.
|
|
-- @player player The spectating player.
|
|
-- @bool[opt] decrease Whether or not to get the next/previous player.
|
|
-- @treturn player The spectated player.
|
|
function serverguard.player:GetSpectatorTarget(pPlayer, decrease)
|
|
if (isentity(decrease)) then
|
|
pPlayer.spectatorIndex = pPlayer.spectatorIndex or 1;
|
|
|
|
return decrease;
|
|
end
|
|
|
|
local players = player.GetAll();
|
|
|
|
for i = 1, #players do
|
|
if (v == pPlayer) then
|
|
table.remove(players, i);
|
|
|
|
break;
|
|
end;
|
|
end;
|
|
|
|
pPlayer.spectatorIndex = pPlayer.spectatorIndex or 0;
|
|
pPlayer.spectatorIndex = decrease and pPlayer.spectatorIndex - 1 or pPlayer.spectatorIndex + 1;
|
|
|
|
if (pPlayer.spectatorIndex > #players) then
|
|
pPlayer.spectatorIndex = 1;
|
|
elseif (pPlayer.spectatorIndex < 1) then
|
|
pPlayer.spectatorIndex = #players;
|
|
end;
|
|
|
|
return players[player.spectatorIndex];
|
|
end;
|
|
|
|
--- Makes a player spectate the set target.
|
|
-- @player player The player to put into spectate mode.
|
|
-- @bool[opt] decrease Whether to get the next/previous target.
|
|
function serverguard.player:SpectateTarget(player, decrease)
|
|
local target = self:GetSpectatorTarget(player, decrease);
|
|
|
|
player:SpectateEntity(target);
|
|
|
|
player.spectateTarget = target;
|
|
end;
|
|
|
|
--- Changes a player's spectator mode.
|
|
-- @player player The player to change the mode of.
|
|
-- @bool[opt] decrease Whether to get the next/previous target.
|
|
function serverguard.player:ChangeSpectatorMode(player, decrease)
|
|
local spectatorModes = {
|
|
OBS_MODE_ROAMING,
|
|
OBS_MODE_CHASE,
|
|
OBS_MODE_IN_EYE
|
|
};
|
|
|
|
player.spectatorMode = decrease and player.spectatorMode - 1 or player.spectatorMode + 1;
|
|
|
|
if (player.spectatorMode > #spectatorModes) then
|
|
player.spectatorMode = 1;
|
|
elseif (player.spectatorMode < 1) then
|
|
player.spectatorMode = #spectatorModes;
|
|
end;
|
|
|
|
local mode = spectatorModes[player.spectatorMode];
|
|
|
|
self:SetupSpectate(player, mode);
|
|
end;
|
|
|
|
if (CLIENT) then
|
|
serverguard.netstream.Hook("sgSetPlayerRank", function(data)
|
|
serverguard.menu:Rebuild();
|
|
end);
|
|
end;
|
|
|
|
--- Gets whether or not the player has the given permission.
|
|
-- @player player The player to check the permissions of.
|
|
-- @string identifier The name of the permission. This can also be a table of string to check for multiple permissions.
|
|
-- @treturn bool Whether or not the player has the given permission.
|
|
function serverguard.player:HasPermission(player, identifier)
|
|
if (self:GetRank(player) == "founder") then
|
|
return true;
|
|
end;
|
|
|
|
local permissionTable = serverguard.ranks:GetData(
|
|
self:GetRank(player), "Permissions"
|
|
);
|
|
|
|
if (permissionTable) then
|
|
local identype = type(identifier)
|
|
|
|
if (identype == "string") then
|
|
return permissionTable[identifier] or false;
|
|
end
|
|
|
|
if (identype == "table") then
|
|
for k, v in pairs(identifier) do
|
|
if (isstring(v) and permissionTable[v]) then
|
|
return true;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
return false;
|
|
end;
|
|
|
|
do
|
|
local playerMeta = FindMetaTable("Player");
|
|
|
|
playerMeta.sgIsAdmin = playerMeta.sgIsAdmin or playerMeta.IsAdmin;
|
|
playerMeta.sgIsSuperAdmin = playerMeta.sgIsSuperAdmin or playerMeta.IsSuperAdmin;
|
|
playerMeta.sgIsUserGroup = playerMeta.sgIsUserGroup or playerMeta.IsUserGroup;
|
|
|
|
--
|
|
-- Override IsAdmin to check serverguard rank.
|
|
--
|
|
|
|
function playerMeta:IsAdmin()
|
|
if (self:IsSuperAdmin() or serverguard.player:HasPermission(self, "Admin")) then
|
|
return true;
|
|
end;
|
|
|
|
return self:sgIsAdmin();
|
|
end;
|
|
|
|
--
|
|
-- Override IsSuperAdmin to check serverguard rank.
|
|
--
|
|
|
|
function playerMeta:IsSuperAdmin()
|
|
if (serverguard.player:HasPermission(self, "Superadmin")) then
|
|
return true;
|
|
end;
|
|
|
|
return self:sgIsSuperAdmin();
|
|
end;
|
|
|
|
--
|
|
-- Override IsUserGroup to check serverguard rank.
|
|
--
|
|
|
|
function playerMeta:IsUserGroup(name)
|
|
if (serverguard.player:GetRank(self) == name) then
|
|
return true;
|
|
end;
|
|
|
|
return self:sgIsUserGroup(name)
|
|
end;
|
|
|
|
--
|
|
-- Override GetUserGroup to check serverguard rank.
|
|
--
|
|
|
|
function playerMeta:GetUserGroup()
|
|
return serverguard.player:GetRank(self);
|
|
end;
|
|
|
|
--
|
|
-- Override Ban to use serverguard ban.
|
|
--
|
|
|
|
function playerMeta:Ban(length, bKick, reason)
|
|
reason = reason or "No Reason";
|
|
|
|
serverguard:BanPlayer(nil, self, length, reason, bKick);
|
|
end;
|
|
end;
|