@@ -4,125 +4,89 @@ local owneraccess
44if SERVER then
55 owneraccess = CreateConVar (" sf_permissions_entity_owneraccess" , " 0" , { FCVAR_ARCHIVE }, " Allows starfall chip's owner to access their player entity" )
66end
7-
8- local P = {}
9- P .id = " entities"
10- P .name = " Entity Permissions"
11- P .settingsoptions = { " Owner Only" , " Can Tool" , " Can Physgun" , " Anything" }
12- P .defaultsetting = 2
13- local truefunc = function () return true end
14- P .checks = {truefunc , truefunc , truefunc , truefunc }
15- SF .Permissions .registerProvider (P )
7+ local cacheLifetime = CreateConVar (" sf_permissions_entity_cachelife" , " 5" , {FCVAR_ARCHIVE , FCVAR_REPLICATED }, " How long to store successful prop permission checks before checking again" )
168
179local ENT_META ,PLY_META = FindMetaTable (" Entity" ),FindMetaTable (" Player" )
1810local Ent_GetNWEntity ,Ent_GetTable ,Ent_IsValid ,Ent_SetNWEntity = ENT_META .GetNWEntity ,ENT_META .GetTable ,ENT_META .IsValid ,ENT_META .SetNWEntity
1911local Ply_IsSuperAdmin ,Ply_SteamID64 = PLY_META .IsSuperAdmin ,PLY_META .SteamID64
2012
13+ local checkOwner , checkCanTool , checkCanPhysgun
14+
2115if CPPI then
2216 function SF .Permissions .getOwner (ent )
2317 return ent :CPPIGetOwner ()
2418 end
2519
2620 if SERVER then
27- P .checks = {
28- function (instance , target )
29- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
30- if target == instance .player and owneraccess :GetBool () or
31- Ply_IsSuperAdmin (instance .player ) or
32- target :CPPIGetOwner ()== instance .player then return true end
33-
34- return false , " You're not the owner of this prop"
35- end ,
36- function (instance , target )
37- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
38- if target == instance .player and owneraccess :GetBool () or
39- target :CPPICanTool (instance .player , " starfall_ent_lib" ) then return true end
40-
41- return false , " You can't toolgun this entity"
42- end ,
43- function (instance , target )
44- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
45- if target == instance .player and owneraccess :GetBool () or
46- target :CPPICanPhysgun (instance .player ) then return true end
47-
48- return false , " You can't physgun this entity"
49- end ,
50- " allow"
51- }
21+ function checkOwner (instance , ent )
22+ if ent == instance .player and owneraccess :GetBool () then return true end
23+ if ent :CPPIGetOwner ()== instance .player then return true end
24+ return false , " You're not the owner of this prop"
25+ end
26+ function checkCanTool (instance , ent )
27+ if ent == instance .player and owneraccess :GetBool () then return true end
28+ if ent :CPPICanTool (instance .player , " starfall_ent_lib" ) then return true end
29+ return false , " You can't toolgun this entity"
30+ end
31+ function checkCanPhysgun (instance , ent )
32+ if ent == instance .player and owneraccess :GetBool () then return true end
33+ if ent :CPPICanPhysgun (instance .player ) then return true end
34+ return false , " You can't physgun this entity"
35+ end
5236 else
53- P .checks = {
54- function (instance , target )
55- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
56- if target == instance .player or
57- LocalPlayer ()== instance .player or
58- Ply_IsSuperAdmin (instance .player ) or
59- target :CPPIGetOwner ()== instance .player then return true end
60-
61- return false , " You're not the owner of this prop"
62- end ,
63- function (instance , target )
64- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
65- if target == instance .player or
66- LocalPlayer ()== instance .player or
67- Ply_IsSuperAdmin (instance .player ) or
68- target :CPPICanTool (instance .player , " starfall_ent_lib" ) then return true end
69-
70- return false , " You can't toolgun this entity"
71- end ,
72- function (instance , target )
73- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
74- if target == instance .player or
75- LocalPlayer ()== instance .player or
76- Ply_IsSuperAdmin (instance .player ) or
77- target :CPPICanPhysgun (instance .player ) then return true end
78-
79- return false , " You can't physgun this entity"
80- end ,
81- " allow"
82- }
83- if not ENT_META .CPPICanTool then P .checks [2 ] = P .checks [1 ] end
84- if not ENT_META .CPPICanPhysgun then P .checks [3 ] = P .checks [1 ] end
37+ function checkOwner (instance , ent )
38+ if ent == instance .player or LocalPlayer ()== instance .player then return true end
39+ if ent :CPPIGetOwner ()== instance .player then return true end
40+ return false , " You're not the owner of this prop"
41+ end
42+ function checkCanTool (instance , ent )
43+ if ent == instance .player or LocalPlayer ()== instance .player then return true end
44+ if ent :CPPICanTool (instance .player , " starfall_ent_lib" ) then return true end
45+ return false , " You can't toolgun this entity"
46+ end
47+ function checkCanPhysgun (instance , ent )
48+ if ent == instance .player or LocalPlayer ()== instance .player then return true end
49+ if ent :CPPICanPhysgun (instance .player ) then return true end
50+ return false , " You can't physgun this entity"
51+ end
52+ if not ENT_META .CPPICanTool then checkCanTool = checkOwner end
53+ if not ENT_META .CPPICanPhysgun then checkCanPhysgun = checkOwner end
8554 end
8655else
8756 if SERVER then
88- P .checks = {
89- function (instance , target )
90- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
91- if target == instance .player and owneraccess :GetBool () or
92- Ply_IsSuperAdmin (instance .player ) or
93- P .props [target ]== instance .player then return true end
94-
95- return false , " You're not the owner of this prop"
96- end ,
97- function (instance , target )
98- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
99- if target == instance .player and owneraccess :GetBool () or
100- hook .Run (" CanTool" , instance .player , SF .dumbTrace (target ), " starfall_ent_lib" ) ~= false then return true end
101-
102- return false , " Target doesn't have toolgun access"
103- end ,
104- function (instance , target )
105- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
106- if target == instance .player and owneraccess :GetBool () then return true end
107-
108- if hook .Run (" PhysgunPickup" , instance .player , target ) ~= false then
109- -- Some mods expect a release when there's a pickup involved.
110- hook .Run (" PhysgunDrop" , instance .player , target )
111- return true
112- end
57+ local PropOwners = SF .EntityTable (" PropProtection" )
58+ local PropOwnersDisconnected = SF .EntityTable (" PropProtectionReconnect" )
59+ SF .PropOwners = PropOwners
11360
114- return false , " Target doesn't have physgun access"
115- end ,
116- " allow"
117- }
118-
119- P .props = SF .EntityTable (" PropProtection" )
12061 function SF .Permissions .getOwner (ent )
121- return P .props [ent ] or NULL
62+ return PropOwners [ent ] or NULL
63+ end
64+
65+ function checkOwner (instance , ent )
66+ if ent == instance .player and owneraccess :GetBool () then return true end
67+ if PropOwners [ent ]== instance .player then return true end
68+ return false , " You're not the owner of this prop"
12269 end
70+ function checkCanTool (instance , ent )
71+ if ent == instance .player and owneraccess :GetBool () then return true end
72+ if hook .Run (" CanTool" , instance .player , SF .dumbTrace (ent ), " starfall_ent_lib" ) ~= false then return true end
73+ return false , " You can't toolgun this entity"
74+ end
75+ function checkCanPhysgun (instance , ent )
76+ if ent == instance .player and owneraccess :GetBool () then return true end
77+
78+ if hook .Run (" PhysgunPickup" , instance .player , ent ) ~= false then
79+ -- Some mods expect a release when there's a pickup involved.
80+ hook .Run (" PhysgunDrop" , instance .player , ent )
81+ return true
82+ end
83+
84+ return false , " You can't physgun this entity"
85+ end
86+
12387
12488 local function PropOwn (ply ,ent )
125- P . props [ent ] = ply
89+ PropOwners [ent ] = ply
12690 Ent_SetNWEntity (ent , " SFPP" , ply )
12791 end
12892
@@ -148,42 +112,122 @@ else
148112 hook .Add (" PlayerSpawnedSWEP" , " SFPP.PlayerSpawnedSWEP" , PropOwn )
149113 hook .Add (" PlayerInitialSpawn" ," SFPP.PlayerInitialSpawn" , function (ply )
150114 local steamid = Ply_SteamID64 (ply )
151- for k , v in pairs (P . props ) do
115+ for k , v in pairs (PropOwnersDisconnected ) do
152116 if v == steamid then
153117 PropOwn (ply ,k )
154118 end
155119 end
156120 end )
157121 hook .Add (" PlayerDisconnected" ," SFPP.PlayerDisconnected" , function (ply )
158122 local steamid = Ply_SteamID64 (ply )
159- for k , v in pairs (P . props ) do
123+ for k , v in pairs (PropOwners ) do
160124 if v == ply then
161- P .props [k ] = steamid
125+ PropOwnersDisconnected [k ] = steamid
126+ PropOwners [k ] = nil
162127 end
163128 end
164129 end )
165130
166131 else
167- P .checks = {
168- function (instance , target )
169- if not Ent_IsValid (target ) then return false , " Entity is invalid" end
170- if target == instance .player or
171- LocalPlayer ()== instance .player or
172- Ply_IsSuperAdmin (instance .player ) or
173- Ent_GetNWEntity (target , " SFPP" )== instance .player or
174- target .SFHoloOwner == instance .player then return true end
175-
176- return false , " You're not the owner of this prop"
177- end ,
178- nil ,
179- nil ,
180- " allow"
181- }
182- P .checks [2 ] = P .checks [1 ]
183- P .checks [3 ] = P .checks [1 ]
184-
185132 function SF .Permissions .getOwner (ent )
186133 return Ent_GetTable (ent ).SFHoloOwner or Ent_GetNWEntity (ent , " SFPP" )
187134 end
135+
136+ function checkOwner (instance , ent )
137+ if ent == instance .player or LocalPlayer ()== instance .player then return true end
138+ if Ent_GetNWEntity (ent , " SFPP" )== instance .player or Ent_GetTable (ent ).SFHoloOwner == instance .player then return true end
139+ return false , " You're not the owner of this prop"
140+ end
141+ checkCanTool = checkOwner
142+ checkCanPhysgun = checkOwner
188143 end
189144end
145+
146+ local overridesMeta = {__mode = " k" }
147+
148+ local EntityPermissionCache = {
149+ __index = {
150+ checkNormal = function (self , instance , ent , checkfunc )
151+ local t = CurTime ()
152+ if t < self .timeout then return true end
153+
154+ local result , reason = checkfunc (instance , ent )
155+ if result then self .timeout = t + cacheLifetime :GetFloat () end
156+ return result , reason
157+ end ,
158+ checkOverrides = function (self , instance , ent , checkfunc )
159+ local t = CurTime ()
160+ if t < self .timeout then return true end
161+
162+ if table .IsEmpty (self .overrides ) then
163+ self .check = self .checkNormal
164+ return self :check (instance , ent , checkfunc )
165+ end
166+ local result , reason
167+ for overrideInst in pairs (self .overrides ) do
168+ result , reason = checkfunc (overrideInst , ent )
169+ if result then self .timeout = t + cacheLifetime :GetFloat () return true end
170+ self .overrides [overrideInst ] = nil
171+ end
172+ return result , reason
173+ end ,
174+ addOverride = function (self , instance )
175+ self .overrides [instance ] = true
176+ self .check = self .checkOverrides
177+ end ,
178+ removeOverride = function (self , instance )
179+ self .overrides [instance ] = nil
180+ if table .IsEmpty (self .overrides ) then
181+ self .check = self .checkNormal
182+ end
183+ end
184+ },
185+ __call = function (t )
186+ local ret = setmetatable ({
187+ timeout = 0 ,
188+ overrides = setmetatable ({}, overridesMeta )
189+ }, t )
190+ ret .check = ret .checkNormal
191+ return ret
192+ end
193+ }
194+ setmetatable (EntityPermissionCache , EntityPermissionCache )
195+
196+ local cacheMeta = {__mode = " k" , __index = function (t ,k ) local r = EntityPermissionCache () t [k ]= r return r end }
197+
198+ local function getEntPermCache (ent_tbl , instance )
199+ local cache = ent_tbl .SF_EntPermCache
200+ if not cache then
201+ cache = setmetatable ({}, cacheMeta )
202+ ent_tbl .SF_EntPermCache = cache
203+ end
204+ return cache [instance ]
205+ end
206+ SF .GetEntPermCache = getEntPermCache
207+
208+ local function check (instance , ent , checkfunc )
209+ local ent_tbl = Ent_GetTable (ent )
210+ if not ent_tbl then return false , " Entity is invalid" end
211+ if Ply_IsSuperAdmin (instance .player ) then return true end
212+ return getEntPermCache (ent_tbl , instance ):check (instance , ent , checkfunc )
213+ end
214+
215+ SF .Permissions .registerProvider ({
216+ id = " entities" ,
217+ name = " Entity Permissions" ,
218+ settingsoptions = { " Owner Only" , " Can Tool" , " Can Physgun" , " Anything" },
219+ defaultsetting = 2 ,
220+ checks = {
221+ function (instance , ent )
222+ return check (instance , ent , checkOwner )
223+ end ,
224+ function (instance , ent )
225+ return check (instance , ent , checkCanTool )
226+ end ,
227+ function (instance , ent )
228+ return check (instance , ent , checkCanPhysgun )
229+ end ,
230+ " allow"
231+ }
232+ })
233+
0 commit comments