Initial commit

This commit is contained in:
pavetr
2026-03-15 14:54:49 +03:00
commit 64f8029c06
4027 changed files with 254888 additions and 0 deletions

View File

@@ -0,0 +1,988 @@
FPP = FPP or {}
util.AddNetworkString("FPP_Groups")
util.AddNetworkString("FPP_GroupMembers")
util.AddNetworkString("FPP_RestrictedToolList")
util.AddNetworkString("FPP_BlockedModels")
FPP.Blocked = FPP.Blocked or {}
FPP.Blocked.Physgun1 = FPP.Blocked.Physgun1 or {}
FPP.Blocked.Spawning1 = FPP.Blocked.Spawning1 or {}
FPP.Blocked.Gravgun1 = FPP.Blocked.Gravgun1 or {}
FPP.Blocked.Toolgun1 = FPP.Blocked.Toolgun1 or {}
FPP.Blocked.PlayerUse1 = FPP.Blocked.PlayerUse1 or {}
FPP.Blocked.EntityDamage1 = FPP.Blocked.EntityDamage1 or {}
FPP.BlockedModels = FPP.BlockedModels or {}
FPP.RestrictedTools = FPP.RestrictedTools or {}
FPP.RestrictedToolsPlayers = FPP.RestrictedToolsPlayers or {}
FPP.Groups = FPP.Groups or {}
FPP.GroupMembers = FPP.GroupMembers or {}
function FPP.Notify(ply, text, bool, total_time)
if ply:EntIndex() == 0 then
ServerLog(text)
return
end
umsg.Start("FPP_Notify", ply)
umsg.String(text)
umsg.Bool(bool)
umsg.Float(total_time or 6)
umsg.End()
ply:PrintMessage(HUD_PRINTCONSOLE, text)
end
function FPP.NotifyAll(text, bool, total_time)
umsg.Start("FPP_Notify")
umsg.String(text)
umsg.Bool(bool)
umsg.Float(total_time or 6)
umsg.End()
for _, ply in ipairs(player.GetAll()) do
ply:PrintMessage(HUD_PRINTCONSOLE, text)
end
end
local function getSettingsChangedEntities(settingsType, setting)
local plys, entities = {}, {}
local blockedString = string.sub(settingsType, 5, 5) .. string.lower(string.sub(settingsType, 6))
blockedString = blockedString == "Playeruse1" and "PlayerUse1" or blockedString -- dirty hack for stupid naming system.
blockedString = blockedString == "Entitydamage1" and "EntityDamage1" or blockedString -- dirty hack for stupid naming system.
if setting == "adminall" then
for _, v in ipairs(ents.GetAll()) do
if not IsValid(v) then continue end
local owner = v:CPPIGetOwner()
if IsValid(owner) then table.insert(entities, v) end
end
for _, v in ipairs(player.GetAll()) do
v.FPP_Privileges = v.FPP_Privileges or {}
if v.FPP_Privileges.FPP_TouchOtherPlayersProps then table.insert(plys, v) end
end
return plys, entities
elseif setting == "worldprops" or setting == "adminworldprops" then
for _, v in ipairs(ents.GetAll()) do
if FPP.Blocked[blockedString][string.lower(v:GetClass())] then continue end
local owner = v:CPPIGetOwner()
if not IsValid(owner) then table.insert(entities, v) end
end
for _, v in ipairs(player.GetAll()) do
v.FPP_Privileges = v.FPP_Privileges or {}
if v.FPP_Privileges.FPP_TouchOtherPlayersProps then table.insert(plys, v) end
end
return setting == "adminworldprops" and plys or player.GetAll(), entities
elseif setting == "canblocked" or setting == "admincanblocked" then
for _, v in ipairs(ents.GetAll()) do
if not FPP.Blocked[blockedString][string.lower(v:GetClass())] then continue end
table.insert(entities, v)
end
for _, v in ipairs(player.GetAll()) do
v.FPP_Privileges = v.FPP_Privileges or {}
if v.FPP_Privileges.FPP_TouchOtherPlayersProps then table.insert(plys, v) end
end
return setting == "admincanblocked" and plys or player.GetAll(), entities
elseif setting == "iswhitelist" then
return player.GetAll(), ents.GetAll()
end
end
util.AddNetworkString("FPP_Settings")
local function SendSettings(ply)
net.Start("FPP_Settings")
FPP.ForAllSettings(function(k, s, v)
net.WriteDouble(v)
end)
net.Send(ply)
end
util.AddNetworkString("FPP_Settings_Update")
local function updateFPPSetting(kind, setting, value)
local skipKind, skipSetting = 0, 0
FPP.Settings[kind][setting] = value
local finalSkipKind
FPP.ForAllSettings(function(k, s)
skipKind = skipKind + 1
if k ~= kind then return true end
finalSkipKind = skipKind - skipSetting
skipSetting = skipSetting + 1
if s ~= setting then return end
return true
end)
net.Start("FPP_Settings_Update")
net.WriteUInt(finalSkipKind, 8)
net.WriteUInt(skipSetting, 8)
net.WriteDouble(value)
net.Broadcast()
end
local function runIfAccess(priv, f)
return function(ply, cmd, args)
CAMI.PlayerHasAccess(ply, priv, function(allowed, _)
if allowed then return f(ply, cmd, args) end
FPP.Notify(ply, string.format("You need the '%s' privilege in order to be able to use this command", priv), false)
end)
end
end
local function FPP_SetSetting(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "FPP_setting: First argument (setting name) not given!", false) return end
if not args[3] then FPP.Notify(ply, "FPP_setting: Third argument (the value of the setting) not given", false) return end
if not FPP.Settings[args[1]] then
FPP.Notify(ply, ("FPP_setting: Setting %s does not exist! Settings that DO exist:"):format(args[1]), false)
for setting, _ in pairs(FPP.Settings) do
FPP.Notify(ply, setting, false)
end
return
end
if not FPP.Settings[args[1]][args[2]] then FPP.Notify(ply, ("FPP_setting: Setting %s.%s does not exist!"):format(args[1], args[2]), false) return end
updateFPPSetting(args[1], args[2], tonumber(args[3]))
MySQLite.queryValue("SELECT var FROM " .. args[1] .. " WHERE var = " .. sql.SQLStr(args[2]) .. ";", function(data)
if not data then
MySQLite.query("INSERT INTO " .. args[1] .. " VALUES(" .. sql.SQLStr(args[2]) .. ", " .. args[3] .. ");")
elseif tonumber(data) ~= args[3] then
MySQLite.query("UPDATE " .. args[1] .. " SET setting = " .. args[3] .. " WHERE var = " .. sql.SQLStr(args[2]) .. ";")
end
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " set " .. string.lower(string.gsub(args[1], "FPP_", "")) .. " " .. args[2] .. " to " .. tostring(args[3]), tobool(tonumber(args[3])))
end)
FPP.calculatePlayerPrivilege("FPP_TouchOtherPlayersProps", function()
local plys, entities = getSettingsChangedEntities(args[1], args[2])
if not plys or not entities or #plys == 0 or #entities == 0 then return end
FPP.recalculateCanTouch(plys, entities)
end)
end
concommand.Add("FPP_setting", runIfAccess("FPP_Settings", FPP_SetSetting))
local function AddBlocked(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "FPP_AddBlocked: Block list not given", false) return end
if not args[2] then FPP.Notify(ply, "FPP_AddBlocked: Entity to block not given", false) return end
if not FPP.Blocked[args[1]] then FPP.Notify(ply, ("FPP_AddBlocked: Block list %s does not exist"):format(args[1]), false) return end
args[2] = string.lower(args[2])
if FPP.Blocked[args[1]][args[2]] then return end
FPP.Blocked[args[1]][args[2]] = true
MySQLite.query(string.format("INSERT INTO FPP_BLOCKED1 (var, setting) VALUES(%s, %s);", sql.SQLStr(args[1]), sql.SQLStr(args[2])))
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " added " .. args[2] .. " to the " .. args[1] .. " black/whitelist", true)
FPP.recalculateCanTouch(player.GetAll(), ents.FindByClass(args[2]))
end
concommand.Add("FPP_AddBlocked", runIfAccess("FPP_Settings", AddBlocked))
-- Models can differ between server and client. Famous example being:
-- models/props_phx/cannonball_solid.mdl <-- serverside
-- models/props_phx/cannonball.mdl <-- clientside
-- Similar problems occur with effects
local function getIntendedBlockedModels(model, ent)
model = string.Replace(string.lower(model), "\\", "/")
if not IsValid(ent) then return {model} end
if ent:GetClass() == "prop_effect" then return {ent.AttachedEntity:GetModel()} end
if model ~= ent:GetModel() then return {model, ent:GetModel()} end
return {model}
end
local function AddBlockedModel(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "FPP_AddBlockedModel: Model not given", false) return end
local models = getIntendedBlockedModels(args[1], tonumber(args[2]) and Entity(args[2]) or nil)
for _, model in pairs(models) do
if FPP.BlockedModels[model] then FPP.Notify(ply, string.format([["%s" is already in the black/whitelist]], model), false) continue end
FPP.BlockedModels[model] = true
MySQLite.query("REPLACE INTO FPP_BLOCKEDMODELS1 VALUES(" .. sql.SQLStr(model) .. ");")
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " added " .. model .. " to the blocked models black/whitelist", true)
end
end
concommand.Add("FPP_AddBlockedModel", runIfAccess("FPP_Settings", AddBlockedModel))
local function RemoveBlocked(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "FPP_RemoveBlocked: Block list not given", false) return end
if not args[2] then FPP.Notify(ply, "FPP_RemoveBlocked: Entity to block not given", false) return end
if not FPP.Blocked[args[1]] then FPP.Notify(ply, ("FPP_RemoveBlocked: Block list %s does not exist"):format(args[1]), false) return end
FPP.Blocked[args[1]][args[2]] = nil
MySQLite.query("DELETE FROM FPP_BLOCKED1 WHERE var = " .. sql.SQLStr(args[1]) .. " AND setting = " .. sql.SQLStr(args[2]) .. ";")
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " removed " .. args[2] .. " from the " .. args[1] .. " black/whitelist", false)
FPP.recalculateCanTouch(player.GetAll(), ents.FindByClass(args[2]))
end
concommand.Add("FPP_RemoveBlocked", runIfAccess("FPP_Settings", RemoveBlocked))
local function RemoveBlockedModel(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "FPP_RemoveBlockedModel: Model not given", false) return end
local models = getIntendedBlockedModels(args[1], tonumber(args[2]) and Entity(args[2]) or nil)
for _, model in pairs(models) do
FPP.BlockedModels[model] = nil
MySQLite.query("DELETE FROM FPP_BLOCKEDMODELS1 WHERE model = " .. sql.SQLStr(model) .. ";")
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " removed " .. model .. " from the blocked models black/whitelist", false)
end
end
concommand.Add("FPP_RemoveBlockedModel", runIfAccess("FPP_Settings", RemoveBlockedModel))
local allowedShares = {
SharePhysgun1 = true,
ShareGravgun1 = true,
SharePlayerUse1 = true,
ShareEntityDamage1 = true,
ShareToolgun1 = true
}
local function ShareProp(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "FPP_ShareProp: Entity not given", false) return end
if not IsValid(Entity(args[1])) then FPP.Notify(ply, "FPP_ShareProp: Entity not valid", false) return end
if not args[2] then FPP.Notify(ply, "FPP_ShareProp: Player to share with not given", false) return end
local ent = Entity(args[1])
if ent:CPPIGetOwner() ~= ply then
FPP.Notify(ply, "You do not have the right to share this entity.", false)
return
end
if not tonumber(args[2]) or not IsValid(Player(tonumber(args[2]))) then -- This is for sharing prop per utility
if not allowedShares[args[2]] then
FPP.Notify(ply, "FPP_ShareProp: Player to share with doesn't exist", false)
return
end
ent[args[2]] = tobool(args[3])
else -- This is for sharing prop per player
local target = Player(tonumber(args[2]))
local toggle = tobool(args[3])
-- Make the table if it isn't there
if not ent.AllowedPlayers and toggle then
ent.AllowedPlayers = {target}
else
if toggle and not table.HasValue(ent.AllowedPlayers, target) then
table.insert(ent.AllowedPlayers, target)
FPP.Notify(target, ply:Nick() .. " shared an entity with you!", true)
elseif not toggle then
for k, v in pairs(ent.AllowedPlayers or {}) do
if v == target then
table.remove(ent.AllowedPlayers, k)
FPP.Notify(target, ply:Nick() .. " unshared an entity with you!", false)
end
end
end
end
end
FPP.recalculateCanTouch(player.GetAll(), {ent})
end
concommand.Add("FPP_ShareProp", ShareProp)
local function RetrieveSettings()
MySQLite.begin()
for k in pairs(FPP.Settings) do
MySQLite.queueQuery("SELECT setting, var FROM " .. k .. ";", function(data)
if not data then return end
for _, value in pairs(data) do
if FPP.Settings[k][value.var] == nil then
-- Likely an old setting that has since been removed from FPP.
-- This setting however still exists in the DB. Time to remove it.
MySQLite.query("DELETE FROM " .. k .. " WHERE var = " .. sql.SQLStr(value.var) .. ";")
continue
end
FPP.Settings[k][value.var] = tonumber(value.setting)
end
end)
end
MySQLite.commit(function()
SendSettings(player.GetAll())
end)
end
local defaultBlocked = {
Physgun1 = {
["func_breakable_surf"] = true,
["func_brush"] = true,
["func_button"] = true,
["func_door"] = true,
["prop_door_rotating"] = true,
["func_door_rotating"] = true
},
Spawning1 = {
["func_breakable_surf"] = true,
["player"] = true,
["func_door"] = true,
["prop_door_rotating"] = true,
["func_door_rotating"] = true,
["ent_explosivegrenade"] = true,
["ent_mad_grenade"] = true,
["ent_flashgrenade"] = true,
["gmod_wire_field_device"] = true
},
Gravgun1 = {["func_breakable_surf"] = true, ["vehicle_"] = true},
Toolgun1 = {
["func_breakable_surf"] = true,
["func_button"] = true,
["player"] = true,
["func_door"] = true,
["prop_door_rotating"] = true,
["func_door_rotating"] = true
},
PlayerUse1 = {},
EntityDamage1 = {}
}
-- Fills the FPP blocked table with default things that are to be blocked
function FPP.FillDefaultBlocked()
local count = 0
MySQLite.begin()
-- All values that are to be inserted
local allValues = {}
for k, v in pairs(defaultBlocked) do
for a in pairs(v) do
FPP.Blocked[k][a] = true
count = count + 1
if not MySQLite.isMySQL() then
MySQLite.query("REPLACE INTO FPP_BLOCKED1 VALUES(" .. count .. ", " .. sql.SQLStr(k) .. ", " .. sql.SQLStr(a) .. ");")
else
table.insert(allValues, string.format("(%i, %s, %s)", count, sql.SQLStr(k), sql.SQLStr(a)))
end
end
end
-- Run it all in a single query if using MySQL.
if MySQLite.isMySQL() then
MySQLite.query(string.format("INSERT IGNORE INTO FPP_BLOCKED1 VALUES %s", table.concat(allValues, ",")))
end
MySQLite.commit()
end
local function RetrieveBlocked()
MySQLite.query("SELECT * FROM FPP_BLOCKED1;", function(data)
if istable(data) then
for _, v in pairs(data) do
if not FPP.Blocked[v.var] then
ErrorNoHalt((v.var or "(nil var)") .. " blocked type does not exist! (Setting: " .. (v.setting or "") .. ")")
continue
end
FPP.Blocked[v.var][string.lower(v.setting)] = true
end
else
-- Give third party addons 5 seconds to add default blocked items
timer.Simple(5, FPP.FillDefaultBlocked)
end
end)
end
--[[-------------------------------------------------------------------------
Default blocked entities
Only save in the database on first start
---------------------------------------------------------------------------]]
function FPP.AddDefaultBlocked(types, classname)
classname = string.lower(classname)
if isstring(types) then
defaultBlocked[types] = defaultBlocked[types] or {}
defaultBlocked[types][classname] = true
return
end
for _, v in pairs(types) do
defaultBlocked[v] = defaultBlocked[v] or {}
defaultBlocked[v][classname] = true
end
end
local function RetrieveBlockedModels()
FPP.BlockedModels = FPP.BlockedModels or {}
-- Sometimes when the database retrieval is corrupt,
-- only parts of the table will be retrieved
-- This is a workaround
if not MySQLite.isMySQL() then
local count = MySQLite.queryValue("SELECT COUNT(*) FROM FPP_BLOCKEDMODELS1;") or 0
if tonumber(count) == 0 then
FPP.AddDefaultBlockedModels() -- Load the default blocked models on first run
end
-- Select with offsets of a thousand.
-- That's about the maximum it can receive properly at once
for i = 0, count, 1000 do
MySQLite.query("SELECT * FROM FPP_BLOCKEDMODELS1 LIMIT 1000 OFFSET " .. i .. ";", function(data)
for _, v in ipairs(data or {}) do
FPP.BlockedModels[v.model] = true
end
end)
end
return
end
-- Retrieve the data normally from MySQL
MySQLite.query("SELECT * FROM FPP_BLOCKEDMODELS1;", function(data)
if not data or #data == 0 then
FPP.AddDefaultBlockedModels() -- Load the default blocked models on first run
end
for _, v in ipairs(data or {}) do
if not v.model then continue end
FPP.BlockedModels[v.model] = true
end
end)
end
local function RetrieveRestrictedTools()
MySQLite.query("SELECT * FROM FPP_TOOLADMINONLY;", function(data)
if istable(data) then
for _, v in ipairs(data) do
FPP.RestrictedTools[v.toolname] = {}
FPP.RestrictedTools[v.toolname]["admin"] = tonumber(v.adminonly)
end
end
end)
MySQLite.query("SELECT * FROM FPP_TOOLRESTRICTPERSON1;", function(perplayerData)
if not istable(perplayerData) then return end
for _, v in ipairs(perplayerData) do
FPP.RestrictedToolsPlayers[v.toolname] = FPP.RestrictedToolsPlayers[v.toolname] or {}
FPP.RestrictedToolsPlayers[v.toolname][v.steamid] = tobool(v.allow)
end
end)
MySQLite.query("SELECT * FROM FPP_TOOLTEAMRESTRICT;", function(data)
if not data then return end
for _, v in ipairs(data) do
FPP.RestrictedTools[v.toolname] = FPP.RestrictedTools[v.toolname] or {}
FPP.RestrictedTools[v.toolname]["team"] = FPP.RestrictedTools[v.toolname]["team"] or {}
table.insert(FPP.RestrictedTools[v.toolname]["team"], tonumber(v.team))
end
end)
end
local function RetrieveGroups()
MySQLite.query("SELECT * FROM FPP_GROUPS3;", function(data)
if not istable(data) then
MySQLite.query("REPLACE INTO FPP_GROUPS3 VALUES('default', 1);")
FPP.Groups["default"] = {}
FPP.Groups["default"].tools = {}
FPP.Groups["default"].allowdefault = true
return
end -- if there are no groups then there isn't much to load
for _, v in ipairs(data) do
FPP.Groups[v.groupname] = {}
FPP.Groups[v.groupname].tools = {}
FPP.Groups[v.groupname].allowdefault = tobool(v.allowdefault)
end
MySQLite.query("SELECT * FROM FPP_GROUPTOOL;", function(grouptooldata)
if not grouptooldata then return end
for _, v in ipairs(grouptooldata) do
FPP.Groups[v.groupname] = FPP.Groups[v.groupname] or {}
FPP.Groups[v.groupname].tools = FPP.Groups[v.groupname].tools or {}
table.insert(FPP.Groups[v.groupname].tools, v.tool)
end
end)
MySQLite.query("SELECT * FROM FPP_GROUPMEMBERS1;", function(members)
if not istable(members) then return end
for _, v in ipairs(members) do
FPP.GroupMembers[v.steamid] = v.groupname
end
end)
end)
end
hook.Add("PlayerInitialSpawn", "FPP_SendSettings", SendSettings)
local function AddGroup(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "Invalid argument(s)", false) return end-- Args: 1 = name, optional: 2 = allowdefault
local name = string.lower(args[1])
local allowdefault = tonumber(args[2]) or 1
if FPP.Groups[name] then
FPP.Notify(ply, "Group already exists", false)
return
end
FPP.Groups[name] = {}
FPP.Groups[name].allowdefault = tobool(allowdefault)
FPP.Groups[name].tools = {}
MySQLite.query("REPLACE INTO FPP_GROUPS3 VALUES(" .. sql.SQLStr(name) .. ", " .. sql.SQLStr(allowdefault) .. ");")
FPP.Notify(ply, "Group added successfully", true)
end
concommand.Add("FPP_AddGroup", runIfAccess("FPP_Settings", AddGroup))
hook.Add("InitPostEntity", "FPP_Load_CAMI", function()
if not CAMI then return end
for groupName, _ in pairs(CAMI.GetUsergroups()) do
if FPP.Groups[groupName] then continue end
FPP.Groups[groupName] = {}
FPP.Groups[groupName].allowdefault = true
FPP.Groups[groupName].tools = {}
end
end)
local function RemoveGroup(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "Invalid argument(s)", false) return end-- Args: 1 = name
local name = string.lower(args[1])
if not FPP.Groups[name] then
FPP.Notify(ply, "Group does not exists", false)
return
end
if name == "default" then
FPP.Notify(ply, "Can not remove default group", false)
return
end
FPP.Groups[name] = nil
MySQLite.query("DELETE FROM FPP_GROUPS3 WHERE groupname = " .. sql.SQLStr(name) .. ";")
MySQLite.query("DELETE FROM FPP_GROUPTOOL WHERE groupname = " .. sql.SQLStr(name) .. ";")
for k, v in pairs(FPP.GroupMembers) do
if v == name then
FPP.GroupMembers[k] = nil -- Set group to standard if group is removed
end
end
FPP.Notify(ply, "Group removed successfully", true)
end
concommand.Add("FPP_RemoveGroup", runIfAccess("FPP_Settings", RemoveGroup))
local function GroupChangeAllowDefault(ply, cmd, args)
if not args[2] then FPP.Notify(ply, "Invalid argument(s)", false) return end-- Args: 1 = groupname, 2 = new value 1/0
local name = string.lower(args[1])
local newval = tonumber(args[2])
if not FPP.Groups[name] then
FPP.Notify(ply, "Group does not exists", false)
return
end
FPP.Groups[name].allowdefault = tobool(newval)
MySQLite.query("REPLACE INTO FPP_GROUPS3 VALUES(" .. sql.SQLStr(name) .. ", " .. sql.SQLStr(newval) .. ");")
FPP.Notify(ply, "Group status changed successfully", true)
end
concommand.Add("FPP_ChangeGroupStatus", runIfAccess("FPP_Settings", GroupChangeAllowDefault))
local function GroupAddTool(ply, cmd, args)
if not args[2] then FPP.Notify(ply, "Invalid argument(s)", false) return end-- Args: 1 = groupname, 2 = tool
local name = args[1]
local tool = string.lower(args[2])
if not FPP.Groups[name] then
FPP.Notify(ply, "Group does not exists", false)
return
end
FPP.Groups[name].tools = FPP.Groups[name].tools or {}
if table.HasValue(FPP.Groups[name].tools, tool) then
FPP.Notify(ply, "Tool is already in group!", false)
return
end
table.insert(FPP.Groups[name].tools, tool)
MySQLite.query("REPLACE INTO FPP_GROUPTOOL VALUES(" .. sql.SQLStr(name) .. ", " .. sql.SQLStr(tool) .. ");")
FPP.Notify(ply, "Tool added successfully", true)
end
concommand.Add("FPP_AddGroupTool", runIfAccess("FPP_Settings", GroupAddTool))
local function GroupRemoveTool(ply, cmd, args)
if not args[2] then FPP.Notify(ply, "Invalid argument(s)", false) return end-- Args: 1 = groupname, 2 = tool
local name = args[1]
local tool = string.lower(args[2])
if not FPP.Groups[name] then
FPP.Notify(ply, "Group does not exists", false)
return
end
if not table.HasValue(FPP.Groups[name].tools, tool) then
FPP.Notify(ply, "Tool does not exist in group!", false)
return
end
for k, v in pairs(FPP.Groups[name].tools) do
if v == tool then
table.remove(FPP.Groups[name].tools, k)
end
end
MySQLite.query("DELETE FROM FPP_GROUPTOOL WHERE groupname = " .. sql.SQLStr(name) .. " AND tool = " .. sql.SQLStr(tool) .. ";")
FPP.Notify(ply, "Tool removed successfully", true)
end
concommand.Add("FPP_RemoveGroupTool", runIfAccess("FPP_Settings", GroupRemoveTool))
-- Args: 1 = player, 2 = group
local function PlayerSetGroup(ply, cmd, args)
if not args[2] then FPP.Notify(ply, "Group not given", false) return end
local name = args[1]
local group = string.lower(args[2])
if IsValid(Player(tonumber(name) or 0)) then name = Player(tonumber(name)):SteamID()
elseif not string.find(name, "STEAM") and name ~= "UNKNOWN" and name ~= "BOT" then FPP.Notify(ply, "Player not found", false) return end
if not FPP.Groups[group] and (not CAMI or not CAMI.GetUsergroup(group)) then
FPP.Notify(ply, "Group does not exists", false)
return
end
if group ~= "default" then
MySQLite.query("REPLACE INTO FPP_GROUPMEMBERS1 VALUES(" .. sql.SQLStr(name) .. ", " .. sql.SQLStr(group) .. ");")
FPP.GroupMembers[name] = group
else
FPP.GroupMembers[name] = nil
MySQLite.query("DELETE FROM FPP_GROUPMEMBERS1 WHERE steamid = " .. sql.SQLStr(name) .. ";")
end
FPP.Notify(ply, "Player group successfully set", true)
end
concommand.Add("FPP_SetPlayerGroup", runIfAccess("FPP_Settings", PlayerSetGroup))
local function SendGroupData(ply, cmd, args)
net.Start("FPP_Groups")
net.WriteTable(FPP.Groups)
net.Send(ply)
end
concommand.Add("FPP_SendGroups", runIfAccess("FPP_Settings", SendGroupData))
local function SendGroupMemberData(ply, cmd, args)
net.Start("FPP_GroupMembers")
net.WriteTable(FPP.GroupMembers)
net.Send(ply)
end
concommand.Add("FPP_SendGroupMembers", runIfAccess("FPP_Settings", SendGroupMemberData))
local function SendBlocked(ply, cmd, args)
if not args[1] or not FPP.Blocked[args[1]] then return end
ply.FPPUmsg1 = ply.FPPUmsg1 or {}
ply.FPPUmsg1[args[1]] = ply.FPPUmsg1[args[1]] or 0
if ply.FPPUmsg1[args[1]] > CurTime() - 5 then return end
ply.FPPUmsg1[args[1]] = CurTime()
for k in pairs(FPP.Blocked[args[1]]) do
umsg.Start("FPP_blockedlist", ply)
umsg.String(args[1])
umsg.String(k)
umsg.End()
end
end
concommand.Add("FPP_sendblocked", SendBlocked)
local function SendBlockedModels(ply, cmd, args)
ply.FPPUmsg2 = ply.FPPUmsg2 or 0
if ply.FPPUmsg2 > CurTime() - 10 then return end
ply.FPPUmsg2 = CurTime()
local models = {}
for k in pairs(FPP.BlockedModels) do table.insert(models, k) end
local data = util.Compress(table.concat(models, "\0"))
if not data then return end
net.Start("FPP_BlockedModels")
net.WriteData(data, #data)
net.Send(ply)
end
concommand.Add("FPP_sendblockedmodels", SendBlockedModels)
local function SendRestrictedTools(ply, cmd, args)
ply.FPPUmsg3 = ply.FPPUmsg3 or 0
if ply.FPPUmsg3 > CurTime() - 5 then return end
ply.FPPUmsg3 = CurTime()
if not args[1] then return end
net.Start("FPP_RestrictedToolList")
net.WriteString(args[1]) -- tool name
net.WriteUInt(FPP.RestrictedTools[args[1]] and FPP.RestrictedTools[args[1]].admin or 0, 2) -- user, admin or superadmin
local teams = FPP.RestrictedTools[args[1]] and FPP.RestrictedTools[args[1]].team or {}
net.WriteUInt(#teams, 10)
for _, t in pairs(teams) do
net.WriteUInt(t, 10)
end
net.Send(ply)
end
concommand.Add("FPP_SendRestrictTool", SendRestrictedTools)
-- Fallback owner, will own entities after disconnect
local function setFallbackOwner(ply, fallback)
ply.FPPFallbackOwner = fallback:SteamID()
end
local function changeFallbackOwner(ply, _, args)
local fallback = tonumber(args[1]) and Player(tonumber(args[1]))
if tonumber(args[1]) == -1 then
ply.FPPFallbackOwner = nil
FPP.Notify(ply, "Fallback owner set", true)
return
end
if not IsValid(fallback) or not fallback:IsPlayer() or fallback == ply then FPP.Notify(ply, "Player invalid", false) return end
setFallbackOwner(ply, fallback)
FPP.Notify(ply, "Fallback owner set", true)
end
concommand.Add("FPP_FallbackOwner", changeFallbackOwner)
--Buddies!
local function changeBuddies(ply, buddy, settings)
if not IsValid(ply) then return end
ply.Buddies = ply.Buddies or {}
ply.Buddies[buddy] = settings
local CPPIBuddies = {}
for k, v in pairs(ply.Buddies) do if table.HasValue(v, true) then table.insert(CPPIBuddies, k) end end
-- Also run at player spawn because clients send their buddies through this command
hook.Run("CPPIFriendsChanged", ply, CPPIBuddies)
-- Update the prop protection
local affectedProps = {}
for _, v in ipairs(ents.GetAll()) do
local owner = v:CPPIGetOwner()
if owner ~= ply then continue end
table.insert(affectedProps, v)
end
FPP.recalculateCanTouch({buddy}, affectedProps)
FPP.RecalculateConstrainedEntities({buddy}, affectedProps)
end
local function SetBuddy(ply, cmd, args)
if not args[6] then FPP.Notify(ply, "FPP_SetBuddy: Not enough arguments given!", false) return end
local buddy = tonumber(args[1]) and Player(tonumber(args[1]))
if not IsValid(buddy) then FPP.Notify(ply, "Player invalid", false) return end
for k, v in pairs(args) do args[k] = tonumber(v) end
local settings = {Physgun = tobool(args[2]), Gravgun = tobool(args[3]), Toolgun = tobool(args[4]), PlayerUse = tobool(args[5]), EntityDamage = tobool(args[6])}
-- Antispam measure
timer.Create("FPP_BuddiesUpdate" .. ply:UserID() .. ", " .. buddy:UserID(), 1, 1, function() changeBuddies(ply, buddy, settings) end)
end
concommand.Add("FPP_SetBuddy", SetBuddy)
local function CleanupDisconnected(ply, cmd, args)
if not args[1] then FPP.Notify(ply, "Invalid argument", false) return end
if args[1] == "disconnected" then
for _, v in ipairs(ents.GetAll()) do
local owner = v:CPPIGetOwner()
if owner and not IsValid(owner) then
v:Remove()
end
end
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " removed all disconnected players' props", true)
return
elseif not tonumber(args[1]) or not IsValid(Player(tonumber(args[1]))) then
FPP.Notify(ply, "Invalid player", false)
return
end
local target_ply = Player(args[1])
for _, v in ipairs(ents.GetAll()) do
local owner = v:CPPIGetOwner()
if owner == target_ply then
if v:IsWeapon() and IsValid(v:GetOwner()) then
continue
end
v:Remove()
end
end
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " removed " .. target_ply:Nick() .. "'s entities", true)
end
concommand.Add("FPP_Cleanup", runIfAccess("FPP_Cleanup", CleanupDisconnected))
local function SetToolRestrict(ply, cmd, args)
if not args[3] then FPP.Notify(ply, "Invalid argument(s)", false) return end--FPP_restricttool <toolname> <type(admin/team)> <toggle(1/0)>
local toolname = args[1]
local RestrictWho = tonumber(args[2]) or args[2]-- "team" or "admin"
local teamtoggle = tonumber(args[4]) --this argument only exists when restricting a tool for a team
FPP.RestrictedTools[toolname] = FPP.RestrictedTools[toolname] or {}
if RestrictWho == "admin" then
FPP.RestrictedTools[toolname].admin = args[3] --weapons.Get("gmod_tool").Tool
--Save to database!
MySQLite.query("REPLACE INTO FPP_TOOLADMINONLY VALUES(" .. sql.SQLStr(toolname) .. ", " .. sql.SQLStr(args[3]) .. ");")
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " changed the admin status of " .. toolname , true)
elseif RestrictWho == "team" then
FPP.RestrictedTools[toolname]["team"] = FPP.RestrictedTools[toolname]["team"] or {}
if teamtoggle == 0 then
for k, v in pairs(FPP.RestrictedTools[toolname]["team"]) do
if v == tonumber(args[3]) then
table.remove(FPP.RestrictedTools[toolname]["team"], k)
break
end
end
elseif not table.HasValue(FPP.RestrictedTools[toolname]["team"], tonumber(args[3])) and teamtoggle == 1 then
table.insert(FPP.RestrictedTools[toolname]["team"], tonumber(args[3]))
end --Remove from the table if it's in there AND it's 0 otherwise do nothing
if tobool(teamtoggle) then -- if the team restrict is enabled
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " restricted " .. toolname .. " to certain teams", true)
MySQLite.query("REPLACE INTO FPP_TOOLTEAMRESTRICT VALUES(" .. sql.SQLStr(toolname) .. ", " .. tonumber(args[3]) .. ");")
else -- otherwise if the restriction for the team is being removed
FPP.NotifyAll(((ply.Nick and ply:Nick()) or "Console") .. " removed teamrestrictions from " .. toolname, true)
MySQLite.query("DELETE FROM FPP_TOOLTEAMRESTRICT WHERE toolname = " .. sql.SQLStr(toolname) .. " AND team = " .. tonumber(args[3]))
end
end
end
concommand.Add("FPP_restricttool", runIfAccess("FPP_Settings", SetToolRestrict))
local function RestrictToolPerson(ply, cmd, args)
if not args[3] then FPP.Notify(ply, "Invalid argument(s)", false) return end--FPP_restricttoolperson <toolname> <userid> <disallow, allow, remove(0,1,2)>
local toolname = args[1]
local target = Player(tonumber(args[2]))
local access = tonumber(args[3])
if not target:IsValid() then FPP.Notify(ply, "Invalid argument(s)", false) return end
if access < 0 or access > 2 then FPP.Notify(ply, "Invalid argument(s)", false) return end
FPP.RestrictedToolsPlayers[toolname] = FPP.RestrictedToolsPlayers[toolname] or {}
-- Disallow, even if other people can use it
if access == 0 or access == 1 then
FPP.RestrictedToolsPlayers[toolname][target:SteamID()] = access == 1
MySQLite.query("REPLACE INTO FPP_TOOLRESTRICTPERSON1 VALUES(" .. sql.SQLStr(toolname) .. ", " .. sql.SQLStr(target:SteamID()) .. ", " .. access .. ");")
elseif access == 2 then
-- reset tool status(make him like everyone else)
FPP.RestrictedToolsPlayers[toolname][target:SteamID()] = nil
MySQLite.query("DELETE FROM FPP_TOOLRESTRICTPERSON1 WHERE toolname = " .. sql.SQLStr(toolname) .. " AND steamid = " .. sql.SQLStr(target:SteamID()) .. ";")
end
FPP.Notify(ply, "Tool restrictions set successfully", true)
end
concommand.Add("FPP_restricttoolplayer", runIfAccess("FPP_Settings", RestrictToolPerson))
local function resetAllSetting(ply)
MySQLite.begin()
MySQLite.queueQuery("DELETE FROM FPP_PHYSGUN1")
MySQLite.queueQuery("DELETE FROM FPP_GRAVGUN1")
MySQLite.queueQuery("DELETE FROM FPP_TOOLGUN1")
MySQLite.queueQuery("DELETE FROM FPP_PLAYERUSE1")
MySQLite.queueQuery("DELETE FROM FPP_ENTITYDAMAGE1")
MySQLite.queueQuery("DELETE FROM FPP_GLOBALSETTINGS1")
MySQLite.queueQuery("DELETE FROM FPP_ANTISPAM1")
MySQLite.queueQuery("DELETE FROM FPP_BLOCKMODELSETTINGS1")
MySQLite.commit(function()
FPP.Settings = nil
FPP.Settings = table.Copy(FPP.InitialSettings)
SendSettings(player.GetAll())
if not IsValid(ply) then return end
FPP.Notify(ply, "Settings successfully reset.", true)
end)
end
concommand.Add("FPP_ResetAllSettings", runIfAccess("FPP_Settings", resetAllSetting))
local function resetBlockedModels(ply)
FPP.BlockedModels = {}
MySQLite.query("DELETE FROM FPP_BLOCKEDMODELS1", FPP.AddDefaultBlockedModels)
FPP.Notify(ply, "Settings successfully reset.", true)
end
concommand.Add("FPP_ResetBlockedModels", runIfAccess("FPP_Settings", resetBlockedModels))
local function refreshPrivatePlayerSettings(ply)
timer.Remove("FPP_RefreshPrivatePlayerSettings" .. ply:EntIndex())
timer.Create("FPP_RefreshPrivatePlayerSettings" .. ply:EntIndex(), 4, 1, function() FPP.recalculateCanTouch({ply}, ents.GetAll()) end)
end
concommand.Add("_FPP_RefreshPrivatePlayerSettings", refreshPrivatePlayerSettings)
--[[-------------------------------------------------------------------------
Load all FPP settings
---------------------------------------------------------------------------]]
function FPP.Init(callback)
MySQLite.begin()
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_BLOCKED1(id INTEGER NOT NULL, var VARCHAR(40) NOT NULL, setting VARCHAR(100) NOT NULL, PRIMARY KEY(id));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_PHYSGUN1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_GRAVGUN1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_TOOLGUN1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_PLAYERUSE1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_ENTITYDAMAGE1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_GLOBALSETTINGS1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_BLOCKMODELSETTINGS1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_ANTISPAM1(var VARCHAR(40) NOT NULL, setting INTEGER NOT NULL, PRIMARY KEY(var));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_TOOLADMINONLY(toolname VARCHAR(40) NOT NULL, adminonly INTEGER NOT NULL, PRIMARY KEY(toolname));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_TOOLTEAMRESTRICT(toolname VARCHAR(40) NOT NULL, team INTEGER NOT NULL, PRIMARY KEY(toolname, team));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_TOOLRESTRICTPERSON1(toolname VARCHAR(40) NOT NULL, steamid VARCHAR(40) NOT NULL, allow INTEGER NOT NULL, PRIMARY KEY(steamid, toolname));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_GROUPS3(groupname VARCHAR(40) NOT NULL, allowdefault INTEGER NOT NULL, PRIMARY KEY(groupname));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_GROUPTOOL(groupname VARCHAR(40) NOT NULL, tool VARCHAR(45) NOT NULL, PRIMARY KEY(groupname, tool));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_GROUPMEMBERS1(steamid VARCHAR(40) NOT NULL, groupname VARCHAR(40) NOT NULL, PRIMARY KEY(steamid));")
MySQLite.queueQuery("CREATE TABLE IF NOT EXISTS FPP_BLOCKEDMODELS1(model VARCHAR(140) NOT NULL PRIMARY KEY);")
if MySQLite.isMySQL() then
MySQLite.queueQuery("ALTER TABLE FPP_BLOCKED1 CHANGE id id INTEGER AUTO_INCREMENT;")
end
MySQLite.commit(function()
RetrieveBlocked()
RetrieveBlockedModels()
RetrieveRestrictedTools()
RetrieveGroups()
RetrieveSettings()
-- Callback when FPP is done creating the tables
if callback then callback() end
end)
end
local assbackup = ASS_RegisterPlugin -- Suddenly after witing this code, ASS spamprotection and propprotection broke. I have no clue why. I guess you should use FPP then
if assbackup then
function ASS_RegisterPlugin(plugin, ...)
if plugin.Name == "Sandbox Spam Protection" or plugin.Name == "Sandbox Prop Protection" then
return
end
return assbackup(plugin, ...)
end
end