aboutsummaryrefslogtreecommitdiff
path: root/gamemode/core/dataloader/sv_loadglobals.lua
blob: bb74572784f60b61284a17f93e67f35a2c533e3d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
---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
--@module sv_loadglobals.lua

print("Load globals called")
local log = nrequire("log.lua")
local function ExecuteOnFolder(dir, recursive, func)
    recursive = recursive ~= nil and recursive or false
    local path = "data/artery/"
    local fpath = table.concat({path,dir,"/*"})
    local files, directories = file.Find(fpath,"GAME")
    print("Looking for files in ", fpath, "Found:")
    print("files:")
    PrintTable(files)
    print("dirs:")
    PrintTable(directories)
    for k,v in pairs(files) do
        local callpath = table.concat({path,dir,"/",v})
        func(callpath)
    end
    if recursive then
        for k,v in pairs(directories) do
            local npath = table.concat({dir,"/",v})
            ExecuteOnFolder(npath,true,func)
        end
    end
end

util.AddNetworkString("artery_loadfile")
util.AddNetworkString("artery_requestcsfile")
util.AddNetworkString("artery_respondfile")
local toload = {}
local co
local function loadglobals()
    co = coroutine.create(function()
        ExecuteOnFolder("global",true,function(f)
            log.debug("Loading global file : " .. f)
            local filetxt = file.Read(f,"GAME")
            local filename = string.GetFileFromFilename(f)
            if string.find(filename,"^cl_") then
                coroutine.yield(f,filetxt)
            elseif string.find(filename,"^sv_") then
                local func = CompileString(filetxt,f,false)
                if type(func) == "function" then
                    xpcall(func,function(e)
                        log.error(string.format("%s : %s",f,e))
                    end)
                else
                    log.error(string.format("Failed to compile file %s :\n%s"),filename,func)
                end
                coroutine.yield()
            else
                local func = CompileString(filetxt,f,false)
                if type(func) == "function" then
                    xpcall(func,function(e)
                        log.error(string.format("%s : %s",f,e))
                    end)
                else
                    log.error(string.format("Failed to compile file %s :\n%s",filename,func))
                end
                coroutine.yield(f,filetxt)
            end
        end)
    end)
end

local csco = {}
local function load_cs_files(ply)
    log.debug("Told to load csfiles for", ply:Nick())
    csco[ply] = coroutine.create(function()
        for k,v in pairs(toload) do print(k) end
        for k,v in pairs(toload) do
            log.debug("Loading cs file:", k,"for",ply:Nick())
            net.Start("artery_loadfile")
            net.WriteString(k)
            local hash = util.CRC(v)
            net.WriteUInt(tonumber(hash),32)
            net.Send(ply)
            coroutine.yield()
        end
    end)
end

local state = "done"
local n
timer.Create("inc_load_timer",0.1,0,function()
    if state == "loading_sv" then
        if coroutine.status(co) == "suspended" then
            local _,fn,t = coroutine.resume(co)
            if fn and t then
                toload[fn] = t
            end
        else
            print("Done loading sv, setting state to load cl")
            state = "loading_cl"
        end
    elseif state == "loading_cl" then
        if not n then
            _,n = next(csco)
        end
        if n and coroutine.status(n) == "suspended" then
            coroutine.resume(n)
        else
            state = "done"
        end
    end
end)

net.Receive("artery_requestcsfile",function(ln,ply)
    local which = net.ReadString()
    net.Start("artery_respondfile")
    net.WriteString(which)
    net.WriteString(toload[which])
    net.Send(ply)
end)

---Reloads client-side files.
-- Reloads all files that have been downloaded client side, does not re-download files.
--@concommand artery_reloadglobals_cs
concommand.Add("artery_reloadglobals_cs",function(ply,cmd,args)
    load_cs_files(ply)
    state = "loading_cl"
end)

---Reloads all global/ files on all clients.
-- Tells all clients to reload their client-side files, and reloads server-side files. ![Requires admin](./req_admin)
--@concommand artery_reloadglobals
concommand.Add("artery_reloadglobals",function(ply,cmd,args)
    if not ply:IsAdmin() then return end
    loadglobals()
    state = "loading_sv"
end)

loadglobals()
state = "loading_sv"
hook.Add("PlayerInitialSpawn","artery_loadglobals",function(ply)
    log.debug("Doing player inital spawn, loading globals for " , ply:Nick())
    timer.Simple(1,function()
        load_cs_files(ply)
        state = "loading_cl"
    end)
end)