diff --git a/luprex/cpp/core/animqueue.cpp b/luprex/cpp/core/animqueue.cpp index ec64519f..15ecb585 100644 --- a/luprex/cpp/core/animqueue.cpp +++ b/luprex/cpp/core/animqueue.cpp @@ -61,18 +61,8 @@ static AnimValue parse_anim_value(LuaCoreStack &LS, LuaSlot val, LuaSlot tmp) { result.set_number(LS.cknumber(val)); } else if (LS.isstring(val)) { result.set_string(LS.ckstring(val)); - } else if (LS.istable(val)) { - util::DXYZ xyz; - LS.rawget(tmp, val, 1); - if (!LS.isnumber(tmp)) return result; - xyz.x = LS.cknumber(tmp); - LS.rawget(tmp, val, 2); - if (!LS.isnumber(tmp)) return result; - xyz.y = LS.cknumber(tmp); - LS.rawget(tmp, val, 3); - if (!LS.isnumber(tmp)) return result; - xyz.z = LS.cknumber(tmp); - result.set_dxyz(xyz); + } else if (LS.isxyz(val)) { + result.set_dxyz(LS.ckxyz(val)); } else if (LS.rawequal(val, LuaToken("auto"))) { result.set_auto(); } else { diff --git a/luprex/cpp/core/luastack.cpp b/luprex/cpp/core/luastack.cpp index 05eb7f2f..b6a7e22b 100644 --- a/luprex/cpp/core/luastack.cpp +++ b/luprex/cpp/core/luastack.cpp @@ -5,15 +5,12 @@ #include "wrap-string.hpp" #include "wrap-set.hpp" #include "wrap-sstream.hpp" +#include "util.hpp" LuaSpecial LuaRegistry(LUA_REGISTRYINDEX); LuaNilMarker LuaNil; LuaNewTableMarker LuaNewTable; -inline bool ascii_islower(char c) { return (c >= 'a') && (c <= 'z'); } -inline bool ascii_isupper(char c) { return (c >= 'A') && (c <= 'Z'); } -inline bool ascii_isdigit(char c) { return (c >= '0') && (c <= '9'); } - LuaFunctionReg::LuaFunctionReg(const char *n, const char *a, const char *d, bool s, lua_CFunction f) { name_ = n; args_ = a; @@ -115,6 +112,21 @@ bool LuaCoreStack::isint(LuaSlot s) const { return false; } +bool LuaCoreStack::isxyz(LuaSlot s) const { + if (lua_istable(L_, s) && (lua_nkeys(L_, s) == 3)) { + int top = lua_gettop(L_); + lua_rawgeti(L_, s, 3); + lua_rawgeti(L_, s, 2); + lua_rawgeti(L_, s, 1); + if (lua_isnumber(L_, -1) && lua_isnumber(L_, -2) && lua_isnumber(L_, -3)) { + lua_settop(L_, top); + return true; + } + lua_settop(L_, top); + } + return false; +} + bool LuaCoreStack::ckboolean(LuaSlot s) const { checkboolean(s, "value"); return lua_toboolean(L_, s) ? true:false; @@ -172,6 +184,26 @@ LuaToken LuaCoreStack::cktoken(LuaSlot s) const { return LuaToken(lua_touserdata(L_, s)); } +util::DXYZ LuaCoreStack::ckxyz(LuaSlot s) const { + if (lua_istable(L_, s) && (lua_nkeys(L_, s) == 3)) { + int top = lua_gettop(L_); + lua_rawgeti(L_, s, 3); + lua_rawgeti(L_, s, 2); + lua_rawgeti(L_, s, 1); + if (lua_isnumber(L_, -1) && lua_isnumber(L_, -2) && lua_isnumber(L_, -3)) { + util::DXYZ result; + result.x = lua_tonumber(L_, -1); + result.y = lua_tonumber(L_, -2); + result.z = lua_tonumber(L_, -3); + lua_settop(L_, top); + return result; + } + lua_settop(L_, top); + } + argerr("argument", "vector"); + return util::DXYZ(); +} + void LuaCoreStack::clearmetatable(LuaSlot tab) const { lua_pushnil(L_); lua_setmetatable(L_, tab); @@ -225,14 +257,7 @@ lua_State *LuaCoreStack::newthread(LuaSlot target) const { } bool LuaCoreStack::valididentifier(std::string_view str) { - if (str.size() == 0) return false; - char c=str[0]; - if ((!ascii_islower(c)) && (!ascii_isupper(c)) && (c!='_')) return false; - for (int i = 1; i < int(str.size()); i++) { - char c = str[i]; - if ((!ascii_islower(c)) && (!ascii_isupper(c)) && (!ascii_isdigit(c)) && (c!='_')) return false; - } - return true; + return sv::is_lua_id(str); } bool LuaCoreStack::validint64(int64_t value) { diff --git a/luprex/cpp/core/luastack.hpp b/luprex/cpp/core/luastack.hpp index 1e6d29c5..5cf11a4f 100644 --- a/luprex/cpp/core/luastack.hpp +++ b/luprex/cpp/core/luastack.hpp @@ -143,6 +143,7 @@ #ifndef LUASTACK_HPP #define LUASTACK_HPP +#include "util.hpp" #include "wrap-string.hpp" #include "wrap-set.hpp" #include @@ -379,6 +380,7 @@ public: bool isboolean(LuaSlot s) const { return lua_type(L_, s) == LUA_TBOOLEAN; } bool isnil(LuaSlot s) const { return lua_type(L_, s) == LUA_TNIL; } bool istoken(LuaSlot s) const { return lua_islightuserdata(L_, s) != 0; } + bool isxyz(LuaSlot s) const; void checktable(LuaSlot s, const char *n) const { if (!istable(s)) argerr(n, "table"); } void checkstring(LuaSlot s, const char *n) const { if (!isstring(s)) argerr(n, "string"); } @@ -391,6 +393,7 @@ public: void checkboolean(LuaSlot s, const char *n) const { if (!isboolean(s)) argerr(n, "boolean"); } void checknil(LuaSlot s, const char *n) const { if (!isnil(s)) argerr(n, "nil"); } void checktoken(LuaSlot s, const char *n) const { if (!istoken(s)) argerr(n, "token"); } + void checkxyz(LuaSlot s, const char *n) const { if (!isxyz(s)) argerr(n, "xyz"); } bool ckboolean(LuaSlot s) const; lua_Integer ckinteger(LuaSlot s) const; @@ -400,6 +403,7 @@ public: std::string_view ckstringview(LuaSlot s) const; lua_State *ckthread(LuaSlot s) const; LuaToken cktoken(LuaSlot s) const; + util::DXYZ ckxyz(LuaSlot s) const; void clearmetatable(LuaSlot tab) const; void setmetatable(LuaSlot tab, LuaSlot mt) const; diff --git a/luprex/cpp/core/planemap.cpp b/luprex/cpp/core/planemap.cpp index 3ab1876a..e9a6dcce 100644 --- a/luprex/cpp/core/planemap.cpp +++ b/luprex/cpp/core/planemap.cpp @@ -840,40 +840,24 @@ void PlaneScan::configure(LuaKeywordParser &kp) { have_plane = true; } - kp.parse(vx, "centerx"); - kp.parse(vy, "centery"); - kp.parse(vz, "centerz"); - if ((!LS.isnil(vx)) || (!LS.isnil(vy)) || (!LS.isnil(vz))) { - LS.checknumber(vx, "centerx"); - LS.checknumber(vy, "centery"); - LS.checknumber(vz, "centerz"); - center_.x = LS.cknumber(vx); - center_.y = LS.cknumber(vy); - center_.z = LS.cknumber(vz); + if (kp.parse(val, "center")) { + LS.checkxyz(val, "center"); + util::DXYZ xyz = LS.ckxyz(val); + center_ = xyz; have_center = true; } if (kp.parse(val, "radius")) { - LS.checknumber(val, "radius"); - radius_.x = LS.cknumber(val); - radius_.y = radius_.z = radius_.x; - have_radius = true; - } - - kp.parse(vx, "radiusx"); - kp.parse(vy, "radiusy"); - kp.parse(vz, "radiusz"); - if ((!LS.isnil(vx)) || (!LS.isnil(vy)) || (!LS.isnil(vz))) { - LS.checknumber(vx, "radiusx"); - LS.checknumber(vy, "radiusy"); - LS.checknumber(vz, "radiusz"); - if (have_radius) { - luaL_error(L, "scan configuration: specified both 'radius' and 'radiusx'"); + if (LS.isnumber(val)) { + radius_.x = LS.cknumber(val); + radius_.y = radius_.z = radius_.x; + have_radius = true; + } else { + LS.checkxyz(val, "radius"); + util::DXYZ xyz = LS.ckxyz(val); + radius_ = xyz; + have_radius = true; } - radius_.x = LS.cknumber(vx); - radius_.y = LS.cknumber(vy); - radius_.z = LS.cknumber(vz); - have_radius = true; } if (kp.parse(val, "shape")) { diff --git a/luprex/cpp/core/util.cpp b/luprex/cpp/core/util.cpp index 34ea008f..da35a7df 100644 --- a/luprex/cpp/core/util.cpp +++ b/luprex/cpp/core/util.cpp @@ -2,7 +2,7 @@ #include "wrap-vector.hpp" #include "util.hpp" #include "fast-float.hpp" - +#include "luastack.hpp" #include #include @@ -178,7 +178,14 @@ int common_prefix_length(string_view a, string_view b) { } bool is_lua_id(string_view str) { - return LuaCoreStack::valididentifier(str); + if (str.size() == 0) return false; + char c=str[0]; + if ((!ascii_isalpha(c)) && (c!='_')) return false; + for (int i = 1; i < int(str.size()); i++) { + char c = str[i]; + if ((!ascii_isalnum(c)) && (c!='_')) return false; + } + return true; } bool is_lua_comment(string_view s) { diff --git a/luprex/cpp/core/util.hpp b/luprex/cpp/core/util.hpp index cec2bc1b..ed8b3641 100644 --- a/luprex/cpp/core/util.hpp +++ b/luprex/cpp/core/util.hpp @@ -29,8 +29,7 @@ #include #include // #include - -#include "luastack.hpp" +#include #include "spookyv2.hpp" namespace sv { @@ -342,7 +341,8 @@ struct NumXYZ { Number x, y, z; NumXYZ() { x=0; y=0; z=0; } NumXYZ(Number ix, Number iy, Number iz) { x=ix; y=iy; z=iz; } - void operator =(const NumXYZ &other) { x = other.x; y = other.y; z = other.z; } + void operator =(const NumXYZ &other) { x = other.x; y = other.y; z = other.z; } + void operator =(const NumXYZ &other) { x = other.x; y = other.y; z = other.z; } void operator =(Number n) { x = n; y = n; z = n; } bool operator ==(const NumXYZ &o) const { return x==o.x && y == o.y && z==o.z; } bool operator !=(const NumXYZ &o) const { return x!=o.x || y != o.y || z!=o.z; } diff --git a/luprex/cpp/core/world-accessor.cpp b/luprex/cpp/core/world-accessor.cpp index 5f932dc0..238a2caf 100644 --- a/luprex/cpp/core/world-accessor.cpp +++ b/luprex/cpp/core/world-accessor.cpp @@ -22,7 +22,7 @@ LuaDefine(tangible_xyz, "tan", "|Returns four values: x, y, z, plane") { LuaArg tanobj; LuaRet x, y, z, plane; - LuaDefStack LS(L, tanobj, x, y, z); + LuaDefStack LS(L, tanobj, x, y, z, plane); World *w = World::fetch_global_pointer(L); Tangible *tan = w->tangible_get(LS, tanobj, false); AnimCoreState pos = tan->anim_queue_.get_final_core_state(); @@ -212,9 +212,11 @@ LuaDefine(tangible_animate, "tan,options,config", LuaDefine(tangible_setclass, "tan,class", "|Set the class of the tangible." + "|" "|The class can be a 'class table' (ie, a table of methods), " "|or it can be a string that names a class. The tangible is " - "|given an __index metamethod that points at the class table.") { + "|given an __index metamethod that points at the class table." + "|") { LuaArg tanobj, classname; LuaVar classtab, mt; LuaDefStack LS(L, tanobj, classname, classtab, mt); @@ -231,8 +233,10 @@ LuaDefine(tangible_setclass, "tan,class", LuaDefine(tangible_getclass, "tan", "|Get the class of the tangible, if any." + "|" "|The return value is a string, the class name, not" - "|the class table.") { + "|the class table." + "|") { LuaArg tanobj; LuaVar classtab; LuaRet classname; @@ -251,6 +255,7 @@ LuaDefine(tangible_getclass, "tan", LuaDefine(tangible_delete, "tan", "|Delete the specified tangible." + "|" "|This cannot be used to delete player tangibles," "|To delete a player, use tangible.redirect") { LuaArg tanobj; @@ -399,46 +404,6 @@ LuaDefine(tangible_place, "", return LS.result(); } -LuaDefine(tangible_near, "tan,radius,omit_nowhere,omit_self", - "|Deprecated. Use tangible.find instead.") { - LuaArg ltan, lradius, lomit_nowhere, lomit_self; - LuaRet list; - LuaDefStack LS(L, ltan, lradius, lomit_nowhere, lomit_self, list); - World *w = World::fetch_global_pointer(L); - Tangible *tan = w->tangible_get(LS, ltan, false); - - PlaneScan scan; - scan.set_radius(LS.cknumber(lradius)); - scan.set_shape(PlaneScan::SPHERE); - scan.set_sorted(true); - scan.set_near(tan->id(), !LS.ckboolean(lomit_self)); - scan.set_omit_nowhere(LS.ckboolean(lomit_nowhere)); - util::IdVector idv; - w->get_near(scan, &idv); - tangible_getall(LS, list, idv); - return LS.result(); -} - -LuaDefine(tangible_scan, "plane,x,y,radius,omit_nowhere", - "|Deprecated. Use tangible.find instead.") { - LuaArg lplane, lx, ly, lradius, lomit_nowhere; - LuaRet list; - LuaDefStack LS(L, lplane, lx, ly, lradius, lomit_nowhere, list); - World *w = World::fetch_global_pointer(L); - - PlaneScan scan; - scan.set_plane(LS.ckstring(lplane)); - scan.set_center_and_radius(util::XYZ(LS.cknumber(lx), LS.cknumber(ly), 0), LS.cknumber(lradius)); - scan.set_shape(PlaneScan::SPHERE); - scan.set_sorted(true); - scan.set_omit_nowhere(LS.ckboolean(lomit_nowhere)); - - util::IdVector idv; - w->get_near(scan, &idv); - tangible_getall(LS, list, idv); - return LS.result(); -} - LuaDefine(tangible_find, "config", "|Find tangibles by their location." "|" @@ -447,25 +412,16 @@ LuaDefine(tangible_find, "config", "|include these parameters in the table:" "|" "| plane : the plane to search (a string)" - "| centerx : x-coordinate of the center of the search" - "| centery : y-coordinate of the center of the search" - "| centerz : z-coordinate of the center of the search" - "| radius : the radius of the search" + "| center : xyz of the center of the search (a vector)" + "| radius : the radius of the search (a vector or number)" "| shape : 'box', 'sphere', or 'cylinder'" "|" "|Shape has a default: 'sphere'. The other parameters do" "|not have default values." "|" - "|Instead of specifying the radius as a single float," - "|you may optionally specify separate radii for each dimension." - "|" - "| radiusx : the radius in the x-dimension." - "| radiusy : the radius in the y-dimension." - "| radiusz : the radius in the z-dimension." - "|" - "|If you specify different radii in each dimension, then the" - "|'sphere' shape will actually be a spheroid, and the 'cylinder'" - "|shape will actually be a cylindroid." + "|If you specify the radius as a vector, ie, different radii in" + "|each dimension, then the 'sphere' shape will actually be a" + "|spheroid, and the 'cylinder' shape will actually be a cylindroid." "|" "|Instead of specifying the center and plane, you can specify" "|a tangible to search near:"