aboutsummaryrefslogtreecommitdiff
path: root/gamemode/nrequire.lua
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2018-03-23 14:57:08 -0400
committerAlexander Pickering <alexandermpickering@gmail.com>2018-03-23 14:57:08 -0400
commita7f7bed257dd96b1027c6343cd59eea4eee9fc3b (patch)
treee35e17cc5a0dc10b48451c3e36b7de6e347817be /gamemode/nrequire.lua
parent3498738f081e3d61faabeba3c632e36ac9d8031f (diff)
downloadartery-a7f7bed257dd96b1027c6343cd59eea4eee9fc3b.tar.gz
artery-a7f7bed257dd96b1027c6343cd59eea4eee9fc3b.tar.bz2
artery-a7f7bed257dd96b1027c6343cd59eea4eee9fc3b.zip
Changed the way nrequire loads client lua
Fixed the way nrequire loads client code Can still be optimized Fixes #1
Diffstat (limited to 'gamemode/nrequire.lua')
-rw-r--r--gamemode/nrequire.lua265
1 files changed, 216 insertions, 49 deletions
diff --git a/gamemode/nrequire.lua b/gamemode/nrequire.lua
index d704907..94f7215 100644
--- a/gamemode/nrequire.lua
+++ b/gamemode/nrequire.lua
@@ -6,6 +6,8 @@
]]
if nrequire ~= nil then return end
+local clienttoload = {}
+
local searchpaths = {
{"gamemodes/artery/gamemode","GAME"},
{"artery/global","DATA"},
@@ -36,7 +38,7 @@ local function BuildIncludeTable(tbl)
local foldername = part:gsub("/$",""):gsub("^/","")
pathparts[#pathparts+1] = foldername
end
- local filename = filepath:gfind("[%w_]+%.[%w_]+$")()
+ local filename = filepath:gfind("[%w_%.]+%.[%w_]+$")()
if output[filename] == nil then
output[filename] = {}
end
@@ -47,7 +49,7 @@ local function BuildIncludeTable(tbl)
end
cursor = cursor[pathparts[folder]]
end
- assert(cursor[pathparts[1]] == nil, string.format("Found 2 files with the same path:\n\t%q",pathparts[1]))
+ assert(cursor[pathparts[1]] == nil, string.format("Found 2 files with the same path:\n\t%s",table.ToString(pathparts,"pathparts",true)))
cursor[pathparts[1]] = v
end
return output
@@ -87,7 +89,7 @@ local function scan(pretbl, name)
for part in name:gmatch("/?[%w_]+/") do
pathparts[#pathparts + 1] = part:gsub("/$",""):gsub("^/","")
end
- local filename = name:gfind("[%w_]+%.[%w_]+$")()
+ local filename = name:gfind("[%w_%.]+%.[%w_]+$")()
assert(filename ~= nil,string.format("Could not file a filename for %q from parts: %s valid files are:\n\t%s",name,table.concat(pathparts,","),table.concat(collect_paths(pretbl),"\n\t")))
local cursor = pretbl[filename]
assert(cursor ~= nil,string.format("Scan did not find a file named %q.\n",filename))
@@ -107,27 +109,32 @@ local function scan(pretbl, name)
end
local paths = {}
-for k,v in pairs(searchpaths) do
- TraverseFolder(v,function(n)
- paths[#paths + 1] = n
- end)
-end
-local ntbl = BuildIncludeTable(paths)
+local ntbl = {}
local reqtbl = {} --Holds already nrequire()'d things
local lastcall = {} --Holds when things were loaded
local deptbl = {} --Holds the dependencies between files
local pathstack = {}
function nrequire(req,...)
-
- local tpath = scan(ntbl,req) -- Find the full path for the nrequired() module
+ local varargs = {...}
+ local tpath
+ if CLIENT then
+ xpcall(function()
+ tpath = scan(ntbl,req)
+ end,function()
+ tpath = scan(ntbl,req .. ".txt")
+ end)
+ else
+ tpath = scan(ntbl,req)
+ end
+ -- local tpath = scan(ntbl,req) -- Find the full path for the nrequired() module
local trace = debug.getinfo(2,"flnSu")
local source = trace.source
deptbl[source] = tpath
--If we've already run it (and its up to date), just return it
- if reqtbl[tpath[1]] and lastcall[tpath[1]] >= file.Time(tpath[1],tpath[2]) then
+ if reqtbl[tpath[1]] --[[and lastcall[tpath[1] ] >= file.Time(tpath[1],tpath[2])]] then
return reqtbl[tpath[1]]
end
@@ -144,19 +151,28 @@ function nrequire(req,...)
return
end
local filetime = file.Time(tpath[1],tpath[2])
- local filefunc = CompileString(filetxt,tpath[1],false)
- if type(filefunc) ~= "function" then
- error(filefunc)
- else
- xpcall(function()
- local m = filefunc()
- hook.Run("artery_file_included",tpath,m)
- reqtbl[tpath[1]] = m
- lastcall[tpath[1]] = filetime
- end,function(err)
- MsgC(Color(209,96,196),"nrequire Error:",err,"\n")
- end)
+ if lastcall[tpath[1]] and lastcall[tpath[1]] < filetime then
+ goto cleanup
+ end
+
+ do -- Needed to follow the scoping rules of lua in regards to goto
+ local filefunc = CompileString(filetxt,tpath[1],false)
+ if type(filefunc) ~= "function" then
+ error(filefunc)
+ else
+ xpcall(function()
+ local m = filefunc(varargs)
+ hook.Run("artery_file_included",tpath,m)
+ reqtbl[tpath[1]] = m
+ lastcall[tpath[1]] = CurTime()
+ end,function(err)
+ MsgC(Color(209,96,196),debug.traceback(),"\n")
+ MsgC(Color(209,96,196),"nrequire Error:",err,"\n")
+ end)
+ end
end
+
+ ::cleanup::
pathstack[#pathstack] = nil
return reqtbl[tpath[1]]
@@ -189,11 +205,18 @@ else
local function run_csfile(txt,name)
assert(#txt > 0, "File was size 0 on: " .. name)
local ptr = CompileString(txt,name,false)
+ local ret = nil
if type(ptr) == "function" then
- ptr()
+ xpcall(function()
+ ret = ptr()
+ end,function(err)
+ MsgC(Color(209,96,196),debug.traceback(),"\n")
+ MsgC(Color(209,96,196),"nrequire Error:",err,"\n")
+ end)
else
- log.error(ptr)
+ error(ptr)
end
+ return ret
end
net.Receive("artery_loadfile",function()
local filename = net.ReadString()
@@ -220,17 +243,18 @@ else
end)
net.Receive("artery_respondfile",function()
local filename = net.ReadString()
+ local filepath = net.ReadString()
local filetext = net.ReadString()
local dirname = string.GetPathFromFilename(filename)
file.CreateDir("artery/client/files/" .. dirname)
assert(#filetext > 0, "Retreived a size 0 file: " .. filename)
file.Write("artery/client/files/" .. filename,filetext)
- run_csfile(filetext,filename)
+ local mod = run_csfile(filetext,filename)
+ reqtbl[filepath] = mod
+ lastcall[filepath] = CurTime()
end)
end
-local clienttoload = {}
-
--[[
Automatically include all the files in the gamemode directory based on the file name.
If the file starts with cl_ it will only be included on the client, if it starts with sv_ it will only be included on the server. If it starts with anything else, it will be shared. Will detect and error on circuar dependancy.
@@ -278,22 +302,142 @@ local function doincludes()
end
end
-doincludes()
-hook.Call("artery_core_loaded")
-local function loadclient(who)
- local routine = coroutine.create(function()
- for k,v in pairs(clienttoload) do
- print("Asking client to load",k)
- net.Start("artery_loadfile")
- net.WriteString(v.name)
- net.WriteUInt(v.hash,32)
- net.WriteString(v.directory)
- net.Send(who)
- coroutine.yield()
+local function redoincludes()
+ print("redoing includes")
+ paths = {} -- Defined above somewhere
+ for k,v in pairs(searchpaths) do
+ print("Searching path:")
+ PrintTable(v)
+ TraverseFolder(v,function(n)
+ print("found file:")
+ PrintTable(n)
+ paths[#paths + 1] = n
+ end)
+ end
+ ntbl = BuildIncludeTable(paths)
+ doincludes()
+ hook.Call("artery_core_loaded")
+end
+
+if SERVER then
+ redoincludes()
+ concommand.Add("artery_doincludes",function(ply,cmd,args)
+ redoincludes()
+ end)
+end
+local runclient = nil
+if SERVER then
+ util.AddNetworkString("artery_downloadfile")
+ util.AddNetworkString("art_downloadfiles")
+ util.AddNetworkString("art_requestfile")
+ util.AddNetworkString("art_respondfile")
+ util.AddNetworkString("artery_request_client_download")
+ local function downloadclient(who)
+ print("Loading client",who)
+ net.Start("art_downloadfiles")
+ net.WriteTable(clienttoload)
+ net.Send(who)
+ -- local routine = coroutine.create(function()
+ -- for k,v in pairs(clienttoload) do
+ -- print("Asking client to load",k)
+ -- net.Start("artery_downloadfile")
+ -- net.WriteString(v.name)
+ -- net.WriteUInt(v.hash,32)
+ -- net.WriteString(v.directory)
+ -- net.WriteString(file.Read(v.name,v.directory))
+ -- net.Send(who)
+ -- coroutine.yield()
+ -- end
+ -- end)
+ -- timer.Create("artery_downloadload_client_timer",1,#clienttoload,function()
+ -- coroutine.resume(routine)
+ -- end)
+ end
+ net.Receive("artery_request_client_download",function(ln,pl)
+ print("artery_request_client_download received by server")
+ downloadclient(pl)
+ end)
+ net.Receive("art_requestfile",function(ln,pl)
+ local filedata = net.ReadTable()
+ local filetxt = file.Read(filedata.name,filedata.directory)
+ net.Start("art_respondfile")
+ net.WriteTable({
+ name = filedata.name,
+ directory = filedata.directory,
+ text = filetxt
+ })
+ net.Send(pl)
+ end)
+else
+ net.Receive("art_downloadfiles",function(ln,pl)
+ local clientfiles = net.ReadTable()
+ local todownload = {}
+
+ for k,v in pairs(clientfiles) do
+ local fullpath = "artery/client/" .. v.directory .. "/" .. v.name .. ".txt"
+ if not file.Exists(fullpath,"DATA") then
+ local thisdownload = {
+ name = v.name,
+ directory = v.directory
+ }
+ todownload[#todownload + 1] = thisdownload
+ elseif util.CRC(file.Read(fullpath,"DATA")) ~= v.hash then
+ local thisdownload = {
+ name = v.name,
+ directory = v.directory
+ }
+ todownload[#todownload + 1] = thisdownload
+ -- else file is up to date and dosn't need re-downloading.
+ end
end
+
+ local routine = coroutine.create(function()
+ for k,v in pairs(todownload) do
+ net.Start("art_requestfile")
+ net.WriteTable(v)
+ net.SendToServer()
+ coroutine.yield()
+ end
+ runclient()
+ end)
+ timer.Create("artery_download_files_timer",0.1,#todownload,function()
+ coroutine.resume(routine)
+ end)
end)
- timer.Create("artery_load_client_timer",1,#clienttoload,function()
- coroutine.resume(routine)
+
+ net.Receive("art_respondfile",function(ln,pl)
+ local tbl = net.ReadTable()
+ print("Received response file:",tbl.name)
+ local fullpath = "artery/client/" .. tbl.directory .. "/" .. tbl.name .. ".txt"
+ local path = string.GetPathFromFilename(fullpath)
+ file.CreateDir(path)
+ print("Writing to ", fullpath)
+ file.Write(fullpath,tbl.text)
+ end)
+
+ net.Receive("artery_downloadfile",function(ln,pl)
+ print("Asked to download file")
+ local clientfiles = net.ReadTable()
+ -- local filename = net.ReadString()
+ -- local filehash = net.ReadUInt(32)
+ -- local filedir = net.ReadString()
+ -- local filetext = net.ReadString()
+ -- print("got filename:",filename,"and filedir:",filedir)
+ -- local dirname = string.GetPathFromFilename(filename)
+ -- file.CreateDir("artery/client/files/" .. dirname)
+ -- assert(#filetext > 0, "Retreived a size 0 file: " .. filename)
+ -- file.Write("artery/client/files/" .. filename,"")
+ end)
+ local function request_file_download()
+ print("Requesting to download client files")
+ net.Start("artery_request_client_download")
+ net.SendToServer()
+ end
+ timer.Simple(0,function()
+ request_file_download()
+ end)
+ concommand.Add("artery_DownloadClient",function(ply,cmd,args)
+ request_file_download()
end)
end
@@ -303,12 +447,35 @@ end)
concommand.Add("PrintReqTbl",function(ply,cmd,args)
PrintTable(reqtbl)
end)
-concommand.Add("PrintClientToLoad",function(ply,cmd,args)
- PrintTable(clienttoload)
-end)
-concommand.Add("Loadclient",function(ply,cmd,args)
- loadclient(ply)
-end)
+if SERVER then
+ concommand.Add("PrintClientToLoad",function(ply,cmd,args)
+ PrintTable(clienttoload)
+ end)
+end
+
+if SERVER then
+ util.AddNetworkString("art_requestclientreload")
+ net.Receive("art_requestclientreload",function(ln,pl)
+ loadclient(pl)
+ end)
+else
+ concommand.Add("artery_LoadClient",function(ply,cmd,args)
+ net.Start("art_requestclientreload")
+ net.SendToServer()
+ --loadclient(ply)
+ end)
+ runclient = function()
+ searchpaths = {
+ {"artery/client/game/","DATA"},
+ {"artery/client/" .. game.GetMap() .. "/", "DATA"}
+ }
+ redoincludes()
+ end
+ runclient()
+ concommand.Add("artery_RunClient",function(ply,cmd,args)
+ runclient()
+ end)
+end
if SERVER then
util.AddNetworkString("art_refresh")