mirror of
https://github.com/ZDoom/Raze.git
synced 2024-11-16 17:32:13 +00:00
8f8bb68ace
This might now be even more confusing for users reading both the source and CON code (where the access is necessarily still via '.clipping'), but at least reading the source now makes sense :P git-svn-id: https://svn.eduke32.com/eduke32@2454 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,noclip;
|
|
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_)
|