314 lines
9.2 KiB
C++
314 lines
9.2 KiB
C++
|
|
#include "world.hpp"
|
|
#include "pprint.hpp"
|
|
|
|
static void tangible_getall(LuaStack &LS0, LuaSlot list, const util::IdVector &idv) {
|
|
LuaVar tangibles, tan;
|
|
LuaStack LS(LS0.state(), tangibles, tan);
|
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
assert(LS.istable(tangibles));
|
|
LS.set(list, LuaNewTable);
|
|
int index = 1;
|
|
for (int64_t id : idv) {
|
|
LS.rawget(tan, tangibles, id);
|
|
assert(LS.istable(tan));
|
|
LS.rawset(list, index++, tan);
|
|
}
|
|
LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_animstate, "c") {
|
|
LuaArg tanobj;
|
|
LuaRet graphic, plane, x, y, z, facing;
|
|
LuaStack LS(L, tanobj, graphic, plane, x, y, z, facing);
|
|
World *w = World::fetch_global_pointer(L);
|
|
Tangible *tan = w->tangible_get(LS, tanobj);
|
|
const AnimStep &aqback = tan->anim_queue_.back();
|
|
LS.set(graphic, aqback.graphic());
|
|
LS.set(plane, aqback.plane());
|
|
LS.set(x, aqback.xyz().x);
|
|
LS.set(y, aqback.xyz().y);
|
|
LS.set(z, aqback.xyz().z);
|
|
LS.set(facing, aqback.facing());
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_animate, "c") {
|
|
LuaArg tanobj, config;
|
|
LuaStack LS(L, tanobj, config);
|
|
World *w = World::fetch_global_pointer(L);
|
|
Tangible *tan = w->tangible_get(LS, tanobj);
|
|
int64_t id = w->alloc_id_predictable();
|
|
const AnimStep &prev = tan->anim_queue_.back();
|
|
AnimStep step;
|
|
step.from_lua(L, config.index(), false, prev);
|
|
if (step.action() == "") {
|
|
luaL_error(L, "animation action must be specified");
|
|
}
|
|
tan->anim_queue_.add(id, step);
|
|
tan->update_plane_item();
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_setclass, "c") {
|
|
LuaArg tanobj, classname;
|
|
LuaVar classtab, mt;
|
|
LuaStack LS(L, tanobj, classname, classtab, mt);
|
|
World *w = World::fetch_global_pointer(L);
|
|
w->tangible_get(LS, tanobj);
|
|
if (LS.classname(classname) != "") {
|
|
LS.set(classtab, classname);
|
|
} else {
|
|
LS.getclass(classtab, classname);
|
|
}
|
|
LS.getmetatable(mt, tanobj);
|
|
LS.rawset(mt, "__index", classtab);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_getclass, "c") {
|
|
LuaArg tanobj;
|
|
LuaVar mt, classtab;
|
|
LuaRet classname;
|
|
LuaStack LS(L, tanobj, mt, classtab, classname);
|
|
World *w = World::fetch_global_pointer(L);
|
|
w->tangible_get(LS, tanobj);
|
|
LS.getmetatable(mt, tanobj);
|
|
LS.rawget(classtab, mt, "__index");
|
|
std::string name = LS.classname(classtab);
|
|
if (name == "") {
|
|
LS.set(classname, LuaNil);
|
|
} else {
|
|
LS.set(classname, name);
|
|
}
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_delete, "c") {
|
|
LuaArg tanobj;
|
|
LuaStack LS(L, tanobj);
|
|
World *w = World::fetch_global_pointer(L);
|
|
Tangible *tan = w->tangible_get(LS, tanobj);
|
|
assert(tan != nullptr); // this should be checked above.
|
|
if (tan->is_an_actor()) {
|
|
luaL_error(L, "Cannot delete a player using tangible.delete, use tangible.redirect instead.");
|
|
return 0;
|
|
}
|
|
w->tangible_delete(tan->id());
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_build, "c") {
|
|
LuaArg config;
|
|
LuaVar classname, classtab, mt;
|
|
LuaRet database;
|
|
LuaStack LS(L, config, classname, classtab, database, mt);
|
|
|
|
LS.checktable(config);
|
|
// Get the class of the new tangible.
|
|
LS.rawget(classname, config, "class");
|
|
|
|
if (LS.isnil(classname)) {
|
|
luaL_error(L, "must specify a class name");
|
|
} else if (LS.classname(classname) != "") {
|
|
LS.set(classtab, classname);
|
|
} else {
|
|
LS.getclass(classtab, classname);
|
|
}
|
|
|
|
// Parse the initial animation step.
|
|
AnimStep initstep, blank;
|
|
initstep.from_lua(L, config.index(), true, blank);
|
|
if (!initstep.has_xyz()) {
|
|
luaL_error(L, "You must specify (X,Y,Z) for new tangible");
|
|
}
|
|
if (!initstep.has_plane()) {
|
|
luaL_error(L, "You must specify plane for new tangible");
|
|
}
|
|
if (!initstep.has_graphic()) {
|
|
luaL_error(L, "You must specify graphic for new tangible");
|
|
}
|
|
|
|
// TODO: generate error if there's extra crap in the config table.
|
|
|
|
World *w = World::fetch_global_pointer(L);
|
|
int64_t new_id = w->alloc_id_predictable();
|
|
Tangible *tan = w->tangible_make(L, new_id, "nowhere", true);
|
|
lua_replace(L, database.index());
|
|
|
|
// Update the class of the new tangible.
|
|
LS.getmetatable(mt, database);
|
|
LS.rawset(mt, "__index", classtab);
|
|
|
|
// Update the animation queue and planemap of the new tangible.
|
|
int64_t stepid = w->alloc_id_predictable();
|
|
tan->anim_queue_.add(stepid, initstep);
|
|
tan->update_plane_item();
|
|
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_get, "c") {
|
|
LuaArg id;
|
|
LuaVar tangibles;
|
|
LuaRet database;
|
|
LuaStack LS(L, id, tangibles, database);
|
|
int64_t nid = LS.ckinteger(id);
|
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
LS.rawget(database, tangibles, id);
|
|
if (!LS.istable(database)) {
|
|
luaL_error(L, "Not a tangible ID: %d", nid);
|
|
}
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_redirect, "c") {
|
|
LuaArg actor1, actor2, bldz;
|
|
LuaStack LS(L, actor1, actor2, bldz);
|
|
World *w = World::fetch_global_pointer(L);
|
|
bool bulldoze = LS.ckboolean(bldz);
|
|
Tangible *tan1 = w->tangible_get(LS, actor1);
|
|
if (!tan1->is_an_actor()) {
|
|
luaL_error(L, "redirect source is not an actor");
|
|
}
|
|
if (LS.isnil(actor2)) {
|
|
w->redirects_[tan1->id()] = 0;
|
|
} else {
|
|
Tangible *tan2 = w->tangible_get(LS, actor2);
|
|
tan2->configure_id_pool_for_actor();
|
|
w->redirects_[tan1->id()] = tan2->id();
|
|
}
|
|
if (bulldoze) {
|
|
w->tangible_delete(tan1->id());
|
|
}
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_id, "c") {
|
|
LuaArg tanobj;
|
|
LuaRet id;
|
|
LuaStack LS(L, tanobj, id);
|
|
LS.set(id, World::tangible_id(LS, tanobj));
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_actor, "c") {
|
|
LuaRet actor;
|
|
LuaVar tangibles;
|
|
LuaStack LS(L, tangibles, actor);
|
|
World *w = World::fetch_global_pointer(L);
|
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
LS.rawget(actor, tangibles, w->lthread_actor_id_);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_place, "c") {
|
|
LuaRet place;
|
|
LuaVar tangibles;
|
|
LuaStack LS(L, tangibles, place);
|
|
World *w = World::fetch_global_pointer(L);
|
|
LS.rawget(tangibles, LuaRegistry, "tangibles");
|
|
LS.rawget(place, tangibles, w->lthread_place_id_);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_near, "c") {
|
|
LuaArg ltan, lradius, lomit_nowhere, lomit_self;
|
|
LuaRet list;
|
|
LuaStack LS(L, ltan, lradius, lomit_nowhere, lomit_self, list);
|
|
World *w = World::fetch_global_pointer(L);
|
|
Tangible *tan = w->tangible_get(LS, ltan);
|
|
double radius = LS.cknumber(lradius);
|
|
bool omit_nowhere = LS.ckboolean(lomit_nowhere);
|
|
bool omit_self = LS.ckboolean(lomit_self);
|
|
const AnimStep &aqback = tan->anim_queue_.back();
|
|
util::IdVector idv = w->plane_map_.scan_radius(aqback.plane(), aqback.xyz().x, aqback.xyz().y, radius, omit_nowhere, tan->id(), omit_self);
|
|
tangible_getall(LS, list, idv);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(tangible_scan, "c") {
|
|
LuaArg lplane, lx, ly, lradius, lomit_nowhere;
|
|
LuaRet list;
|
|
LuaStack LS(L, lplane, lx, ly, lradius, lomit_nowhere, list);
|
|
World *w = World::fetch_global_pointer(L);
|
|
std::string plane = LS.ckstring(lplane);
|
|
double x = LS.cknumber(lx);
|
|
double y = LS.cknumber(ly);
|
|
double radius = LS.cknumber(lradius);
|
|
bool omit_nowhere = LS.ckboolean(lomit_nowhere);
|
|
util::IdVector idv = w->plane_map_.scan_radius(plane, x, y, radius, omit_nowhere, 0, false);
|
|
tangible_getall(LS, list, idv);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(world_wait, "f") {
|
|
if ((lua_gettop(L) != 1) || (lua_type(L, -1) != LUA_TNUMBER)) {
|
|
luaL_error(L, "Argument to wait must be a number.");
|
|
}
|
|
return lua_yield(L, 1);
|
|
}
|
|
|
|
LuaDefine(tangible_nopredict, "c") {
|
|
if (lua_gettop(L) != 0) {
|
|
luaL_error(L, "tangible.nopredict takes no arguments");
|
|
}
|
|
World *w = World::fetch_global_pointer(L);
|
|
if (util::world_type_authoritative(w->world_type_)) {
|
|
return 0;
|
|
} else {
|
|
return lua_yield(L, 0);
|
|
}
|
|
}
|
|
|
|
LuaDefine(world_getregistry, "f") {
|
|
lua_pushvalue(L, LUA_REGISTRYINDEX);
|
|
return 1;
|
|
}
|
|
|
|
LuaDefine(world_xtype, "f") {
|
|
LuaArg tab;
|
|
LuaRet rtype;
|
|
LuaStack LS(L, tab, rtype);
|
|
int xt = LS.xtype(tab);
|
|
LS.set(rtype, xt);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(world_settabletype, "f") {
|
|
LuaArg tab, ttype;
|
|
LuaStack LS(L, tab, ttype);
|
|
if (!LS.istable(tab)) {
|
|
luaL_error(L, "Not a table");
|
|
}
|
|
int tt = LS.ckinteger(ttype);
|
|
if ((tt < LUA_TT_GENERAL) || (tt > LUA_TT_CLASS)) {
|
|
luaL_error(L, "table type out of range");
|
|
}
|
|
LS.settabletype(tab, tt);
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(world_pprint, "f") {
|
|
World *w = World::fetch_global_pointer(L);
|
|
std::ostream *ostream = w->lthread_print_stream();
|
|
LuaStack LS(L);
|
|
for (int i = 1; i <= lua_gettop(L); i++) {
|
|
LuaSpecial root(i);
|
|
pprint(LS, root, true, ostream);
|
|
(*ostream) << std::endl;
|
|
}
|
|
return LS.result();
|
|
}
|
|
|
|
LuaDefine(world_print, "f") {
|
|
World *w = World::fetch_global_pointer(L);
|
|
std::ostream *ostream = w->lthread_print_stream();
|
|
LuaStack LS(L);
|
|
for (int i = 1; i <= lua_gettop(L); i++) {
|
|
LuaSpecial root(i);
|
|
atomic_print(LS, root, ostream);
|
|
(*ostream) << std::endl;
|
|
}
|
|
return LS.result();
|
|
} |