From e2dc5bf1fec1e634a60801aca3acf41422e0c880 Mon Sep 17 00:00:00 2001 From: Alexander Pickering Date: Tue, 9 Jan 2018 18:19:26 -0500 Subject: Changed nrequire() to do the job of dataloader As a side effect, this means that mods can now nrequire() from other mods, and that the dataloader is depriciated. --- gamemode/client/cl_inventory.lua | 18 +- gamemode/core/dataloader/cl_loadglobals.lua | 2 + gamemode/core/dataloader/sv_loadglobals.lua | 2 + gamemode/core/inventory/cl_invtracker.lua | 4 +- gamemode/core/inventory/inventory.lua | 7 +- gamemode/init.lua | 10 ++ gamemode/nrequire.lua | 256 ++++++++++++---------------- 7 files changed, 138 insertions(+), 161 deletions(-) diff --git a/gamemode/client/cl_inventory.lua b/gamemode/client/cl_inventory.lua index 1fe53b0..002ea73 100644 --- a/gamemode/client/cl_inventory.lua +++ b/gamemode/client/cl_inventory.lua @@ -38,13 +38,6 @@ inv.tabsheet = nil local clt = nrequire("cl_invtracker.lua") -local player_data --The data the player needs to show the q panel -net.Receive("art_load_player_data",function() - player_data = net.ReadTable() - credits = player_data.credits - if creditslabel then creditslabel:SetText(credits or 0) end -end) - local function CreateSheetTree(tabs,dpropertysheet) for k,v in pairs(tabs) do if type(k) == "string" then @@ -64,8 +57,6 @@ end local function BuildInventory() if qframe and IsValid(qframe) then return end - --if not player_data then error("no player data!") player_data = {credits = 0} end - if not player_data then return end --We havn't loaded in yet... qframe = vgui.Create("DFrame") qframe:SetPos(0,0) qframe:SetSize(width / 4, height) @@ -102,8 +93,13 @@ end ---Shows the player's inventory. -- If the player's inventory hasn't been built yet, builds the inventory, then displays it. function inv.ShowInventory() - if not qframe then BuildInventory() - else qframe:Show() end + print('Showing inventory') + if not qframe then + BuildInventory() + assert(qframe ~= nil, "qframe was still nil after building inventory") + else + qframe:Show() + end state.invopen = true droppanel = vgui.Create("DPanel") droppanel:SetSize(ScrW(),ScrH()) diff --git a/gamemode/core/dataloader/cl_loadglobals.lua b/gamemode/core/dataloader/cl_loadglobals.lua index c4837c8..d2d3950 100644 --- a/gamemode/core/dataloader/cl_loadglobals.lua +++ b/gamemode/core/dataloader/cl_loadglobals.lua @@ -1,3 +1,5 @@ +do return end + local log = nrequire("log.lua") local function run_csfile(txt,name) diff --git a/gamemode/core/dataloader/sv_loadglobals.lua b/gamemode/core/dataloader/sv_loadglobals.lua index 84212e6..9621c5e 100644 --- a/gamemode/core/dataloader/sv_loadglobals.lua +++ b/gamemode/core/dataloader/sv_loadglobals.lua @@ -1,3 +1,5 @@ +do return end + ---Loads code from the data directory. -- Simple data loader, loads code from the data directory, sv_* files only get loaded server side, cl_* files only get loaded client-side, other files are loaded shared --@server sv_loadglobals.lua diff --git a/gamemode/core/inventory/cl_invtracker.lua b/gamemode/core/inventory/cl_invtracker.lua index e808627..41c9eff 100644 --- a/gamemode/core/inventory/cl_invtracker.lua +++ b/gamemode/core/inventory/cl_invtracker.lua @@ -65,7 +65,6 @@ local drawsheeton = function(id,inventory,higharchy) end net.Receive("art_ObserveInventory",function() - print("Got call to observe inventory") local id = net.ReadUInt(32) local inv_type = net.ReadString() local datalen = net.ReadUInt(32) @@ -96,8 +95,6 @@ net.Receive("art_UpdateInventory",function() local position = net.ReadTable() if isput then local item_name = net.ReadString() - print("Putting ", item_name, "into inventory ",id, " at position") - PrintTable(position) local item_data = net.ReadData(net.ReadUInt(32)) local item = itm.GetItemFromData(item_name,item_data) known_inventories[id]:Put(position,item) @@ -123,6 +120,7 @@ net.Receive("art_CloseInventory",function() end) concommand.Add("PrintKnownInventories",function(ply,cmd,args) + print("Printing known inventories") PrintTable(known_inventories) end) diff --git a/gamemode/core/inventory/inventory.lua b/gamemode/core/inventory/inventory.lua index 9215a49..1fb3dba 100644 --- a/gamemode/core/inventory/inventory.lua +++ b/gamemode/core/inventory/inventory.lua @@ -85,14 +85,13 @@ local function DefaultRemoveObserver(self,observer_id) end end local function SetDefaultObservers(tbl) + log.debug("Setting default observers on ", tbl.Name) tbl.AddObserver = DefaultAddObserver tbl.RemoveObserver = DefaultRemoveObserver --Call the observer's puts as well as this inventory's put. local oldput,oldremove = tbl.Put,tbl.Remove tbl.Put = function(self,position,item) for k,v in pairs(self.observers) do - --print("Calling put on observer:") - --PrintTable(v) v:Put(position,item) end return oldput(self,position,item) @@ -178,6 +177,10 @@ end concommand.Add("artery_printinventories", function(ply,cmd,args) PrintTable(inventories) end) +concommand.Add("artery_printmyinventories",function(ply,cmd,args) + print("Inventories of:",ply:Nick()) + PrintTable(ply.data.inventories) +end) ---To Be Depriciated. function inv.DeriveInventory(name) diff --git a/gamemode/init.lua b/gamemode/init.lua index d822e81..adb2b94 100644 --- a/gamemode/init.lua +++ b/gamemode/init.lua @@ -1,4 +1,14 @@ +if CLIENT then return end + +local ouans = util.AddNetworkString +function util.AddNetworkString(str) + print("Added network string:",str) + ouans(str) +end + AddCSLuaFile( "shared.lua" ) AddCSLuaFile( "cl_init.lua" ) AddCSLuaFile("nrequire.lua") include( "shared.lua" ) + +util.AddNetworkString = ouans diff --git a/gamemode/nrequire.lua b/gamemode/nrequire.lua index 29e350d..24f0266 100644 --- a/gamemode/nrequire.lua +++ b/gamemode/nrequire.lua @@ -4,69 +4,53 @@ artery_nrequire_defined artery_core_loaded ]] ---Don't run ourselves, or we'll get stuck in a recursive loop! if nrequire ~= nil then return end -local path = (GM or GAMEMODE).Folder:gsub("gamemodes/","") .. "/gamemode" ---[[ - Calls func on all the files under dir. -]] -local function TraverseFolder(dir, func) - local fpath = table.concat({path,dir,"/*"}) - local files, directories = file.Find(fpath,"LUA") + +local searchpaths = { + {"gamemodes/artery/gamemode","GAME"}, + {"artery/global","DATA"}, + {"data/artery/global","GAME"}, +} + +--dir is a table of {string_path, string_directory} +local function TraverseFolder(dir,func) + local find_path = table.concat({dir[1],"/*"},"") + local files,directories = file.Find(find_path,dir[2]) for k,v in pairs(files) do - if string.GetExtensionFromFilename(v) == "lua" then - local callpath = table.concat({path,dir,"/",v}) - func(callpath) - end + local callpath = table.concat({dir[1],"/",v},"") + func({callpath,dir[2]}) end for k,v in pairs(directories) do - local npath = table.concat({dir,"/",v}) - TraverseFolder(npath,func) + local npath = table.concat({dir[1],"/",v},"") + TraverseFolder({npath,dir[2]},func) end end ---[[ - Creates a funny kind of tree. The root points to tables with file names, each file name points to a table containing the folder name it is under. If that folder is under more folders, then the folder table points to more tables in reverse order. The leaf contains the file path. - Ex: - { - [file.lua] = { - [some] = { - [foldername] = "foldername/some/file.lua" - } - [other] = { - [foldername] = "foldername/other/file.lua" - } - } - } - is created from - foldername/ - some/ - file.lua - other/ - file.lua -]] -local function rebuild_include_table(f) - local ret = {} - for k,v in pairs(f) do +local function BuildIncludeTable(tbl) + local output = {} + for k,v in pairs(tbl) do + local filepath = v[1] + local fileloc = v[2] local pathparts = {} - for part in v:gmatch("/?[%w_]+/") do - pathparts[#pathparts + 1] = part:gsub("/$",""):gsub("^/","") + for part in filepath:gmatch("/?[%w_]+/") do + local foldername = part:gsub("/$",""):gsub("^/","") + pathparts[#pathparts+1] = foldername end - local filename = v:gfind("[%w_]+%.lua$")() - if ret[filename] == nil then - ret[filename] = {} + local filename = filepath:gfind("[%w_]+%.[%w_]+$")() + if output[filename] == nil then + output[filename] = {} end - local cursor = ret[filename] - for folder = #pathparts, 2, -1 do + local cursor = output[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])) + assert(cursor[pathparts[1]] == nil, string.format("Found 2 files with the same path:\n\t%q",pathparts[1])) cursor[pathparts[1]] = v end - return ret + return output end --Finds the number of elements in a table, even if it is not an array @@ -82,13 +66,13 @@ end local function collect_paths(pretbl) local ret = {} for k,v in pairs(pretbl) do - if type(v) ~= "string" then + if v[1] == nil then local resp = collect_paths(v) for i,j in pairs(resp) do ret[#ret + 1] = j end else - ret[#ret + 1] = v + ret[#ret + 1] = string.format("%s (%s)",v[1],v[2]) end end return ret @@ -103,136 +87,127 @@ local function scan(pretbl, name) for part in name:gmatch("/?[%w_]+/") do pathparts[#pathparts + 1] = part:gsub("/$",""):gsub("^/","") end - local filename = name:gfind("[%w_]+%.lua")() + 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, valid files are:\n\t%s",filename,table.concat(collect_paths(pretbl),"\n\t"))) + assert(cursor ~= nil,string.format("Scan did not find a file named %q.\n",filename)) local rev = {} for i = 1, #pathparts do rev[#pathparts - i + 1] = pathparts[i] end for k,v in ipairs(rev) do if cursor == nil then error(string.format("Scan could not complete file path translation while translateing %q at %s",table.concat(rev,","),v)) end cursor = cursor[v] end - while type(cursor) ~= "string" do + while cursor ~= nil and #cursor ~= 2 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\nSpecify more of the file path.",name,table.concat(collect_paths(cursor),"\n\t"))) cursor = cursor[next(cursor)] end + assert(type(cursor) ~= "nil", string.format("Could not find %s under %s, found under\n\t %s",filename,name, table.concat(collect_paths(pretbl[filename]),"\n\t"))) 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 +for k,v in pairs(searchpaths) do + TraverseFolder(v,function(n) + paths[#paths + 1] = n + end) end +local ntbl = BuildIncludeTable(paths) - +local reqtbl = {} --Holds already nrequire()'d things +local lastcall = {} --Holds when things were loaded +local deptbl = {} --Holds the dependencies between files local pathstack = {} ---local coroutines = {} ---[[ - Returns the table returned by executing a file. The table is cached after is is loaded, so calling nrequire() on a file twice will only run it once. -]] -function nrequire(req) - local tpath = scan(ntbl,req) --Find the full path from partial path - if reqtbl[tpath] then --And just return it if we've already included it. - return reqtbl[tpath] +function nrequire(req,...) + + + local tpath = scan(ntbl,req) -- Find the full path for the nrequired() module + + local trace = debug.getinfo(1,"flnSu") + local source = trace.source + deptbl[source] = tpath + + --If we've already run it, just return it + if reqtbl[tpath[1]] then + return reqtbl[tpath[1]] end - --Otherwise, make sure we don't have a circular dependancy + + --Otherwise, make sure we don't have a circular depedency for k,v in pairs(pathstack) do - assert(v ~= tpath,string.format("Circular dependancy detected:\n\t%s\n\t\t|\n\t\tV\n\t%s",table.concat(pathstack,"\n\t\t|\n\t\tV\n\t"),v)) + assert(v ~= tpath[1],string.format("Circular dependancy detected:\n\t%s\n\t\t|\n\t\tV\n\t%s",table.concat(pathstack,"\n\t\t|\n\t\tV\n\t"),v)) end - - --Override print so it's easy to see what file is printing what - --local tab_rep = {} - --for k = 1, #pathstack do tab_rep[k] = "\t" end - --print(string.format("%sIncluding %q",table.concat(tab_rep),tpath)) - --local oldprint = print - --print = function(...) oldprint(" ",unpack({...})) end - - --Deal with bookkeeping dealing with circular dependancies, and include - pathstack[#pathstack + 1] = tpath - reqtbl[tpath] = include(tpath) - hook.Call("artery_file_included",nil,tpah) - --[[ - co = coroutine.create(function() - reqtbl[tpath] = include(tpath) - --print("Finished ", tpath) - end) - coroutines[#coroutines + 1] = co - coroutine.resume(co) - ]] - pathstack[#pathstack] = nil - - --[[ - --Try to resume everyone else waiting on something - for k,v in pairs(coroutines) do - --V will be nil when the coroutine finishes, which removes it from the list, nifty. - coroutine.resume(v) + + --Actually run the file + pathstack[#pathstack + 1] = tpath[1] + local filetxt = file.Read(tpath[1],tpath[2]) + 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) end - ]] - - --Undo the crazy print - --print = oldprint - --print(string.format("%sIncluded %q",table.concat(tab_rep),tpath)) - return reqtbl[tpath] + pathstack[#pathstack] = nil + + return reqtbl[tpath[1]] + end -hook.Call("artery_nrequire_defined") - --[[ 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. ]] local function doincludes() paths = {} - TraverseFolder("",ins) - ntbl = rebuild_include_table(paths) + for k,v in pairs(searchpaths) do + TraverseFolder(v,function(n) + paths[#paths + 1] = n + end) + end + ntbl = BuildIncludeTable(paths) reqtbl = reqtbl or {} for k,v in pairs(paths) do - if v:match("/?sv_[%w_]+%.lua$") then + local filename = v[1] + MsgN("Filename:",filename) + if filename == "gamemodes/artery/gamemode/init.lua" then + continue + end + if filename:match("/?sv_[%w_]+%.[%w_]+$") then if SERVER then - nrequire(v) + nrequire(filename) end - elseif v:match("/?cl_[%w_]+%.lua$") then + elseif filename:match("/?cl_[%w_]+%.[%w_]+$") then if CLIENT then - nrequire(v) + nrequire(filename) + else + AddCSLuaFile(filename) end else - nrequire(v) + if SERVER then + AddCSLuaFile(filename) + end + nrequire(filename) end pathstack = {} end end -local function refresh(filename) - local filepath = scan(ntbl,filename) - if filepath:match("/?sv_[%w_]+%.lua$") then - if SERVER then - reqtbl[filepath] = nil - nrequire(filepath) - end - elseif filepath:match("/?cl_[%w_]+%.lua$") then - if CLIENT then - reqtbl[filepath] = nil - nrequire(filepath) - end - else - reqtbl[filepath] = nil - nrequire(filepath) - end -end +doincludes() -doincludes() --Do it the first time through +concommand.Add("PrintDepTbl",function(ply,cmd,args) + PrintTable(deptbl) +end) +concommand.Add("PrintReqTbl",function(ply,cmd,args) + PrintTable(reqtbl) +end) ---Totaly refresh all files server and client side if SERVER then util.AddNetworkString("art_refresh") concommand.Add("art_manualrefresh",function(ply,cmd,args) @@ -245,15 +220,6 @@ if SERVER then end if CLIENT then net.Receive("art_refresh",doincludes) end - -if SERVER then - util.AddNetworkString("art_reffile") - concommand.Add("art_refreshfile", function(ply,cmd,args) - if not ply:IsAdmin() then return end - refresh(args[1]) - net.Start("art_reffile") - net.WriteString(args[1]) - net.Broadcast() - end) -end -if CLIENT then net.Receive("art_reffile",function() refresh(net.ReadString()) end) end +concommand.Add("artery_manualrefresh",function(ply,cmd,args) + doincludes() +end) -- cgit v1.2.3-70-g09d2