Last active
June 26, 2023 16:56
-
-
Save Python1320/96e654c7a784a97121bd to your computer and use it in GitHub Desktop.
[GMod] individual player metatables with __index function now only a table (performance maybe)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local entity = FindMetaTable( "Entity" ) | |
local meta = FindMetaTable( "Player" ) | |
local panel = CLIENT and FindMetaTable( "Panel" ) | |
local GetEngineTable = entity.GetTable | |
local pltostring = FindMetaTable"Player".__tostring | |
local R=debug.getregistry() | |
local lowest = math.huge | |
local setted = meta | |
local function SetPlyMeta(t) if R[lowest]~=setted then ErrorNoHalt("1WOO".. (R[lowest]==panel and "<A>" or '<B>') .."OT\n") end setted = t R[lowest]=t end | |
local function GetPlyMeta() if R[lowest]~=setted then ErrorNoHalt( "2WOO".. (R[lowest]==panel and "<A>" or '<B>') .."OT\n") end return R[lowest] end | |
local fufu={} | |
MsgN"Finding Player meta from registry:" | |
for k,v in next,R do | |
if v==meta then | |
print(" > ",k) | |
if tonumber(k) and lowest>tonumber(k) then | |
fufu[k]=true | |
end | |
end | |
end | |
local idx=0 | |
local function NewPlyMeta() | |
idx=idx+1 | |
local myid=idx | |
local data = {MetaName = "Player"} | |
local datameta = {__index=meta} | |
setmetatable(data,datameta) | |
local t={ | |
__index = data, | |
__newindex = data, | |
__tostring = function(self) return "PlayerIDX"..myid..pltostring(self) end, | |
--__metatable = meta, | |
--__len = function() end, | |
MetaName = "Player", | |
} | |
return t | |
end | |
hook.Add("Initialize","a",function() | |
MsgN"Finding Player meta from registry with filter:" | |
for k,v in next,R do | |
if v==meta then | |
print(">",k,fufu[k]) | |
end | |
end | |
lowest=-1 | |
for k,v in next,R do | |
if v==meta then | |
if fufu[k] and tonumber(k) and lowest<tonumber(k) then | |
lowest = k | |
print("GOTCHA",k) | |
end | |
end | |
end | |
SetPlyMeta(NewPlyMeta()) | |
end) | |
local created=setmetatable({},{__mode='k'}) | |
hook.Add("OnEntityCreated","a",function(pl) | |
if created[pl] then | |
ErrorNoHalt("WAT RECREATE ",pl) | |
return | |
end | |
local plMeta_ = GetPlyMeta() | |
local plMeta = getmetatable(pl) | |
if plMeta==FindMetaTable"Player" then | |
ErrorNoHalt("WTF "..pltostring(pl).."\n") | |
end | |
if plMeta==FindMetaTable"Entity" then | |
return | |
end | |
if plMeta_ ~= plMeta then return end | |
SetPlyMeta(NewPlyMeta()) | |
created[pl]=true | |
local dat = plMeta.__newindex | |
local datmeta = getmetatable(dat) | |
local tbl = GetEngineTable(pl) | |
if tbl==dat then ErrorNoHalt"WTF REINIT!!?!?!?!?\n" return end | |
setmetatable(tbl,datmeta) | |
plMeta.__index = tbl | |
plMeta.__newindex = tbl | |
for k,v in next,dat do | |
tbl[k]=tbl[k] or v | |
end | |
end) | |
local meta2={} meta2=getmetatable(meta) | |
if not meta2 then meta2={} setmetatable(meta,meta2) end | |
meta2.__index = entity | |
if ( !sql.TableExists( "playerpdata" ) ) then | |
sql.Query( "CREATE TABLE IF NOT EXISTS playerpdata ( infoid TEXT NOT NULL PRIMARY KEY, value TEXT );" ) | |
end | |
-- This is totally in the wrong place. | |
function player.GetByUniqueID( ID ) | |
for _, pl in pairs( player.GetAll() ) do | |
if ( IsValid( pl ) && pl:IsPlayer() && pl:UniqueID() == ID ) then | |
return pl | |
end | |
end | |
return false | |
end | |
--[[--------------------------------------------------------- | |
Name: DebugInfo | |
Params: | |
Desc: Prints debug information for the player | |
( this is just an example ) | |
-----------------------------------------------------------]] | |
function meta:DebugInfo() | |
Msg( "Name: " .. self:Name() .. "\n" ) | |
Msg( "Pos: " .. tostring( self:GetPos() ) .. "\n" ) | |
end | |
-- Helpful aliases | |
meta.GetName = meta.Nick | |
meta.Name = meta.Nick | |
--[[--------------------------------------------------------- | |
Name: ConCommand | |
Params: | |
Desc: Overrides the default ConCommand function | |
-----------------------------------------------------------]] | |
if ( CLIENT ) then | |
local SendConCommand = meta.ConCommand | |
local CommandList = nil | |
function meta:ConCommand( command, bSkipQueue ) | |
if ( bSkipQueue ) then | |
SendConCommand( self, command ) | |
else | |
CommandList = CommandList or {} | |
table.insert( CommandList, command ) | |
end | |
end | |
local function SendQueuedConsoleCommands() | |
if (!CommandList) then return end | |
local BytesSent = 0 | |
for k, v in pairs( CommandList ) do | |
SendConCommand( LocalPlayer(), v ) | |
CommandList[ k ] = nil | |
-- Only send x bytes per tick | |
BytesSent = BytesSent + v:len() | |
if ( BytesSent > 128 ) then | |
break | |
end | |
end | |
-- Turn the table into a nil so we can return easy | |
if ( table.Count( CommandList ) == 0 ) then | |
CommandList = nil | |
end | |
end | |
hook.Add( "Tick", "SendQueuedConsoleCommands", SendQueuedConsoleCommands ) | |
end | |
--[[--------------------------------------------------------- | |
GetPData | |
- Saves persist data for this player | |
-----------------------------------------------------------]] | |
function meta:GetPData( name, default ) | |
name = Format( "%s[%s]", self:UniqueID(), name ) | |
local val = sql.QueryValue( "SELECT value FROM playerpdata WHERE infoid = " .. SQLStr(name) .. " LIMIT 1" ) | |
if ( val == nil ) then return default end | |
return val | |
end | |
--[[--------------------------------------------------------- | |
SetPData | |
- Set persistant data | |
-----------------------------------------------------------]] | |
function meta:SetPData( name, value ) | |
name = Format( "%s[%s]", self:UniqueID(), name ) | |
sql.Query( "REPLACE INTO playerpdata ( infoid, value ) VALUES ( "..SQLStr(name)..", "..SQLStr(value).." )" ) | |
end | |
--[[--------------------------------------------------------- | |
RemovePData | |
- Remove persistant data | |
-----------------------------------------------------------]] | |
function meta:RemovePData( name ) | |
name = Format( "%s[%s]", self:UniqueID(), name ) | |
sql.Query( "DELETE FROM playerpdata WHERE infoid = "..SQLStr(name) ) | |
end | |
-- | |
-- If they have their preferred default weapon then switch to it | |
-- | |
function meta:SwitchToDefaultWeapon( name ) | |
local weapon = self:GetInfo( "cl_defaultweapon" ) | |
if ( self:HasWeapon( weapon ) ) then | |
self:SelectWeapon( weapon ) | |
end | |
end | |
-- | |
-- Can use flashlight? | |
-- | |
function meta:AllowFlashlight( bAble ) self.m_bFlashlight = bAble end | |
function meta:CanUseFlashlight() return self.m_bFlashlight end | |
-- A function to set up player hands, so coders don't have to copy all the code everytime. | |
-- Call this in PlayerSpawn hook | |
function meta:SetupHands( ply ) | |
local oldhands = self:GetHands() | |
if ( IsValid( oldhands ) ) then | |
oldhands:Remove() | |
end | |
local hands = ents.Create( "gmod_hands" ) | |
if ( IsValid( hands ) ) then | |
hands:DoSetup( self, ply ) | |
hands:Spawn() | |
end | |
end | |
-- | |
-- Those functions have been removed from the engine since AddFlag and RemoveFlag | |
-- made them obsolete, but we'll keep a Lua version of them for backward compatibility | |
-- | |
if SERVER then | |
--[[--------------------------------------------------------- | |
Freeze | |
- Freezes or unfreezes the player | |
-----------------------------------------------------------]] | |
function meta:Freeze( b ) | |
if ( b ) then | |
self:AddFlags( FL_FROZEN ) | |
else | |
self:RemoveFlags( FL_FROZEN ) | |
end | |
end | |
--[[--------------------------------------------------------- | |
GodEnable | |
- Enables godmode on the player | |
-----------------------------------------------------------]] | |
function meta:GodEnable() | |
self:AddFlags( FL_GODMODE ) | |
end | |
--[[--------------------------------------------------------- | |
GodDisable | |
- Disables godmode on the player | |
-----------------------------------------------------------]] | |
function meta:GodDisable() | |
self:RemoveFlags( FL_GODMODE ) | |
end | |
end | |
--[[--------------------------------------------------------- | |
IsFrozen | |
- Returns true if the player is frozen | |
-----------------------------------------------------------]] | |
function meta:IsFrozen() | |
return self:IsFlagSet( FL_FROZEN ) | |
end | |
--[[--------------------------------------------------------- | |
HasGodMode | |
- Returns true if the player is in godmode | |
-----------------------------------------------------------]] | |
function meta:HasGodMode() | |
return self:IsFlagSet( FL_GODMODE ) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment