Merge pull request #3 from thegrb93/updates

Clientside CPPI Support (eg. for Starfall)
This commit is contained in:
Nebual 2019-10-26 12:52:53 -07:00 committed by GitHub
commit 6f5c0e0eb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 150 additions and 57 deletions

View File

@ -6,23 +6,71 @@
if !NADMOD then
NADMOD = {}
NADMOD.PropOwners = {}
NADMOD.PropNames = {}
NADMOD.PPConfig = {}
NADMOD.Friends = {}
end
local Props = NADMOD.PropOwners
local PropNames = NADMOD.PropNames
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 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

View File

@ -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)
local tbl = {}
for k,v in pairs(NADMOD.Props) do
net.WriteUInt(k,16)
net.WriteString(v.Name)
tbl[k] = v.SteamID
end
net.Send(ply)
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
end
if !NADMOD.Props[ent:EntIndex()] then
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[ent:EntIndex()] then return end
if !NADMOD.Props[index] then return false end
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)