do local T=setmetatable({},{__index=function(T,z)T[z]={}return T[z]end,__mode="\107"})local z=setmetatable({},{__index=function(T,z)T[z]={}return T[z]end;__mode="\107"})local C=64 local M=32 local s={"\110\117\109\098\101\114";"\115\116\114\105\110\103","\098\111\111\108\101\097\110";"\110\105\108","\086\101\099\116\111\114\050";"\086\101\099\116\111\114\051";"\067\070\114\097\109\101","\067\111\108\111\114\051","\066\114\105\099\107\067\111\108\111\114","\085\068\105\109\050","\085\068\105\109"}for T,z in ipairs(s)do s[z]=true end local function E(z,E)local H=typeof(z)if not s[H]then error(string.format("\073\110\118\097\108\105\100 \118\097\108\117\101 \112\097\115\115\101\100 \116\111 \078\101\116\119\111\114\107\058\080\097\099\107 \040\118\097\108\117\101\115 \111\102 \116\121\112\101 \037\115 \097\114\101 \110\111\116 \115\117\112\112\111\114\116\101\100\041",H))end if H=="\098\111\111\108\101\097\110"or H=="\110\105\108"or z==""then return z elseif H=="\115\116\114\105\110\103"and#z>C then return"\000"..z end local Q=T[E]local b=Q[z]if not b then if#Q<M then local T=#Q+1 b={char=string.char(T);value=z;last=0}Q[T]=b Q[z]=b else for T,z in ipairs(Q)do if not b or z.last<b.last then b=z end end Q[b.value]=nil Q[z]=b b.value=z end if IsServer then Network:FireClient(E,"\083\101\116\080\097\099\107\101\100\086\097\108\117\101",b.char,b.value)else Network:FireServer("\083\101\116\080\097\099\107\101\100\086\097\108\117\101",b.char,b.value)end end b.last=os.clock()return b.char end local function H(T,C)local M=typeof(T)if M~="\115\116\114\105\110\103"or T==""then return T end local s=string.byte(T,1)if s==0 then return string.sub(T,2)end return z[C][s]end if IsServer then function Network.Pack(C,T,z)assert(typeof(z)=="\073\110\115\116\097\110\099\101"and z:IsA("\080\108\097\121\101\114"),"\099\108\105\101\110\116 \105\115 \110\111\116 \097 \112\108\097\121\101\114")return E(T,z)end function Network.Unpack(C,T,z)assert(typeof(z)=="\073\110\115\116\097\110\099\101"and z:IsA("\080\108\097\121\101\114"),"\099\108\105\101\110\116 \105\115 \110\111\116 \097 \112\108\097\121\101\114")return H(T,z)end Network:BindEvents({SetPackedValue=function(T,E,H)if typeof(E)~="\115\116\114\105\110\103"or#E~=1 then return T:Kick()end local Q=string.byte(E)if Q<1 or Q>M then return T:Kick()end local b=typeof(H)if not s[b]or b=="\115\116\114\105\110\103"and#H>C then return T:Kick()end z[T][Q]=H end})else function Network.Pack(z,T)return E(T,"\083\101\114\118\101\114")end function Network.Unpack(z,T)return H(T,"\083\101\114\118\101\114")end Network:BindEvents({SetPackedValue=function(T,C)z.Server[string.byte(T)]=C end})end end
--

do
	local SendingCache = setmetatable({}, { __index = function(t, i) t[i] = {} return t[i] end, __mode = "k" })
	local ReceivingCache = setmetatable({}, { __index = function(t, i) t[i] = {} return t[i] end, __mode = "k" })
	local MaxStringLength = 64
	local CacheSize = 32 -- must be under 256, keeping it low because adding a new entry goes through the entire cache
	
	local ValidTypes = {
		"number", "string", "boolean", "nil",
		"Vector2", "Vector3", "CFrame",
		"Color3", "BrickColor",
		"UDim2", "UDim"
	}
	
	for i,v in ipairs(ValidTypes) do ValidTypes[v] = true end
	
	local function addEntry(value, client)
		local valueType = typeof(value)
		
		if not ValidTypes[valueType] then
			error(string.format("Invalid value passed to Network:Pack (values of type %s are not supported)", valueType))
		end
		
		if valueType == "boolean" or valueType == "nil" or value == "" then
			return value -- already one-byte
		elseif valueType == "string" and #value > MaxStringLength then
			return "\0" .. value
		end
		
		local cache = SendingCache[client]
		local info = cache[value]
		
		if not info then
			if #cache < CacheSize then
				local index = #cache + 1
				info = { char = string.char(index), value = value, last = 0 }
				
				cache[index] = info
				cache[value] = info
			else
				for i,other in ipairs(cache) do
					if not info or other.last < info.last then
						info = other
					end
				end
				
				cache[info.value] = nil
				cache[value] = info
				
				info.value = value
			end
			
			if IsServer then
				Network:FireClient(client, "SetPackedValue", info.char, info.value)
			else
				Network:FireServer("SetPackedValue", info.char, info.value)
			end
		end
		
		info.last = os.clock()
		
		return info.char
	end
	
	local function getEntry(value, client)
		local valueType = typeof(value)
		if valueType ~= "string" or value == "" then
			return value
		end
		
		local index = string.byte(value, 1)
		if index == 0 then
			return string.sub(value, 2)
		end
		
		return ReceivingCache[client][index]
	end
	
	if IsServer then
		function Network:Pack(value, client)
			assert(typeof(client) == "Instance" and client:IsA("Player"), "client is not a player")
			return addEntry(value, client)
		end
		
		function Network:Unpack(value, client)
			assert(typeof(client) == "Instance" and client:IsA("Player"), "client is not a player")
			return getEntry(value, client)
		end
		
		Network:BindEvents({
			SetPackedValue = function(client, char, value)
				if typeof(char) ~= "string" or #char ~= 1 then
					return client:Kick()
				end
				
				local index = string.byte(char)
				if index < 1 or index > CacheSize then
					return client:Kick()
				end
				
				local valueType = typeof(value)
				if not ValidTypes[valueType] or valueType == "string" and #value > MaxStringLength then
					return client:Kick()
				end
				
				ReceivingCache[client][index] = value
			end
		})
	else
		function Network:Pack(value)
			return addEntry(value, "Server")
		end
		
		function Network:Unpack(value)
			return getEntry(value, "Server")
		end
		
		Network:BindEvents({
			SetPackedValue = function(char, value)
				ReceivingCache.Server[string.byte(char)] = value
			end
		})
	end
end
