GlobalStrings get reset for no good reason - this makes absolutely no sense.
8 replies, posted
I seriously cannot wrap my head around this. We've been trying to solve it pretty much all day, this makes absolutely no sense.
We're trying to implement prop protection for our gamemode and running into technical problems. Here's what we're trying to do:
1. When a player spawns a prop, we SetNWString on it with key "EGOwner" and value of the creator's Unique ID.
2. When a player decides to share his props with someone (currently with /share chat command), we SetGlobalString with key ("EGShare_"..UniqueID) and value of _every_uniqueid_shared_with
3. When a player tries to use a tool on an entity, we check the entity's EGOwner NWString. If it's equal to the player's UniqueID, allow the tool. If not, check the EGOwner's share list using string.explode on GetGlobalString and, if the player's UniqueID is not in that table, disallow the tool.
The problem we're running into is as follows:
1. Player A spawns a prop.
2. Player B tries to make a button on prop. It doesn't allow him (good).
3. Player A shares his prop with Player B.
4. Player B tries to make a button on the prop. It allows the tool (good).
5. Right now Player B can create as many buttons on the prop as he wants - nothing is broken.
6. Either player welds or ropes the prop to the floor. (world)
7. Player B tries to make a button on the prop. It doesn't work (!)
8. At this time, the Global String had somehow reset itself to "".
9. In some of our tests (but not all), the client's Global String was still showing the list (so the tool's ray showed up), but the server's version of the Global String had somehow reset. It makes no sense that the two got out of sync, since we only write to it on the server's side.
Please help me debug this. All relevant code is in code blocks below.
init.lua:
[lua]AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
include( "shared.lua" )
include( "entity_guard.lua" )
include( "undocatcher.lua" )[/lua]
shared.lua:
[lua]GM.Name = "Test Gamemode"
GM.Author = "NeatNit"
DeriveGamemode( "sandbox" )
function GM:Initialize()
-- Do nothing.
end[/lua]
cl_init.lua:
[lua]include( "shared.lua" )
include( "entity_guard.lua" )[/lua]
undocatcher.lua:
[lua]
local oldfunc = undo.Finish
--[[------------------------------------------------------------------------------
Catch undos - call the UndoCaught hook when a player did any undoable action.
---------------------------------------------------------------------------------]]
function undo.Finish()
local OUT = {} -- OUT = Old Undo Table
for uid, undos in pairs(undo.GetTable() ) do
OUT[uid] = table.GetKeys(undos)
end
oldfunc() -- Do the ACTUAL undo.Finish()
local CUT = undo.GetTable() -- CUT = Current Undo Table
for uid, undos in pairs(CUT) do
for undokey, undodata in pairs(undos) do
if !OUT[uid] or !table.HasValue(OUT[uid], undokey) then hook.Run( "UndoCaught", uid, undodata ) end
end
end
end[/lua]
entity_guard.lua:
[lua]AddCSLuaFile()
function GuardNewEntity(uid, undodata)
for k, NewEntity in pairs(undodata["Entities"]) do
if NewEntity then
NewEntity:SetNWString("EGOwner", uid)
print ("New entity spawned by " .. uid .. ":")
print (NewEntity)
print ("GetNWString (EGOwner) of entity is " .. NewEntity:GetNWString("EGOwner", "IDK"))
end
end
end
hook.Add("UndoCaught", "Guard New Entity", GuardNewEntity)
function InterpretSays(sender, text, teamChat)
local playerstable = player.GetHumans()
if string.sub(text, 1, 7) == "/share " then
guestname = string.sub(text, 8)
for plynum, plydata in pairs(playerstable) do
if guestname == (plydata:Nick()) then
Share(sender, plydata)
end
end
end
if string.sub(text, 1, 9) == "/unshare " then
guestname = string.sub(text, 10)
for plynum, plydata in pairs(playerstable) do
if guestname == (plydata:Nick()) then
UnShare(sender, plydata)
--And notify
end
end
end
if string.sub(text, 1, 11) == "/unshareall" then
UnShareAll(sender)
end
return true end
hook.Add("PlayerSay", "Triggers Team Sequence", InterpretSays)
function Share(sender, plydata)
local host = sender:UniqueID()
local guest = plydata:UniqueID()
local sharestring = GetGlobalString("EGShare_" .. host, "")
local sharetable = string.Explode("_", GetGlobalString("EGShare_" .. host, ""))
local newsharestring = sharestring .. "_" .. guest
if plydata and sender then
if !table.HasValue(sharetable, guest) then
SetGlobalString("EGShare_" .. host, newsharestring)
print (host .. " is now sharing with " .. guest)
print ("Newly calculated newsharestring is now " .. newsharestring)
print (host .. "'s global string is now " .. GetGlobalString("EGShare_" .. host, "IDK"))
end
end
end
function UnShare(sender, plydata)
local host = sender:UniqueID()
local guest = plydata:UniqueID()
local sharestring = GetGlobalString("EGShare_" .. host, "")
local sharetable = string.Explode("_", GetGlobalString("EGShare_" .. host, ""))
if plydata and sender then
if table.HasValue(sharetable, guest) then
local newsharestring = string.Replace(sharestring, "_" .. guest, "")
SetGlobalString("EGShare_" .. host, newsharestring)
print (host .. " unshared " .. guest)
print ("Newly calculated newsharestring is " .. newsharestring)
print (host .. "'s global string is now " .. GetGlobalString("EGShare_" .. host, "IDK"))
end
end
end
function UnShareAll(sender)
local host = sender:UniqueID()
if sender then
SetGlobalString("EGShare_" .. host, "")
print (host .. " unshared all!")
print (host .. "'s global string is now " .. GetGlobalString("EGShare_" .. host, "IDK"))
end
end
function EGAllow(EGOwner, uid)
local sharestring = GetGlobalString("EGShare_" .. EGOwner, "")
local sharetable = string.Explode("_", GetGlobalString("EGShare_" .. EGOwner, ""))
print (sharestring)
PrintTable (sharetable)
if EGOwner == uid then print ("cantooler is owner! allowing!") return true
elseif table.HasValue(sharetable, uid) then print ("tooler's id exists in owners' global string! allowing!") return true
else return false
end
end
function GM:CanTool( ply , tr , tool )
local uid = ply:UniqueID()
local tooldEnt = tr.Entity
local EGOwner = tr.Entity:GetNWString("EGOwner", "nil")
if IsValid(tooldEnt) and !EGAllow(EGOwner, uid) then return false
elseif (tool == "remover") then return true else
return true--AllowDisallow(uid) - Replace "true" when mergine
end
--[[ if (table.HasValue(bannedTools , tool)) then return false else
Needs to include upper if statement when merging!
end ]]
return true
end[/lua]
I think this may be a gmod/engine bug. Any help is [b][i]HUGELY[/i][/b] appreciated. I think I'm about to pull my hair out.
Why the hell are you even using GlobalVars for this? Use NWVars, or better yet, net library or something.
Are you testing this on Dev branch?
[QUOTE=Robotboy655;47041083]Why the hell are you even using GlobalVars for this? Use NWVars, or better yet, net library or something.
Are you testing this on Dev branch?[/QUOTE]
No, not the dev branch.
Why wouldn't I use Global vars - what are they meant for then? I thought they were essentially there to save me the trouble of networking everything to the client by myself - a variable that is synced across server and all clients.
I mean, I'm not going to argue with you. Using the net library is, in fact, what we're gonna do, so thanks for that tip. But why is THAT not working??
I have no idea why it does not work, maybe because GlobalVars are bad.
They are supposed to be used for networking one global variable to clients.
You should be using Player:SetNWString("ShareWith", str ) for example.
[QUOTE=Robotboy655;47041275]I have no idea why it does not work, maybe because GlobalVars are bad.
They are supposed to be used for networking one global variable to clients.
You should be using Player:SetNWString("ShareWith", str ) for example.[/QUOTE]
its not working because he's trying to set a global variable on a players client. Using setGlobalAnything on client doesn't sync with the server for obvious reasons, same with network variables
[QUOTE=AJ10017;47041714]its not working because he's trying to set a global variable on a players client. Using setGlobalAnything on client doesn't sync with the server for obvious reasons, same with network variables[/QUOTE]
He executes the functions that set the global var from a serverside only hook PlayerSay
TTT uses global vars for how many rounds are left, thats a good use. You wouldn't use a global var for player specific stuff
SetGlobal* = SetNW* on the world entity.
[QUOTE=Willox;47042460]SetGlobal* = SetNW* on the world entity.[/QUOTE]
Okay, so that means the world's NWString gets, for some reason, reset every time something is constrained to it (we've noted rope and weld, not tried anything else). Sounds like a bug to me!
Thanks a ton for the tips, Robotboy! I'd still like to know why you say "GlobalVars are bad", sounds like a strange thing to say without any basis. (assuming this bug didn't exist)
Sorry, you need to Log In to post a reply to this thread.