aboutsummaryrefslogtreecommitdiff
path: root/gamemode/nrequire.lua
diff options
context:
space:
mode:
authorAlexander Pickering <alexandermpickering@gmail.com>2017-01-04 23:27:36 -0500
committerAlexander Pickering <alexandermpickering@gmail.com>2017-01-04 23:27:36 -0500
commit4879eb1d78520ce0ac9b0bb0ef5244cf65ad7c99 (patch)
treeac47724191a8959c19b2408d4da384d64b6098ec /gamemode/nrequire.lua
parent2c4329e2b6e19182a441f79a5c3010011f8ae767 (diff)
downloadartery-4879eb1d78520ce0ac9b0bb0ef5244cf65ad7c99.tar.gz
artery-4879eb1d78520ce0ac9b0bb0ef5244cf65ad7c99.tar.bz2
artery-4879eb1d78520ce0ac9b0bb0ef5244cf65ad7c99.zip
Started refactoring item and inventory system
Diffstat (limited to 'gamemode/nrequire.lua')
-rw-r--r--gamemode/nrequire.lua171
1 files changed, 171 insertions, 0 deletions
diff --git a/gamemode/nrequire.lua b/gamemode/nrequire.lua
new file mode 100644
index 0000000..ba71f17
--- /dev/null
+++ b/gamemode/nrequire.lua
@@ -0,0 +1,171 @@
+--[[
+ A replacement for require
+]]
+if nrequire ~= nil then return end
+print("hello from nrequire!")
+local path = (GM or GAMEMODE).Folder:gsub("gamemodes/","") .. "/gamemode"
+local function TraverseFolder(dir, func)
+ local fpath = table.concat({path,dir,"/*"})
+ local files, directories = file.Find(fpath,"LUA")
+ for k,v in pairs(files) do
+ if string.GetExtensionFromFilename(v) == "lua" then
+ local callpath = table.concat({path,dir,"/",v})
+ func(callpath)
+ end
+ end
+ for k,v in pairs(directories) do
+ local npath = table.concat({dir,"/",v})
+ TraverseFolder(npath,func)
+ end
+end
+
+local function rebuild_include_table(f)
+ local ret = {}
+ for k,v in pairs(f) do
+ local pathparts = {}
+ for part in v:gmatch("/?[%w_]+/") do
+ pathparts[#pathparts + 1] = part:gsub("/$",""):gsub("^/","")
+ end
+ local filename = v:gfind("[%w_]+%.lua$")()
+ if ret[filename] == nil then
+ ret[filename] = {}
+ end
+ local cursor = ret[filename]
+ for folder = #pathparts, 2, -1 do
+ if cursor[pathparts[folder]] == nil then
+ cursor[pathparts[folder]] = {}
+ end
+ cursor = cursor[pathparts[folder]]
+ end
+ assert(cursor[pathparts[1]] == nil,string.format("Found 2 files with the same path:\n\t%s\n\t%s",cursor[pathparts[1]],pathparts[1]))
+ cursor[pathparts[1]] = v
+ end
+ return ret
+end
+
+--Finds the number of elements in a table, even if it is not an array
+local function tbllen(tbl)
+ local count = 0
+ for k,v in pairs(tbl) do count = count + 1 end
+ return count
+end
+
+--[[
+ Finds all the paths from a pretable
+]]
+local function collect_paths(pretbl)
+ local ret = {}
+ for k,v in pairs(pretbl) do
+ if type(v) ~= "string" then
+ local resp = collect_paths(v)
+ for i,j in pairs(resp) do
+ ret[#ret + 1] = j
+ end
+ else
+ ret[#ret + 1] = v
+ end
+ end
+ return ret
+end
+
+--[[
+ Scans the prefix table built by rebuild_include_table to find the file path for the partial name of an included file.
+]]
+local function scan(pretbl, name)
+ local pathparts = {}
+ for part in name:gmatch("/?[%w_]+/") do
+ pathparts[#pathparts + 1] = part:gsub("/$",""):gsub("^/","")
+ end
+ local filename = name:gfind("[%w_]+%.lua")()
+ local cursor = pretbl[filename]
+ assert(cursor ~= nil,string.format("Scan did not find a file named %q, valid files are:\n\t%s",filename,table.concat(pretbl,"\n\t")))
+ local rev = {}
+ for i = 1, #pathparts do rev[#pathparts - i + 1] = pathparts[i] end
+ for k,v in ipairs(rev) do cursor = cursor[v] end
+ while type(cursor) ~= "string" do
+ assert(type(cursor) ~= "nil",string.format("Could not find a valid file for path %q, file paths:\n\t%s",name,table.concat(collect_paths(pretbl),"\n\t")))
+ assert(tbllen(cursor) == 1,string.format("Ambiguous scan, there are two or more paths that match %q\n\t%s",name,table.concat(collect_paths(cursor),"\n\t")))
+ cursor = cursor[next(cursor)]
+ end
+ return cursor
+end
+
+local paths = {}
+local ins = function(n) paths[#paths + 1] = n end
+TraverseFolder("",ins)
+local ntbl = rebuild_include_table(paths)
+local reqtbl = {}
+for k,v in pairs(paths) do
+ if SERVER and not v:match("/?sv_[%w_]+%.lua$") then
+ print("Adding CS lua file",v)
+ AddCSLuaFile(v)
+ end
+end
+
+local pathstack = {}
+local incyields = {}
+function nrequire(req)
+ print("nrequire")
+ local tpath = scan(ntbl,req)
+ if reqtbl[tpath] then
+ print("nrequire cache hit")
+ return reqtbl[tpath]
+ end
+ for k,v in pairs(pathstack) do
+ assert(v ~= tpath,string.format("Circular dependancy detected:\n\t%s",table.concat(pathstack,"\n\t\t|\n\t\tv\n\t")))
+ end
+ print(string.format("Including %q\n",tpath))
+ pathstack[#pathstack + 1] = tpath
+ reqtbl[#reqtbl + 1] = include(tpath)
+ print(string.format("Included %q\n",tpath))
+ return reqtbl[#reqtbl]
+ --[[
+ incyields[#incyields + 1] = coroutine.create(function()
+ print(string.format("Including %q\n",tpath))
+ reqtbl[#reqtbl + 1] = include(tpath)
+ print(string.format("Included %q\n",tpath))
+ end)
+ ]]
+end
+
+local function doincludes()
+ print("doing includes")
+ paths = {}
+ TraverseFolder("",ins)
+ ntbl = rebuild_include_table(paths)
+ reqtbl = {}
+ for k,v in pairs(paths) do
+ if v:match("/?sv_[%w_]+%.lua$") then
+ if SERVER then
+ nrequire(v)
+ end
+ elseif v:match("/?cl_[%w_]+%.lua$") then
+ if CLIENT then
+ nrequire(v)
+ end
+ else
+ nrequire(v)
+ end
+ pathstack = {}
+ end
+
+ while #incyields > 0 do
+ for k,v in pairs(incyields) do
+ if coroutine.status(v) == "dead" then
+ incyields[k] = nil
+ else
+ coroutine.resume(v)
+ end
+ end
+ end
+end
+
+doincludes()
+if SERVER then util.AddNetworkString("art_refresh") end
+if CLIENT then net.Receive("art_refresh",doincludes) end
+
+concommand.Add("art_manualrefresh",function(ply,cmd,args)
+ doincludes()
+ net.Start("art_refresh")
+ net.Broadcast()
+end)