diff --git a/README.md b/README.md index 680847e21e911aef710f5cb1c0f1246571de4640..1933047ee7e8957c5fde277fff5c4742d859727d 100644 --- a/README.md +++ b/README.md @@ -452,3 +452,11 @@ end This library packages my fork of [netwrapper](https://github.com/xaviergmail/netwrapper). NetWrapper is a lightweight, bandwidth-focused wrapper around the existing `net` library. You can view its documentation [here](./lua/xlib/netwrapper) as well as examples [here](./lua/xlib/netwrapper/example.lua) + + +### Contributing +If you would like to contribute, feel free to create a pull request. As this is a personal project, I can't guarantee that every request will be merged. However, if it benefits the project, I will gladly consider it. + +I'm not enforcing any strict code guidelines as this project is already all over the place but please try to match the project's dominant style. + +If you would like to enable autorefresh support while modifying XLib files themselves, create an empty file named `XLIB_AUTOLOAD` inside the `garrysmod` directory. diff --git a/lua/autorun/!xlib_autorun.lua b/lua/autorun/!xlib_autorun.lua index 37aba9cc7fd0f4e50bdffd51b7cb0dec57ee7eec..08b36f0674ad2ab90137927fc3917a3f6877ca77 100644 --- a/lua/autorun/!xlib_autorun.lua +++ b/lua/autorun/!xlib_autorun.lua @@ -1,3 +1,6 @@ +-- If you want to modify XLib itself with autorefresh support, +-- Create an empty `XLIB_AUTOLOAD` file in the garry's mod directory + local clfile = "xlib/xlib_autorun_cl.lua" if SERVER then @@ -11,4 +14,4 @@ else if file.Exists(clfile, "LUA") then include("includes/modules/xlib.lua") end -end \ No newline at end of file +end diff --git a/lua/includes/modules/gdbc.lua b/lua/includes/modules/gdbc.lua index 9e00ed85879b16494659f183e8972c7beaf192f3..78151bc9684eb090f76674e946892f9846c064d3 100644 --- a/lua/includes/modules/gdbc.lua +++ b/lua/includes/modules/gdbc.lua @@ -229,15 +229,22 @@ function Query:run(...) end function query.onError(q, err, sql) - local e = err:lower() - if e:find("connection was killed") or err:find("gone away") or err:find("can't connect") then + local e = err:Trim():lower() + if e:match("connection was killed") or err:match("gone away") or err:match("can't connect") then ErrorNoHalt("GDBC: Connection to SQL server was lost. ("..err..")\nRe-running query:\n"..sql) q:start() return end + if e:match("wsrep has not yet prepared node for application use") then + hook.Run("GDBC:Error", err:Trim()) + end + local args = {err=err, sql=sql, traceback=traceback} - log(id, "FAILED:\n"..SPrintTable(args).."\n") + local str = "GDBC Query FAILED:\n"..SPrintTable(args).."\n" + log(id, str) + hook.Run("Log::Error", { text = str }) + if fakedelay:GetBool() then timer.Simple(fakedelay:GetInt()/1000, function() self:onFailure(err, sql, traceback) end) else diff --git a/lua/xlib/sh_.xlib.lua b/lua/xlib/sh_.xlib.lua index 1b16c002220d5b2564bdd282a3bf8b9b25218250..8bf97d1f58e32e954b77732607caf825136d3de1 100644 --- a/lua/xlib/sh_.xlib.lua +++ b/lua/xlib/sh_.xlib.lua @@ -4,7 +4,7 @@ function XLIB.PostInitialize(fn) if GAMEMODE then fn() else - hook.Add("Initialize", "XLIB.PostInitialize"..tostring(fn), fn) + hook.Add("Initialize", "XLIB.PostInitialize:"..tostring(fn), fn) end end @@ -12,7 +12,7 @@ function XLIB.PreInitialize(fn) if GAMEMODE then fn() else - hook.Add("PostGamemodeLoaded", "XLIB.PreInitialize"..tostring(fn), fn) + hook.Add("PostGamemodeLoaded", "XLIB.PreInitialize:"..tostring(fn), fn) end end @@ -21,7 +21,7 @@ function XLIB.PostInitEntity(fn) if XLIB.DidInitPostEntity then fn() else - hook.Add("InitPostEntity", "XLIB.PostInitialize"..tostring(fn), fn) + hook.Add("InitPostEntity", "XLIB.PostInitialize:"..tostring(fn), fn) end end @@ -29,6 +29,18 @@ hook.Add("InitPostEntity", "XLIB.PostInitEntity", function() XLIB.DidInitPostEntity = true end) +function XLIB.OnFirstTick(fn) + if GAMEMODE then + fn() + else + local id = "XLIB.OnFirstTick:"..tostring(fn) + hook.Add("Tick", id, function() + hook.Remove("Tick", id) + fn() + end) + end +end + if CLIENT then function XLIB.EnsureLocalPlayer(fn) if IsValid(LocalPlayer()) then diff --git a/lua/xlib_extended/sh_delayhttp.lua b/lua/xlib_extended/sh_delayhttp.lua new file mode 100644 index 0000000000000000000000000000000000000000..1c8ad60faec01f8b2e4efca75a8fd8b11eecf7b1 --- /dev/null +++ b/lua/xlib_extended/sh_delayhttp.lua @@ -0,0 +1,66 @@ +--[[ +This is to address thirdparty scripts and/or legacy code making HTTP calls too early +https://github.com/Facepunch/garrysmod-issues/issues/1010#issuecomment-53056089 + +This implementation works by detouring any HTTP / http.* calls and +delaying their invocation until the first tick. + +This implementation makes an attempt to keep compatibility with other +scripts that may already be detouring these functions. +]] + +XLIB.HTTP = XLIB.HTTP or {} + +local detour = XLIB.HTTP +detour.requests = detour.requests or {} + +detour.OFetch = detour.OFetch or http.Fetch +detour.OPost = detour.OPost or http.Post +detour.OHTTP = detour.OHTTP or HTTP + +detour.ready = false + + +for key, tbl in pairs { Fetch = http, Post = http, HTTP = _G} do + tbl[key] = function(...) + local orig = detour["O"..key] + if not detour.ready then + local extra = "" + + if key == "HTTP" then + extra = "Unable to get return value for detoured HTTP() call at this point!".. + " Returning true by default.\n".. + " Consider fixing your code to manually delay the call to HTTP()" + end + + XLIB.WarnTrace(("Delaying http call to first game tick (%s)"..extra):format(key)) + + table.insert(detour.requests, { + func = orig, + args = table.PackNil(...), + }) + + if key == "HTTP" then + return true + end + else + return orig(...) + end + end +end + +local function process() + detour.ready = true + + local requests = detour.requests + detour.requests = {} + + for _, cb in ipairs(requests) do + cb.func(table.UnpackNil(cb.args)) + end +end + +hook.Add("Tick", "xlib.delayhttprequests", function() + hook.Remove("Tick", "xlib.delayhttprequests") + process() +end)