Jump to content

Recommended Posts

Hello. I'm making a mod that stores some data on worldstate. I made some variables, as you can see in the snippet below, but printing it on server and on client returns different values.

Spoiler
	AddClassPostConstruct("components/worldstate", function(self, inst)
		local _watchershack = UpvalueHacker.GetUpvalue(self.AddWatcher, "_watchers")

		local function SetVariablehack(var, val, togglename) --copied from components/worldstate.lua, so _watchers is consistent and i dont have to override the entire component
			if self.data[var] ~= val and val ~= nil then
				self.data[var] = val

				local watchers = _watchershack[var]
				if watchers ~= nil then
					for k, v in pairs(watchers) do
						for i, fn in ipairs(v) do
							fn[1](fn[2], val)
						end
					end
				end

				if togglename then
					watchers = _watchershack[(val and "start" or "stop") .. togglename]
					if watchers ~= nil then
						for k, v in pairs(watchers) do
							for i, fn in ipairs(v) do
								fn[1](fn[2])
							end
						end
					end
				end
			end
		end

		local function OnAdminOnly(src, tbl)
			print("OnAdminOnly event", _G.TheShard:GetShardId())
			for k, v in pairs(tbl) do
				print("OnAdminOnly event tbl", tbl, k, v)
			end

			local name = tbl.name
			local but = tbl.preset
			local bool = tbl.boolean

			SetVariablehack("cr_" .. but, bool)

			if bool then
				adminonly_func(but)
			end

			--SendModRPCToShard(SHARD_MOD_RPC["cr"]["adminonly_shard"], nil, name, but, bool)
		end

		for _, k in ipairs(button_list) do
			self.data["cr_" .. k] = button_presets[k].admin_default --boolean
		end

		inst:ListenForEvent("cr_adminonly", OnAdminOnly)
	end)

	AddModRPCHandler("cr", "adminonly", function(_, name, but, bool) --bool is 1 for true or 0 for false, because sending a false as an argument for an rpc sends it as nil instead, for some reason.
		print("adminonly_rpc func", name, but, bool, _G.TheShard:GetShardId())

		local str
		if bool == 1 then
			bool = true
			str = "disabled"
		elseif bool == 0 then
			bool = false
			str = "enabled"
		end

		_G.c_announce(name .. " has " .. str .. " the " .. button_presets[but].name .. " button.")

		_G.TheWorld:PushEvent("cr_adminonly", { name = name, preset = but, boolean = bool })
	end)

 

button_presets.god.admin_default is false, so that's the default value. Printing on server and client returns the same default value of false. Then, I do TheWorld:PushEvent("cr_adminonly", {name = ThePlayer.name, preset = "god", boolean = true}), and printing on server returns true, while client still returns false.

I need to check if a button in a widget should be enabled or disabled, accessing it as TheWorld.state.cr_god or similar.

Right now I made a workaround, assigning a netvar and updating it by watching world state with a component, which does read it properly.

Spoiler
local buttons = { "god", "craft", "speed", "suicidedespawn", "mime", "wonkey", "grogginess", "size", "wardrobe", "map", "beard" }

local cr_player = Class(function(self, inst)
	for i,k in ipairs(buttons) do
		inst.cr_buttons[k].adminonly = net_bool(inst.GUID, "cr_" .. k .. "_adminonly")
		inst.cr_buttons[k].adminonly:set(false)

      		inst:WatchWorldState("cr_" .. k, function()
			inst.cr_buttons[k].adminonly:set(TheWorld.state["cr_" .. k])
		end)
	end
end)

return cr_player

 

This means instead of accessing a button as TheWorld.state.cr_god, I access it as self.owner.cr_buttons.god.adminonly:value(). The problem with this workaround is that I'm storing the same data, on every player, while nor server nor other players ever access this value. It's really wasteful.

I need these worldstate variables the same between all shards, too, but right now I just need this to work at least on overworld. In my testing, it works perfectly fine on servers without caves. However, I only have been able to test it while being the host, and I've not tested it on a dedicated server. So that's probably why.

I should note that using upvaluehacker to get _watchers table in the first code snippet is not ideal, and I could have probably just gotten the entire SetVariable function instead, but I tried overriding the entire worldstate.lua file, and got the same results of different data on client and server, so I think it's irrelevant.

Edited by Hamurlik
typo as a reason is irrelevant

Sorry, I entirely misunderstood how world state works. I think world state just holds variables on client side, they are not synced. I had to make a component with netvars that are synced with their world state counterpart

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
  • Create New...