mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 10:40:46 +00:00
Lunatic: begin gamevar system. Not much there yet.
In Lunatic, gamevars (variables that are saved with savegames) are per-module. git-svn-id: https://svn.eduke32.com/eduke32@3642 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
parent
49290a090c
commit
023ff8f190
2 changed files with 82 additions and 24 deletions
|
@ -12,6 +12,7 @@ local math = math
|
|||
|
||||
local assert = assert
|
||||
local error = error
|
||||
local getfenv = getfenv
|
||||
local getmetatable = getmetatable
|
||||
local ipairs = ipairs
|
||||
local loadstring = loadstring
|
||||
|
@ -62,7 +63,7 @@ local setmtonce = defs_c.setmtonce
|
|||
|
||||
-- Must be after loading "defs_common" which redefines "print" to use
|
||||
-- OSD_Printf()
|
||||
local print = print
|
||||
local print, printf = print, defs_c.printf
|
||||
|
||||
|
||||
---=== EDuke32 game definitions ===---
|
||||
|
@ -1250,22 +1251,26 @@ do
|
|||
end
|
||||
end
|
||||
|
||||
local function check_valid_modname(modname, errlev)
|
||||
if (type(modname) ~= "string") then
|
||||
error("module name must be a string", errlev+1)
|
||||
|
||||
local package_loaded = {} -- false/true/table
|
||||
local modname_stack = {} -- [<depth>]=string
|
||||
local module_gamevars = {} -- [<modname>] = { <gvname1>, <gvname2>, ... }
|
||||
|
||||
local function getcurmodname(thisfuncname)
|
||||
if (#modname_stack == 0) then
|
||||
error("'"..thisfuncname.."' must be called at the top level of a require'd file", 3)
|
||||
-- ... as opposed to "at runtime".
|
||||
end
|
||||
|
||||
-- TODO: restrict valid names?
|
||||
return modname_stack[#modname_stack]
|
||||
end
|
||||
|
||||
|
||||
local function errorf(level, fmt, ...)
|
||||
local errmsg = string.format(fmt, ...)
|
||||
error(errmsg, level+1)
|
||||
end
|
||||
|
||||
|
||||
local package_loaded = {}
|
||||
local modname_stack = {}
|
||||
local ERRLEV = 5
|
||||
|
||||
local function readintostr(fn)
|
||||
|
@ -1299,6 +1304,15 @@ local function readintostr(fn)
|
|||
return ffi.string(str, sz)
|
||||
end
|
||||
|
||||
|
||||
local required_module_mt = {
|
||||
__newindex = function()
|
||||
-- TODO: allow gamevars to be nil?
|
||||
error("modifying module table forbidden", 2)
|
||||
end,
|
||||
__metatable = true,
|
||||
}
|
||||
|
||||
-- The "require" function accessible to Lunatic code.
|
||||
-- Base modules in allowed_modules are wrapped so that they cannot be
|
||||
-- modified, user modules are searched in the EDuke32 search
|
||||
|
@ -1306,22 +1320,49 @@ end
|
|||
-- * never messes with the global environment, it only returns the module.
|
||||
-- * allows passing varargs beyond the name to the module.
|
||||
local function our_require(modname, ...)
|
||||
check_valid_modname(modname, 2)
|
||||
-- Check module name is valid first.
|
||||
-- TODO: restrict valid names?
|
||||
if (type(modname) ~= "string") then
|
||||
error("module name must be a string", 2)
|
||||
end
|
||||
|
||||
-- see whether it's a base module name first
|
||||
-- Handle the section between module() and require("end_gamevars").
|
||||
if (modname == "end_gamevars") then
|
||||
local thismodname = getcurmodname("require")
|
||||
|
||||
if (module_gamevars[thismodname] ~= nil) then
|
||||
error("\"require 'end_gamevars'\" must be called at most once per require'd file", 2)
|
||||
end
|
||||
|
||||
local gvnames = {}
|
||||
|
||||
for name in pairs(getfenv(2)) do
|
||||
gvnames[#gvnames] = name
|
||||
if (ffiC._DEBUG_LUNATIC ~= 0) then
|
||||
printf("MODULE %s GAMEVAR %s", thismodname, name)
|
||||
end
|
||||
end
|
||||
|
||||
module_gamevars[thismodname] = gvnames
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- See whether it's a base module name.
|
||||
if (allowed_modules[modname] ~= nil) then
|
||||
return allowed_modules[modname]
|
||||
end
|
||||
|
||||
--- search user modules
|
||||
--- Search user modules...
|
||||
|
||||
local omod = package_loaded[modname]
|
||||
if (omod ~= nil) then
|
||||
if (omod==true) then
|
||||
if (omod==false) then
|
||||
error("Loop while loading modules", ERRLEV-1)
|
||||
end
|
||||
|
||||
-- already loaded
|
||||
assert(omod==true or type(omod)=="table")
|
||||
return omod
|
||||
end
|
||||
|
||||
|
@ -1336,7 +1377,7 @@ local function our_require(modname, ...)
|
|||
errorf(ERRLEV-1, "Couldn't load \"%s\": %s", modname, errmsg)
|
||||
end
|
||||
|
||||
package_loaded[modname] = true
|
||||
package_loaded[modname] = false -- 'not yet loaded'
|
||||
table.insert(modname_stack, modname)
|
||||
|
||||
-- Run the module code!
|
||||
|
@ -1348,14 +1389,9 @@ local function our_require(modname, ...)
|
|||
|
||||
if (type(modtab) == "table") then
|
||||
-- Protect module table if there is one...
|
||||
local mt = {
|
||||
__index = modtab,
|
||||
__newindex = function(tab,idx,val)
|
||||
error("modifying module table forbidden", 2)
|
||||
end,
|
||||
}
|
||||
|
||||
setmetatable(modtab, mt)
|
||||
setmetatable(modtab, required_module_mt)
|
||||
else
|
||||
package_loaded[modname] = true
|
||||
end
|
||||
|
||||
return modtab
|
||||
|
@ -1370,12 +1406,18 @@ local module_mt = {
|
|||
|
||||
-- Our 'module' replacement doesn't get the module name from the function args
|
||||
-- since a malicious user could remove other loaded modules this way.
|
||||
-- Also, our 'module' has no varargs ("option functions" in Lua).
|
||||
-- Also, our 'module' takes no varargs ("option functions" in Lua).
|
||||
-- TODO: make transactional?
|
||||
local function our_module()
|
||||
local modname = modname_stack[#modname_stack]
|
||||
if (type(modname) ~= "string") then
|
||||
if (#modname_stack == 0) then
|
||||
error("'module' must be called at the top level of a require'd file", 2)
|
||||
-- ... as opposed to "at runtime".
|
||||
end
|
||||
|
||||
local modname = getcurmodname("module")
|
||||
|
||||
if (type(package_loaded[modname])=="table") then
|
||||
error("'module' must be called at most once per require'd file", 2)
|
||||
end
|
||||
|
||||
local M = setmetatable({}, module_mt)
|
||||
|
@ -1411,6 +1453,7 @@ G_.ipairs = ipairs
|
|||
G_.pairs = pairs
|
||||
G_.pcall = pcall
|
||||
G_.print = print
|
||||
G_.printf = printf
|
||||
G_.module = our_module
|
||||
G_.next = next
|
||||
G_.require = our_require
|
||||
|
@ -1881,6 +1924,8 @@ setmetatable(
|
|||
__index = function (_, n)
|
||||
error("attempt to read undeclared variable '"..n.."'", 2)
|
||||
end,
|
||||
|
||||
__metatable = true,
|
||||
})
|
||||
|
||||
-- Change the environment of the running Lua thread so that everything
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
local require = require
|
||||
local con = require("con")
|
||||
local bit = require("bit")
|
||||
local math = require("math")
|
||||
|
@ -47,3 +48,15 @@ local function rotatesprite_test()
|
|||
end
|
||||
|
||||
gameevent(gv.EVENT_DISPLAYREST, rotatesprite_test)
|
||||
|
||||
|
||||
module(...) --====================
|
||||
|
||||
local not_a_gamevar = "nyet"
|
||||
|
||||
test_gamevar = 123
|
||||
test_gamevar2 = 'qwe'
|
||||
|
||||
require "end_gamevars" --==========
|
||||
|
||||
not_a_gamevar2 = "no"
|
||||
|
|
Loading…
Reference in a new issue