GMod doesn't find a .lua module (Module not found!)

Hey there folks!

I’ll try to keep this short, so let’s dive right into my problems.
But firstoff, here my project setup (at least the relevant stuff) as hierarchy (and yes, this is just a dummy mod for testing)(assuming, we are in the gamemodes folder alrdy):
{
-gamemode
–modules
—myjson.lua
–init.lua
}

Okay, so here’s what I want to do: Have a .lua file be a module, thus every function being accessible when using require(“XY”)
Here are the error-prints:
*Couldn’t include file ‘includes\modules\myjson.lua’ (File not found) (@gamemodes/mycewlgm/gamemode/init.lua (line 8))

[ERROR] gamemodes/mycewlgm/gamemode/init.lua:8: Module not found!

  1. require - [C]:-1
  2. unknown - gamemodes/mycewlgm/gamemode/init.lua:8*

Here’s my code:
myjson.lua


print "[MyJSON] Running myjson.lua!"

local print = print
local PrintTable = PrintTable
local file = file

-- Using either package.seeall or the vars above will allow me to use each's functionality
-- It also (for the current test) doesn't matter which way around I am going
module ("MyJSON"--[[, package.seeall]])

local function InitializePlayerDir()
	if not file.IsDir("playerdata", "DATA") then
		file.CreateDir("playerdata") 
	end
end
hook.Add("Initialize","InitializePlayerDir", InitializePlayerDir)



function SaveAllPlayerData(_ply)
	print ("[MyJSON] Saving player-data of player", _ply)
	local _plyFile = "playerdata/" .. _ply:UniqueID() .. ".txt"

	local _transform = {pos = _ply:GetPos(), rot = _ply:GetAngles()}
	PrintTable(_transform)
	local _jsonTable = util.TableToJSON(_transform)
	file.Write(_plyFile, _jsonTable)
end
--hook.Add("PlayerDisconnected", "SaveAllPlayerData", SaveAllPlayerData)

function LoadAllPlayerData(_ply)
	local _plyFile = "playerdata/" .. _ply:UniqueID() .. ".txt"
	if not file.Exists(_plyFile, "DATA") then return end

	print ("[MyJSON] Loading player-data of player", _ply)
	for _, _ply in pairs(player.GetAll()) do
		_ply:ChatPrint(string.format("%s is about to spawn!", _ply:Nick()))
	end

	_fileContent = file.Read(_plyFile, "DATA")
	_luaTable = util.JSONToTable(_fileContent)
	print (_luaTable.pos, _luaTable.rot)
	_ply:SetPos(_luaTable.pos)
	_ply:SetEyeAngles(_luaTable.rot)
end


init.lua


AddCSLuaFile "cl_init.lua"
AddCSLuaFile "shared.lua"

include "shared.lua"
--include "mysql.lua"
--include "plyspawn.lua"

require "MyJSON"

hook.Add("Initialize", "InitializeJSON", InitializePlayerDir)
hook.Add("PlayerDisconnected", "SaveAllPDataJSON", SaveAllPlayerData)

Now, I should mention, that the code itself (IE the functions) work perfectly fine, I’ve already tested that, it’s only, that GMod doesn’t either recognise or correctly handle’s the myjson.lua file being marked with module(“MyJSON”) and then performing a require(“MyJSON”). I am not sure why.

HOWEVER, if I remove (or mark as comments) the lines module(“MyJSON”) and require(“MyJSON”) and instead use include(“myjson.lua”) (thus obviously running the code in that script) I get no error and everything work’s perfectly fine (as stated in the beginning).

I have even tried this work-around:
myjson.lua


print "[MyJSON] Running myjson.lua!"

local m = {}

local function InitializePlayerDir()
	if not file.IsDir("playerdata", "DATA") then
		file.CreateDir("playerdata") 
	end
end
hook.Add("Initialize","InitializePlayerDir", InitializePlayerDir)



function m.SaveAllPlayerData(_ply)
	print ("[MyJSON] Saving player-data of player", _ply)
	local _plyFile = "playerdata/" .. _ply:UniqueID() .. ".txt"

	local _transform = {pos = _ply:GetPos(), rot = _ply:GetAngles()}
	PrintTable(_transform)
	local _jsonTable = util.TableToJSON(_transform)
	file.Write(_plyFile, _jsonTable)
end
--hook.Add("PlayerDisconnected", "SaveAllPlayerData", SaveAllPlayerData)

