mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-11-18 10:11:50 +00:00
ebd7fc402b
git-svn-id: https://svn.eduke32.com/eduke32@2329 1a8010ca-5511-0410-912e-c29ae57300e0
616 lines
16 KiB
Text
616 lines
16 KiB
Text
-- definitions of BUILD and game types for the Lunatic Interpreter
|
|
-- INTERNAL!
|
|
|
|
local ffi = require("ffi")
|
|
|
|
---- sector, wall, sprite, ... ----
|
|
ffi.cdef[[
|
|
#pragma pack(push,1)
|
|
typedef struct
|
|
{
|
|
const int16_t wallptr, wallnum;
|
|
int32_t ceilingz, floorz;
|
|
int16_t ceilingstat, floorstat;
|
|
int16_t ceilingpicnum, ceilingheinum;
|
|
int8_t ceilingshade;
|
|
uint8_t ceilingpal, ceilingxpanning, ceilingypanning;
|
|
int16_t floorpicnum, floorheinum;
|
|
int8_t floorshade;
|
|
uint8_t floorpal, floorxpanning, floorypanning;
|
|
uint8_t visibility, filler;
|
|
int16_t lotag, hitag, extra;
|
|
} sectortype;
|
|
|
|
typedef struct
|
|
{
|
|
int32_t x, y;
|
|
const int16_t point2, nextwall, nextsector; int16_t cstat;
|
|
int16_t picnum, overpicnum;
|
|
int8_t shade;
|
|
uint8_t pal, xrepeat, yrepeat, xpanning, ypanning;
|
|
int16_t lotag, hitag, extra;
|
|
} walltype;
|
|
|
|
typedef struct
|
|
{
|
|
int32_t x, y, z;
|
|
int16_t cstat, picnum;
|
|
int8_t shade;
|
|
uint8_t pal, clipdist, filler;
|
|
uint8_t xrepeat, yrepeat;
|
|
int8_t xoffset, yoffset;
|
|
const int16_t sectnum, statnum;
|
|
int16_t ang, owner, xvel, yvel, zvel;
|
|
int16_t lotag, hitag, extra;
|
|
} spritetype;
|
|
|
|
typedef struct {
|
|
const uint32_t mdanimtims;
|
|
const int16_t mdanimcur;
|
|
int16_t angoff, pitch, roll;
|
|
int32_t xoff, yoff, zoff;
|
|
uint8_t flags;
|
|
uint8_t xpanning, ypanning;
|
|
const uint8_t filler;
|
|
float alpha;
|
|
const int32_t _do_not_use1;
|
|
const int32_t _do_not_use2;
|
|
} spriteext_t;
|
|
|
|
typedef struct {
|
|
int32_t x, y, z;
|
|
} vec3_t;
|
|
#pragma pack(pop)
|
|
|
|
enum
|
|
{
|
|
MAXSECTORS = 4096,
|
|
MAXWALLS = 16384,
|
|
MAXSPRITES = 16384,
|
|
|
|
MAXSTATUS = 1024,
|
|
|
|
MAXBUNCHES = 256,
|
|
CEILING = 0,
|
|
FLOOR = 1,
|
|
};
|
|
]]
|
|
|
|
assert(ffi.sizeof('sectortype')==40)
|
|
assert(ffi.sizeof('walltype')==32)
|
|
assert(ffi.sizeof('spritetype')==44)
|
|
|
|
---- engine data and functions ----
|
|
|
|
ffi.cdef[[int32_t engine_main_arrays_are_static;]]
|
|
|
|
-- NOTE TO SELF: This is not C, never EVER write
|
|
-- if (x)
|
|
-- when checking a C variable x for 'thuthiness'
|
|
if (ffi.C.engine_main_arrays_are_static ~= 0) then
|
|
-- print('main arrays are static');
|
|
ffi.cdef[[
|
|
sectortype sector[];
|
|
walltype wall[];
|
|
spritetype sprite[];
|
|
spriteext_t spriteext[];
|
|
]]
|
|
else
|
|
-- print('main arrays are pointers');
|
|
ffi.cdef[[
|
|
sectortype *sector;
|
|
walltype *wall;
|
|
spritetype *sprite;
|
|
spriteext_t *spriteext;
|
|
]]
|
|
end
|
|
|
|
ffi.cdef[[
|
|
const int16_t numsectors, numwalls;
|
|
const int32_t numyaxbunches;
|
|
|
|
const int16_t headspritesect[MAXSECTORS+1], headspritestat[MAXSTATUS+1];
|
|
const int16_t prevspritesect[MAXSPRITES], prevspritestat[MAXSPRITES];
|
|
const int16_t nextspritesect[MAXSPRITES], nextspritestat[MAXSPRITES];
|
|
|
|
const int16_t headsectbunch[2][MAXBUNCHES], nextsectbunch[2][MAXSECTORS];
|
|
|
|
|
|
int16_t yax_getbunch(int16_t i, int16_t cf);
|
|
]]
|
|
|
|
|
|
---- game structs ----
|
|
ffi.cdef[[
|
|
#pragma pack(push,1)
|
|
// ACTOR_T, might still need to make some fields read-only
|
|
typedef struct
|
|
{
|
|
const int32_t t_data[10]; // 40b sometimes used to hold offsets to con code
|
|
int16_t picnum,ang,extra,owner; //8b
|
|
int16_t movflag,tempang,timetosleep; //6b
|
|
|
|
int32_t flags, bposx,bposy,bposz; //16b
|
|
int32_t floorz,ceilingz,lastvx,lastvy; //16b
|
|
int32_t lasttransport; //4b
|
|
|
|
const int16_t lightId, lightcount, lightmaxrange, cgg; //8b
|
|
int16_t actorstayput, dispicnum, shootzvel; // 6b
|
|
|
|
const int8_t _do_not_use[24];
|
|
} actor_t;
|
|
#pragma pack(pop)
|
|
|
|
enum
|
|
{
|
|
MAXMOUSEBUTTONS = 10,
|
|
MAXMOUSEAXES = 2,
|
|
MAXJOYBUTTONS = (32+4),
|
|
MAXJOYAXES = 8,
|
|
NUMGAMEFUNCTIONS = 56,
|
|
};
|
|
|
|
typedef struct {
|
|
vec3_t camera;
|
|
int32_t const_visibility,uw_framerate;
|
|
int32_t camera_time,folfvel,folavel,folx,foly,fola;
|
|
int32_t reccnt,crosshairscale;
|
|
|
|
int32_t runkey_mode,statusbarscale,mouseaiming,weaponswitch,drawweapon; // JBF 20031125
|
|
int32_t democams,color,msgdisptime,statusbarmode;
|
|
int32_t m_noexits,noexits,autovote,automsg,idplayers;
|
|
int32_t team, viewbob, weaponsway, althud, weaponscale, textscale;
|
|
|
|
int32_t entered_name,screen_tilting,shadows,fta_on,executions,auto_run;
|
|
int32_t coords,tickrate,levelstats,m_coop,coop,screen_size,lockout,crosshair;
|
|
int32_t playerai,angleinterpolation,obituaries;
|
|
|
|
int32_t respawn_monsters,respawn_items,respawn_inventory,recstat,monsters_off,brightness;
|
|
int32_t m_respawn_items,m_respawn_monsters,m_respawn_inventory,m_recstat,m_monsters_off,detail;
|
|
int32_t m_ffire,ffire,m_player_skill,m_level_number,m_volume_number,multimode;
|
|
int32_t player_skill,level_number,volume_number,m_marker,marker,mouseflip;
|
|
|
|
int32_t configversion;
|
|
|
|
int16_t cameraang, camerasect, camerahoriz;
|
|
int16_t pause_on,from_bonus;
|
|
int16_t camerasprite,last_camsprite;
|
|
int16_t last_level,secretlevel, bgstretch;
|
|
|
|
struct {
|
|
int32_t UseJoystick;
|
|
int32_t UseMouse;
|
|
int32_t AutoAim;
|
|
int32_t ShowOpponentWeapons;
|
|
int32_t MouseDeadZone,MouseBias;
|
|
int32_t SmoothInput;
|
|
|
|
// JBF 20031211: Store the input settings because
|
|
// (currently) jmact can't regurgitate them
|
|
int32_t MouseFunctions[MAXMOUSEBUTTONS][2];
|
|
int32_t MouseDigitalFunctions[MAXMOUSEAXES][2];
|
|
int32_t MouseAnalogueAxes[MAXMOUSEAXES];
|
|
int32_t MouseAnalogueScale[MAXMOUSEAXES];
|
|
int32_t JoystickFunctions[MAXJOYBUTTONS][2];
|
|
int32_t JoystickDigitalFunctions[MAXJOYAXES][2];
|
|
int32_t JoystickAnalogueAxes[MAXJOYAXES];
|
|
int32_t JoystickAnalogueScale[MAXJOYAXES];
|
|
int32_t JoystickAnalogueDead[MAXJOYAXES];
|
|
int32_t JoystickAnalogueSaturate[MAXJOYAXES];
|
|
uint8_t KeyboardKeys[NUMGAMEFUNCTIONS][2];
|
|
|
|
//
|
|
// Sound variables
|
|
//
|
|
int32_t FXDevice;
|
|
int32_t MusicDevice;
|
|
int32_t FXVolume;
|
|
int32_t MusicVolume;
|
|
int32_t SoundToggle;
|
|
int32_t MusicToggle;
|
|
int32_t VoiceToggle;
|
|
int32_t AmbienceToggle;
|
|
|
|
int32_t NumVoices;
|
|
int32_t NumChannels;
|
|
int32_t NumBits;
|
|
int32_t MixRate;
|
|
|
|
int32_t ReverseStereo;
|
|
|
|
//
|
|
// Screen variables
|
|
//
|
|
|
|
int32_t ScreenMode;
|
|
|
|
int32_t ScreenWidth;
|
|
int32_t ScreenHeight;
|
|
int32_t ScreenBPP;
|
|
|
|
int32_t ForceSetup;
|
|
int32_t NoAutoLoad;
|
|
|
|
int32_t scripthandle;
|
|
int32_t setupread;
|
|
|
|
int32_t CheckForUpdates;
|
|
int32_t LastUpdateCheck;
|
|
int32_t useprecache;
|
|
} config;
|
|
|
|
char overhead_on,last_overhead,showweapons;
|
|
char god,warp_on,cashman,eog,showallmap;
|
|
char show_help,scrollmode,clipping;
|
|
char ridecule[10][40];
|
|
char savegame[10][22];
|
|
char pwlockout[128],rtsname[128];
|
|
char display_bonus_screen;
|
|
char show_level_text;
|
|
} user_defs;
|
|
|
|
// KEEPINSYNC2
|
|
enum GameEvent_t {
|
|
EVENT_INIT,
|
|
EVENT_ENTERLEVEL,
|
|
EVENT_RESETWEAPONS,
|
|
EVENT_RESETINVENTORY,
|
|
EVENT_HOLSTER,
|
|
EVENT_LOOKLEFT,
|
|
EVENT_LOOKRIGHT,
|
|
EVENT_SOARUP,
|
|
EVENT_SOARDOWN,
|
|
EVENT_CROUCH,
|
|
EVENT_JUMP,
|
|
EVENT_RETURNTOCENTER,
|
|
EVENT_LOOKUP,
|
|
EVENT_LOOKDOWN,
|
|
EVENT_AIMUP,
|
|
EVENT_FIRE,
|
|
EVENT_CHANGEWEAPON,
|
|
EVENT_GETSHOTRANGE,
|
|
EVENT_GETAUTOAIMANGLE,
|
|
EVENT_GETLOADTILE,
|
|
EVENT_CHEATGETSTEROIDS,
|
|
EVENT_CHEATGETHEAT,
|
|
EVENT_CHEATGETBOOT,
|
|
EVENT_CHEATGETSHIELD,
|
|
EVENT_CHEATGETSCUBA,
|
|
EVENT_CHEATGETHOLODUKE,
|
|
EVENT_CHEATGETJETPACK,
|
|
EVENT_CHEATGETFIRSTAID,
|
|
EVENT_QUICKKICK,
|
|
EVENT_INVENTORY,
|
|
EVENT_USENIGHTVISION,
|
|
EVENT_USESTEROIDS,
|
|
EVENT_INVENTORYLEFT,
|
|
EVENT_INVENTORYRIGHT,
|
|
EVENT_HOLODUKEON,
|
|
EVENT_HOLODUKEOFF,
|
|
EVENT_USEMEDKIT,
|
|
EVENT_USEJETPACK,
|
|
EVENT_TURNAROUND,
|
|
EVENT_DISPLAYWEAPON,
|
|
EVENT_FIREWEAPON,
|
|
EVENT_SELECTWEAPON,
|
|
EVENT_MOVEFORWARD,
|
|
EVENT_MOVEBACKWARD,
|
|
EVENT_TURNLEFT,
|
|
EVENT_TURNRIGHT,
|
|
EVENT_STRAFELEFT,
|
|
EVENT_STRAFERIGHT,
|
|
EVENT_WEAPKEY1,
|
|
EVENT_WEAPKEY2,
|
|
EVENT_WEAPKEY3,
|
|
EVENT_WEAPKEY4,
|
|
EVENT_WEAPKEY5,
|
|
EVENT_WEAPKEY6,
|
|
EVENT_WEAPKEY7,
|
|
EVENT_WEAPKEY8,
|
|
EVENT_WEAPKEY9,
|
|
EVENT_WEAPKEY10,
|
|
EVENT_DRAWWEAPON,
|
|
EVENT_DISPLAYCROSSHAIR,
|
|
EVENT_DISPLAYREST,
|
|
EVENT_DISPLAYSBAR,
|
|
EVENT_RESETPLAYER,
|
|
EVENT_INCURDAMAGE,
|
|
EVENT_AIMDOWN,
|
|
EVENT_GAME,
|
|
EVENT_PREVIOUSWEAPON,
|
|
EVENT_NEXTWEAPON,
|
|
EVENT_SWIMUP,
|
|
EVENT_SWIMDOWN,
|
|
EVENT_GETMENUTILE,
|
|
EVENT_SPAWN,
|
|
EVENT_LOGO,
|
|
EVENT_EGS,
|
|
EVENT_DOFIRE,
|
|
EVENT_PRESSEDFIRE,
|
|
EVENT_USE,
|
|
EVENT_PROCESSINPUT,
|
|
EVENT_FAKEDOMOVETHINGS,
|
|
EVENT_DISPLAYROOMS,
|
|
EVENT_KILLIT,
|
|
EVENT_LOADACTOR,
|
|
EVENT_DISPLAYBONUSSCREEN,
|
|
EVENT_DISPLAYMENU,
|
|
EVENT_DISPLAYMENUREST,
|
|
EVENT_DISPLAYLOADINGSCREEN,
|
|
EVENT_ANIMATESPRITES,
|
|
EVENT_NEWGAME,
|
|
MAXEVENTS
|
|
};
|
|
]]
|
|
|
|
ffi.cdef[[
|
|
actor_t actor[MAXSPRITES];
|
|
user_defs ud;
|
|
]]
|
|
|
|
---- _G tweaks -- pull in only 'safe' stuff ----
|
|
|
|
local G_ = {} -- our soon-to-be global environment
|
|
local oG = _G
|
|
|
|
G_.coroutine = coroutine
|
|
G_.assert = assert
|
|
G_.tostring = tostring
|
|
G_.tonumber = tonumber
|
|
--rawget
|
|
G_.xpcall = xpcall
|
|
G_.ipairs = ipairs
|
|
G_.print = print
|
|
G_.pcall = pcall
|
|
--gcinfo --DEPRECATED
|
|
--module
|
|
--setfenv
|
|
--require
|
|
--rawset
|
|
--jit
|
|
G_.bit = bit
|
|
--package
|
|
G_.error = error
|
|
--debug
|
|
--loadfile
|
|
--rawequal
|
|
--load
|
|
G_.unpack = unpack
|
|
G_.pairs = pairs
|
|
G_.table = table
|
|
G_._VERSION = _VERSION
|
|
--newproxy --NOT STD?
|
|
--collectgarbage
|
|
--dofile
|
|
G_.next = next
|
|
G_.math = math
|
|
--loadstring
|
|
--_G
|
|
G_.select = select
|
|
G_.string = string
|
|
G_.type = type
|
|
--getmetatable
|
|
--getfenv
|
|
--setmetatable
|
|
|
|
G_._G = G_
|
|
|
|
-- REMOVE this for release
|
|
DBG_ = {}
|
|
DBG_.loadstring = oG.loadstring
|
|
|
|
---- Set up restricted access to ffi.C from lunatic. ----
|
|
local ffiC = ffi.C
|
|
|
|
-- error(..., 2) is to blame the caller and get its line numbers
|
|
|
|
local det = {} -- dummy empty table
|
|
local tmpmt = {
|
|
__index = function() error('dummy variable: read access forbidden', 2) end,
|
|
__newindex = function() error('dummy variable: write access forbidden', 2) end,
|
|
__metatable = true -- forbid setting the metatable
|
|
}
|
|
oG.setmetatable(det, tmpmt)
|
|
|
|
-- GLOBAL gv: provides access to C global *scalars*
|
|
gv = {
|
|
-- all non-scalars need to be explicitly listed
|
|
-- and access to them is redirected to the dummy
|
|
-- empty table... this is somewhat ugly
|
|
sector = det,
|
|
wall = det,
|
|
sprite = det,
|
|
spriteext = det,
|
|
|
|
headspritesect = det, headspritestat = det,
|
|
prevspritesect = det, prevspritestat = det,
|
|
nextspritesect = det, nextspritestat = det,
|
|
|
|
actor = det,
|
|
ud = det,
|
|
}
|
|
local tmpmt = {
|
|
__index = ffiC,
|
|
__newindex = function() error("cannot create new or write into existing fields of 'gv'", 2) end,
|
|
__metatable = true,
|
|
}
|
|
oG.setmetatable(gv, tmpmt)
|
|
|
|
---- indirect C array access ----
|
|
sector = {}
|
|
local tmpmt = {
|
|
__index = function(tab, key)
|
|
if (key >= 0 and key < ffiC.numsectors) then return ffiC.sector[key] end
|
|
error('out-of-bounds sector[] read access', 2)
|
|
end,
|
|
|
|
__newindex = function(tab, key, val) error('cannot write directly to sector[] struct', 2) end,
|
|
__metatable = true,
|
|
}
|
|
oG.setmetatable(sector, tmpmt)
|
|
|
|
wall = {}
|
|
local tmpmt = {
|
|
__index = function(tab, key)
|
|
if (key >= 0 and key < ffiC.numwalls) then return ffiC.wall[key] end
|
|
error('out-of-bounds wall[] read access', 2)
|
|
end,
|
|
|
|
__newindex = function(tab, key, val) error('cannot write directly to wall[] struct', 2) end,
|
|
__metatable = true,
|
|
}
|
|
oG.setmetatable(wall, tmpmt)
|
|
|
|
-- create a safe indirection for a ffi.C array
|
|
local function creategtab(ctab, maxidx, name)
|
|
local tab = {}
|
|
local tmpmt = {
|
|
__index = function(tab, key)
|
|
if (key>=0 and key < maxidx) then
|
|
return ctab[key]
|
|
end
|
|
error('out-of-bounds '..name..' read access', 2)
|
|
end,
|
|
__newindex = function(tab, key, val)
|
|
error('cannot write directly to '..name, 2)
|
|
end,
|
|
__metatable = true,
|
|
}
|
|
oG.setmetatable(tab, tmpmt)
|
|
return tab
|
|
end
|
|
|
|
sprite = creategtab(ffiC.sprite, ffiC.MAXSPRITES, 'sprite[] struct')
|
|
spriteext = creategtab(ffiC.spriteext, ffiC.MAXSPRITES, 'spriteext[] struct')
|
|
headspritesect = creategtab(ffiC.headspritesect, ffiC.MAXSECTORS, 'headspritesect[]')
|
|
headspritestat = creategtab(ffiC.headspritestat, ffiC.MAXSTATUS, 'headspritestat[]')
|
|
nextspritesect = creategtab(ffiC.nextspritesect, ffiC.MAXSPRITES, 'nextspritesect[]')
|
|
nextspritestat = creategtab(ffiC.nextspritestat, ffiC.MAXSPRITES, 'nextspritestat[]')
|
|
prevspritesect = creategtab(ffiC.prevspritesect, ffiC.MAXSPRITES, 'prevspritesect[]')
|
|
prevspritestat = creategtab(ffiC.prevspritestat, ffiC.MAXSPRITES, 'prevspritestat[]')
|
|
|
|
actor = creategtab(ffiC.actor, ffiC.MAXSPRITES, 'actor[]')
|
|
|
|
function TEMP_getvollev() -- REMOVE
|
|
return ffiC.ud.volume_number+1, ffiC.ud.level_number+1
|
|
end
|
|
|
|
---- per-sector/per-statnum sprite iterators ----
|
|
local function iter_spritesofsect(sect, i)
|
|
if (i < 0) then
|
|
i = ffiC.headspritesect[sect]
|
|
else
|
|
i = ffiC.nextspritesect[i]
|
|
end
|
|
|
|
if (i >= 0) then return i end
|
|
end
|
|
|
|
function spritesofsect(sect)
|
|
if (sect < 0 or sect >= ffiC.numsectors) then
|
|
error("passed invalid sectnum to spritesofsect iterator", 2)
|
|
end
|
|
|
|
return iter_spritesofsect, sect, -1
|
|
end
|
|
|
|
local function iter_spritesofstat(stat, i)
|
|
if (i < 0) then
|
|
i = ffiC.headspritestat[stat]
|
|
else
|
|
i = ffiC.nextspritestat[i]
|
|
end
|
|
|
|
if (i >= 0) then return i end
|
|
end
|
|
|
|
function spritesofstat(stat)
|
|
if (stat < 0 or stat >= ffiC.MAXSTATUS) then
|
|
error("passed invalid statnum to spritesofstat iterator", 2)
|
|
end
|
|
|
|
return iter_spritesofstat, stat, -1
|
|
end
|
|
|
|
-- TROR iterators
|
|
local function iter_sectorsofbunch(cf, i)
|
|
if (i < 0) then
|
|
i = ffiC.headsectbunch[cf][-i-1];
|
|
else
|
|
i = ffiC.nextsectbunch[cf][i];
|
|
end
|
|
|
|
if (i >= 0) then return i end
|
|
end
|
|
|
|
function sectorsofbunch(bunchnum, cf)
|
|
if (bunchnum < 0 or bunchnum >= ffiC.numyaxbunches) then
|
|
error("passed invalid bunchnum to sectorsofbunch iterator", 2)
|
|
end
|
|
if (cf ~= 0 and cf ~= 1) then
|
|
error("passed invalid 'cf' to sectorsofbunch iterator, must be 0 or 1", 2)
|
|
end
|
|
|
|
return iter_sectorsofbunch, cf, -bunchnum-1
|
|
end
|
|
|
|
function getbunch(sectnum, cf)
|
|
if (sectnum < 0 or sectnum >= ffiC.numsectors) then
|
|
error('out-of-bounds sector[] read access', 2)
|
|
end
|
|
if (cf ~= 0 and cf ~= 1) then
|
|
error("passed invalid 'cf' to getbunch, must be 0 or 1", 2)
|
|
end
|
|
|
|
return yax_getbunch(sectnum, cf)
|
|
end
|
|
|
|
|
|
-- 'simple' code for prohibiting initial assignments to create new variables,
|
|
-- from 14.2 of PiL
|
|
function gamevar(name, initval) -- aka 'declare'
|
|
rawset(G_, name, initval or false)
|
|
end
|
|
|
|
|
|
-- add new variables/functions living in the global environment
|
|
G_.DBG_ = DBG_ -- REMOVE this for release
|
|
G_.gv = gv
|
|
G_.sector = sector
|
|
G_.wall = wall
|
|
G_.sprite = sprite
|
|
G_.spriteext = spriteext
|
|
G_.headspritesect = headspritesect
|
|
G_.headspritestat = headspritestat
|
|
G_.nextspritesect = nextspritesect
|
|
G_.nextspritestat = nextspritestat
|
|
G_.prevspritesect = prevspritesect
|
|
G_.prevspritestat = prevspritestat
|
|
|
|
G_.actor = actor
|
|
|
|
-- functions
|
|
G_.spritesofsect = spritesofsect
|
|
G_.spritesofstat = spritesofstat
|
|
G_.sectorsofbunch = sectorsofbunch
|
|
G_.getbunch = getbunch
|
|
|
|
G_.TEMP_getvollev = TEMP_getvollev -- REMOVE
|
|
G_.gamevar = gamevar
|
|
|
|
G_.setevent = setevent -- included in lunatic.c
|
|
|
|
|
|
-- PiL 14.2 continued
|
|
setmetatable(
|
|
G_, {
|
|
__newindex = function (_, n)
|
|
error("attempt to write to undeclared variable "..n, 2)
|
|
end,
|
|
__index = function (_, n)
|
|
error("attempt to read undeclared variable "..n, 2)
|
|
end,
|
|
})
|
|
|
|
-- change the environment of the running Lua thread to the table G_
|
|
setfenv(0, G_)
|