mg_vars = mg_vars or {}
mg_vars.requestdata = mg_vars.requestdata or true

net.Receive("mg_vars_ask", function()
	local tbl = net.ReadTable()
	local local_ply
	mg_vars.requestdata = false
	for var_ply, vars in pairs(tbl) do
		if IsValid(var_ply) then
			for name, var in pairs(vars) do
				var_ply:SetMGVar(name, var)
			end
		else
			mg_vars.requestdata = true
			break
		end
	end
end)

net.Receive("mg_vars_update", function()
	local ply = net.ReadEntity()
	if !IsValid(ply) then return end
	local name = net.ReadString()
	local typ = net.ReadUInt(4)
	local var
	if typ == 1 then
		var = net.ReadBool()
	elseif typ == 2 then
		var = net.ReadFloat()
	elseif typ == 3 then
		var = net.ReadString()
	elseif typ == 4 then
		var = net.ReadEntity()
	else
		return
	end
	ply:SetMGVar(name, var)
end)

local Player = FindMetaTable("Entity")
function Player:SetMGVar(name, var)
	local is_bool = isbool(var)
	local is_num = isnumber(var)
	local is_str = isstring(var)
	local is_ent = isentity(var)
	local prev_var = mg_vars[self] and mg_vars[self][name]
	if prev_var == var then return end
	if is_bool and (!prev_var and var == false) then return end
	if is_num and (!prev_var and var == 0) then return end
	if is_str and (!prev_var and var == "") then return end
	if is_ent and (!prev_var and var == NULL) then return end
	mg_vars[self] = mg_vars[self] or {}
	local old = mg_vars[self][name]
	if var == "" or var == 0 or var == false or var == NULL then
		mg_vars[self][name] = nil
	else
		if mg_vars[self][name] == var then return end
		mg_vars[self][name] = var
	end
	hook.Run("mg_vars_update", self, name, var, old)
end

function Player:GetMGVar(name, fallback)
	return mg_vars[self] and mg_vars[self][name] or (fallback or false)
end

hook.Add("InitPostEntity", "mg_vars_ask", function()
	hook.Remove("InitPostEntity", "mg_vars_ask")
	timer.Create("mg_vars_ask", 10, 0, function()
		if mg_vars.requestdata then
			net.Start("mg_vars_ask")
			net.SendToServer()
		else
			timer.Remove("mg_vars_ask")
		end
	end)
end)