forked from Nebual/NadmodPP
Merge pull request #3 from thegrb93/updates
Clientside CPPI Support (eg. for Starfall)
This commit is contained in:
commit
6f5c0e0eb7
@ -6,23 +6,71 @@
|
||||
if !NADMOD then
|
||||
NADMOD = {}
|
||||
NADMOD.PropOwners = {}
|
||||
NADMOD.PropNames = {}
|
||||
NADMOD.PPConfig = {}
|
||||
NADMOD.Friends = {}
|
||||
end
|
||||
|
||||
local Props = NADMOD.PropOwners
|
||||
net.Receive("nadmod_propowners",function(len)
|
||||
local num = net.ReadUInt(16)
|
||||
for k=1,num do
|
||||
local id,str = net.ReadUInt(16), net.ReadString()
|
||||
if str == "-" then Props[id] = nil
|
||||
elseif str == "W" then Props[id] = "World"
|
||||
elseif str == "O" then Props[id] = "Ownerless"
|
||||
else Props[id] = str
|
||||
local PropNames = NADMOD.PropNames
|
||||
net.Receive("nadmod_propowners",function(len)
|
||||
local nameMap = {}
|
||||
for i=1, net.ReadUInt(8) do
|
||||
nameMap[i] = net.ReadString()
|
||||
end
|
||||
for i=1, net.ReadUInt(32) do
|
||||
local id, str = net.ReadUInt(16), nameMap[net.ReadUInt(8)]
|
||||
if id==0 then break end
|
||||
if str == "-" then Props[id] = nil PropNames[id] = nil
|
||||
elseif str == "W" then PropNames[id] = "World"
|
||||
elseif str == "O" then PropNames[id] = "Ownerless"
|
||||
else
|
||||
Props[id] = str
|
||||
local ply = player.GetBySteamID(str)
|
||||
PropNames[id] = ply and ply:IsValid() and ply:Nick() or "N/A"
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function NADMOD.GetPropOwner(ent)
|
||||
local id = Props[ent:EntIndex()]
|
||||
return id and player.GetBySteamID(id)
|
||||
end
|
||||
|
||||
function NADMOD.PlayerCanTouch(ply, ent)
|
||||
-- If PP is off or the ent is worldspawn, let them touch it
|
||||
if not tobool(NADMOD.PPConfig["toggle"]) then return true end
|
||||
if ent:IsWorld() then return ent:GetClass()=="worldspawn" end
|
||||
if !IsValid(ent) or !IsValid(ply) or ent:IsPlayer() or !ply:IsPlayer() then return false end
|
||||
|
||||
local index = ent:EntIndex()
|
||||
if not Props[index] then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Ownerless props can be touched by all
|
||||
if PropNames[index] == "Ownerless" then return true end
|
||||
-- Admins can touch anyones props + world
|
||||
if NADMOD.PPConfig["adminall"] and NADMOD.IsPPAdmin(ply) then return true end
|
||||
-- Players can touch their own props
|
||||
local plySteam = ply:SteamID()
|
||||
if Props[index] == plySteam then return true end
|
||||
-- Friends can touch LocalPlayer()'s props
|
||||
if Props[index] == LocalPlayer():SteamID() and NADMOD.Friends[plySteam] then return true end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- Does your admin mod not seem to work with Nadmod PP? Try overriding this function!
|
||||
function NADMOD.IsPPAdmin(ply)
|
||||
if NADMOD.HasPermission then
|
||||
return NADMOD.HasPermission(ply, "PP_All")
|
||||
else
|
||||
-- If the admin mod NADMOD isn't present, just default to using IsAdmin
|
||||
return ply:IsAdmin()
|
||||
end
|
||||
end
|
||||
|
||||
local nadmod_overlay_convar = CreateConVar("nadmod_overlay", 2, {FCVAR_NOTIFY, FCVAR_ARCHIVE, FCVAR_REPLICATED}, "0 - Disables NPP Overlay. 1 - Minimal overlay of just owner info. 2 - Includes model, entityID, class")
|
||||
local font = "ChatFont"
|
||||
hook.Add("HUDPaint", "NADMOD.HUDPaint", function()
|
||||
@ -32,7 +80,7 @@ hook.Add("HUDPaint", "NADMOD.HUDPaint", function()
|
||||
if !tr.HitNonWorld then return end
|
||||
local ent = tr.Entity
|
||||
if ent:IsValid() && !ent:IsPlayer() then
|
||||
local text = "Owner: " .. (Props[ent:EntIndex()] or "N/A")
|
||||
local text = "Owner: " .. (PropNames[ent:EntIndex()] or "N/A")
|
||||
surface.SetFont(font)
|
||||
local Width, Height = surface.GetTextSize(text)
|
||||
local boxWidth = Width + 25
|
||||
@ -138,8 +186,9 @@ function NADMOD.AdminPanel(Panel, runByNetReceive)
|
||||
end
|
||||
for k, ply in pairs(player.GetAll()) do
|
||||
if IsValid(ply) then
|
||||
Panel:Button( ply:Nick().." ("..(counts[ply:Nick()] or 0)..")", "nadmod_cleanupprops", ply:EntIndex() )
|
||||
dccount = dccount - (counts[ply:Nick()] or 0)
|
||||
local steamid = ply:SteamID()
|
||||
Panel:Button( ply:Nick().." ("..(counts[steamid] or 0)..")", "nadmod_cleanupprops", ply:EntIndex() )
|
||||
dccount = dccount - (counts[steamid] or 0)
|
||||
end
|
||||
end
|
||||
|
||||
@ -217,3 +266,16 @@ net.Receive("nadmod_notify", function(len)
|
||||
surface.PlaySound("ambient/water/drip"..math.random(1, 4)..".wav")
|
||||
print(text)
|
||||
end)
|
||||
|
||||
CPPI = {}
|
||||
local metaent = FindMetaTable("Entity")
|
||||
local metaply = FindMetaTable("Player")
|
||||
|
||||
function CPPI:GetName() return "Nadmod Prop Protection" end
|
||||
function CPPI:GetVersion() return "" end
|
||||
function metaply:CPPIGetFriends() return {} end
|
||||
function metaent:CPPIGetOwner() return NADMOD.GetPropOwner(self) end
|
||||
function metaent:CPPICanTool(ply,mode) return NADMOD.PlayerCanTouch(ply,self) end
|
||||
function metaent:CPPICanPhysgun(ply) return NADMOD.PlayerCanTouch(ply,self) end
|
||||
function metaent:CPPICanPickup(ply) return NADMOD.PlayerCanTouch(ply,self) end
|
||||
function metaent:CPPICanPunt(ply) return NADMOD.PlayerCanTouch(ply,self) end
|
||||
|
@ -80,6 +80,41 @@ function NADMOD.IsPPAdmin(ply)
|
||||
end
|
||||
end
|
||||
|
||||
function NADMOD.SendPropOwners(props, ply)
|
||||
net.Start("nadmod_propowners")
|
||||
local nameMap = {}
|
||||
local nameMapi = 0
|
||||
local count = 0
|
||||
for k,v in pairs(props) do
|
||||
if not nameMap[v] then
|
||||
nameMapi = nameMapi + 1
|
||||
nameMap[v] = nameMapi
|
||||
nameMap[nameMapi] = v
|
||||
end
|
||||
count = count + 1
|
||||
end
|
||||
net.WriteUInt(nameMapi,8)
|
||||
for i=1, nameMapi do
|
||||
net.WriteString(nameMap[i])
|
||||
end
|
||||
|
||||
net.WriteUInt(count,32)
|
||||
for k,v in pairs(props) do
|
||||
net.WriteUInt(k,16)
|
||||
net.WriteUInt(nameMap[v],8)
|
||||
end
|
||||
if ply then net.Send(ply) else net.Broadcast() end
|
||||
end
|
||||
|
||||
function NADMOD.RefreshOwners()
|
||||
if not timer.Exists("NADMOD.RefreshOwners") then
|
||||
timer.Create("NADMOD.RefreshOwners", 0, 1, function()
|
||||
NADMOD.SendPropOwners(NADMOD.PropOwnersSmall)
|
||||
NADMOD.PropOwnersSmall = {}
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
function NADMOD.PPInitPlayer(ply)
|
||||
local steamid = ply:SteamID()
|
||||
for _,v in pairs(NADMOD.Props) do
|
||||
@ -89,13 +124,11 @@ function NADMOD.PPInitPlayer(ply)
|
||||
if v.Ent.SetPlayer then v.Ent:SetPlayer(ply) end
|
||||
end
|
||||
end
|
||||
net.Start("nadmod_propowners")
|
||||
net.WriteUInt(table.Count(NADMOD.Props),16)
|
||||
for k,v in pairs(NADMOD.Props) do
|
||||
net.WriteUInt(k,16)
|
||||
net.WriteString(v.Name)
|
||||
end
|
||||
net.Send(ply)
|
||||
local tbl = {}
|
||||
for k,v in pairs(NADMOD.Props) do
|
||||
tbl[k] = v.SteamID
|
||||
end
|
||||
NADMOD.SendPropOwners(tbl, ply)
|
||||
end
|
||||
hook.Add("PlayerInitialSpawn", "NADMOD.PPInitPlayer", NADMOD.PPInitPlayer)
|
||||
|
||||
@ -110,21 +143,6 @@ function NADMOD.PPOwnWeapons(ply)
|
||||
end
|
||||
hook.Add("PlayerSpawn", "NADMOD.PPOwnWeapons", NADMOD.PPOwnWeapons)
|
||||
|
||||
function NADMOD.RefreshOwners()
|
||||
if next(NADMOD.PropOwnersSmall) then
|
||||
net.Start("nadmod_propowners")
|
||||
net.WriteUInt(table.Count(NADMOD.PropOwnersSmall),16)
|
||||
for k,v in pairs(NADMOD.PropOwnersSmall) do
|
||||
net.WriteUInt(k,16)
|
||||
net.WriteString(v)
|
||||
end
|
||||
//net.WriteTable(NADMOD.PropOwnersSmall)
|
||||
net.Broadcast()
|
||||
table.Empty(NADMOD.PropOwnersSmall)
|
||||
end
|
||||
end
|
||||
timer.Create("NADMOD.RefreshOwners", 1, 0, NADMOD.RefreshOwners)
|
||||
|
||||
function NADMOD.IsFriendProp(ply, ent)
|
||||
if IsValid(ent) && IsValid(ply) && ply:IsPlayer() && NADMOD.Props[ent:EntIndex()] then
|
||||
local ownerSteamID = NADMOD.Props[ent:EntIndex()].SteamID
|
||||
@ -138,39 +156,45 @@ end
|
||||
|
||||
function NADMOD.PlayerCanTouch(ply, ent)
|
||||
-- If PP is off or the ent is worldspawn, let them touch it
|
||||
if not tobool(NADMOD.PPConfig["toggle"]) or ent:IsWorld() then return true end
|
||||
|
||||
if not tobool(NADMOD.PPConfig["toggle"]) then return true end
|
||||
if ent:IsWorld() then return ent:GetClass()=="worldspawn" end
|
||||
if !IsValid(ent) or !IsValid(ply) or ent:IsPlayer() or !ply:IsPlayer() then return false end
|
||||
|
||||
if not NADMOD.Props[ent:EntIndex()] then
|
||||
local index = ent:EntIndex()
|
||||
if not NADMOD.Props[index] then
|
||||
if index == 0 then
|
||||
-- Players cannot take ownership of EntIndex 0 ents (constraints, func_'s, map lights)
|
||||
NADMOD.SetOwnerWorld(ent)
|
||||
return false
|
||||
end
|
||||
|
||||
local class = ent:GetClass()
|
||||
if(string.find(class, "stone_") == 1 or string.find(class, "rock_") == 1 or string.find(class, "stargate_") == 0 or string.find(class, "dhd_") == 0 or class == "flag" or class == "item" or class == "predicted_viewmodel" or class == "gmod_hands" or class == "physgun_beam") then
|
||||
if(class == "predicted_viewmodel" or class == "gmod_hands" or class == "physgun_beam") then
|
||||
NADMOD.SetOwnerWorld(ent)
|
||||
elseif ent.GetPlayer and IsValid(ent:GetPlayer()) then
|
||||
NADMOD.PlayerMakePropOwner(ent:GetPlayer(), ent)
|
||||
elseif ent.GetOwner and (IsValid(ent:GetOwner()) or ent:GetOwner():IsWorld()) then
|
||||
NADMOD.PlayerMakePropOwner(ent:GetOwner(), ent)
|
||||
elseif ent:EntIndex() == 0 then
|
||||
-- Players cannot take ownership of EntIndex 0 ents (constraints, func_'s, map lights)
|
||||
return false
|
||||
else
|
||||
NADMOD.PlayerMakePropOwner(ply, ent)
|
||||
NADMOD.Notify(ply, "You now own this " .. class .. " (" .. string.sub(table.remove(string.Explode("/", ent:GetModel() or "?")), 1,-5) .. ")" )
|
||||
return true
|
||||
end
|
||||
|
||||
if !NADMOD.Props[index] then
|
||||
-- To get here implies the ent has a 'valid' GetPlayer()/GetOwner(), but still couldn't get set properly
|
||||
-- For example, if an NPC is sitting in jeep (??), the jeep's GetPlayer returns the driver? or something
|
||||
ent:CPPISetOwnerless(true)
|
||||
if !NADMOD.Props[index] then return false end
|
||||
end
|
||||
end
|
||||
if !NADMOD.Props[ent:EntIndex()] then
|
||||
-- To get here implies the ent has a 'valid' GetPlayer()/GetOwner(), but still couldn't get set properly
|
||||
-- For example, if an NPC is sitting in jeep (??), the jeep's GetPlayer returns the driver? or something
|
||||
ent:CPPISetOwnerless(true)
|
||||
if !NADMOD.Props[ent:EntIndex()] then return end
|
||||
end
|
||||
|
||||
-- Ownerless props can be touched by all
|
||||
if NADMOD.Props[ent:EntIndex()].Name == "O" then return true end
|
||||
if NADMOD.Props[index].Name == "O" then return true end
|
||||
-- Admins can touch anyones props + world
|
||||
if NADMOD.PPConfig["adminall"] and NADMOD.IsPPAdmin(ply) then return true end
|
||||
-- Players can touch their own props and friends
|
||||
if NADMOD.Props[ent:EntIndex()].SteamID == ply:SteamID() or NADMOD.IsFriendProp(ply, ent) then return true end
|
||||
if NADMOD.Props[index].SteamID == ply:SteamID() or NADMOD.IsFriendProp(ply, ent) then return true end
|
||||
|
||||
return false
|
||||
end
|
||||
@ -264,9 +288,11 @@ function NADMOD.PlayerMakePropOwner(ply,ent)
|
||||
SteamID = ply:SteamID(),
|
||||
Name = ply:Nick()
|
||||
}
|
||||
NADMOD.PropOwnersSmall[ent:EntIndex()] = ply:Nick()
|
||||
NADMOD.PropOwnersSmall[ent:EntIndex()] = ply:SteamID()
|
||||
ent.SPPOwner = ply
|
||||
NADMOD.RefreshOwners()
|
||||
end
|
||||
|
||||
-- Hook into the cleanup and sbox-limit adding functions to catch most props
|
||||
if(cleanup) then
|
||||
local backupcleanupAdd = cleanup.Add
|
||||
@ -299,6 +325,7 @@ function metaent:CPPISetOwnerless(bool)
|
||||
}
|
||||
NADMOD.PropOwnersSmall[self:EntIndex()] = "O"
|
||||
self.SPPOwner = game.GetWorld()
|
||||
NADMOD.RefreshOwners()
|
||||
else
|
||||
NADMOD.EntityRemoved(self)
|
||||
end
|
||||
@ -313,14 +340,15 @@ function NADMOD.SetOwnerWorld(ent)
|
||||
}
|
||||
NADMOD.PropOwnersSmall[ent:EntIndex()] = "W"
|
||||
ent.SPPOwner = game.GetWorld()
|
||||
NADMOD.RefreshOwners()
|
||||
end
|
||||
|
||||
-- Loop through all entities that exist when the map is loaded, these are all "world owned" entities
|
||||
function NADMOD.WorldOwner()
|
||||
local WorldEnts = 0
|
||||
for k,v in pairs(ents.FindByClass("*")) do
|
||||
for k,v in pairs(ents.GetAll()) do
|
||||
if(!v:IsPlayer() and (v:EntIndex() == 0 or !NADMOD.Props[v:EntIndex()])) and not IsValid(v.SPPOwner) then
|
||||
if game.GetMap() == "gm_construct" and v:GetClass() == "func_brush" then
|
||||
if v:GetClass() == "func_brush" and game.GetMap() == "gm_construct" then
|
||||
v:CPPISetOwnerless(true)
|
||||
else
|
||||
NADMOD.SetOwnerWorld(v)
|
||||
@ -331,12 +359,15 @@ function NADMOD.WorldOwner()
|
||||
print("Nadmod Prop Protection: "..WorldEnts.." props belong to world")
|
||||
end
|
||||
if CurTime() < 5 then timer.Create("NADMOD.PPFindWorldProps",7,1,NADMOD.WorldOwner) end
|
||||
hook.Add("PostCleanupMap","NADMOD.PPFindWorldProps",NADMOD.WorldOwner)
|
||||
hook.Add("PostCleanupMap","NADMOD.MapCleaned",function()
|
||||
timer.Simple(0,function() NADMOD.WorldOwner() end)
|
||||
end)
|
||||
|
||||
|
||||
function NADMOD.EntityRemoved(ent)
|
||||
NADMOD.Props[ent:EntIndex()] = nil
|
||||
NADMOD.PropOwnersSmall[ent:EntIndex()] = "-"
|
||||
NADMOD.RefreshOwners()
|
||||
if ent:IsValid() and ent:IsPlayer() and not ent:IsBot() then
|
||||
-- This is more reliable than PlayerDisconnect
|
||||
local steamid, nick = ent:SteamID(), ent:Nick()
|
||||
@ -382,10 +413,10 @@ function NADMOD.CleanupPlayerProps(steamid)
|
||||
return count
|
||||
end
|
||||
|
||||
function NADMOD.CleanPlayer(tar)
|
||||
function NADMOD.CleanPlayer(ply, tar)
|
||||
if IsValid(tar) and tar:IsPlayer() then
|
||||
local count = NADMOD.CleanupPlayerProps(tar:SteamID())
|
||||
NADMOD.Notify(tar:Nick().."'s props have been cleaned up ("..count..")")
|
||||
NADMOD.Notify((ply:IsValid() and ply:Nick() or "Console") .. " cleaned up " ..tar:Nick().."'s props ("..count..")")
|
||||
end
|
||||
end
|
||||
|
||||
@ -395,14 +426,14 @@ function NADMOD.CleanupProps(ply, cmd, args)
|
||||
local count = NADMOD.CleanupPlayerProps(ply:SteamID())
|
||||
NADMOD.Notify(ply,"Your props have been cleaned up ("..count..")")
|
||||
elseif !ply:IsValid() or NADMOD.IsPPAdmin(ply) then
|
||||
NADMOD.CleanPlayer(Entity(EntIndex))
|
||||
NADMOD.CleanPlayer(ply, Entity(EntIndex))
|
||||
end
|
||||
end
|
||||
concommand.Add("nadmod_cleanupprops", NADMOD.CleanupProps)
|
||||
|
||||
function NADMOD.CleanPlayerConCommand(ply, cmd, args, fullstr)
|
||||
if ply:IsValid() and not NADMOD.IsPPAdmin(ply) then return end
|
||||
NADMOD.CleanPlayer(NADMOD.FindPlayer(fullstr))
|
||||
NADMOD.CleanPlayer(ply, NADMOD.FindPlayer(fullstr))
|
||||
end
|
||||
concommand.Add("nadmod_cleanplayer", NADMOD.CleanPlayerConCommand)
|
||||
|
||||
@ -418,7 +449,7 @@ function NADMOD.CleanName(ply, cmd, args, fullstr)
|
||||
count = count + 1
|
||||
end
|
||||
end
|
||||
NADMOD.Notify(fullstr.."'s props ("..count..") have been cleaned up")
|
||||
NADMOD.Notify((ply:IsValid() and ply:Nick() or "Console") .. " cleaned up " ..fullstr.."'s props ("..count..")")
|
||||
end
|
||||
concommand.Add("nadmod_cleanname",NADMOD.CleanName)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user