Last active
September 13, 2016 15:52
-
-
Save CaptainPRICE/b495058446b86ddb97f85791b58f43e5 to your computer and use it in GitHub Desktop.
Steam. IDs... IDs... IDs... Let's clean this mess up (GMod).
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
-- Made/Published to clear up misinformation, for you to possibly learn something new from it. - CaptainPRICE | |
-- Tell me in the comments (below) if you have spot bug(s), or if you have any suggestions or improvements as I would like to hear them! | |
-- See my comment here: https://github.com/wiremod/wire/pull/1217#issuecomment-246211364 | |
local game = game | |
local IS_DEDICATED, IS_SINGLEPLAYER, MAX_NUM_PLAYERS = game.IsDedicated(), game.SinglePlayer(), game.MaxPlayers() | |
print(CLIENT and "CLIENT" or (SERVER and "SERVER" or "MENU"), IS_SINGLEPLAYER and "SP" or "MP", IS_DEDICATED and "DEDICATED" or "LISTEN", "MAX=" .. MAX_NUM_PLAYERS, "v" .. VERSION, BRANCH) | |
if not debug then return print("debug library is missing") end | |
local debug = debug | |
if not string then return print("string library is missing") end | |
local string = string | |
if not player then return print("player library is missing") end | |
local player = player | |
local _R = debug.getregistry() | |
local ENTITY = FindMetaTable("Entity") | |
if not ENTITY then | |
ENTITY = _R.Entity | |
if not ENTITY then return end | |
end | |
local PLAYER = FindMetaTable("Player") | |
local PLAYER_BASE | |
if not PLAYER then | |
PLAYER = _R.Player | |
if not PLAYER then return end | |
end | |
PLAYER_BASE = PLAYER.MetaBaseClass | |
if not PLAYER_BASE then return end | |
--print(PLAYER.MetaName .. " inherits from " .. PLAYER_BASE.MetaName) -- Prints: "Player inherits from Entity" | |
local print = print | |
local tostring = tostring | |
local typeof = type | |
local gsub = string.gsub | |
local formatvar = function(str, var) | |
if not isstring(str) then return end | |
str = gsub(gsub(str, "{:tostring:}", (isstring(var) and ('"' .. var .. '"')) or tostring(var)), "{:typeof:}", typeof(var)) | |
return str | |
end | |
local FormatVar = function(name, var) | |
return formatvar(name .. " = {:tostring:} ({:typeof:})", var) | |
end | |
local PrintValue = function(actor, name) | |
if not IsValid(actor) or not isstring(name) then return end | |
local is_bot = actor:IsBot() | |
local func = is_bot and ENTITY[name] or (PLAYER[name] or PLAYER_BASE[name]) -- Use Entity for bots; otherwise use Player, if it is not found in Player, then search the Player's base class (Entity) | |
if not isfunction(func) then return end | |
local value = func(actor) | |
name = (is_bot and "Bot:" or "Ply:") .. name .. "()" | |
print(FormatVar(name, value)) | |
end | |
local CAN_HAVE_BOTS = not IS_SINGLEPLAYER or (MAX_NUM_PLAYERS > 1) | |
local humans = player.GetHumans() | |
local Bot = CAN_HAVE_BOTS and player.GetBots()[1] or NULL | |
local Ply = (CAN_HAVE_BOTS and CLIENT) and LocalPlayer() or humans[math.random(1, #humans)] | |
print(FormatVar("Bot", Bot), FormatVar("Ply", Ply)) | |
if CLIENT then | |
local GetPlayerInfo = PLAYER.GetPlayerInfo or _R.Player.GetPlayerInfo | |
if isfunction(GetPlayerInfo) then | |
if IsValid(Bot) then | |
print(FormatVar("Bot:GetPlayerInfo().friendid", GetPlayerInfo(Bot).friendid)) | |
end | |
if IsValid(Ply) then | |
print(FormatVar("Ply:GetPlayerInfo().friendid", GetPlayerInfo(Ply).friendid)) | |
end | |
--print(FormatVar("NULL:GetPlayerInfo().friendid", GetPlayerInfo(NULL).friendid)) -- ERROR! | |
end | |
end | |
for _, func_name in next, { "AccountID", "EntIndex", "SteamID", "SteamID64", "UniqueID", "UserID" } do | |
PrintValue(Bot, func_name) | |
PrintValue(Ply, func_name) | |
end | |
-- First run in singleplayer (SP) on serverside, then clientside. | |
-- Second run in multiplayer (MP) on serverside, then clientside. | |
-- Script output (at version: 160905 - dev branch): | |
--[[ | |
SERVER SP LISTEN MAX=1 v160905 dev | |
Bot = [NULL Entity] (Entity) Ply = Player [1][CaptainPRICE] (Player) | |
Ply:AccountID() = nil (nil) | |
Ply:EntIndex() = 1 (number) | |
Ply:SteamID() = "STEAM_0:0:0" (string) | |
Ply:SteamID64() = nil (nil) | |
Ply:UniqueID() = "1" (string) | |
Ply:UserID() = 2 (number) | |
CLIENT SP LISTEN MAX=1 v160905 dev | |
Bot = [NULL Entity] (Entity) Ply = Player [1][CaptainPRICE] (Player) | |
Ply:GetPlayerInfo().friendid = 131959820 (number) | |
Ply:AccountID() = 131959820 (number) | |
Ply:EntIndex() = 1 (number) | |
Ply:SteamID() = "STEAM_0:0:65979910" (string) | |
Ply:SteamID64() = "76561198092225548" (string) | |
Ply:UniqueID() = "1" (string) | |
Ply:UserID() = 2 (number) | |
SERVER MP LISTEN MAX=128 v160905 dev | |
Bot = Player [2][Bot01] (Player) Ply = Player [1][CaptainPRICE] (Player) | |
Bot:AccountID() = 0 (number) | |
Ply:AccountID() = 131959820 (number) | |
Bot:EntIndex() = 2 (number) | |
Ply:EntIndex() = 1 (number) | |
Bot:SteamID() = "BOT" (string) | |
Ply:SteamID() = "STEAM_0:0:65979910" (string) | |
Bot:SteamID64() = "90071996842377216" (string) | |
Ply:SteamID64() = "76561198092225548" (string) | |
Bot:UniqueID() = "1513418020" (string) | |
Ply:UniqueID() = "445831337" (string) | |
Bot:UserID() = 4 (number) | |
Ply:UserID() = 3 (number) | |
CLIENT MP LISTEN MAX=128 v160905 dev | |
Bot = Player [2][Bot01] (Player) Ply = Player [1][CaptainPRICE] (Player) | |
Bot:GetPlayerInfo().friendid = 0 (number) | |
Ply:GetPlayerInfo().friendid = 131959820 (number) | |
Bot:AccountID() = nil (nil) | |
Ply:AccountID() = 131959820 (number) | |
Bot:EntIndex() = 2 (number) | |
Ply:EntIndex() = 1 (number) | |
Bot:SteamID() = "NULL" (string) | |
Ply:SteamID() = "STEAM_0:0:65979910" (string) | |
Bot:SteamID64() = nil (nil) | |
Ply:SteamID64() = "76561198092225548" (string) | |
Bot:UniqueID() = "1513418020" (string) | |
Ply:UniqueID() = "445831337" (string) | |
Bot:UserID() = 4 (number) | |
Ply:UserID() = 3 (number) | |
]] |
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
-- Made/Published to clear up misinformation, for you to possibly learn something new from it. - CaptainPRICE | |
-- Tell me in the comments (below) if you have spot bug(s), or if you have any suggestions or improvements as I would like to hear them! | |
local game = game | |
local IS_DEDICATED, IS_SINGLEPLAYER, MAX_NUM_PLAYERS = game.IsDedicated(), game.SinglePlayer(), game.MaxPlayers() | |
print(CLIENT and "CLIENT" or (SERVER and "SERVER" or "MENU"), IS_SINGLEPLAYER and "SP" or "MP", IS_DEDICATED and "DEDICATED" or "LISTEN", "MAX=" .. MAX_NUM_PLAYERS, "v" .. VERSION, BRANCH) | |
if not debug then return print("debug library is missing") end | |
local debug = debug | |
if not math then return print("math library is missing") end | |
local math = math | |
if not string then return print("string library is missing") end | |
local string = string | |
if not player then return print("player library is missing") end | |
local player = player | |
--if not team then return print("team library is missing") end | |
--local team = team | |
local _R = debug.getregistry() | |
local ENTITY = FindMetaTable("Entity") | |
if not ENTITY then | |
ENTITY = _R.Entity | |
if not ENTITY then return end | |
end | |
local PLAYER = FindMetaTable("Player") | |
local PLAYER_BASE | |
if not PLAYER then | |
PLAYER = _R.Player | |
if not PLAYER then return end | |
end | |
PLAYER_BASE = PLAYER.MetaBaseClass | |
if not istable(PLAYER_BASE) then return end -- It must have a base class | |
--print(PLAYER.MetaName .. " inherits from " .. PLAYER_BASE.MetaName) -- Prints: "Player inherits from Entity" | |
local VEHICLE = FindMetaTable("Vehicle") | |
local VEHICLE_BASE | |
if not VEHICLE then | |
VEHICLE = _R.Vehicle | |
if not VEHICLE then return end | |
end | |
VEHICLE_BASE = VEHICLE.MetaBaseClass | |
if not istable(VEHICLE_BASE) then return end -- It must have a base class | |
--print(VEHICLE.MetaName .. " inherits from " .. VEHICLE_BASE.MetaName) -- Prints: "Vehicle inherits from Entity" | |
local print = print | |
local tostring = tostring | |
local typeof = type | |
local gsub = string.gsub | |
-- A small function to make variable display nicer | |
local formatvar = function(var, str) | |
if not isstring(str) then return end | |
str = gsub(gsub(str, "{:tostring:}", (isstring(var) and ('"' .. var .. '"')) or tostring(var)), "{:typeof:}", typeof(var)) | |
return str | |
end | |
local FormatVar = function(var, name) | |
return formatvar(var, name .. " = {:tostring:} ({:typeof:})") | |
end | |
-- Attempts to find a function in a class (from metatable and registry) for the given Entity/Player/Vehicle (it is specifically for entities) | |
local GetFunctionFromClass = function(actor, name, force) | |
if not force and (not IsValid(actor) or not isentity(actor)) then return end | |
if actor:IsPlayer() then | |
-- Use Player class, if it is not found in Player, then search the Player's base class (Entity) | |
return ((PLAYER[name] or _R.Player[name]) or PLAYER_BASE[name]) or _R.Entity[name], ((isfunction(PLAYER[name]) and PLAYER.MetaName) or isfunction(PLAYER_BASE[name]) and PLAYER_BASE.MetaName) or --[[typeof(actor)]]"Player" | |
end | |
if actor:IsVehicle() then | |
-- Use Vehicle class, if it is not found in Vehicle, then search the Vehicle's base class (Entity) | |
return ((VEHICLE[name] or _R.Vehicle[name]) or VEHICLE_BASE[name]) or _R.Entity[name], ((isfunction(VEHICLE[name]) and VEHICLE.MetaName) or isfunction(VEHICLE_BASE[name]) and VEHICLE_BASE.MetaName) or --[[typeof(actor)]]"Vehicle" | |
end | |
-- Else, it is some other type of entity such as CSEnt (we don't really care about here, or do we?) | |
-- But, just look up Entity class for it | |
return ENTITY[name] or _R.Entity[name], ENTITY.MetaName or --[[typeof(actor)]]"Entity" -- Entity is the base class | |
end | |
-- Addition to FormatVar function above, returns nicely formatted string of var. var is expected to be Entity/Player/Vehicle (it will evaluate a (name) function on its class) | |
local FormatClassVar = function(var, name, force) | |
local class_func, class_name = GetFunctionFromClass(var, name, force) | |
if isfunction(class_func) and isstring(class_name) then | |
return FormatVar(class_func(var), class_name .. ":" .. name .. "()") -- Like it? :) | |
end | |
-- Else, it is a failure - should not happen, please report if it does | |
ErrorNoHalt("typeof(class_func) = " .. typeof(class_func), '\n', "typeof(class_name) = " .. typeof(class_name), '\n') | |
return var, name, class_func, class_name | |
end | |
-- Prints it out nicely, use specifically for entities | |
local PrintEvalEntityValue = function(actor, name, force) | |
if force or (IsValid(actor) and isstring(name)) then | |
print(FormatClassVar(actor, name, force)) | |
end | |
end | |
--------------------------------------------------------------------------------------------------------------------------------------- | |
local CAN_HAVE_BOTS = not IS_SINGLEPLAYER or (MAX_NUM_PLAYERS > 1) | |
local humans = player.GetHumans() | |
local Bot = CAN_HAVE_BOTS and player.GetBots()[1] or NULL | |
local Ply = (CAN_HAVE_BOTS and CLIENT) and LocalPlayer() or humans[math.random(1, #humans)] | |
print(FormatVar(Bot, "Bot"), FormatVar(Ply, "Ply")) | |
local FORCE = true -- Set to true to bypass validation checks; otherwise false | |
-- Simply alter the data table as you please ˘\_(^^)_/˘ | |
local data = { | |
{ | |
"Ply", -- 1. (n) Text which is printed before evaluation | |
Ply, -- 2. (e) Entity value to use (it will automatically detect its class, but it has to inherit from Entity class as that is the "ultimate" base class for any entity) | |
"EntIndex", -- 3. (fn) Name of the function to evaluate on the class with above entity value (it is smart about finding it) | |
Color(70, 200, 70) -- 4. (c) *OPTIONAL* Color to use for text specified at slot/index 1 | |
}, | |
{ | |
"Ply", | |
Ply, | |
"UserID", | |
team.GetColor(Ply:Team()) -- Use Ply's team color | |
}, | |
{ | |
"NULL", | |
NULL, -- Note: NULL is an instance of Entity class (not Player/Vehicle/etc...) | |
"EntIndex" | |
} | |
} | |
if CAN_HAVE_BOTS and IsValid(Bot) then | |
table.Merge(data, { | |
{ | |
"Bot", | |
Bot, | |
"EntIndex", | |
Color(0, 100, 240) | |
}, | |
{ | |
"Bot", | |
Bot, | |
"UserID", | |
team.GetColor(Bot:Team()) -- Use Bot's team color | |
} | |
}) | |
end | |
for i, v in next, data do | |
local n, e, fn, c = v[1], v[2], v[3], v[4] | |
if not isentity(e) or not isstring(fn) then | |
ErrorNoHalt("data table contains values of wrong types (possibly incorrect order at index " .. i .. "?)", '\n', "typeof(n) = " .. typeof(n), '\n', "typeof(e) = " .. typeof(e), '\n', "typeof(fn) = " .. typeof(fn), '\n', "typeof(c) = " .. typeof(c), '\n') | |
print(i, v, n, e, fn, c) | |
break | |
end | |
if not isstring(n) or #n < 1 then n = "-" end -- Default text | |
--print(n, FormatClassVar(e, fn)) -- Display results (FormatClassVar function will run the named function and print it nicely) | |
if IsColor(c) then | |
MsgC(c, n) | |
else | |
Msg(n) | |
end | |
Msg('\t') | |
PrintEvalEntityValue(e, fn, FORCE) | |
end | |
for k, v in next, player.GetAll() do -- Print all | |
print(k .. " - " .. tostring(v) .. " { EntIndex = " .. v:EntIndex() .. ", UserID = " .. v:UserID() .. " }") | |
end | |
-- _G.Entity function expects Entity EntIndex - not Player UserID! (No matter what.) | |
-- _G.Player function expects Player UserID - not Entity EntIndex! (No matter what.) | |
-- Screenshot (proof): https://cloud.githubusercontent.com/assets/9789070/18476543/c67d332a-79ca-11e6-9d1e-d3ff5dc64e15.png | |
-- First run in singleplayer (SP) on serverside, then clientside. | |
-- Second run in multiplayer (MP) on serverside, then clientside. | |
-- Script output (at version: 160905 - dev branch): | |
--[[ | |
SERVER SP LISTEN MAX=1 v160905 dev | |
Bot = [NULL Entity] (Entity) Ply = Player [1][CaptainPRICE] (Player) | |
Ply Entity:EntIndex() = 1 (number) | |
Ply Player:UserID() = 2 (number) | |
NULL Entity:EntIndex() = 0 (number) | |
1 - Player [1][CaptainPRICE] { EntIndex = 1, UserID = 2 } | |
CLIENT SP LISTEN MAX=1 v160905 dev | |
Bot = [NULL Entity] (Entity) Ply = Player [1][CaptainPRICE] (Player) | |
Ply Entity:EntIndex() = 1 (number) | |
Ply Player:UserID() = 2 (number) | |
NULL Entity:EntIndex() = 0 (number) | |
1 - Player [1][CaptainPRICE] { EntIndex = 1, UserID = 2 } | |
SERVER MP LISTEN MAX=128 v160905 dev | |
Bot = Player [2][Bot01] (Player) Ply = Player [1][CaptainPRICE] (Player) | |
Bot Entity:EntIndex() = 2 (number) | |
Bot Player:UserID() = 4 (number) | |
NULL Entity:EntIndex() = 0 (number) | |
1 - Player [1][CaptainPRICE] { EntIndex = 1, UserID = 3 } | |
2 - Player [2][Bot01] { EntIndex = 2, UserID = 4 } | |
CLIENT MP LISTEN MAX=128 v160905 dev | |
Bot = Player [2][Bot01] (Player) Ply = Player [1][CaptainPRICE] (Player) | |
Bot Entity:EntIndex() = 2 (number) | |
Bot Player:UserID() = 4 (number) | |
NULL Entity:EntIndex() = 0 (number) | |
1 - Player [1][CaptainPRICE] { EntIndex = 1, UserID = 3 } | |
2 - Player [2][Bot01] { EntIndex = 2, UserID = 4 } | |
]] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment