Advertisement
Python1320

FFFFFUUUUUUUUUU

Jul 23rd, 2011
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 16.15 KB | None | 0 0
  1.  
  2. local Tag="hdata"
  3.  
  4.  
  5. -- HELPERS -------------------------------------------------------------
  6.  
  7. local tostring=tostring
  8. local setmetatable=setmetatable
  9. local hook=hook
  10. local table=table
  11. local pairs=pairs
  12. local type=type
  13. local string=string
  14. local HTTPGet=HTTPGet
  15.  
  16.  
  17. local class do -- http://lua-users.org/wiki/SimpleLuaClasses
  18.     -- class.lua
  19.     -- Compatible with Lua 5.1 (not 5.0).
  20.     class = function(base, init)
  21.        local c = {}    -- a new class instance
  22.        if not init and type(base) == 'function' then
  23.           init = base
  24.           base = nil
  25.        elseif type(base) == 'table' then
  26.         -- our new class is a shallow copy of the base class!
  27.           for i,v in pairs(base) do
  28.              c[i] = v
  29.           end
  30.           c._base = base
  31.        end
  32.        -- the class will be the metatable for all its objects,
  33.        -- and they will look up their methods in it.
  34.        c.__index = c
  35.  
  36.        -- expose a constructor which can be called by <classname>(<args>)
  37.        local mt = {}
  38.        mt.__call = function(class_tbl, ...)
  39.        local obj = {}
  40.        setmetatable(obj,c)
  41.        if init then
  42.           init(obj,...)
  43.        else
  44.           -- make sure that any stuff from the base class is initialized!
  45.           if base and base.init then
  46.           base.init(obj, ...)
  47.           end
  48.        end
  49.        return obj
  50.        end
  51.        c.init = init
  52.        c.is_a = function(self, klass)
  53.           local m = getmetatable(self)
  54.           while m do
  55.              if m == klass then return true end
  56.              m = m._base
  57.           end
  58.           return false
  59.        end
  60.        setmetatable(c, mt)
  61.        return c
  62.     end
  63. end -- http://lua-users.org/wiki/SimpleLuaClasses
  64.  
  65. --[[TEST
  66. local _class = class(function(a,name)
  67.    a.name = name
  68. end)
  69. --_class.__newindex=function(a,b,c) print("asserttest","newindex",type(a),type(b),type(c)) rawset(a,b,c) end
  70. _class.__tostring=function(s)return s.name end
  71. local name="test"
  72. local _=_class(name)
  73. assert(tostring(_)==name)
  74. _.testkey="testvalue"
  75. _=nil
  76. _class=nil
  77. --]]--ETEST
  78.  
  79.  
  80. local insert=table.insert
  81. local remove=table.remove
  82. local Empty=table.Empty
  83.  
  84.  
  85.  
  86.  
  87. local function unescape (str)
  88.     str = string.gsub (str, "+", " ")
  89.     str = string.gsub (str, "%%(%x%x)", function(h) return string.char(tonumber(h,16)) end)
  90.     str = string.gsub (str, "\r\n", "\n")
  91.     return str
  92. end
  93.  
  94. local function escape (str)
  95.     str = string.gsub (str, "\n", "\r\n")
  96.     str = string.gsub (str, "([^0-9a-zA-Z ])", -- locale independent
  97.         function (c) return string.format ("%%%02X", string.byte(c)) end)
  98.     str = string.gsub (str, " ", "+")
  99.     return str
  100. end
  101.  
  102.  
  103.  
  104. -------------------------------------------------------------
  105. -------------------------------------------------------------
  106. -------------------------------------------------------------
  107.  
  108.  
  109.  
  110. local FIFO do -- STACK IMPLEMENTATION
  111.     FIFO=class()
  112.     function FIFO:__tostring() return "< Stack "..tostring(self:len()).." >" end
  113.  
  114.     -- Pop
  115.     function FIFO:pop()
  116.         return remove( self , self.lilo and #self or 1 )
  117.     end
  118.  
  119.     -- push
  120.     function FIFO.push(a,b)
  121.         insert( a , b )
  122.         return a
  123.     end
  124.  
  125.     function FIFO:len()
  126.         return #self
  127.     end
  128.  
  129.     function FIFO:length()
  130.         return #self
  131.     end
  132.  
  133.     function FIFO:clear()
  134.         return Empty( self )
  135.     end
  136.    
  137. end -- STACK IMPLEMENTATION
  138.  
  139. --[[TEST
  140. local _=FIFO()
  141. assert(_:push("a")==_)
  142. assert(_:push("b")==_)
  143. assert(_:pop()=="a")
  144. print("asserttest",_)
  145. assert(_:pop()=="b")
  146. assert(!_:pop())
  147.  
  148. _=nil
  149. --]]--ETEST
  150.  
  151. local thinks do -- THINK IMPLEMENTATION
  152.     local Now=SysTime
  153.    
  154.     thinks=class(function(self,add_shutdown_hook)
  155.         if add_shutdown_hook==true then
  156.             print("adding shutdown hook for",self)
  157.             hook.Add('Shutdown',self,function()
  158.                 print(self,"shutting down with thinking")
  159.                 if not self or not self.ThinkForever then return end
  160.                 print(self,"Finishing thinking")
  161.                 self:ThinkForever(10)
  162.             end)
  163.         end
  164.     end)
  165.     meta.name="Think Queue"
  166.  
  167.     function thinks:__tostring() return "< ".."Thinks".." - "..table.Count(self).." thinks >" end
  168.    
  169.     function thinks:Add(obj,thinkfunc)
  170.         self[obj]=thinkfunc or true
  171.         if not hook:GetTable().Think[Tag] then
  172.             --dprint("Adding think")
  173.             hook.Add('Think',Tag,function() self:Think() end)
  174.         end
  175.     end
  176.     function thinks:Remove(obj)
  177.         if self[obj] then
  178.             self[obj]=nil
  179.             return true
  180.         end
  181.         return false
  182.     end
  183.    
  184.     function thinks:Exec( thinkfunc,obj )  
  185.         local bOk, strReturn = pcall( thinkfunc,obj )
  186.         if !bOk then
  187.             ErrorNoHalt( "Think failure:"+strReturn )
  188.         end
  189.     end
  190.    
  191.     function thinks:Think()
  192.         local done=true
  193.         for obj,thinkfunc in pairs(self) do
  194.             done=false
  195.             self:Exec( thinkfunc,obj ) 
  196.         end
  197.         if done then
  198.             --dprint("Removing thinking")
  199.             hook.Remove('Think',Tag)
  200.         end
  201.     end
  202.    
  203.     function thinks:ThinkForever(timeout)
  204.        
  205.         -- optimization
  206.         if table.Count(self) == 0 then return end
  207.        
  208.         local started=Now()
  209.         local done=false
  210.         if !timeout then error"no timeout specified" end
  211.         while not done do
  212.             done=true
  213.             for obj,thinkfunc in pairs(self) do
  214.                 done=false
  215.                 self:Exec( thinkfunc,obj )
  216.             end
  217.            
  218.             if (Now()-started) < timeout then
  219.                 ErrorNoHalt(tostring(self).." exceeded timeout ("..timeout.." seconds), killed!\n")
  220.                 break
  221.             end
  222.            
  223.         end
  224.        
  225.         if done then
  226.             print(self,"Emptied queue")
  227.         end
  228.        
  229.     end
  230.    
  231. end -- THINK IMPLEMENTATION
  232.  
  233. --[[TEST
  234. local _=thinks()
  235. local boo=false
  236. _:Add("!",function() boo=true _:Remove("!") end)
  237. _:Add("_",function() end)
  238. _:Think()_:Think()_:Think()_:Think()_:Think()
  239. assert(boo==true)
  240. print("asserttest",_)
  241. assert(_:Remove("_")==true)
  242. print("asserttest",_)
  243. _:Think()
  244. --]]--ETEST
  245.  
  246. local thinks=thinks(true)
  247.  
  248.  
  249. local HTTPQueryObject do -- HTTP QUERY OBJECT HELPERS
  250.     HTTPQueryObject=class()
  251.    
  252.  
  253.     function HTTPQueryObject:__tostring()  
  254.         return "< ".."HTTPQueryObject".." - Timeout "..tostring(self:GetTimeout() or 0).." - Started "..tostring(self:GetStarted()).." >"
  255.     end
  256.  
  257.     AccessorFunc(HTTPQueryObject,"__headers","Header",FORCE_STRING)
  258.     AccessorFunc(HTTPQueryObject,"__callback","Callback")
  259.     AccessorFunc(HTTPQueryObject,"__timeout","Timeout",FORCE_NUMBER)
  260.     AccessorFunc(HTTPQueryObject,"__started","Started",FORCE_BOOL)
  261.        
  262.  
  263. end -- HTTP QUERY OBJECT HELPERS
  264.  
  265.  
  266.  
  267. --[[TEST
  268. local _=HTTPQueryObject()
  269. _:SetStarted(true)
  270. assert(_:GetStarted()==true)
  271. print("asserttest",_)
  272. assert(tostring(_)!="")
  273. _=nil
  274. --]]--ETEST
  275.  
  276.  
  277.  
  278.  
  279. local queryqueue do -- QUERY QUEUE IMPLEMENTATION
  280.    
  281.     queryqueue  = class(function( tbl, host )
  282.         local http = tbl:GetHTTPGet()
  283.         assert(http:Finished()==false)
  284.         tbl:__sethost(host or "http://gmod.iriz.org:20090")
  285.         tbl.stack=FIFO()
  286.         return tbl
  287.     end)
  288.    
  289.     function queryqueue:__tostring()   
  290.         return "< ".."Query Object".." >"
  291.     end
  292.            
  293.  
  294.     function queryqueue:GetProcess()
  295.         return self.__proc
  296.     end
  297.     function queryqueue:SetProcess(proc)
  298.         self.__proc = proc
  299.     end
  300.    
  301.     function queryqueue:GetHTTPGet(new)
  302.         if new or not self.__HTTPGet then
  303.             self.__HTTPGet=HTTPGet()
  304.         end
  305.         return self.__HTTPGet
  306.     end
  307.    
  308.     -- not finished if not even started!!
  309.     function queryqueue:HTTPIsFinished()
  310.         return self:GetHTTPGet():Finished()
  311.     end
  312.    
  313.  
  314.    
  315.     function queryqueue:GetCurrentData( raw )
  316.             local buf = self:GetHTTPGet():GetBuffer()
  317.             local len = self:GetHTTPGet():DownloadSize()
  318.            
  319.             -- http.Get does this for some reason...
  320.             local data = raw and buf or buf:gsub( "\r\n","\n")
  321.            
  322.             return data,len
  323.     end
  324.    
  325.     function queryqueue:Download(host,header)  
  326.         if header and header:len() > 0 then -- hack
  327.             header="Accept: */*\n"..header
  328.         else
  329.             header = ""
  330.         end
  331.        
  332.         self:GetHTTPGet():Download(host,header)
  333.        
  334.     end
  335.    
  336.     function queryqueue:Process(proc)
  337.        
  338.         local started = proc:GetStarted()
  339.         if not started then
  340.             proc:SetStarted(true)
  341.             self:GetHTTPGet(true) -- We need to reset it :\
  342.             --dprint("Started processing new",proc,"to",self:gethost())
  343.            
  344.             --proc:GetTimeout()
  345.            
  346.             self:Download( self:gethost(), proc:GetHeader())
  347.         end
  348.        
  349.        
  350.         if proc:GetStarted() and self:HTTPIsFinished() then
  351.             local proc = self:GetProcess()
  352.             self:SetProcess( nil )
  353.            
  354.             local callback = proc:GetCallback()
  355.             if not callback then
  356.                 --dprint("processed",proc,"without callbacks?")
  357.                 return
  358.             end
  359.            
  360.             local buf,len=self:GetCurrentData()
  361.            
  362.             local ok, ret = pcall( callback, buf, len )
  363.             if not ok then
  364.                 ErrorNoHalt( meta.name.." callback error: "+ret+"\n" )
  365.             end
  366.  
  367.         end
  368.        
  369.     end
  370.  
  371.     function queryqueue:Think()
  372.         local proc=self:GetProcess()
  373.         if proc then
  374.             self:Process(proc)
  375.             return
  376.         end
  377.         if self:GetProcess() then return end
  378.         local newdata=self.stack:pop()
  379.         if newdata then
  380.             --print("grabbing new process",newdata)
  381.             self:SetProcess( newdata )
  382.             return
  383.         end
  384.         --dprint("stopped thinking",self)
  385.         thinks:Remove(self)
  386.     end
  387.  
  388.     function queryqueue:Wake()
  389.         if self.stack:len() > 0 then
  390.             --dprint("waking up")
  391.             thinks:Add(self,self.Think)
  392.         end
  393.     end
  394.  
  395.     function queryqueue:query(header,callback,timeout)
  396.        
  397.         local proc = HTTPQueryObject()
  398.        
  399.         if header then
  400.             proc:SetHeader(header)
  401.         end
  402.         if callback then
  403.             proc:SetCallback(callback)
  404.         end
  405.         if timeout then
  406.             proc:SetTimeout(timeout)
  407.         end
  408.            
  409.         self.stack:push(proc)
  410.         self:Wake()
  411.     end
  412.     function queryqueue:gethost()
  413.         return self.def_host
  414.     end
  415.     function queryqueue:__sethost(host)
  416.         self.def_host = host
  417.     end
  418.    
  419.     function queryqueue:GetQueueLength()
  420.         return self.stack:len()
  421.     end
  422.  
  423. end -- QUERY QUEUE IMPLEMENTATION
  424.  
  425.  
  426.  
  427. --[[TEST
  428. local host="http://iriz.org"
  429. _G._=queryqueue(host)
  430. local _=_G._
  431. assert(_:HTTPIsFinished()==false)
  432. _:query(nil,function(a,b)print("callback:",a:len()) assert(a:len()>0) end,0)
  433. _:query(nil,function(a,b)print("callback:",a:len()) assert(a:len()>0) end,0)
  434. assert(_:GetQueueLength()==2)
  435. print("host:",_:gethost())
  436. assert(_:gethost()==host)
  437. --]]--ETEST
  438.  
  439. local hyperdata do -- HYPERDATA IMPLEMENTATION
  440.  
  441.     hyperdata=class(function(tbl,host)
  442.         tbl.httpqueue=queryqueue(host or "http://gmod.iriz.org:20090") or "HURR??"
  443.         --dprint("New",self)
  444.         return tbl
  445.     end)
  446.    
  447.     function hyperdata:__tostring()
  448.         return "< ".."Hyperdata".." - "..tostring(self:gethost()).." >"
  449.     end
  450.  
  451.     function hyperdata:gethost()
  452.         return self:GetQueryQueue():gethost()
  453.     end
  454.  
  455.     function hyperdata:test(callback)
  456.         http.Get(self:gethost(),"",function(_,b)
  457.             callback(b>0)
  458.         end)
  459.     end
  460.  
  461.     function hyperdata:GetQueryQueue()
  462.         return self.httpqueue
  463.     end
  464.     function hyperdata:GetTaskCount()
  465.         return self.httpqueue:GetQueueLength()
  466.     end
  467.    
  468.     function hyperdata:request_kv(keyvalues,callback)
  469.         if !keyvalues then error"need juice" end
  470.         local payload=""
  471.         local first=true
  472.         for k,v in pairs(keyvalues) do
  473.             --dprint"ADDING SHIT"
  474.             local str=(first and "" or "\n")..escape(tostring(k))..": "..escape(tostring(v))
  475.             first=false
  476.             payload=payload..str
  477.         end
  478.         self:GetQueryQueue():query(payload,callback,0)
  479.     end
  480.    
  481.    
  482. end -- HYPERDATA IMPLEMENTATION
  483.  
  484.  
  485.  
  486. /*
  487.  
  488. local _=hyperdata("http://iriz.org:20090")
  489. --_:test(function(works)
  490. --  assert(works)
  491.     _:request_kv(
  492.         { type="test",
  493.             Data=data,
  494.         },function(str,len)
  495.         local binary=str:find("\0",1,true)
  496.         print("Backend response ("..len.."): '"..tostring(binary and "binary data" or str).."'")
  497.         if binary then
  498.             file.Write("bintest_recv.txt",str)
  499.             if data!=str then
  500.                 for i=1,#data do
  501.                     if data[i]!=str[i] then
  502.                         print("DATA DIFF AT POS "..i,string.byte(data[i]),string.byte(str[i]))
  503.                         print("diffbytes:","'"..data[i].."'","'"..str[i].."'")
  504.                         break
  505.                     end
  506.                 end
  507.             else
  508.                 print"data is the same :o"
  509.             end
  510.            
  511.         end
  512.     end)
  513. --end)*/
  514.  
  515. /*
  516. _G.hcoins=hyperdata("http://iriz.org:20090")
  517. local coins=_G.hcoins
  518. function coins:GetCoins(steamid64,callback)
  519.     local steamid64=steamid64
  520.    
  521.     coins:request_kv(
  522.         { type="getcoins",
  523.             sid64=steamid64,
  524.         },function(str,len)
  525.             if len==0 then
  526.                 callback(false,"no reply")
  527.             end
  528.             if str:sub(1,6)!="COINS=" then
  529.                 if str:find("NOTFOUND",1,true) then
  530.                     callback(-1,steamid64)
  531.                 end
  532.                 callback(false,str)
  533.                 return
  534.             end
  535.             local coins=tonumber(str:match("COINS%=(%d+)"))
  536.             if !coins then
  537.                 callback(false,"bad coin reply:"..str)
  538.             end
  539.             callback(coins,steamid64)
  540.         end)
  541. end
  542.  
  543. function coins:SetCoins(steamid64,newcoins,callback)
  544.     local steamid64=steamid64
  545.     local newcoins=tonumber(newcoins)
  546.     coins:request_kv(
  547.         { type="setcoins",
  548.             sid64=steamid64,
  549.             coins=tostring(newcoins)
  550.         },function(str,len)
  551.             if len==0 then
  552.                 callback(false,"no reply")
  553.             end
  554.             if str:sub(1,8)!="SETCOINS" then
  555.                 callback(false,str)
  556.             else
  557.                 callback(true,steamid64,newcoins)
  558.             end
  559.         end)
  560. end
  561.  
  562. Say("setting coins to 5555555")
  563. coins:SetCoins("0",5555555,function(coins,a)Say(type(coins),coins,a)end)
  564. coins:GetCoins("0",function(coins)Say(type(coins),coins)end)
  565.  
  566. */
  567.  
  568. local playing_time=class(hyperdata,function(c,host)
  569.     hyperdata.init(c,host)
  570. end)
  571.  
  572.  
  573. function playing_time:GetPlayingTimeDB(ident,callback)
  574.    
  575.     local cb=callback
  576.     local function callback(a,b,c)
  577.         if not a then
  578.             print("Error while retrieveing playing time for ident ",b,c)
  579.         end
  580.         cb(a,b,c)
  581.     end
  582.    
  583.     self:request_kv(
  584.         {   type    = "playingtime",
  585.             id      = ident,
  586.         },
  587.         function(str,len)
  588.            
  589.             if len==0 then callback(false,ident,"no reply") end
  590.            
  591.             if str:find("time")!=1 then
  592.                 if str:find("NOTFOUND",1,true)==1 then
  593.                     callback(0,ident)
  594.                 end
  595.                 callback(false,ident,str)
  596.                 return
  597.             end
  598.            
  599.             local time=tonumber(str:match("time%=(%d+)"))
  600.             if !time then
  601.                 callback(false,ident,"bad time reply:"..str)
  602.             end
  603.             callback(time,ident)
  604.         end)
  605. end    
  606.  
  607. function playing_time:AddPlayingTimeDB(ident,added_time_seconds,callback)
  608.     local cb=callback
  609.     local function callback(a,b,c)
  610.         if not a then
  611.             print("Error while retrieveing playing time for ident ",b,c)
  612.         end
  613.         cb(a,b,c)
  614.     end
  615.  
  616.     self:request_kv({ type  = "playingtime",
  617.    
  618.             id      = ident,
  619.             add=added_time_seconds
  620.         },
  621.         function(str,len)
  622.             if len==0 then callback(false,"no reply") end
  623.             if str:find("SET",1,true)!=1 then
  624.                 callback(false,ident,str)
  625.             else
  626.                 callback(true,ident,added_time_seconds)
  627.             end
  628.         end)
  629. end
  630.  
  631. -- get a new connection. After all players aren't depending on each others with their coins..
  632. local function PlayingTimeDBConnection()
  633.     return playing_time("http://gmod.iriz.org:20090")
  634. end
  635.  
  636. local Now=SysTime
  637.  
  638. local function InitPlayingTime(pl)
  639.     print("InitPlayingTime",pl)
  640.     pl.ptimedb = PlayingTimeDBConnection()
  641.    
  642.     pl.ptime_offset=Now()
  643.     pl.ptime_can_update=false
  644.     pl.db_playing_time=0
  645.     pl.ptimedb:GetPlayingTimeDB(tostring(pl:UniqueID()),function(time)
  646.         if not IsValid(pl) then return end
  647.         if time then
  648.             print("Got playing time for",pl,"=",time)
  649.             pl.ptime_can_update=true
  650.             pl.db_playing_time=time
  651.         end
  652.     end)
  653. end
  654.  
  655. local ITER_CONTINUE=true
  656.  
  657. for k,pl in pairs(player.GetHumans()) do
  658.     InitPlayingTime(pl)
  659. end
  660.  
  661. local function UpdatePlayer( pl )
  662.     if not pl.ptimedb then
  663.         InitPlayingTime( pl )
  664.         return
  665.     end
  666.     if not pl.ptime_can_update then
  667.         --print("!ptime_can_update",pl)
  668.         return ITER_CONTINUE
  669.     end
  670.    
  671.     if pl.ptimedb:GetTaskCount()>1 then print("locked",pl,pl.ptimedb:GetTaskCount()) return end
  672.    
  673.     local accumulated=Now()-pl.ptime_offset
  674.    
  675.     local accumulated=math.floor( accumulated ) -- we don't transfer floats, just full integers
  676.     if accumulated <1 then  
  677.         --print("Not enough accumulated",pl,"acc:",accumulated)
  678.         return
  679.     end
  680.    
  681.     pl.ptime_can_update=false
  682.         pl.ptime_offset=pl.ptime_offset+accumulated
  683.         pl.db_playing_time = pl.db_playing_time + accumulated
  684.    
  685.    
  686.     print("Updating ",pl,"accu:",accumulated,"in db:",pl.db_playing_time)
  687.    
  688.     pl.ptimedb:AddPlayingTimeDB( tostring(pl:UniqueID()),  accumulated, function(success)
  689.         if not IsValid(pl) then return end
  690.         pl.ptime_can_update=true
  691.         if success then
  692.         else
  693.             print("reverting accumulation for",pl,", set failed")
  694.             pl.ptime_offset=pl.ptime_offset - accumulated
  695.             pl.db_playing_time = pl.db_playing_time - accumulated      
  696.         end
  697.     end)
  698.    
  699. end
  700.  
  701. function _R.Player.GetPlayingTime()
  702.     return self.db_playing_time+Now()-ptime_offset
  703. end
  704.  
  705. local id=0
  706. local IteratePlayers = function()
  707.     local ply
  708.     local i=0
  709.     while true do
  710.         i=i+1 if i > #player.GetHumans() then break end
  711.         local  plys=#player.GetHumans()
  712.         if plys == 0 then return end
  713.         id=id + 1
  714.         id =id>plys and 1 or id
  715.         ply=player.GetHumans()[id]
  716.         local ret = UpdatePlayer(ply)
  717.        
  718.         if ret!=ITER_CONTINUE then break end
  719.        
  720.     end
  721.    
  722. end
  723. timer.Create('PlayingTime',0,0,IteratePlayers)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement