All pastes #553696 Raw Edit

jlulian38

public lua v1 · immutable
·published 2007-06-09 21:02 UTC
rendered paste body
@@--Server--No shared for brevity so we have to rethrow crap in.--ConstantsFLG_NEWSTREAM = 0FLG_DATA = 1FLG_CLOSE = 4FLG_RESET = 5TYP_NUM = 105TYP_STR = 106TYP_PTR_STR = 107TYP_PTR_TAB = 108MAX_STR = 128DEBUG = true--Variablesstream = {}streamc = {}filter = {}streams = {}function debugMsg(s)	if DEBUG then Msg(s.."\n") endendfunction Stream(name,scp) --starts a new container stream and shits it all up and ready. 	local strm = startStream(name)	debugMsg("New master-stream ("..name..")")	table.insert(scp.strmindex,name)	strm.queue = {}	for _,v in pairs(scp:GetPlayers()) do		strm:AddStream(startStreamPlayer(name,v))		debugMsg("Adding sub-stream for ("..tostring(v)..")")	end	return strmendfunction StreamAdd(name,ply) --o_O	streams[name]:AddStream(ply)endfunction startStream(name)	--this is a container	local o = {}	for k,v in pairs(streamc) do o[k]=v end	o.streams = {} --individual player streams	streams[name] = o	return oendfunction streamc:AddStream(strm) --adds an internal stream to a containers table, and links it's queue	table.insert(self.streams,strm)	strm.queue = self.queueendfunction streamc:Run() --runs a stream internal thingy	for _,v in pairs(self.streams) do		v:Run()	endendfunction startStreamPlayer(name,ply) 	local o = {}	--really dumb way to do this	for k,v in pairs(stream) do o[k]=v end	o.data = {} --holds local copy of data.	o.sync = {} --holds sync info (what to send etc etc)	o.name = name --stream name	o.rcp = RecipientFilter()	o.rcp:AddPlayer(ply)	o.qPos = 1	o.wait = 10	o.hook = 0	o:Start()	return o;endfunction streamFilter()	return filter:New()endfunction stream:Start()	--notifies client of new stream (internal)	self:Send(FLG_NEWSTREAM,self.name,TYP_PTR)endfunction stream:Send(flag,name,typ,id,pid,data) //this all around function sends all data //it sends the queue shit or FLAGS and what not //(flags like Closer and Reseter'r)         umsg.Start("stream_umsg")		umsg.Short(flag)		umsg.String(self.name)		if (flag == FLG_DATA) then            /*debugMsg("\nSending data!")            debugMsg("Stream:"..self.name)            debugMsg("Name:"..name)            debugMsg("Type:"..typ)            debugMsg("ID:"..id)            debugMsg("PID:"..pid)              if data then                debugMsg("Data:"..data)            end            debugMsg("This should show up on the client now!\n")*/   			umsg.Short(typ) //hurr I forgot this...			umsg.Long(id)			umsg.Long(pid)			if (typ == TYP_NUM) then				umsg.Long(data)			elseif (typ == TYP_STR) then				umsg.String(data)			end --num,string or nothing (pointer)			umsg.String(name)		end	umsg.End()endfunction streamc:Queue(name,data,pid) //parses and queues up data. 	local typ = type(data)           //(no return, tables in internal streams are linked to the container's	local pid = pid or 0	if (typ == "number") then		table.insert(self.queue,{name=name,typ=TYP_NUM,data=data,pid=pid,data=data})		local id = #self.queue		local tab = self.queue[id]		tab.id=id		tab.pid=pid		tab.name=name	elseif (typ == "table") then		table.insert(self.queue,{name=name,typ=TYP_PTR_TAB,id=#self.queue+1,pid=pid})		self:TableParse(data,#self.queue) 	elseif (typ == "string") then		if #data > MAX_STR then //this chunk loops infintely, we need to fix that...			table.insert(self.queue,{name=name,typ=TYP_PTR_STR,id=#self.queue+1,pid=pid})			local sid = #self.queue			local chk = true			while (chk) do				if #data > MAX_STR then					local addStr=data:sub(0,127)					data = data:gsub(addStr,'')					self:Queue("",addStr,sid)				else					chk=false				end			end		else			table.insert(self.queue,{name=name,typ=TYP_STR,id=#self.queue+1,pid=pid,data=data})		end	endendfunction streamc:TableParse(t, tid)	for i,v in pairs(t) do		self:Queue(i,v,tid)	endendfunction stream:Run() //runs all the streaming bits, gets tables data and sends it with the umsg'r	self.hook = self.hook + 1	if self.hook > self.wait then		if (self.qPos <= #self.queue) then //only send data if the queue is bigger than			local qTab = self.queue[self.qPos] //our current position (has new data)			local typ = qTab.typ 			local id = qTab.id			local pid = qTab.pid			local data = qTab.data or false			local name = qTab.name or ""			self:Send(FLG_DATA,name,typ,id,pid,data) //send with data flag and all info.			self.qPos = self.qPos + 1		end		self.hook = 0	endend --called by container (I was gonna hook this >.>)function stream:Close() --internal stream close	self:Send(FLG_CLOSE)endfunction streamc:Close() --closes all child streams and deletes itself(!)	for k,v in pairs(self.streams) do		v:Close()	end		streams[self.name] = nil --bam!endfunction streamc:Reset() --makes a constainer call all it's child streams and resets them.	self.queue = {}	for _,v in pairs(self.streams) do		v.qPos = 1		self:Send(FLG_RESET)	endendfunction filter:New() --this is a weird work around to the lack of getting players from a recipient filter, lets me do crazy shit.	local o = {}	for k,v in pairs(filter) do o[k]=v end	o.strmindex = {}	o.players = {}	o.playerhook = function (ply) if self.all then self:AddPlayer(ply) for k,v in pairs(self.strmindex) do StreamAdd(v,ply) end end end	hook.Add("PlayerInitialSpawn","weird thing"..math.random(1,10000),o.playerhook)	return oendfunction filter:AddPlayer(ply)	table.insert(self.players,ply)endfunction filter:AddAllPlayers(ply)	self.all = true -- we're sending to all make sure of that	local a = player.GetAll()	for _,v in pairs(a) do		self:AddPlayer(v)	endendfunction filter:GetPlayers()	return self.playersendfunction streamHook()	for _,v in pairs(streams) do		v:Run()	endendhook.Add("Think","server side stream hook",streamHook)--test codemyFil = streamFilter()myFil:AddAllPlayers()mStream = Stream("test_stream",myFil) --have to self populate...timer.Simple(15,function () tStream = startStreamPlayer("test_stream",player.GetByID(1)) tStream:Start() mStream:AddStream(tStream) tStream.wait = 2 end)test_tab = {}for i=1,100 do	test_tab[i]=(i+1)/2^3endfor i=1,100 do	test_tab[math.random(1,100)]="THIS IS RANDOM OLOL?"endmStream:Queue("test_data",test_tab)@@--Clientside--No shared for brevity so we have to rethrow crap in.--ConstantsFLG_NEWSTREAM = 0 FLG_DATA = 1 --Data is being sentFLG_CLOSE = 4FLG_RESET = 5TYP_NUM = 105TYP_STR = 106TYP_PTR_STR = 107TYP_PTR_TAB = 108DEBUG = true --for awhile, keep it this way.--Variablesstream = {}strTable = {} --holds all streams.function debugMsg(s)	if DEBUG then Msg(s.."\n") endendfunction streamHook(data)	--shorts are friggen long, I was hoping for like flag passing, this could do fuckin' math.		local flags = data:ReadShort() --first short, is ALWAYS, the flags.	local name = data:ReadString() --first string is the stream name	debugMsg("Stream:"..name)	debugMsg("Flags:"..tostring(flags))	if (flags == FLG_NEWSTREAM) then		stream:New(name)	elseif (flags == FLG_DATA) then		local sndtype = data:ReadShort() --second short is type		local sndid = data:ReadLong() --first long is this ones id		local sndpid = data:ReadLong() --2nd long is a pointer id (itself if not applicable)		debugMsg("Data Sent!")		debugMsg("Type:"..sndtype)		debugMsg("ID:"..sndid)		debugMsg("Pointer:"..sndpid)		local snddata		if (sndtype == TYP_NUM) then			snddata = data:ReadLong()		elseif (sndtype == TYP_STR) then			snddata = data:ReadString() --a part of a string probably		elseif (sndtype == TYP_PTR_STR or sndtype == TYP_PTR_TAB) then			snddata = false --PTR is a table or string (they're cut up into chunks)		end		local sndname = data:ReadString() --name		debugMsg("Name:"..sndname)		if snddata then debugMsg("Data:"..snddata.."\n\n") end		--chuck all that into our function		if not strTable[name] then debugMsg("No stream ("..name..")") return end		strTable[name]:RecievePacket(sndname,sndtype,sndid,sndpid,snddata)	elseif (flags == FLG_CLOSE) then		strTable[name] = nil --gets rid of our stream	elseif (flags == FLG_RESET) then --clears data and reset the queue (server and client side)		strTable[name].queue = {}		strTable[name].data = {}	endendusermessage.Hook("stream_umsg",streamHook)function stream:New(name)	local o = {}	for k,v in pairs(self) do o[k]=v end	o.queue = {}	o.data = {}	o.name = name	strTable[name] = oendfunction stream:GetTable()	return self.dataendfunction stream:RecievePacket(name,stype,id,pid,data)	local tab = self.queue	if (pid ~= 0) then		if (tab[pid] ~= nil) then			if (tab[pid].type == TYP_PTR_TAB) then				tab = tab[pid].ptr			elseif (tab[pid].type == TYP_PTR_STR) then				self.queue[pid].ptr[name]=self.queue[pid].ptr[name]..data //crazy line of code o_O				return			end		end	end	if (tab == self.queue) then		tab = self.data //if we haven't changed to another table, change to self.data	end	if (stype == TYP_PTR_TAB) then	   debugMsg("New Table pointer: ("..name..")")		tab[name] = {}		self.queue[id] = {}		self.queue[id].ptr = tab[name]		self.queue[id].type = stype	elseif (stype == TYP_PTR_STR) then		tab[name] = ""		self.queue[id] = {}		self.queue[id].ptr = tab		self.queue[id].name = name		self.queue[id].type = stype	else	   tab[name]=data //short and sweet (finally)	endend