diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c61e181a5..ef2304410 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -159,6 +159,9 @@ stages: Debian testing GCC: stage: build + + when: manual + image: debian:testing-slim allow_failure: true @@ -198,6 +201,8 @@ Debian testing GCC: Windows x86: stage: build + when: on_success + artifacts: paths: - "bin/" @@ -228,6 +233,8 @@ Windows x86: Debian stable:amd64: stage: build + when: on_success + artifacts: paths: - "bin/" @@ -270,6 +277,8 @@ Debian stable:amd64: Debian stable:i386: stage: build + when: manual + artifacts: paths: - "bin/" @@ -311,6 +320,8 @@ Debian stable:i386: Debian stable:arm64: stage: build + when: manual + artifacts: paths: - "bin/" @@ -353,6 +364,8 @@ Debian stable:arm64: Windows x64: stage: build + when: manual + artifacts: paths: - "bin/" @@ -383,6 +396,8 @@ Windows x64: Debian stable Clang: stage: build + when: manual + allow_failure: true artifacts: @@ -422,6 +437,8 @@ Debian stable Clang: Debian stable musl: stage: build + when: manual + allow_failure: true artifacts: @@ -459,6 +476,8 @@ Debian stable musl: Debian testing Clang: extends: Debian stable Clang + when: manual + image: debian:testing-slim artifacts: @@ -473,6 +492,8 @@ Debian testing Clang: Debian testing musl: extends: Debian stable musl + when: manual + image: debian:testing-slim artifacts: diff --git a/appveyor.yml b/appveyor.yml index 63d801b73..d0d94b982 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 2.2.13.{branch}-{build} +version: 2.2.14.{branch}-{build} os: MinGW environment: diff --git a/src/d_main.c b/src/d_main.c index 80907a013..274e4ceb3 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -1614,6 +1614,9 @@ void D_SRB2Main(void) if (D_CheckNetGame()) autostart = true; + if (!dedicated) + pickedchar = R_SkinAvailable(cv_defaultskin.string); + // check for a driver that wants intermission stats // start the apropriate game based on parms if (M_CheckParm("-metal")) @@ -1627,8 +1630,6 @@ void D_SRB2Main(void) autostart = true; } - pickedchar = R_SkinAvailable(cv_defaultskin.string); - // user settings come before "+" parameters. if (dedicated) COM_ImmedExecute(va("exec \"%s"PATHSEP"adedserv.cfg\"\n", srb2home)); diff --git a/src/d_player.h b/src/d_player.h index 7ad5b9f81..ca700d4e1 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -607,6 +607,7 @@ typedef struct player_s tic_t jointime; // Timer when player joins game to change skin/color tic_t quittime; // Time elapsed since user disconnected, zero if connected + tic_t lastinputtime; // the last tic the player has made any input #ifdef HWRENDER fixed_t fovadd; // adjust FOV for hw rendering #endif diff --git a/src/deh_lua.c b/src/deh_lua.c index 0b789547b..e596e166f 100644 --- a/src/deh_lua.c +++ b/src/deh_lua.c @@ -297,7 +297,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) CacheAndPushConstant(L, word, (lua_Integer)PF_FULLSTASIS); return 1; } - else if (fastcmp(p, "USEDOWN")) // Remove case when 2.3 nears release... + // TODO: 2.3: Delete this alias + else if (fastcmp(p, "USEDOWN")) { CacheAndPushConstant(L, word, (lua_Integer)PF_SPINDOWN); return 1; @@ -583,7 +584,8 @@ static int ScanConstants(lua_State *L, boolean mathlib, const char *word) return 0; } - if (fastcmp(word, "BT_USE")) // Remove case when 2.3 nears release... + // TODO: 2.3: Delete this alias + if (fastcmp(word, "BT_USE")) { CacheAndPushConstant(L, word, (lua_Integer)BT_SPIN); return 1; @@ -771,8 +773,7 @@ int LUA_SOCLib(lua_State *L) lua_register(L,"getActionName",lib_getActionName); luaL_newmetatable(L, META_ACTION); - lua_pushcfunction(L, action_call); - lua_setfield(L, -2, "__call"); + LUA_SetCFunctionField(L, "__call", action_call); lua_pop(L, 1); return 0; diff --git a/src/deh_soc.c b/src/deh_soc.c index 59eb0a9bd..6162034de 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -911,6 +911,7 @@ static void readspriteframe(MYFILE *f, spriteinfo_t *sprinfo, UINT8 frame) sprinfo->pivot[frame].x = value; else if (fastcmp(word, "YPIVOT")) sprinfo->pivot[frame].y = value; + // TODO: 2.3: Delete else if (fastcmp(word, "ROTAXIS")) deh_warning("SpriteInfo: ROTAXIS is deprecated and will be removed."); else @@ -1617,6 +1618,7 @@ void readlevelheader(MYFILE *f, INT32 num) sizeof(mapheaderinfo[num-1]->musname), va("Level header %d: music", num)); } } + // TODO: 2.3: Delete else if (fastcmp(word, "MUSICSLOT")) deh_warning("Level header %d: MusicSlot parameter is deprecated and will be removed.\nUse \"Music\" instead.", num); else if (fastcmp(word, "MUSICTRACK")) diff --git a/src/g_demo.c b/src/g_demo.c index cb168dfd9..7026c3391 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -1492,8 +1492,9 @@ void G_BeginRecording(void) demo_p += 16; // Skin - for (i = 0; i < 16 && cv_skin.string[i]; i++) - name[i] = cv_skin.string[i]; + const char *skinname = skins[players[0].skin].name; + for (i = 0; i < 16 && skinname[i]; i++) + name[i] = skinname[i]; for (; i < 16; i++) name[i] = '\0'; M_Memcpy(demo_p,name,16); diff --git a/src/g_game.c b/src/g_game.c index fae311694..438428b90 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -51,6 +51,7 @@ #include "r_fps.h" // frame interpolation/uncapped #include "lua_hud.h" +#include "lua_libs.h" gameaction_t gameaction; gamestate_t gamestate = GS_NULL; @@ -1170,7 +1171,7 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer) // why build a ticcmd if we're paused? // Or, for that matter, if we're being reborn. // ...OR if we're blindfolded. No looking into the floor. - if (paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG) + if (ignoregameinputs || paused || P_AutoPause() || (gamestate == GS_LEVEL && (player->playerstate == PST_REBORN || ((gametyperules & GTR_TAG) && (leveltime < hidetime * TICRATE) && (player->pflags & PF_TAGIT))))) {//@TODO splitscreen player cmd->angleturn = ticcmd_oldangleturn[forplayer]; @@ -4346,7 +4347,7 @@ void G_LoadGameSettings(void) } #define GAMEDATA_ID 0x86E4A27C // Change every major version, as usual -#define COMPAT_GAMEDATA_ID 0xFCAFE211 // Can be removed entirely for 2.3 +#define COMPAT_GAMEDATA_ID 0xFCAFE211 // TODO: 2.3: Delete // G_LoadGameData // Loads the main data file, which stores information such as emblems found, etc. diff --git a/src/g_input.c b/src/g_input.c index fa30c1984..8b5056331 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -18,6 +18,8 @@ #include "hu_stuff.h" // need HUFONT start & end #include "netcode/d_net.h" #include "console.h" +#include "lua_script.h" +#include "lua_libs.h" #define MAXMOUSESENSITIVITY 100 // sensitivity steps @@ -116,7 +118,10 @@ void G_MapEventsToControls(event_t *ev) { case ev_keydown: if (ev->key < NUMINPUTS) - gamekeydown[ev->key] = 1; + { + if (!ignoregameinputs) + gamekeydown[ev->key] = 1; + } #ifdef PARANOIA else { @@ -144,7 +149,7 @@ void G_MapEventsToControls(event_t *ev) case ev_joystick: // buttons are virtual keys i = ev->key; - if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) + if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on || ignoregameinputs) break; if (ev->x != INT32_MAX) joyxmove[i] = ev->x; if (ev->y != INT32_MAX) joyymove[i] = ev->y; @@ -152,7 +157,7 @@ void G_MapEventsToControls(event_t *ev) case ev_joystick2: // buttons are virtual keys i = ev->key; - if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on) + if (i >= JOYAXISSET || menuactive || CON_Ready() || chat_on || ignoregameinputs) break; if (ev->x != INT32_MAX) joy2xmove[i] = ev->x; if (ev->y != INT32_MAX) joy2ymove[i] = ev->y; @@ -997,7 +1002,7 @@ static void setcontrol(INT32 (*gc)[2]) INT32 player = ((void*)gc == (void*)&gamecontrolbis ? 1 : 0); boolean nestedoverride = false; - // Update me for 2.3 + // TODO: 2.3: Delete the "use" alias namectrl = (stricmp(COM_Argv(1), "use")) ? COM_Argv(1) : "spin"; for (numctrl = 0; numctrl < NUM_GAMECONTROLS && stricmp(namectrl, gamecontrolname[numctrl]); diff --git a/src/lua_baselib.c b/src/lua_baselib.c index 45bb162c4..16f238abe 100644 --- a/src/lua_baselib.c +++ b/src/lua_baselib.c @@ -1031,6 +1031,20 @@ static int lib_pRailThinker(lua_State *L) return 1; } +static int lib_pCheckSkyHit(lua_State *L) +{ + mobj_t *mobj = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + line_t *line = *((line_t **)luaL_checkudata(L, 2, META_LINE)); + //HUDSAFE + INLEVEL + if (!mobj) + return LUA_ErrInvalid(L, "mobj_t"); + if (!line) + return LUA_ErrInvalid(L, "line_t"); + lua_pushboolean(L, P_CheckSkyHit(mobj, line)); + return 1; +} + static int lib_pXYMovement(lua_State *L) { mobj_t *actor = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -1425,6 +1439,18 @@ static int lib_pGivePlayerRings(lua_State *L) return 0; } +static int lib_pGivePlayerSpheres(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + INT32 num_spheres = (INT32)luaL_checkinteger(L, 2); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_GivePlayerSpheres(player, num_spheres); + return 0; +} + static int lib_pGivePlayerLives(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1680,6 +1706,17 @@ static int lib_pDoJump(lua_State *L) return 0; } +static int lib_pDoSpinDashDust(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + P_DoSpinDashDust(player); + return 0; +} + static int lib_pSpawnThokMobj(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1730,6 +1767,48 @@ static int lib_pSwitchShield(lua_State *L) return 0; } +static int lib_pDoTailsOverlay(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *tails = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!tails) + return LUA_ErrInvalid(L, "mobj_t"); + P_DoTailsOverlay(player, tails); + return 0; +} + +static int lib_pDoMetalJetFume(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *fume = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!fume) + return LUA_ErrInvalid(L, "mobj_t"); + P_DoMetalJetFume(player, fume); + return 0; +} + +static int lib_pDoFollowMobj(lua_State *L) +{ + player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); + mobj_t *followmobj = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + NOHUD + INLEVEL + if (!player) + return LUA_ErrInvalid(L, "player_t"); + if (!followmobj) + return LUA_ErrInvalid(L, "mobj_t"); + P_DoFollowMobj(player, followmobj); + return 0; +} + static int lib_pPlayerCanEnterSpinGaps(lua_State *L) { player_t *player = *((player_t **)luaL_checkudata(L, 1, META_PLAYER)); @@ -1801,6 +1880,7 @@ static int lib_pMove(lua_State *L) return 2; } +// TODO: 2.3: Delete static int lib_pTeleportMove(lua_State *L) { mobj_t *ptmthing = tmthing; @@ -2211,6 +2291,21 @@ static int lib_pDoMatchSuper(lua_State *L) return 0; } +static int lib_pTouchSpecialThing(lua_State *L) +{ + mobj_t *special = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); + mobj_t *toucher = *((mobj_t **)luaL_checkudata(L, 2, META_MOBJ)); + boolean heightcheck = lua_optboolean(L, 3); + NOHUD + INLEVEL + if (!special || !toucher) + return LUA_ErrInvalid(L, "mobj_t"); + if (!toucher->player) + return luaL_error(L, "P_TouchSpecialThing requires a valid toucher.player."); + P_TouchSpecialThing(special, toucher, heightcheck); + return 0; +} + // P_SPEC //////////// @@ -2313,6 +2408,7 @@ static int lib_pMobjTouchingSectorSpecial(lua_State *L) return 1; } +// TODO: 2.3: Delete static int lib_pThingOnSpecial3DFloor(lua_State *L) { mobj_t *mo = *((mobj_t **)luaL_checkudata(L, 1, META_MOBJ)); @@ -3617,6 +3713,7 @@ static int lib_gAddPlayer(lua_State *L) newplayer->jointime = 0; newplayer->quittime = 0; + newplayer->lastinputtime = 0; // Read the skin argument (defaults to Sonic) if (!lua_isnoneornil(L, 1)) @@ -4126,6 +4223,7 @@ static luaL_Reg lib[] = { {"P_CreateFloorSpriteSlope",lib_pCreateFloorSpriteSlope}, {"P_RemoveFloorSpriteSlope",lib_pRemoveFloorSpriteSlope}, {"P_RailThinker",lib_pRailThinker}, + {"P_CheckSkyHit",lib_pCheckSkyHit}, {"P_XYMovement",lib_pXYMovement}, {"P_RingXYMovement",lib_pRingXYMovement}, {"P_SceneryXYMovement",lib_pSceneryXYMovement}, @@ -4158,6 +4256,7 @@ static luaL_Reg lib[] = { {"P_SpawnShieldOrb",lib_pSpawnShieldOrb}, {"P_SpawnGhostMobj",lib_pSpawnGhostMobj}, {"P_GivePlayerRings",lib_pGivePlayerRings}, + {"P_GivePlayerSpheres",lib_pGivePlayerSpheres}, {"P_GivePlayerLives",lib_pGivePlayerLives}, {"P_GiveCoopLives",lib_pGiveCoopLives}, {"P_ResetScore",lib_pResetScore}, @@ -4179,10 +4278,14 @@ static luaL_Reg lib[] = { {"P_HomingAttack",lib_pHomingAttack}, {"P_SuperReady",lib_pSuperReady}, {"P_DoJump",lib_pDoJump}, + {"P_DoSpinDashDust",lib_pDoSpinDashDust}, {"P_SpawnThokMobj",lib_pSpawnThokMobj}, {"P_SpawnSpinMobj",lib_pSpawnSpinMobj}, {"P_Telekinesis",lib_pTelekinesis}, {"P_SwitchShield",lib_pSwitchShield}, + {"P_DoTailsOverlay",lib_pDoTailsOverlay}, + {"P_DoMetalJetFume",lib_pDoMetalJetFume}, + {"P_DoFollowMobj",lib_pDoFollowMobj}, {"P_PlayerCanEnterSpinGaps",lib_pPlayerCanEnterSpinGaps}, {"P_PlayerShouldUseSpinHeight",lib_pPlayerShouldUseSpinHeight}, @@ -4201,6 +4304,7 @@ static luaL_Reg lib[] = { {"P_FloorzAtPos",lib_pFloorzAtPos}, {"P_CeilingzAtPos",lib_pCeilingzAtPos}, {"P_DoSpring",lib_pDoSpring}, + {"P_TouchSpecialThing",lib_pTouchSpecialThing}, {"P_TryCameraMove", lib_pTryCameraMove}, {"P_TeleportCameraMove", lib_pTeleportCameraMove}, @@ -4350,8 +4454,7 @@ int LUA_BaseLib(lua_State *L) // Set metatable for string lua_pushliteral(L, ""); // dummy string lua_getmetatable(L, -1); // get string metatable - lua_pushcfunction(L,lib_concat); // push concatination function - lua_setfield(L,-2,"__add"); // ... store it as mathematical addition + LUA_SetCFunctionField(L, "__add", lib_concat); lua_pop(L, 2); // pop metatable and dummy string lua_newtable(L); diff --git a/src/lua_consolelib.c b/src/lua_consolelib.c index 0ab8ad9c3..1fabe2c00 100644 --- a/src/lua_consolelib.c +++ b/src/lua_consolelib.c @@ -194,6 +194,7 @@ static int lib_comAddCommand(lua_State *L) if (lua_gettop(L) >= 3) { // For the third argument, only take a boolean or a number. lua_settop(L, 3); + // TODO: 2.3: Remove boolean option if (lua_type(L, 3) == LUA_TBOOLEAN) { CONS_Alert(CONS_WARNING, @@ -374,6 +375,9 @@ static int lib_cvRegisterVar(lua_State *L) size_t count = 0; CV_PossibleValue_t *cvpv; + const char * const MINMAX[2] = {"MIN", "MAX"}; + int minmax_unset = 3; + lua_pushnil(L); while (lua_next(L, 4)) { @@ -392,16 +396,45 @@ static int lib_cvRegisterVar(lua_State *L) lua_pushnil(L); while (lua_next(L, 4)) { + INT32 n; + const char * strval; + // stack: [...] PossibleValue table, index, value // 4 5 6 if (lua_type(L, 5) != LUA_TSTRING || lua_type(L, 6) != LUA_TNUMBER) FIELDERROR("PossibleValue", "custom PossibleValue table requires a format of string=integer, i.e. {MIN=0, MAX=9999}"); - cvpv[i].strvalue = Z_StrDup(lua_tostring(L, 5)); - cvpv[i].value = (INT32)lua_tonumber(L, 6); - i++; + + strval = lua_tostring(L, 5); + + if ( + stricmp(strval, MINMAX[n=0]) == 0 || + stricmp(strval, MINMAX[n=1]) == 0 + ){ + /* need to shift forward */ + if (minmax_unset == 3) + { + memmove(&cvpv[2], &cvpv[0], + i * sizeof *cvpv); + i += 2; + } + cvpv[n].strvalue = MINMAX[n]; + minmax_unset &= ~(1 << n); + } + else + { + n = i++; + cvpv[n].strvalue = Z_StrDup(strval); + } + + cvpv[n].value = (INT32)lua_tonumber(L, 6); + lua_pop(L, 1); } + + if (minmax_unset && minmax_unset != 3) + FIELDERROR("PossibleValue", "custom PossibleValue table requires requires both MIN and MAX keys if one is present"); + cvpv[i].value = 0; cvpv[i].strvalue = NULL; cvar->PossibleValue = cvpv; @@ -626,10 +659,7 @@ static int cvar_get(lua_State *L) int LUA_ConsoleLib(lua_State *L) { // Metatable for consvar_t - luaL_newmetatable(L, META_CVAR); - lua_pushcfunction(L, cvar_get); - lua_setfield(L, -2, "__index"); - lua_pop(L,1); + LUA_RegisterUserdataMetatable(L, META_CVAR, cvar_get, NULL, NULL); cvar_fields_ref = Lua_CreateFieldTable(L, cvar_opt); diff --git a/src/lua_hudlib.c b/src/lua_hudlib.c index 159344faa..0ec636468 100644 --- a/src/lua_hudlib.c +++ b/src/lua_hudlib.c @@ -1396,52 +1396,16 @@ int LUA_HudLib(lua_State *L) luaL_register(L, NULL, lib_draw); lib_draw_ref = luaL_ref(L, LUA_REGISTRYINDEX); - luaL_newmetatable(L, META_HUDINFO); - lua_pushcfunction(L, hudinfo_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, hudinfo_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, hudinfo_num); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getHudInfo); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_hudinfolen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "hudinfo"); - - luaL_newmetatable(L, META_COLORMAP); - lua_pushcfunction(L, colormap_get); - lua_setfield(L, -2, "__index"); - lua_pop(L,1); - - luaL_newmetatable(L, META_PATCH); - lua_pushcfunction(L, patch_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, patch_set); - lua_setfield(L, -2, "__newindex"); - lua_pop(L,1); + LUA_RegisterUserdataMetatable(L, META_HUDINFO, hudinfo_get, hudinfo_set, hudinfo_num); + LUA_RegisterUserdataMetatable(L, META_COLORMAP, colormap_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_PATCH, patch_get, patch_set, NULL); + LUA_RegisterUserdataMetatable(L, META_CAMERA, camera_get, camera_set, NULL); patch_fields_ref = Lua_CreateFieldTable(L, patch_opt); - - luaL_newmetatable(L, META_CAMERA); - lua_pushcfunction(L, camera_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, camera_set); - lua_setfield(L, -2, "__newindex"); - lua_pop(L,1); - camera_fields_ref = Lua_CreateFieldTable(L, camera_opt); + LUA_RegisterGlobalUserdata(L, "hudinfo", lib_getHudInfo, NULL, lib_hudinfolen); + luaL_register(L, "hud", lib_hud); return 0; } diff --git a/src/lua_infolib.c b/src/lua_infolib.c index 3764acf6a..ed78811ce 100644 --- a/src/lua_infolib.c +++ b/src/lua_infolib.c @@ -318,6 +318,7 @@ static int PopPivotSubTable(spriteframepivot_t *pivot, lua_State *L, int stk, in pivot[idx].x = (INT32)value; else if (ikey == 2 || (key && fastcmp(key, "y"))) pivot[idx].y = (INT32)value; + // TODO: 2.3: Delete else if (ikey == 3 || (key && fastcmp(key, "rotaxis"))) LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") else if (ikey == -1 && (key != NULL)) @@ -571,6 +572,7 @@ static int framepivot_get(lua_State *L) lua_pushinteger(L, framepivot->x); else if (fastcmp("y", field)) lua_pushinteger(L, framepivot->y); + // TODO: 2.3: Delete else if (fastcmp("rotaxis", field)) { LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed."); @@ -600,6 +602,7 @@ static int framepivot_set(lua_State *L) framepivot->x = luaL_checkinteger(L, 3); else if (fastcmp("y", field)) framepivot->y = luaL_checkinteger(L, 3); + // TODO: 2.3: delete else if (fastcmp("rotaxis", field)) LUA_UsageWarning(L, "\"rotaxis\" is deprecated and will be removed.") else @@ -1914,206 +1917,28 @@ int LUA_InfoLib(lua_State *L) lua_newtable(L); lua_setfield(L, LUA_REGISTRYINDEX, LREG_ACTIONS); - luaL_newmetatable(L, META_STATE); - lua_pushcfunction(L, state_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, state_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, state_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_MOBJINFO); - lua_pushcfunction(L, mobjinfo_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, mobjinfo_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, mobjinfo_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); + LUA_RegisterUserdataMetatable(L, META_STATE, state_get, state_set, state_num); + LUA_RegisterUserdataMetatable(L, META_MOBJINFO, mobjinfo_get, mobjinfo_set, mobjinfo_num); + LUA_RegisterUserdataMetatable(L, META_SKINCOLOR, skincolor_get, skincolor_set, skincolor_num); + LUA_RegisterUserdataMetatable(L, META_COLORRAMP, colorramp_get, colorramp_set, colorramp_len); + LUA_RegisterUserdataMetatable(L, META_SFXINFO, sfxinfo_get, sfxinfo_set, sfxinfo_num); + LUA_RegisterUserdataMetatable(L, META_SPRITEINFO, spriteinfo_get, spriteinfo_set, spriteinfo_num); + LUA_RegisterUserdataMetatable(L, META_PIVOTLIST, pivotlist_get, pivotlist_set, pivotlist_num); + LUA_RegisterUserdataMetatable(L, META_FRAMEPIVOT, framepivot_get, framepivot_set, framepivot_num); + LUA_RegisterUserdataMetatable(L, META_LUABANKS, lib_getluabanks, lib_setluabanks, lib_luabankslen); mobjinfo_fields_ref = Lua_CreateFieldTable(L, mobjinfo_opt); - luaL_newmetatable(L, META_SKINCOLOR); - lua_pushcfunction(L, skincolor_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, skincolor_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, skincolor_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_COLORRAMP); - lua_pushcfunction(L, colorramp_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, colorramp_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, colorramp_len); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - - luaL_newmetatable(L, META_SFXINFO); - lua_pushcfunction(L, sfxinfo_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, sfxinfo_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, sfxinfo_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_SPRITEINFO); - lua_pushcfunction(L, spriteinfo_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, spriteinfo_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, spriteinfo_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_PIVOTLIST); - lua_pushcfunction(L, pivotlist_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, pivotlist_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, pivotlist_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_FRAMEPIVOT); - lua_pushcfunction(L, framepivot_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, framepivot_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, framepivot_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSprname); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_sprnamelen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "sprnames"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSpr2name); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_spr2namelen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "spr2names"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSpr2default); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setSpr2default); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_spr2namelen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "spr2defaults"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getState); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setState); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_statelen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "states"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getMobjInfo); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setMobjInfo); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_mobjinfolen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "mobjinfo"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSkinColor); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setSkinColor); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_skincolorslen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "skincolors"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSfxInfo); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setSfxInfo); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_sfxlen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_pushvalue(L, -1); - lua_setglobal(L, "S_sfx"); - lua_setglobal(L, "sfxinfo"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSpriteInfo); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setSpriteInfo); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_spriteinfolen); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "spriteinfo"); - - luaL_newmetatable(L, META_LUABANKS); - lua_pushcfunction(L, lib_getluabanks); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setluabanks); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_luabankslen); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); + LUA_RegisterGlobalUserdata(L, "sprnames", lib_getSprname, NULL, lib_sprnamelen); + LUA_RegisterGlobalUserdata(L, "spr2names", lib_getSpr2name, NULL, lib_spr2namelen); + LUA_RegisterGlobalUserdata(L, "spr2defaults", lib_getSpr2default, lib_setSpr2default, lib_spr2namelen); + LUA_RegisterGlobalUserdata(L, "states", lib_getState, lib_setState, lib_statelen); + LUA_RegisterGlobalUserdata(L, "mobjinfo", lib_getMobjInfo, lib_setMobjInfo, lib_mobjinfolen); + LUA_RegisterGlobalUserdata(L, "skincolors", lib_getSkinColor, lib_setSkinColor, lib_skincolorslen); + LUA_RegisterGlobalUserdata(L, "spriteinfo", lib_getSpriteInfo, lib_setSpriteInfo, lib_spriteinfolen); + LUA_RegisterGlobalUserdata(L, "sfxinfo", lib_getSfxInfo, lib_setSfxInfo, lib_sfxlen); + // TODO: 2.3: Delete this alias + LUA_RegisterGlobalUserdata(L, "S_sfx", lib_getSfxInfo, lib_setSfxInfo, lib_sfxlen); return 0; } diff --git a/src/lua_inputlib.c b/src/lua_inputlib.c index 1f75ee6fe..ef3a9011f 100644 --- a/src/lua_inputlib.c +++ b/src/lua_inputlib.c @@ -20,6 +20,7 @@ #include "lua_libs.h" boolean mousegrabbedbylua = true; +boolean ignoregameinputs = false; /////////////// // FUNCTIONS // @@ -145,6 +146,51 @@ static luaL_Reg lib[] = { {NULL, NULL} }; +/////////////// +// VARIABLES // +/////////////// + +static int lib_get(lua_State *L) +{ + const char *field = luaL_checkstring(L, 2); + + if (fastcmp(field, "mouse")) + { + LUA_PushUserdata(L, &mouse, META_MOUSE); + return 1; + } + else if (fastcmp(field, "mouse2")) + { + LUA_PushUserdata(L, &mouse2, META_MOUSE); + return 1; + } + else if (fastcmp(field, "ignoregameinputs")) + { + lua_pushboolean(L, ignoregameinputs); + return 1; + } + else + { + return 0; + } +} + +static int lib_set(lua_State *L) +{ + const char *field = luaL_checkstring(L, 2); + + if (fastcmp(field, "ignoregameinputs")) + { + ignoregameinputs = luaL_checkboolean(L, 3); + } + else + { + lua_rawset(L, 1); + } + + return 0; +} + /////////////////// // gamekeydown[] // /////////////////// @@ -239,32 +285,18 @@ static int mouse_num(lua_State *L) int LUA_InputLib(lua_State *L) { - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getGameKeyDown); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_setGameKeyDown); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, lib_lenGameKeyDown); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "gamekeydown"); - - luaL_newmetatable(L, META_KEYEVENT); - lua_pushcfunction(L, keyevent_get); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_MOUSE); - lua_pushcfunction(L, mouse_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, mouse_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); + LUA_RegisterUserdataMetatable(L, META_KEYEVENT, keyevent_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_MOUSE, mouse_get, NULL, mouse_num); + // Register the library, then add __index and __newindex + // metamethods to it to allow global variables luaL_register(L, "input", lib); + LUA_CreateAndSetMetatable(L, lib_get, lib_set, NULL, false); + + LUA_CreateAndSetUserdataField(L, -1, "gamekeydown", lib_getGameKeyDown, lib_setGameKeyDown, lib_lenGameKeyDown, false); + // TODO: 2.3: Delete this alias (moved to input library) + LUA_RegisterGlobalUserdata(L, "gamekeydown", lib_getGameKeyDown, lib_setGameKeyDown, lib_lenGameKeyDown); + lua_pop(L, 1); + return 0; } diff --git a/src/lua_libs.h b/src/lua_libs.h index 7f8d21f38..2e3c70652 100644 --- a/src/lua_libs.h +++ b/src/lua_libs.h @@ -13,6 +13,7 @@ extern lua_State *gL; extern boolean mousegrabbedbylua; +extern boolean ignoregameinputs; #define MUTABLE_TAGS diff --git a/src/lua_maplib.c b/src/lua_maplib.c index e34397993..df06e9721 100644 --- a/src/lua_maplib.c +++ b/src/lua_maplib.c @@ -35,7 +35,7 @@ enum sector_e { sector_floorpic, sector_floorxoffset, sector_flooryoffset, - sector_floorangle, + sector_floorangle, sector_ceilingpic, sector_ceilingxoffset, sector_ceilingyoffset, @@ -43,7 +43,7 @@ enum sector_e { sector_lightlevel, sector_floorlightlevel, sector_floorlightabsolute, - sector_floorlightsec, + sector_floorlightsec, sector_ceilinglightlevel, sector_ceilinglightabsolute, sector_ceilinglightsec, @@ -77,14 +77,14 @@ static const char *const sector_opt[] = { "ceilingpic", "ceilingxoffset", "ceilingyoffset", - "ceilingangle", + "ceilingangle", "lightlevel", "floorlightlevel", "floorlightabsolute", "floorlightsec", "ceilinglightlevel", "ceilinglightabsolute", - "ceilinglightsec", + "ceilinglightsec", "special", "tag", "taglist", @@ -663,11 +663,11 @@ static int sector_get(lua_State *L) lua_pushfixed(L, sector->flooryoffset); return 1; } - case sector_floorangle: + case sector_floorangle: { lua_pushangle(L, sector->floorangle); return 1; - } + } case sector_ceilingpic: // ceilingpic { levelflat_t *levelflat = &levelflats[sector->ceilingpic]; @@ -691,7 +691,7 @@ static int sector_get(lua_State *L) { lua_pushangle(L, sector->ceilingangle); return 1; - } + } case sector_lightlevel: lua_pushinteger(L, sector->lightlevel); return 1; @@ -703,7 +703,7 @@ static int sector_get(lua_State *L) return 1; case sector_floorlightsec: lua_pushinteger(L, sector->floorlightsec); - return 1; + return 1; case sector_ceilinglightlevel: lua_pushinteger(L, sector->ceilinglightlevel); return 1; @@ -712,7 +712,7 @@ static int sector_get(lua_State *L) return 1; case sector_ceilinglightsec: lua_pushinteger(L, sector->ceilinglightsec); - return 1; + return 1; case sector_special: lua_pushinteger(L, sector->special); return 1; @@ -842,7 +842,7 @@ static int sector_set(lua_State *L) break; case sector_floorangle: sector->floorangle = luaL_checkangle(L, 3); - break; + break; case sector_ceilingpic: sector->ceilingpic = P_AddLevelFlatRuntime(luaL_checkstring(L, 3)); break; @@ -866,7 +866,7 @@ static int sector_set(lua_State *L) break; case sector_floorlightsec: sector->floorlightsec = (INT32)luaL_checkinteger(L, 3); - break; + break; case sector_ceilinglightlevel: sector->ceilinglightlevel = (INT16)luaL_checkinteger(L, 3); break; @@ -875,7 +875,7 @@ static int sector_set(lua_State *L) break; case sector_ceilinglightsec: sector->ceilinglightsec = (INT32)luaL_checkinteger(L, 3); - break; + break; case sector_special: sector->special = (INT16)luaL_checkinteger(L, 3); break; @@ -1043,17 +1043,7 @@ static int line_get(lua_State *L) lua_pushinteger(L, line->special); return 1; case line_tag: - // HELLO - // THIS IS LJ SONIC - // HOW IS YOUR DAY? - // BY THE WAY WHEN 2.3 OR 3.0 OR 4.0 OR SRB3 OR SRB4 OR WHATEVER IS OUT - // YOU SHOULD REMEMBER TO CHANGE THIS SO IT ALWAYS RETURNS A UNSIGNED VALUE - // HAVE A NICE DAY - // - // - // - // - // you are ugly + // TODO: 2.3: Always return a unsigned value lua_pushinteger(L, Tag_FGet(&line->tags)); return 1; case line_taglist: @@ -1108,6 +1098,7 @@ static int line_get(lua_State *L) case line_polyobj: LUA_PushUserdata(L, line->polyobj, META_POLYOBJ); return 1; + // TODO: 2.3: Delete case line_text: { if (udmf) @@ -1241,6 +1232,7 @@ static int side_get(lua_State *L) case side_repeatcnt: lua_pushinteger(L, side->repeatcnt); return 1; + // TODO: 2.3: Delete case side_text: { if (udmf) @@ -2843,170 +2835,36 @@ static int mapheaderinfo_get(lua_State *L) int LUA_MapLib(lua_State *L) { - luaL_newmetatable(L, META_SECTORLINES); - lua_pushcfunction(L, sectorlines_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, sectorlines_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_SECTOR); - lua_pushcfunction(L, sector_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, sector_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, sector_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); + LUA_RegisterUserdataMetatable(L, META_SECTORLINES, sectorlines_get, NULL, sectorlines_num); + LUA_RegisterUserdataMetatable(L, META_SECTOR, sector_get, sector_set, sector_num); + LUA_RegisterUserdataMetatable(L, META_SUBSECTOR, subsector_get, NULL, subsector_num); + LUA_RegisterUserdataMetatable(L, META_LINE, line_get, NULL, line_num); + LUA_RegisterUserdataMetatable(L, META_LINEARGS, lineargs_get, NULL, lineargs_len); + LUA_RegisterUserdataMetatable(L, META_LINESTRINGARGS, linestringargs_get, NULL, linestringargs_len); + LUA_RegisterUserdataMetatable(L, META_SIDENUM, sidenum_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_SIDE, side_get, side_set, side_num); + LUA_RegisterUserdataMetatable(L, META_VERTEX, vertex_get, NULL, vertex_num); + LUA_RegisterUserdataMetatable(L, META_FFLOOR, ffloor_get, ffloor_set, NULL); + LUA_RegisterUserdataMetatable(L, META_BBOX, bbox_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_SLOPE, slope_get, slope_set, NULL); + LUA_RegisterUserdataMetatable(L, META_VECTOR2, vector2_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_VECTOR3, vector3_get, NULL, NULL); + LUA_RegisterUserdataMetatable(L, META_MAPHEADER, mapheaderinfo_get, NULL, NULL); sector_fields_ref = Lua_CreateFieldTable(L, sector_opt); - - luaL_newmetatable(L, META_SUBSECTOR); - lua_pushcfunction(L, subsector_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, subsector_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - subsector_fields_ref = Lua_CreateFieldTable(L, subsector_opt); - - luaL_newmetatable(L, META_LINE); - lua_pushcfunction(L, line_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, line_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - line_fields_ref = Lua_CreateFieldTable(L, line_opt); - - luaL_newmetatable(L, META_LINEARGS); - lua_pushcfunction(L, lineargs_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lineargs_len); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_LINESTRINGARGS); - lua_pushcfunction(L, linestringargs_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, linestringargs_len); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_SIDENUM); - lua_pushcfunction(L, sidenum_get); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_SIDE); - lua_pushcfunction(L, side_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, side_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, side_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - side_fields_ref = Lua_CreateFieldTable(L, side_opt); - - luaL_newmetatable(L, META_VERTEX); - lua_pushcfunction(L, vertex_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, vertex_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - vertex_fields_ref = Lua_CreateFieldTable(L, vertex_opt); - - luaL_newmetatable(L, META_FFLOOR); - lua_pushcfunction(L, ffloor_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, ffloor_set); - lua_setfield(L, -2, "__newindex"); - lua_pop(L, 1); - ffloor_fields_ref = Lua_CreateFieldTable(L, ffloor_opt); - -#ifdef HAVE_LUA_SEGS - luaL_newmetatable(L, META_SEG); - lua_pushcfunction(L, seg_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, seg_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - seg_fields_ref = Lua_CreateFieldTable(L, seg_opt); - - luaL_newmetatable(L, META_NODE); - lua_pushcfunction(L, node_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, node_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - node_fields_ref = Lua_CreateFieldTable(L, node_opt); - - luaL_newmetatable(L, META_NODEBBOX); - //lua_pushcfunction(L, nodebbox_get); - //lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, nodebbox_call); - lua_setfield(L, -2, "__call"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_NODECHILDREN); - lua_pushcfunction(L, nodechildren_get); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); -#endif - - luaL_newmetatable(L, META_BBOX); - lua_pushcfunction(L, bbox_get); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_SLOPE); - lua_pushcfunction(L, slope_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, slope_set); - lua_setfield(L, -2, "__newindex"); - lua_pop(L, 1); - slope_fields_ref = Lua_CreateFieldTable(L, slope_opt); - - luaL_newmetatable(L, META_VECTOR2); - lua_pushcfunction(L, vector2_get); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_VECTOR3); - lua_pushcfunction(L, vector3_get); - lua_setfield(L, -2, "__index"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_MAPHEADER); - lua_pushcfunction(L, mapheaderinfo_get); - lua_setfield(L, -2, "__index"); - - //lua_pushcfunction(L, mapheaderinfo_num); - //lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - mapheaderinfo_fields_ref = Lua_CreateFieldTable(L, mapheaderinfo_opt); + LUA_RegisterGlobalUserdata(L, "subsectors", lib_getSubsector, NULL, lib_numsubsectors); + LUA_RegisterGlobalUserdata(L, "sides", lib_getSide, NULL, lib_numsides); + LUA_RegisterGlobalUserdata(L, "vertexes", lib_getVertex, NULL, lib_numvertexes); + LUA_RegisterGlobalUserdata(L, "mapheaderinfo", lib_getMapheaderinfo, NULL, lib_nummapheaders); + LUA_PushTaggableObjectArray(L, "sectors", lib_iterateSectors, lib_getSector, @@ -3015,16 +2873,6 @@ int LUA_MapLib(lua_State *L) &numsectors, §ors, sizeof (sector_t), META_SECTOR); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSubsector); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numsubsectors); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "subsectors"); - LUA_PushTaggableObjectArray(L, "lines", lib_iterateLines, lib_getLine, @@ -3033,56 +2881,22 @@ int LUA_MapLib(lua_State *L) &numlines, &lines, sizeof (line_t), META_LINE); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSide); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numsides); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "sides"); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getVertex); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numvertexes); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "vertexes"); - #ifdef HAVE_LUA_SEGS - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSeg); - lua_setfield(L, -2, "__index"); + LUA_RegisterUserdataMetatable(L, META_SEG, seg_get, NULL, seg_num); + LUA_RegisterUserdataMetatable(L, META_NODE, node_get, NULL, node_num); + LUA_RegisterUserdataMetatable(L, META_NODECHILDREN, nodechildren_get, NULL, NULL); - lua_pushcfunction(L, lib_numsegs); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "segs"); + seg_fields_ref = Lua_CreateFieldTable(L, seg_opt); + node_fields_ref = Lua_CreateFieldTable(L, node_opt); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getNode); - lua_setfield(L, -2, "__index"); + luaL_newmetatable(L, META_NODEBBOX); + //LUA_SetCFunctionField(L, "__index", nodebbox_get); + LUA_SetCFunctionField(L, "__call", nodebbox_call); + lua_pop(L, 1); - lua_pushcfunction(L, lib_numnodes); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "nodes"); + LUA_RegisterGlobalUserdata(L, "segs", lib_getSeg, NULL, lib_numsegs); + LUA_RegisterGlobalUserdata(L, "nodes", lib_getNode, NULL, lib_numnodes); #endif - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getMapheaderinfo); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_nummapheaders); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "mapheaderinfo"); return 0; } diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c index d0fe6863f..1bc6019de 100644 --- a/src/lua_mathlib.c +++ b/src/lua_mathlib.c @@ -125,6 +125,7 @@ static int lib_fixeddiv(lua_State *L) return 1; } +// TODO: 2.3: Delete static int lib_fixedrem(lua_State *L) { LUA_Deprecated(L, "FixedRem(a, b)", "a % b"); diff --git a/src/lua_mobjlib.c b/src/lua_mobjlib.c index fddf958be..19f30b70e 100644 --- a/src/lua_mobjlib.c +++ b/src/lua_mobjlib.c @@ -1163,43 +1163,12 @@ static int lib_nummapthings(lua_State *L) int LUA_MobjLib(lua_State *L) { - luaL_newmetatable(L, META_MOBJ); - lua_pushcfunction(L, mobj_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, mobj_set); - lua_setfield(L, -2, "__newindex"); - lua_pop(L,1); + LUA_RegisterUserdataMetatable(L, META_MOBJ, mobj_get, mobj_set, NULL); + LUA_RegisterUserdataMetatable(L, META_THINGARGS, thingargs_get, NULL, thingargs_len); + LUA_RegisterUserdataMetatable(L, META_THINGSTRINGARGS, thingstringargs_get, NULL, thingstringargs_len); + LUA_RegisterUserdataMetatable(L, META_MAPTHING, mapthing_get, mapthing_set, mapthing_num); mobj_fields_ref = Lua_CreateFieldTable(L, mobj_opt); - - luaL_newmetatable(L, META_THINGARGS); - lua_pushcfunction(L, thingargs_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, thingargs_len); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_THINGSTRINGARGS); - lua_pushcfunction(L, thingstringargs_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, thingstringargs_len); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_MAPTHING); - lua_pushcfunction(L, mapthing_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, mapthing_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, mapthing_num); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - mapthing_fields_ref = Lua_CreateFieldTable(L, mapthing_opt); LUA_PushTaggableObjectArray(L, "mapthings", diff --git a/src/lua_playerlib.c b/src/lua_playerlib.c index 827e5a405..d12aa1c3f 100644 --- a/src/lua_playerlib.c +++ b/src/lua_playerlib.c @@ -223,6 +223,7 @@ enum player_e player_blocked, player_jointime, player_quittime, + player_lastinputtime, player_ping, #ifdef HWRENDER player_fovadd, @@ -371,6 +372,7 @@ static const char *const player_opt[] = { "blocked", "jointime", "quittime", + "lastinputtime", "ping", #ifdef HWRENDER "fovadd", @@ -407,7 +409,7 @@ static int player_get(lua_State *L) case player_realmo: LUA_PushUserdata(L, plr->mo, META_MOBJ); break; - // Kept for backward-compatibility + // TODO: 2.3: Kept for backward-compatibility // Should be fixed to work like "realmo" later case player_mo: if (plr->spectator) @@ -826,6 +828,9 @@ static int player_get(lua_State *L) case player_quittime: lua_pushinteger(L, plr->quittime); break; + case player_lastinputtime: + lua_pushinteger(L, plr->lastinputtime); + break; case player_ping: lua_pushinteger(L, playerpingtable[plr - players]); break; @@ -1349,6 +1354,9 @@ static int player_set(lua_State *L) case player_quittime: plr->quittime = (tic_t)luaL_checkinteger(L, 3); break; + case player_lastinputtime: + plr->lastinputtime = (tic_t)luaL_checkinteger(L, 3); + break; #ifdef HWRENDER case player_fovadd: plr->fovadd = luaL_checkfixed(L, 3); @@ -1523,48 +1531,13 @@ static int ticcmd_set(lua_State *L) int LUA_PlayerLib(lua_State *L) { - luaL_newmetatable(L, META_PLAYER); - lua_pushcfunction(L, player_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, player_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, player_num); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); + LUA_RegisterUserdataMetatable(L, META_PLAYER, player_get, player_set, player_num); + LUA_RegisterUserdataMetatable(L, META_POWERS, power_get, power_set, power_len); + LUA_RegisterUserdataMetatable(L, META_TICCMD, ticcmd_get, ticcmd_set, NULL); player_fields_ref = Lua_CreateFieldTable(L, player_opt); - - luaL_newmetatable(L, META_POWERS); - lua_pushcfunction(L, power_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, power_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, power_len); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - - luaL_newmetatable(L, META_TICCMD); - lua_pushcfunction(L, ticcmd_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, ticcmd_set); - lua_setfield(L, -2, "__newindex"); - lua_pop(L,1); - ticcmd_fields_ref = Lua_CreateFieldTable(L, ticcmd_opt); - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getPlayer); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_lenPlayer); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "players"); + LUA_RegisterGlobalUserdata(L, "players", lib_getPlayer, NULL, lib_lenPlayer); return 0; } diff --git a/src/lua_polyobjlib.c b/src/lua_polyobjlib.c index c3d9d9d1a..6c016f8b2 100644 --- a/src/lua_polyobjlib.c +++ b/src/lua_polyobjlib.c @@ -447,41 +447,10 @@ static int lib_numPolyObjects(lua_State *L) int LUA_PolyObjLib(lua_State *L) { - luaL_newmetatable(L, META_POLYOBJVERTICES); - lua_pushcfunction(L, polyobjvertices_get); - lua_setfield(L, -2, "__index"); + LUA_RegisterUserdataMetatable(L, META_POLYOBJVERTICES, polyobjvertices_get, NULL, polyobjvertices_num); + LUA_RegisterUserdataMetatable(L, META_POLYOBJLINES, polyobjlines_get, NULL, polyobjlines_num); + LUA_RegisterUserdataMetatable(L, META_POLYOBJ, polyobj_get, polyobj_set, polyobj_num); - lua_pushcfunction(L, polyobjvertices_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_POLYOBJLINES); - lua_pushcfunction(L, polyobjlines_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, polyobjlines_num); - lua_setfield(L, -2, "__len"); - lua_pop(L, 1); - - luaL_newmetatable(L, META_POLYOBJ); - lua_pushcfunction(L, polyobj_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, polyobj_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, polyobj_num); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getPolyObject); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numPolyObjects); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "polyobjects"); + LUA_RegisterGlobalUserdata(L, "polyobjects", lib_getPolyObject, NULL, lib_numPolyObjects); return 0; } diff --git a/src/lua_script.c b/src/lua_script.c index 392935b4f..5cacc3f01 100644 --- a/src/lua_script.c +++ b/src/lua_script.c @@ -415,9 +415,11 @@ int LUA_PushGlobals(lua_State *L, const char *word) } else if (fastcmp(word, "stagefailed")) { lua_pushboolean(L, stagefailed); return 1; + // TODO: 2.3: Deprecated (moved to the input library) } else if (fastcmp(word, "mouse")) { LUA_PushUserdata(L, &mouse, META_MOUSE); return 1; + // TODO: 2.3: Deprecated (moved to the input library) } else if (fastcmp(word, "mouse2")) { LUA_PushUserdata(L, &mouse2, META_MOUSE); return 1; @@ -576,8 +578,7 @@ static void LUA_ClearState(void) // lock the global namespace lua_getmetatable(L, LUA_GLOBALSINDEX); - lua_pushcfunction(L, setglobals); - lua_setfield(L, -2, "__newindex"); + LUA_SetCFunctionField(L, "__newindex", setglobals); lua_newtable(L); lua_setfield(L, -2, "__metatable"); lua_pop(L, 1); @@ -1813,20 +1814,107 @@ void LUA_PushTaggableObjectArray lua_newuserdata(L, 0); lua_createtable(L, 0, 2); lua_createtable(L, 0, 2); - lua_pushcfunction(L, iterator); - lua_setfield(L, -2, "iterate"); + LUA_SetCFunctionField(L, "iterate", iterator); LUA_InsertTaggroupIterator(L, garray, max_elements, element_array, sizeof_element, meta); lua_createtable(L, 0, 1); - lua_pushcfunction(L, indexer); - lua_setfield(L, -2, "__index"); + LUA_SetCFunctionField(L, "__index", indexer); lua_setmetatable(L, -2); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, counter); - lua_setfield(L, -2, "__len"); + LUA_SetCFunctionField(L, "__len", counter); lua_setmetatable(L, -2); lua_setglobal(L, field); } + +static void SetBasicMetamethods( + lua_State *L, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len +) +{ + if (get) + LUA_SetCFunctionField(L, "__index", get); + if (set) + LUA_SetCFunctionField(L, "__newindex", set); + if (len) + LUA_SetCFunctionField(L, "__len", len); +} + +void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value) +{ + lua_pushcfunction(L, value); + lua_setfield(L, -2, name); +} + +void LUA_RegisterUserdataMetatable( + lua_State *L, + const char *name, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len +) +{ + luaL_newmetatable(L, name); + SetBasicMetamethods(L, get, set, len); + lua_pop(L, 1); +} + +// If keep is true, leaves the metatable on the stack. +// Otherwise, the stack size remains unchanged. +void LUA_CreateAndSetMetatable( + lua_State *L, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len, + boolean keep +) +{ + lua_newtable(L); + SetBasicMetamethods(L, get, set, len); + + lua_pushvalue(L, -1); + lua_setmetatable(L, -3); + + if (!keep) + lua_pop(L, 1); +} + +// If keep is true, leaves the userdata and metatable on the stack. +// Otherwise, the stack size remains unchanged. +void LUA_CreateAndSetUserdataField( + lua_State *L, + int index, + const char *name, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len, + boolean keep +) +{ + if (index < 0 && index > LUA_REGISTRYINDEX) + index -= 3; + + lua_newuserdata(L, 0); + LUA_CreateAndSetMetatable(L, get, set, len, true); + + lua_pushvalue(L, -2); + lua_setfield(L, index, name); + + if (!keep) + lua_pop(L, 2); +} + +void LUA_RegisterGlobalUserdata( + lua_State *L, + const char *name, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len +) +{ + LUA_CreateAndSetUserdataField(L, LUA_GLOBALSINDEX, name, get, set, len, false); +} diff --git a/src/lua_script.h b/src/lua_script.h index d0b06a719..53d848f8e 100644 --- a/src/lua_script.h +++ b/src/lua_script.h @@ -73,6 +73,42 @@ void LUA_PushTaggableObjectArray size_t sizeof_element, const char *meta); +void LUA_SetCFunctionField(lua_State *L, const char *name, lua_CFunction value); + +void LUA_RegisterUserdataMetatable( + lua_State *L, + const char *name, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len +); + +void LUA_CreateAndSetMetatable( + lua_State *L, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len, + boolean keep +); + +void LUA_CreateAndSetUserdataField( + lua_State *L, + int index, + const char *name, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len, + boolean keep +); + +void LUA_RegisterGlobalUserdata( + lua_State *L, + const char *name, + lua_CFunction get, + lua_CFunction set, + lua_CFunction len +); + void LUA_InsertTaggroupIterator ( lua_State *L, taggroup_t *garray[], diff --git a/src/lua_skinlib.c b/src/lua_skinlib.c index 041c5d598..3debd3746 100644 --- a/src/lua_skinlib.c +++ b/src/lua_skinlib.c @@ -373,49 +373,14 @@ static int sprite_get(lua_State *L) int LUA_SkinLib(lua_State *L) { - luaL_newmetatable(L, META_SKIN); - lua_pushcfunction(L, skin_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, skin_set); - lua_setfield(L, -2, "__newindex"); - - lua_pushcfunction(L, skin_num); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); + LUA_RegisterUserdataMetatable(L, META_SKIN, skin_get, skin_set, skin_num); + LUA_RegisterUserdataMetatable(L, META_SOUNDSID, soundsid_get, NULL, soundsid_num); + LUA_RegisterUserdataMetatable(L, META_SKINSPRITES, lib_getSkinSprite, NULL, lib_numSkinsSprites); + LUA_RegisterUserdataMetatable(L, META_SKINSPRITESLIST, sprite_get, NULL, NULL); skin_fields_ref = Lua_CreateFieldTable(L, skin_opt); - luaL_newmetatable(L, META_SOUNDSID); - lua_pushcfunction(L, soundsid_get); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, soundsid_num); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - - luaL_newmetatable(L, META_SKINSPRITES); - lua_pushcfunction(L, lib_getSkinSprite); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numSkinsSprites); - lua_setfield(L, -2, "__len"); - lua_pop(L,1); - - luaL_newmetatable(L, META_SKINSPRITESLIST); - lua_pushcfunction(L, sprite_get); - lua_setfield(L, -2, "__index"); - lua_pop(L,1); - - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_pushcfunction(L, lib_getSkin); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numSkins); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "skins"); + LUA_RegisterGlobalUserdata(L, "skins", lib_getSkin, NULL, lib_numSkins); return 0; } diff --git a/src/lua_taglib.c b/src/lua_taglib.c index 2ba60df99..9e73a050c 100644 --- a/src/lua_taglib.c +++ b/src/lua_taglib.c @@ -372,8 +372,7 @@ void LUA_InsertTaggroupIterator lua_pushcclosure(L, lib_numTaggroupElements, 2); lua_setfield(L, -2, "__len"); - lua_pushcfunction(L, element_iterator); - lua_setfield(L, -2, "__call"); + LUA_SetCFunctionField(L, "__call", element_iterator); lua_pushcclosure(L, lib_getTaggroup, 1); lua_setfield(L, -2, "tagged"); } @@ -414,11 +413,9 @@ set_taglist_metatable(lua_State *L, const char *meta) lua_setfenv(L, -2); lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, taglist_len); - lua_setfield(L, -2, "__len"); + LUA_SetCFunctionField(L, "__len", taglist_len); - lua_pushcfunction(L, taglist_equal); - lua_setfield(L, -2, "__eq"); + LUA_SetCFunctionField(L, "__eq", taglist_equal); #ifdef MUTABLE_TAGS return luaL_ref(L, LUA_REGISTRYINDEX); #endif @@ -426,17 +423,11 @@ set_taglist_metatable(lua_State *L, const char *meta) int LUA_TagLib(lua_State *L) { - lua_newuserdata(L, 0); - lua_createtable(L, 0, 2); - lua_createtable(L, 0, 1); - lua_pushcfunction(L, lib_iterateTags); - lua_setfield(L, -2, "iterate"); - lua_setfield(L, -2, "__index"); - - lua_pushcfunction(L, lib_numTags); - lua_setfield(L, -2, "__len"); - lua_setmetatable(L, -2); - lua_setglobal(L, "tags"); + LUA_CreateAndSetUserdataField(L, LUA_GLOBALSINDEX, "tags", NULL, NULL, lib_numTags, true); + lua_createtable(L, 0, 1); + LUA_SetCFunctionField(L, "iterate", lib_iterateTags); + lua_setfield(L, -2, "__index"); + lua_pop(L, 2); open_taglist(L); diff --git a/src/lua_thinkerlib.c b/src/lua_thinkerlib.c index cff92f34d..f1be8c789 100644 --- a/src/lua_thinkerlib.c +++ b/src/lua_thinkerlib.c @@ -127,8 +127,7 @@ static int lib_startIterate(lua_State *L) int LUA_ThinkerLib(lua_State *L) { luaL_newmetatable(L, META_ITERATIONSTATE); - lua_pushcfunction(L, iterationState_gc); - lua_setfield(L, -2, "__gc"); + LUA_SetCFunctionField(L, "__gc", iterationState_gc); lua_pop(L, 1); lua_createtable(L, 0, 1); diff --git a/src/netcode/d_clisrv.c b/src/netcode/d_clisrv.c index f06192f2c..7804b068f 100644 --- a/src/netcode/d_clisrv.c +++ b/src/netcode/d_clisrv.c @@ -113,6 +113,7 @@ consvar_t cv_blamecfail = CVAR_INIT ("blamecfail", "Off", CV_SAVE|CV_NETVAR, CV_ static CV_PossibleValue_t playbackspeed_cons_t[] = {{1, "MIN"}, {10, "MAX"}, {0, NULL}}; consvar_t cv_playbackspeed = CVAR_INIT ("playbackspeed", "1", 0, playbackspeed_cons_t, NULL); +consvar_t cv_idletime = CVAR_INIT ("idletime", "0", CV_SAVE, CV_Unsigned, NULL); consvar_t cv_dedicatedidletime = CVAR_INIT ("dedicatedidletime", "10", CV_SAVE, CV_Unsigned, NULL); void ResetNode(INT32 node) @@ -226,6 +227,7 @@ static void Got_AddPlayer(UINT8 **p, INT32 playernum) newplayer->jointime = 0; newplayer->quittime = 0; + newplayer->lastinputtime = 0; READSTRINGN(*p, player_names[newplayernum], MAXPLAYERNAME); @@ -492,6 +494,10 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) HU_AddChatText(va("\x82*%s has been banned (%s)", player_names[pnum], reason), false); kickreason = KR_BAN; break; + case KICK_MSG_IDLE: + HU_AddChatText(va("\x82*%s has left the game (Inactive for too long)", player_names[pnum]), false); + kickreason = KR_TIMEOUT; + break; } if (pnum == consoleplayer) @@ -507,6 +513,8 @@ static void Got_KickCmd(UINT8 **p, INT32 playernum) M_StartMessage(M_GetText("Server closed connection\n(synch failure)\nPress ESC\n"), NULL, MM_NOTHING); else if (msg == KICK_MSG_PING_HIGH) M_StartMessage(M_GetText("Server closed connection\n(Broke ping limit)\nPress ESC\n"), NULL, MM_NOTHING); + else if (msg == KICK_MSG_IDLE) + M_StartMessage(M_GetText("Server closed connection\n(Inactive for too long)\nPress ESC\n"), NULL, MM_NOTHING); else if (msg == KICK_MSG_BANNED) M_StartMessage(M_GetText("You have been banned by the server\n\nPress ESC\n"), NULL, MM_NOTHING); else if (msg == KICK_MSG_CUSTOM_KICK) @@ -1267,6 +1275,32 @@ static void UpdatePingTable(void) } } +static void IdleUpdate(void) +{ + INT32 i; + if (!server || !netgame) + return; + + for (i = 1; i < MAXPLAYERS; i++) + { + if (cv_idletime.value && playeringame[i] && playernode[i] != UINT8_MAX && !players[i].quittime && !players[i].spectator && !players[i].bot && !IsPlayerAdmin(i) && i != serverplayer) + { + if (players[i].cmd.forwardmove || players[i].cmd.sidemove || players[i].cmd.buttons) + players[i].lastinputtime = 0; + else + players[i].lastinputtime++; + + if (players[i].lastinputtime > (tic_t)cv_idletime.value * TICRATE * 60) + { + players[i].lastinputtime = 0; + SendKick(i, KICK_MSG_IDLE | KICK_MSG_KEEP_BODY); + } + } + else + players[i].lastinputtime = 0; + } +} + // Handle timeouts to prevent definitive freezes from happenning static void HandleNodeTimeouts(void) { @@ -1299,6 +1333,8 @@ void NetKeepAlive(void) GetPackets(); + IdleUpdate(); + #ifdef MASTERSERVER MasterClient_Ticker(); #endif @@ -1419,6 +1455,8 @@ void NetUpdate(void) GetPackets(); // get packet from client or from server + IdleUpdate(); + // The client sends the command after receiving from the server // The server sends it before because this is better in single player diff --git a/src/netcode/d_clisrv.h b/src/netcode/d_clisrv.h index d87ead9ec..db9a780cd 100644 --- a/src/netcode/d_clisrv.h +++ b/src/netcode/d_clisrv.h @@ -48,7 +48,7 @@ typedef enum KR_TIMEOUT = 4, //Connection Timeout KR_BAN = 5, //Banned by server KR_LEAVE = 6, //Quit the game - + KR_IDLE = 7, //Remained still for too long } kickreason_t; /* the max number of name changes in some time period */ @@ -73,7 +73,7 @@ extern UINT32 realpingtable[MAXPLAYERS]; extern UINT32 playerpingtable[MAXPLAYERS]; extern tic_t servermaxping; -extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_dedicatedidletime; +extern consvar_t cv_netticbuffer, cv_resynchattempts, cv_blamecfail, cv_playbackspeed, cv_idletime, cv_dedicatedidletime; // Used in d_net, the only dependence void D_ClientServerInit(void); diff --git a/src/netcode/d_netcmd.c b/src/netcode/d_netcmd.c index 5f67399c1..09add0565 100644 --- a/src/netcode/d_netcmd.c +++ b/src/netcode/d_netcmd.c @@ -601,6 +601,7 @@ void D_RegisterServerCommands(void) CV_RegisterVar(&cv_showjoinaddress); CV_RegisterVar(&cv_blamecfail); CV_RegisterVar(&cv_dedicatedidletime); + CV_RegisterVar(&cv_idletime); COM_AddCommand("ping", Command_Ping_f, COM_LUA); CV_RegisterVar(&cv_nettimeout); diff --git a/src/netcode/protocol.h b/src/netcode/protocol.h index a992e3b69..c084d920c 100644 --- a/src/netcode/protocol.h +++ b/src/netcode/protocol.h @@ -331,6 +331,7 @@ typedef struct #define KICK_MSG_PING_HIGH 6 #define KICK_MSG_CUSTOM_KICK 7 #define KICK_MSG_CUSTOM_BAN 8 +#define KICK_MSG_IDLE 9 #define KICK_MSG_KEEP_BODY 0x80 #endif diff --git a/src/p_local.h b/src/p_local.h index 007954312..c26c09860 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -204,6 +204,7 @@ void P_Earthquake(mobj_t *inflictor, mobj_t *source, fixed_t radius); boolean P_HomingAttack(mobj_t *source, mobj_t *enemy); /// \todo doesn't belong in p_user boolean P_SuperReady(player_t *player); void P_DoJump(player_t *player, boolean soundandstate); +void P_DoSpinDashDust(player_t *player); #define P_AnalogMove(player) (P_ControlStyle(player) == CS_LMAOGALOG) boolean P_TransferToNextMare(player_t *player); UINT8 P_FindLowestMare(void); @@ -214,6 +215,10 @@ void P_SpawnThokMobj(player_t *player); void P_SpawnSpinMobj(player_t *player, mobjtype_t type); void P_Telekinesis(player_t *player, fixed_t thrust, fixed_t range); +void P_DoTailsOverlay(player_t *player, mobj_t *tails); +void P_DoMetalJetFume(player_t *player, mobj_t *fume); +void P_DoFollowMobj(player_t *player, mobj_t *followmobj); + void P_PlayLivesJingle(player_t *player); #define P_PlayRinglossSound(s) S_StartSound(s, (mariomode) ? sfx_mario8 : sfx_altow1 + P_RandomKey(4)); #define P_PlayDeathSound(s) S_StartSound(s, sfx_altdi1 + P_RandomKey(4)); @@ -298,6 +303,7 @@ void P_RunOverlays(void); void P_HandleMinecartSegments(mobj_t *mobj); void P_MobjThinker(mobj_t *mobj); boolean P_RailThinker(mobj_t *mobj); +boolean P_CheckSkyHit(mobj_t *mo, line_t *line); void P_PushableThinker(mobj_t *mobj); void P_SceneryThinker(mobj_t *mobj); diff --git a/src/p_mobj.c b/src/p_mobj.c index 8bc74e3b8..7a5aaf424 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -1779,14 +1779,15 @@ bustupdone: // // P_CheckSkyHit // -static boolean P_CheckSkyHit(mobj_t *mo) +boolean P_CheckSkyHit(mobj_t *mo, line_t *line) { - if (ceilingline && ceilingline->backsector - && ceilingline->backsector->ceilingpic == skyflatnum - && ceilingline->frontsector - && ceilingline->frontsector->ceilingpic == skyflatnum - && (mo->z >= ceilingline->frontsector->ceilingheight - || mo->z >= ceilingline->backsector->ceilingheight)) + if (line && (line->special == 41 || + (line->backsector + && line->backsector->ceilingpic == skyflatnum + && line->frontsector + && line->frontsector->ceilingpic == skyflatnum + && (mo->z >= line->frontsector->ceilingheight + || mo->z >= line->backsector->ceilingheight)))) return true; return false; } @@ -1893,7 +1894,7 @@ void P_XYMovement(mobj_t *mo) mo->fuse += ((5 - mo->threshold) * TICRATE); // Check for hit against sky here - if (P_CheckSkyHit(mo)) + if (P_CheckSkyHit(mo, ceilingline)) { // Hack to prevent missiles exploding // against the sky. @@ -1913,7 +1914,7 @@ void P_XYMovement(mobj_t *mo) mo->flags &= ~MF_STICKY; //Don't check again! // Check for hit against sky here - if (P_CheckSkyHit(mo)) + if (P_CheckSkyHit(mo, ceilingline)) { // Hack to prevent missiles exploding // against the sky. @@ -1972,7 +1973,7 @@ void P_XYMovement(mobj_t *mo) else if (mo->flags & MF_MISSILE) { // explode a missile - if (P_CheckSkyHit(mo)) + if (P_CheckSkyHit(mo, ceilingline)) { // Hack to prevent missiles exploding // against the sky. @@ -10572,14 +10573,14 @@ static fixed_t P_DefaultMobjShadowScale (mobj_t *thing) case MT_EXPLOSIONRING: case MT_SCATTERRING: case MT_GRENADERING: - + case MT_BOUNCEPICKUP: case MT_RAILPICKUP: case MT_AUTOPICKUP: case MT_EXPLODEPICKUP: case MT_SCATTERPICKUP: case MT_GRENADEPICKUP: - + case MT_REDRING: case MT_THROWNBOUNCE: case MT_THROWNINFINITY: @@ -13320,7 +13321,7 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean return true; } -// Pre-UDMF backwards compatibility stuff. Remove for 2.3 +// TODO: 2.3: Delete (Pre-UDMF backwards compatibility stuff) static void P_SetAmbush(mapthing_t *mthing, mobj_t *mobj) { if (mobj->type == MT_NIGHTSBUMPER diff --git a/src/p_saveg.h b/src/p_saveg.h index 73fcfd583..545008e7e 100644 --- a/src/p_saveg.h +++ b/src/p_saveg.h @@ -18,7 +18,7 @@ #pragma interface #endif -#define NEWSKINSAVES (INT16_MAX) // Purely for backwards compatibility, remove this for 2.3 +#define NEWSKINSAVES (INT16_MAX) // TODO: 2.3: Delete (Purely for backwards compatibility) // Persistent storage/archiving. // These are the load / save game routines. diff --git a/src/p_setup.c b/src/p_setup.c index 0390761b6..7f6fcd36c 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -1679,7 +1679,7 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char if ((id = strchr(id, ' '))) id++; } - } + } else if (fastcmp(param, "xpanningfloor")) sectors[i].floorxoffset = FLOAT_TO_FIXED(atof(val)); else if (fastcmp(param, "ypanningfloor")) @@ -6132,6 +6132,7 @@ static void P_ConvertBinarySectorTypes(void) case 14: //Non-ramp sector sectors[i].specialflags |= SSF_NOSTEPDOWN; break; + // TODO: 2.3: Delete case 15: //Bouncy FOF CONS_Alert(CONS_WARNING, M_GetText("Deprecated bouncy FOF sector type detected. Please use linedef type 76 instead.\n")); break; @@ -6166,12 +6167,14 @@ static void P_ConvertBinarySectorTypes(void) sectors[i].flags |= MSF_TRIGGERLINE_PLANE; sectors[i].triggerer = TO_PLAYER; break; + // TODO: 2.3: Delete case 6: //Trigger linedef executor (Emerald check) CONS_Alert(CONS_WARNING, M_GetText("Deprecated emerald check sector type detected. Please use linedef types 337-339 instead.\n")); sectors[i].triggertag = tag; sectors[i].flags &= ~MSF_TRIGGERLINE_PLANE; sectors[i].triggerer = TO_PLAYEREMERALDS; break; + // TODO: 2.3: Delete case 7: //Trigger linedef executor (NiGHTS mare) CONS_Alert(CONS_WARNING, M_GetText("Deprecated NiGHTS mare sector type detected. Please use linedef types 340-342 instead.\n")); sectors[i].triggertag = tag; @@ -6181,9 +6184,11 @@ static void P_ConvertBinarySectorTypes(void) case 8: //Check for linedef executor on FOFs sectors[i].flags |= MSF_TRIGGERLINE_MOBJ; break; + // TODO: 2.3: Delete case 10: //Special stage time/spheres requirements CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for special stage requirements detected. Please use the SpecialStageTime and SpecialStageSpheres level header options instead.\n")); break; + // TODO: 2.3: Delete case 11: //Custom global gravity CONS_Alert(CONS_WARNING, M_GetText("Deprecated sector type for global gravity detected. Please use the Gravity level header option instead.\n")); break; @@ -6822,7 +6827,7 @@ static void P_ConvertBinaryThingTypes(void) default: break; } - + // Clear binary thing height hacks, to prevent interfering with UDMF-only flags mapthings[i].options &= 0xF; } diff --git a/src/p_spec.c b/src/p_spec.c index 28ecc60f4..aa4ee37cf 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -2661,7 +2661,7 @@ static void P_ProcessLineSpecial(line_t *line, mobj_t *mo, sector_t *callsec) titlemapcameraref = altview; else if (!mo->player->awayviewtics || mo->player->awayviewmobj != altview) { P_SetTarget(&mo->player->awayviewmobj, altview); - + if (mo->player == &players[displayplayer]) P_ResetCamera(mo->player, &camera); // reset p1 camera on p1 getting an awayviewmobj else if (splitscreen && mo->player == &players[secondarydisplayplayer]) @@ -4178,6 +4178,7 @@ sector_t *P_MobjTouchingSectorSpecial(mobj_t *mo, INT32 section, INT32 number) return NULL; } +// TODO: 2.3: Delete // Deprecated in favor of P_MobjTouchingSectorSpecial // Kept for Lua backwards compatibility only sector_t *P_ThingOnSpecial3DFloor(mobj_t *mo) @@ -6229,6 +6230,7 @@ void P_SpawnSpecials(boolean fromnetsave) sector->flags |= MSF_TRIGGERSPECIAL_TOUCH; } + // TODO: 2.3: Delete everything below // Process deprecated binary sector specials if (udmf || !sector->special) continue; diff --git a/src/p_user.c b/src/p_user.c index 7aed5269f..c0e87bf73 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -2773,6 +2773,7 @@ static void P_CheckBouncySectors(player_t *player) if (!(rover->fofflags & FOF_EXISTS)) continue; // FOFs should not be bouncy if they don't even "exist" + // TODO: 2.3: Delete // Handle deprecated bouncy FOF sector type if (!udmf && GETSECSPECIAL(rover->master->frontsector->special, 1) == 15) { @@ -4601,7 +4602,7 @@ void P_DoJump(player_t *player, boolean soundandstate) } } -static void P_DoSpinDashDust(player_t *player) +void P_DoSpinDashDust(player_t *player) { UINT32 i; mobj_t *particle; @@ -11191,7 +11192,7 @@ static void P_MinecartThink(player_t *player) } // Handle Tails' fluff -static void P_DoTailsOverlay(player_t *player, mobj_t *tails) +void P_DoTailsOverlay(player_t *player, mobj_t *tails) { // init... boolean smilesonground = P_IsObjectOnGround(player->mo); @@ -11388,7 +11389,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) tails->y = player->mo->y + P_ReturnThrustY(tails, tails->angle, FixedMul(backwards, tails->scale)); tails->z = player->mo->z + zoffs; P_SetThingPosition(tails); - + if (player->mo->flags2 & MF2_SHADOW) tails->flags2 |= MF2_SHADOW; else @@ -11396,7 +11397,7 @@ static void P_DoTailsOverlay(player_t *player, mobj_t *tails) } // Metal Sonic's jet fume -static void P_DoMetalJetFume(player_t *player, mobj_t *fume) +void P_DoMetalJetFume(player_t *player, mobj_t *fume) { static const UINT8 FUME_SKINCOLORS[] = { @@ -11534,6 +11535,30 @@ static void P_DoMetalJetFume(player_t *player, mobj_t *fume) } } +// Handle Followmobj behavior +void P_DoFollowMobj(player_t *player, mobj_t *followmobj) +{ + if (LUA_HookFollowMobj(player, followmobj) || P_MobjWasRemoved(followmobj)) + {;} + else + { + switch (followmobj->type) + { + case MT_TAILSOVERLAY: // c: + P_DoTailsOverlay(player, followmobj); + break; + case MT_METALJETFUME: + P_DoMetalJetFume(player, followmobj); + break; + default: + var1 = 1; + var2 = 0; + A_CapeChase(followmobj); + break; + } + } +} + // // P_PlayerThink // @@ -11604,7 +11629,7 @@ void P_PlayerThink(player_t *player) P_SetTarget(&player->awayviewmobj, NULL); // remove awayviewmobj asap if invalid player->awayviewtics = 1; // reset to one, the below code will immediately set it to zero } - + if (player->awayviewtics && player->awayviewtics != -1) { player->awayviewtics--; @@ -12276,11 +12301,11 @@ void P_PlayerThink(player_t *player) if (!(player->stronganim)) player->stronganim = player->panim; else if (player->panim != player->stronganim) - player->powers[pw_strong] = STR_NONE; - } + player->powers[pw_strong] = STR_NONE; + } else if (player->stronganim) player->stronganim = 0; - + //pw_super acts as a timer now if (player->powers[pw_super] && (player->mo->state < &states[S_PLAY_SUPER_TRANS1] @@ -12387,7 +12412,7 @@ void P_PlayerThink(player_t *player) if (player->jumpfactor < FixedMul(skins[player->skin].jumpfactor, 5*FRACUNIT/4)) // Boost jump height. player->jumpfactor += FRACUNIT/300; - if ((player->charflags & SF_MACHINE) && (!(player->powers[pw_strong] == STR_METAL))) + if ((player->charflags & SF_MACHINE) && (!(player->powers[pw_strong] == STR_METAL))) player->powers[pw_strong] = STR_METAL; } @@ -13010,27 +13035,7 @@ void P_PlayerAfterThink(player_t *player) } if (player->followmobj) - { - if (LUA_HookFollowMobj(player, player->followmobj) || P_MobjWasRemoved(player->followmobj)) - {;} - else - { - switch (player->followmobj->type) - { - case MT_TAILSOVERLAY: // c: - P_DoTailsOverlay(player, player->followmobj); - break; - case MT_METALJETFUME: - P_DoMetalJetFume(player, player->followmobj); - break; - default: - var1 = 1; - var2 = 0; - A_CapeChase(player->followmobj); - break; - } - } - } + P_DoFollowMobj(player, player->followmobj); } P_DoPlayerHeadSigns(player); // Spawn Tag/CTF signs over player's head diff --git a/src/version.h b/src/version.h index 3242cad67..8d8f8978e 100644 --- a/src/version.h +++ b/src/version.h @@ -1,4 +1,4 @@ -#define SRB2VERSION "2.2.13"/* this must be the first line, for cmake !! */ +#define SRB2VERSION "2.2.14"/* this must be the first line, for cmake !! */ // The Modification ID; must be obtained from a Master Server Admin ( https://mb.srb2.org/members/?key=ms_admin ). // DO NOT try to set this otherwise, or your modification will be unplayable through the Master Server. @@ -9,7 +9,7 @@ // it's only for detection of the version the player is using so the MS can alert them of an update. // Only set it higher, not lower, obviously. // Note that we use this to help keep internal testing in check; this is why v2.2.0 is not version "1". -#define MODVERSION 54 +#define MODVERSION 55 // Define this as a prerelease version suffix (pre#, RC#) -//#define BETAVERSION "pre1" +#define BETAVERSION "nightly" diff --git a/src/win32/Srb2win.rc b/src/win32/Srb2win.rc index b69900746..9ee9b7d3f 100644 --- a/src/win32/Srb2win.rc +++ b/src/win32/Srb2win.rc @@ -77,8 +77,8 @@ END #include "../doomdef.h" // Needed for version string VS_VERSION_INFO VERSIONINFO - FILEVERSION 2,2,13,0 - PRODUCTVERSION 2,2,13,0 + FILEVERSION 2,2,14,0 + PRODUCTVERSION 2,2,14,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L