function m.LoadAllPlayerData(_ply)
	local _plyFile = "playerdata/" .. _ply:UniqueID() .. ".txt"
	if not file.Exists(_plyFile, "DATA") then return end

	print ("[MyJSON] Loading player-data of player", _ply)
	for _, _ply in pairs(player.GetAll()) do
		_ply:ChatPrint(string.format("%s is about to spawn!", _ply:Nick()))
	end

	_fileContent = file.Read(_plyFile, "DATA")
	_luaTable = util.JSONToTable(_fileContent)
	print (_luaTable.pos, _luaTable.rot)
	_ply:SetPos(_luaTable.pos)
	_ply:SetEyeAngles(_luaTable.rot)
end

return m

init.lua


AddCSLuaFile "cl_init.lua"
AddCSLuaFile "shared.lua"

include "shared.lua"
--include "mysql.lua"
--include "plyspawn.lua"

M = require "myjson"

hook.Add("Initialize", "InitializeJSON", M.InitializePlayerDir)
hook.Add("PlayerDisconnected", "SaveAllPDataJSON", M.SaveAllPlayerData)

But then this error occurs (don’t mind the different line-numbers btw, I have duplcated each code and commented the old one out, just fyi):
*Couldn’t include file ‘includes\modules\myjson.lua’ (File not found) (@gamemodes/mycewlgm/gamemode/init.lua (line 26))

[ERROR] gamemodes/mycewlgm/gamemode/init.lua:26: Module not found!

  1. require - [C]:-1
  2. unknown - gamemodes/mycewlgm/gamemode/init.lua:26*
    Basically the same error as the other.

Funny enough tho, using the above work-around in Lua’s standalone interpreter, or rather in SciTE it works just fine.

Maybe someone out there can help, will be looking forward to that and thanks in advance, for everyone looking at this thread!
Greetz,
-Lili Shi

The problem with require/module in GMod is that it requires the file to be in lua/includes. require also doesn’t return anything. Instead, with Garry’s Mod Lua, you should either create a global table for your library if you only want a single instance, or return a unique metatable from the file and use include. Also, for future reference, these:


print = print
PrintTable = PrintTable
file = file

have to be local to the file.

Yeah, just corrected the code in my post, as I just forgot to make them local when i rewrote everything.

Anyways, just tested making and accessing a global table like so:
myjson.lua


print "[MyJSON] Running myjson.lua!"

MyJSON = {}

local function InitializePlayerDir()
	print "[MyJSON] Initializing the Player-Directory"
	if not file.IsDir("playerdata", "DATA") then
		print "[MyJSON] Creating dir 'data/playerdata'!"
		file.CreateDir("playerdata") 
	end
end
hook.Add("Initialize","InitializePlayerDir", InitializePlayerDir)



function MyJSON.SaveAllPlayerData(_ply)
	print ("[MyJSON] Saving player-data of player", _ply)
	local _plyFile = "playerdata/" .. _ply:UniqueID() .. ".txt"

	local _transform = {pos = _ply:GetPos(), rot = _ply:GetAngles()}
	PrintTable(_transform)
	local _jsonTable = util.TableToJSON(_transform)
	file.Write(_plyFile, _jsonTable)
end
--hook.Add("PlayerDisconnected", "SaveAllPlayerData", SaveAllPlayerData)

function MyJSON.LoadAllPlayerData(_ply)
	local _plyFile = "playerdata/" .. _ply:UniqueID() .. ".txt"
	if not file.Exists(_plyFile, "DATA") then return end

	print ("[MyJSON] Loading player-data of player", _ply)
	for _, _ply in pairs(player.GetAll()) do
		_ply:ChatPrint(string.format("%s is about to spawn!", _ply:Nick()))
	end

	_fileContent = file.Read(_plyFile, "DATA")
	_luaTable = util.JSONToTable(_fileContent)
	print (_luaTable.pos, _luaTable.rot)
	_ply:SetPos(_luaTable.pos)
	_ply:SetEyeAngles(_luaTable.rot)
end

init.lua


AddCSLuaFile "cl_init.lua"
AddCSLuaFile "shared.lua"

include "shared.lua"
--include "mysql.lua"
if not MyJSON then include "modules/myjson.lua"; end
include "plyspawn.lua"
--M = require "myjson"

hook.Add("Initialize", "InitializeJSON", MyJSON.InitializePlayerDir)
hook.Add("PlayerDisconnected", "SaveAllPDataJSON", MyJSON.SaveAllPlayerData)

And as simple as that, it worked. Thank you, mister, guess will later mark this thread as solved, though there’s 1 more question: If module-files have to be in the includes directory, how come gamemodes like darkrp can flawlessly use the module() function in structures outside that directory, if you have an answer to that?

Anyways, thanks again, mate.
Greetz,
-Lili Shi

module doesn’t necessarily have to be in lua/includes, but it does if you want to require it. You can still use include on a module but it defeats the purpose. It’s deprecated in Lua 5.2 because it’s useless when you can simply use a file return, instead.