local u=require(script.Parent.Parent.Signal)local k=(game:GetService("\082\117\110\083\101\114\118\105\099\101")):IsServer()local F={boolean="\066\111\111\108\086\097\108\117\101",string="\083\116\114\105\110\103\086\097\108\117\101";table="\082\101\109\111\116\101\069\118\101\110\116";CFrame="\067\070\114\097\109\101\086\097\108\117\101",Color3="\067\111\108\111\114\051\086\097\108\117\101",BrickColor="\066\114\105\099\107\067\111\108\111\114\086\097\108\117\101",number="\078\117\109\098\101\114\086\097\108\117\101",Instance="\079\098\106\101\099\116\086\097\108\117\101",Ray="\082\097\121\086\097\108\117\101";Vector3="\086\101\099\116\111\114\051\086\097\108\117\101",["\110\105\108"]="\079\098\106\101\099\116\086\097\108\117\101"}local c={}c.__index=c function c.Is(u)return type(u)=="\116\097\098\108\101"and getmetatable(u)==c end function c.new(b,e)assert(k,"\082\101\109\111\116\101\080\114\111\112\101\114\116\121 \099\097\110 \111\110\108\121 \098\101 \099\114\101\097\116\101\100 \111\110 \116\104\101 \115\101\114\118\101\114")if e~=nil then assert(type(e)=="\115\116\114\105\110\103","\079\118\101\114\114\105\100\101\067\108\097\115\115 \109\117\115\116 \098\101 \097 \115\116\114\105\110\103\059 \103\111\116 "..type(e))assert(e:match("\086\097\108\117\101\036"),"\079\118\101\114\114\105\100\101\067\108\097\115\115 \109\117\115\116 \098\101 \111\102 \115\117\112\101\114 \116\121\112\101 \086\097\108\117\101\066\097\115\101 \040\101\046\103\046 \073\110\116\086\097\108\117\101\041\059 \103\111\116 "..e)end local i=typeof(b)local J=e or F[i]assert(J,"\082\101\109\111\116\101\080\114\111\112\101\114\116\121 \100\111\101\115 \110\111\116 \115\117\112\112\111\114\116 \116\121\112\101 \""..(i.."\""))local y=setmetatable({_value=b,_type=i,_isTable=i=="\116\097\098\108\101",_object=Instance.new(J)},c)if y._isTable then local k=Instance.new("\082\101\109\111\116\101\070\117\110\099\116\105\111\110")k.Name="\084\097\098\108\101\082\101\113\117\101\115\116"k.Parent=y._object function k.OnServerInvoke(u)return y._value end y.Changed=u.new()else y.Changed=y._object.Changed end y:Set(b)return y end function c.Replicate(u)if u._isTable then u:Set(u._value)end end function c.Set(k,u)if k._isTable then k._object:FireAllClients(u)k.Changed:Fire(u)else k._object.Value=u end k._value=u end function c.Get(u)return u._value end function c.Destroy(u)u._object:Destroy()end return c



local Signal = require(script.Parent.Parent.Signal)

local IS_SERVER = game:GetService("RunService"):IsServer()

local typeClassMap = {
	boolean = "BoolValue";
	string = "StringValue";
	table = "RemoteEvent";
	CFrame = "CFrameValue";
	Color3 = "Color3Value";
	BrickColor = "BrickColorValue";
	number = "NumberValue";
	Instance = "ObjectValue";
	Ray = "RayValue";
	Vector3 = "Vector3Value";
	["nil"] = "ObjectValue";
}


local RemoteProperty = {}
RemoteProperty.__index = RemoteProperty


function RemoteProperty.Is(object)
	return type(object) == "table" and getmetatable(object) == RemoteProperty
end


function RemoteProperty.new(value, overrideClass)

	assert(IS_SERVER, "RemoteProperty can only be created on the server")

	if overrideClass ~= nil then
		assert(type(overrideClass) == "string", "OverrideClass must be a string; got " .. type(overrideClass))
		assert(overrideClass:match("Value$"), "OverrideClass must be of super type ValueBase (e.g. IntValue); got " .. overrideClass)
	end

	local t = typeof(value)
	local class = overrideClass or typeClassMap[t]
	assert(class, "RemoteProperty does not support type \"" .. t .. "\"")

	local self = setmetatable({
		_value = value;
		_type = t;
		_isTable = (t == "table");
		_object = Instance.new(class);
	}, RemoteProperty)

	if self._isTable then
		local req = Instance.new("RemoteFunction")
		req.Name = "TableRequest"
		req.Parent = self._object
		function req.OnServerInvoke(_player)
			return self._value
		end
		self.Changed = Signal.new()
	else
		self.Changed = self._object.Changed
	end

	self:Set(value)

	return self

end


function RemoteProperty:Replicate()
	if self._isTable then
		self:Set(self._value)
	end
end


function RemoteProperty:Set(value)
	if self._isTable then
		self._object:FireAllClients(value)
		self.Changed:Fire(value)
	else
		self._object.Value = value
	end
	self._value = value
end


function RemoteProperty:Get()
	return self._value
end


function RemoteProperty:Destroy()
	self._object:Destroy()
end


return RemoteProperty
