305 lines
12 KiB
Lua
305 lines
12 KiB
Lua
local meta = FindMetaTable("Player")
|
|
|
|
DarkRP.ServerDarkRPVars = DarkRP.ServerDarkRPVars or {}
|
|
DarkRP.ServerPrivateDarkRPVars = DarkRP.ServerPrivateDarkRPVars or {}
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Pooled networking strings
|
|
---------------------------------------------------------------------------]]
|
|
util.AddNetworkString("DarkRP_InitializeVars")
|
|
util.AddNetworkString("DarkRP_PlayerVar")
|
|
util.AddNetworkString("DarkRP_PlayerVarRemoval")
|
|
util.AddNetworkString("DarkRP_DarkRPVarDisconnect")
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Player vars
|
|
---------------------------------------------------------------------------]]
|
|
|
|
local warningsShown = {}
|
|
local function checkDarkRPVarRegistration(name)
|
|
local DarkRPVar = DarkRP.RegisteredDarkRPVars[name]
|
|
if DarkRPVar then return end
|
|
|
|
if warningsShown[name] then return end
|
|
warningsShown[name] = true
|
|
|
|
DarkRP.errorNoHalt(string.format([[Warning! DarkRPVar '%s' wasn't registered!
|
|
Please contact the author of the DarkRP Addon to fix this.
|
|
Until this is fixed you don't need to worry about anything. Everything will keep working.
|
|
It's just that registering DarkRPVars would make DarkRP faster.]], name), 4)
|
|
end
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Remove a player's DarkRPVar
|
|
---------------------------------------------------------------------------]]
|
|
function meta:removeDarkRPVar(var, target)
|
|
local vars = DarkRP.ServerDarkRPVars[self]
|
|
hook.Call("DarkRPVarChanged", nil, self, var, vars and vars[var], nil)
|
|
target = target or player.GetAll()
|
|
|
|
DarkRP.ServerDarkRPVars[self] = DarkRP.ServerDarkRPVars[self] or {}
|
|
DarkRP.ServerDarkRPVars[self][var] = nil
|
|
|
|
checkDarkRPVarRegistration(var)
|
|
|
|
net.Start("DarkRP_PlayerVarRemoval")
|
|
net.WriteUInt(self:UserID(), 16)
|
|
DarkRP.writeNetDarkRPVarRemoval(var)
|
|
net.Send(target)
|
|
end
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Set a player's DarkRPVar
|
|
---------------------------------------------------------------------------]]
|
|
function meta:setDarkRPVar(var, value, target)
|
|
target = target or player.GetAll()
|
|
|
|
if value == nil then return self:removeDarkRPVar(var, target) end
|
|
|
|
local vars = DarkRP.ServerDarkRPVars[self]
|
|
hook.Call("DarkRPVarChanged", nil, self, var, vars and vars[var], value)
|
|
|
|
DarkRP.ServerDarkRPVars[self] = DarkRP.ServerDarkRPVars[self] or {}
|
|
DarkRP.ServerDarkRPVars[self][var] = value
|
|
|
|
checkDarkRPVarRegistration(var)
|
|
|
|
net.Start("DarkRP_PlayerVar")
|
|
net.WriteUInt(self:UserID(), 16)
|
|
DarkRP.writeNetDarkRPVar(var, value)
|
|
net.Send(target)
|
|
end
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Set a private DarkRPVar
|
|
---------------------------------------------------------------------------]]
|
|
function meta:setSelfDarkRPVar(var, value)
|
|
DarkRP.ServerPrivateDarkRPVars[self] = DarkRP.ServerPrivateDarkRPVars[self] or {}
|
|
DarkRP.ServerPrivateDarkRPVars[self][var] = true
|
|
|
|
self:setDarkRPVar(var, value, self)
|
|
end
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Get a DarkRPVar
|
|
---------------------------------------------------------------------------]]
|
|
function meta:getDarkRPVar(var, fallback)
|
|
local vars = DarkRP.ServerDarkRPVars[self]
|
|
if vars == nil then return fallback end
|
|
|
|
local results = vars[var]
|
|
if results == nil then return fallback end
|
|
|
|
return results
|
|
end
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Backwards compatibility: Set ply.DarkRPVars attribute
|
|
---------------------------------------------------------------------------]]
|
|
function meta:setDarkRPVarsAttribute()
|
|
DarkRP.ServerDarkRPVars[self] = DarkRP.ServerDarkRPVars[self] or {}
|
|
-- With a reference to the table, ply.DarkRPVars should always remain
|
|
-- up-to-date. One needs only be careful that DarkRP.ServerDarkRPVars[ply]
|
|
-- is never replaced by a different table.
|
|
self.DarkRPVars = DarkRP.ServerDarkRPVars[self]
|
|
end
|
|
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Send the DarkRPVars to a client
|
|
---------------------------------------------------------------------------]]
|
|
function meta:sendDarkRPVars()
|
|
if self:EntIndex() == 0 then return end
|
|
|
|
local plys = player.GetAll()
|
|
|
|
net.Start("DarkRP_InitializeVars")
|
|
net.WriteUInt(#plys, 8)
|
|
for _, target in ipairs(plys) do
|
|
net.WriteUInt(target:UserID(), 16)
|
|
|
|
local vars = {}
|
|
for var, value in pairs(DarkRP.ServerDarkRPVars[target] or {}) do
|
|
if self ~= target and (DarkRP.ServerPrivateDarkRPVars[target] or {})[var] then continue end
|
|
table.insert(vars, var)
|
|
end
|
|
|
|
local vars_cnt = #vars
|
|
net.WriteUInt(vars_cnt, DarkRP.DARKRP_ID_BITS + 2) -- Allow for three times as many unknown DarkRPVars than the limit
|
|
for i = 1, vars_cnt, 1 do
|
|
DarkRP.writeNetDarkRPVar(vars[i], DarkRP.ServerDarkRPVars[target][vars[i]])
|
|
end
|
|
end
|
|
net.Send(self)
|
|
end
|
|
concommand.Add("_sendDarkRPvars", function(ply)
|
|
if ply.DarkRPVarsSent and ply.DarkRPVarsSent > (CurTime() - 3) then return end -- prevent spammers
|
|
ply.DarkRPVarsSent = CurTime()
|
|
ply:sendDarkRPVars()
|
|
end)
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Admin DarkRPVar commands
|
|
---------------------------------------------------------------------------]]
|
|
local function setRPName(ply, args)
|
|
if not args[2] or string.len(args[2]) < 2 or string.len(args[2]) > 30 then
|
|
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("invalid_x", DarkRP.getPhrase("arguments"), "<2/>30"))
|
|
return
|
|
end
|
|
|
|
local name = table.concat(args, " ", 2)
|
|
|
|
local target = DarkRP.findPlayer(args[1])
|
|
|
|
if not target then
|
|
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("could_not_find", args[1]))
|
|
return
|
|
end
|
|
|
|
local oldname = target:Nick()
|
|
|
|
DarkRP.retrieveRPNames(name, function(taken)
|
|
if not IsValid(target) then return end
|
|
|
|
if taken then
|
|
DarkRP.notify(ply, 1, 5, DarkRP.getPhrase("unable", "RPname", DarkRP.getPhrase("already_taken")))
|
|
return
|
|
end
|
|
|
|
DarkRP.storeRPName(target, name)
|
|
target:setDarkRPVar("rpname", name)
|
|
|
|
DarkRP.notify(ply, 0, 4, DarkRP.getPhrase("you_set_x_name", oldname, name))
|
|
|
|
local nick = ""
|
|
if ply:EntIndex() == 0 then
|
|
nick = "Console"
|
|
else
|
|
nick = ply:Nick()
|
|
end
|
|
DarkRP.notify(target, 0, 4, DarkRP.getPhrase("x_set_your_name", nick, name))
|
|
if ply:EntIndex() == 0 then
|
|
DarkRP.log("Console set " .. target:SteamName() .. "'s name to " .. name, Color(30, 30, 30))
|
|
else
|
|
DarkRP.log(ply:Nick() .. " (" .. ply:SteamID() .. ") set " .. target:SteamName() .. "'s name to " .. name, Color(30, 30, 30))
|
|
end
|
|
end)
|
|
end
|
|
DarkRP.definePrivilegedChatCommand("forcerpname", "DarkRP_AdminCommands", setRPName)
|
|
|
|
local function freerpname(ply, args)
|
|
local name = args ~= "" and args or IsValid(ply) and ply:Nick() or ""
|
|
|
|
MySQLite.query(("UPDATE darkrp_player SET rpname = NULL WHERE rpname = %s"):format(MySQLite.SQLStr(name)))
|
|
|
|
local nick = IsValid(ply) and ply:Nick() or "Console"
|
|
DarkRP.log(("%s has freed the rp name '%s'"):format(nick, name), Color(30, 30, 30))
|
|
DarkRP.notify(ply, 0, 4, ("'%s' has been freed"):format(name))
|
|
end
|
|
DarkRP.definePrivilegedChatCommand("freerpname", "DarkRP_AdminCommands", freerpname)
|
|
|
|
local function RPName(ply, args)
|
|
if ply.LastNameChange and ply.LastNameChange > (CurTime() - 5) then
|
|
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("have_to_wait", math.ceil(5 - (CurTime() - ply.LastNameChange)), "/rpname"))
|
|
return ""
|
|
end
|
|
|
|
if not GAMEMODE.Config.allowrpnames then
|
|
DarkRP.notify(ply, 1, 6, DarkRP.getPhrase("disabled", "/rpname", ""))
|
|
return ""
|
|
end
|
|
|
|
args = args:find"^%s*$" and '' or args:match"^%s*(.*%S)"
|
|
|
|
local canChangeName, reason = hook.Call("CanChangeRPName", GAMEMODE, ply, args)
|
|
if canChangeName == false then
|
|
DarkRP.notify(ply, 1, 4, DarkRP.getPhrase("unable", "/rpname", reason or ""))
|
|
return ""
|
|
end
|
|
|
|
ply:setRPName(args)
|
|
ply.LastNameChange = CurTime()
|
|
return ""
|
|
end
|
|
DarkRP.defineChatCommand("rpname", RPName)
|
|
DarkRP.defineChatCommand("name", RPName)
|
|
DarkRP.defineChatCommand("nick", RPName)
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Setting the RP name
|
|
---------------------------------------------------------------------------]]
|
|
function meta:setRPName(name, firstRun)
|
|
-- Make sure nobody on this server already has this RP name
|
|
local lowername = string.lower(tostring(name))
|
|
DarkRP.retrieveRPNames(name, function(taken)
|
|
if not IsValid(self) or string.len(lowername) < 2 and not firstrun then return end
|
|
-- If we found that this name exists for another player
|
|
if taken then
|
|
if firstRun then
|
|
-- If we just connected and another player happens to be using our steam name as their RP name
|
|
-- Put a 1 after our steam name
|
|
DarkRP.storeRPName(self, name .. " 1")
|
|
DarkRP.notify(self, 0, 12, DarkRP.getPhrase("someone_stole_steam_name"))
|
|
else
|
|
DarkRP.notify(self, 1, 5, DarkRP.getPhrase("unable", "/rpname", DarkRP.getPhrase("already_taken")))
|
|
return ""
|
|
end
|
|
else
|
|
if not firstRun then -- Don't save the steam name in the database
|
|
DarkRP.notifyAll(2, 6, DarkRP.getPhrase("rpname_changed", self:SteamName(), name))
|
|
DarkRP.storeRPName(self, name)
|
|
end
|
|
end
|
|
end)
|
|
end
|
|
|
|
--[[---------------------------------------------------------------------------
|
|
Maximum entity values
|
|
---------------------------------------------------------------------------]]
|
|
local maxEntities = {}
|
|
function meta:addCustomEntity(entTable)
|
|
maxEntities[self] = maxEntities[self] or {}
|
|
maxEntities[self][entTable.cmd] = maxEntities[self][entTable.cmd] or 0
|
|
maxEntities[self][entTable.cmd] = maxEntities[self][entTable.cmd] + 1
|
|
end
|
|
|
|
function meta:removeCustomEntity(entTable)
|
|
maxEntities[self] = maxEntities[self] or {}
|
|
maxEntities[self][entTable.cmd] = maxEntities[self][entTable.cmd] or 0
|
|
maxEntities[self][entTable.cmd] = maxEntities[self][entTable.cmd] - 1
|
|
end
|
|
|
|
function meta:customEntityLimitReached(entTable)
|
|
maxEntities[self] = maxEntities[self] or {}
|
|
maxEntities[self][entTable.cmd] = maxEntities[self][entTable.cmd] or 0
|
|
local max = entTable.getMax and entTable.getMax(self) or entTable.max
|
|
|
|
return max ~= 0 and maxEntities[self][entTable.cmd] >= max
|
|
end
|
|
|
|
function meta:customEntityCount(entTable)
|
|
local entities = maxEntities[self]
|
|
if entities == nil then return 0 end
|
|
|
|
entities = entities[entTable.cmd]
|
|
if entities == nil then return 0 end
|
|
|
|
return entities
|
|
end
|
|
|
|
-- We use EntityRemoved to clear players of tables, because it is always called
|
|
-- after the PlayerDisconnected hook. This is called _after_ the GAMEMODE
|
|
-- function, to make sure that all regular hooks can still use DarkRPVars until
|
|
-- the very end. See https://github.com/FPtje/DarkRP/pull/3270
|
|
(GAMEMODE or GM).DarkRPPostEntityRemoved = function(_gm, ent)
|
|
if not ent:IsPlayer() then return end
|
|
|
|
maxEntities[ent] = nil
|
|
DarkRP.ServerDarkRPVars[ent] = nil
|
|
DarkRP.ServerPrivateDarkRPVars[ent] = nil
|
|
|
|
net.Start("DarkRP_DarkRPVarDisconnect")
|
|
net.WriteUInt(ent:UserID(), 16)
|
|
net.Broadcast()
|
|
end
|