diff options
Diffstat (limited to 'src/script/lua_api')
-rw-r--r-- | src/script/lua_api/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/script/lua_api/l_base.cpp | 5 | ||||
-rw-r--r-- | src/script/lua_api/l_base.h | 3 | ||||
-rw-r--r-- | src/script/lua_api/l_client.cpp | 261 | ||||
-rw-r--r-- | src/script/lua_api/l_client.h | 33 | ||||
-rw-r--r-- | src/script/lua_api/l_clientobject.cpp | 342 | ||||
-rw-r--r-- | src/script/lua_api/l_clientobject.h | 106 | ||||
-rw-r--r-- | src/script/lua_api/l_env.cpp | 169 | ||||
-rw-r--r-- | src/script/lua_api/l_env.h | 12 | ||||
-rw-r--r-- | src/script/lua_api/l_inventoryaction.cpp | 215 | ||||
-rw-r--r-- | src/script/lua_api/l_inventoryaction.h | 74 | ||||
-rw-r--r-- | src/script/lua_api/l_item.cpp | 20 | ||||
-rw-r--r-- | src/script/lua_api/l_localplayer.cpp | 148 | ||||
-rw-r--r-- | src/script/lua_api/l_localplayer.h | 28 | ||||
-rw-r--r-- | src/script/lua_api/l_mainmenu.cpp | 4 | ||||
-rw-r--r-- | src/script/lua_api/l_server.cpp | 1 | ||||
-rw-r--r-- | src/script/lua_api/l_util.cpp | 5 |
17 files changed, 1400 insertions, 28 deletions
diff --git a/src/script/lua_api/CMakeLists.txt b/src/script/lua_api/CMakeLists.txt index 32f6a2793..3f1b89085 100644 --- a/src/script/lua_api/CMakeLists.txt +++ b/src/script/lua_api/CMakeLists.txt @@ -28,6 +28,8 @@ set(common_SCRIPT_LUA_API_SRCS set(client_SCRIPT_LUA_API_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/l_camera.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_client.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_clientobject.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_localplayer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_mainmenu.cpp ${CMAKE_CURRENT_SOURCE_DIR}/l_minimap.cpp diff --git a/src/script/lua_api/l_base.cpp b/src/script/lua_api/l_base.cpp index f842671b8..fce6282a5 100644 --- a/src/script/lua_api/l_base.cpp +++ b/src/script/lua_api/l_base.cpp @@ -55,6 +55,11 @@ Client *ModApiBase::getClient(lua_State *L) { return getScriptApiBase(L)->getClient(); } + +Game *ModApiBase::getGame(lua_State *L) +{ + return getScriptApiBase(L)->getGame(); +} #endif IGameDef *ModApiBase::getGameDef(lua_State *L) diff --git a/src/script/lua_api/l_base.h b/src/script/lua_api/l_base.h index aa5905d26..9ba50dabf 100644 --- a/src/script/lua_api/l_base.h +++ b/src/script/lua_api/l_base.h @@ -32,6 +32,7 @@ extern "C" { #ifndef SERVER class Client; +class Game; class GUIEngine; #endif @@ -47,11 +48,11 @@ public: static ServerInventoryManager *getServerInventoryMgr(lua_State *L); #ifndef SERVER static Client* getClient(lua_State *L); + static Game* getGame(lua_State *L); static GUIEngine* getGuiEngine(lua_State *L); #endif // !SERVER static IGameDef* getGameDef(lua_State *L); - static Environment* getEnv(lua_State *L); // When we are not loading the mod, this function returns "." diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index aaced7cd0..265c7d3fc 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -24,16 +24,19 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/clientevent.h" #include "client/sound.h" #include "client/clientenvironment.h" +#include "client/game.h" #include "common/c_content.h" #include "common/c_converter.h" #include "cpp_api/s_base.h" #include "gettext.h" #include "l_internal.h" +#include "l_clientobject.h" #include "lua_api/l_nodemeta.h" #include "gui/mainmenumanager.h" #include "map.h" #include "util/string.h" #include "nodedef.h" +#include "client/keycode.h" #define checkCSMRestrictionFlag(flag) \ ( getClient(L)->checkCSMRestrictionFlag(CSMRestrictionFlags::flag) ) @@ -414,6 +417,253 @@ int ModApiClient::l_get_csm_restrictions(lua_State *L) return 1; } +// send_damage(damage) +int ModApiClient::l_send_damage(lua_State *L) +{ + u16 damage = luaL_checknumber(L, 1); + getClient(L)->sendDamage(damage); + return 0; +} + +// place_node(pos) +int ModApiClient::l_place_node(lua_State *L) +{ + Client *client = getClient(L); + ClientMap &map = client->getEnv().getClientMap(); + LocalPlayer *player = client->getEnv().getLocalPlayer(); + ItemStack selected_item, hand_item; + player->getWieldedItem(&selected_item, &hand_item); + const ItemDefinition &selected_def = selected_item.getDefinition(getGameDef(L)->idef()); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + NodeMetadata *meta = map.getNodeMetadata(pos); + g_game->nodePlacement(selected_def, selected_item, pos, pos, pointed, meta, true); + return 0; +} + +// dig_node(pos) +int ModApiClient::l_dig_node(lua_State *L) +{ + Client *client = getClient(L); + v3s16 pos = read_v3s16(L, 1); + PointedThing pointed; + pointed.type = POINTEDTHING_NODE; + pointed.node_abovesurface = pos; + pointed.node_undersurface = pos; + client->interact(INTERACT_START_DIGGING, pointed); + client->interact(INTERACT_DIGGING_COMPLETED, pointed); + client->removeNode(pos); + return 0; +} + +// get_inventory(location) +int ModApiClient::l_get_inventory(lua_State *L) +{ + Client *client = getClient(L); + InventoryLocation inventory_location; + Inventory *inventory; + std::string location; + + location = readParam<std::string>(L, 1); + + try { + inventory_location.deSerialize(location); + inventory = client->getInventory(inventory_location); + if (! inventory) + throw SerializationError(std::string("Attempt to access nonexistant inventory (") + location + ")"); + push_inventory_lists(L, *inventory); + } catch (SerializationError &) { + lua_pushnil(L); + } + + return 1; +} + +// set_keypress(key_setting, pressed) -> returns true on success +int ModApiClient::l_set_keypress(lua_State *L) +{ + std::string setting_name = "keymap_" + readParam<std::string>(L, 1); + bool pressed = lua_isboolean(L, 2) && readParam<bool>(L, 2); + try { + KeyPress keyCode = getKeySetting(setting_name.c_str()); + if (pressed) + g_game->input->setKeypress(keyCode); + else + g_game->input->unsetKeypress(keyCode); + lua_pushboolean(L, true); + } catch (SettingNotFoundException &) { + lua_pushboolean(L, false); + } + return 1; +} + +// drop_selected_item() +int ModApiClient::l_drop_selected_item(lua_State *L) +{ + g_game->dropSelectedItem(); + return 0; +} + +// get_objects_inside_radius(pos, radius) +int ModApiClient::l_get_objects_inside_radius(lua_State *L) +{ + ClientEnvironment &env = getClient(L)->getEnv(); + + v3f pos = checkFloatPos(L, 1); + float radius = readParam<float>(L, 2) * BS; + + std::vector<DistanceSortedActiveObject> objs; + env.getActiveObjects(pos, radius, objs); + + int i = 0; + lua_createtable(L, objs.size(), 0); + for (const auto obj : objs) { + push_objectRef(L, obj.obj->getId()); + lua_rawseti(L, -2, ++i); + } + return 1; +} + +// make_screenshot() +int ModApiClient::l_make_screenshot(lua_State *L) +{ + getClient(L)->makeScreenshot(); + return 0; +} + +/* +`pointed_thing` +--------------- + +* `{type="nothing"}` +* `{type="node", under=pos, above=pos}` + * Indicates a pointed node selection box. + * `under` refers to the node position behind the pointed face. + * `above` refers to the node position in front of the pointed face. +* `{type="object", ref=ObjectRef}` + +Exact pointing location (currently only `Raycast` supports these fields): + +* `pointed_thing.intersection_point`: The absolute world coordinates of the + point on the selection box which is pointed at. May be in the selection box + if the pointer is in the box too. +* `pointed_thing.box_id`: The ID of the pointed selection box (counting starts + from 1). +* `pointed_thing.intersection_normal`: Unit vector, points outwards of the + selected selection box. This specifies which face is pointed at. + Is a null vector `{x = 0, y = 0, z = 0}` when the pointer is inside the + selection box. +*/ + +// interact(action, pointed_thing) +int ModApiClient::l_interact(lua_State *L) +{ + std::string action_str = readParam<std::string>(L, 1); + InteractAction action; + + if (action_str == "start_digging") + action = INTERACT_START_DIGGING; + else if (action_str == "stop_digging") + action = INTERACT_STOP_DIGGING; + else if (action_str == "digging_completed") + action = INTERACT_DIGGING_COMPLETED; + else if (action_str == "place") + action = INTERACT_PLACE; + else if (action_str == "use") + action = INTERACT_USE; + else if (action_str == "activate") + action = INTERACT_ACTIVATE; + else + return 0; + + lua_getfield(L, 2, "type"); + if (! lua_isstring(L, -1)) + return 0; + std::string type_str = lua_tostring(L, -1); + lua_pop(L, 1); + + PointedThingType type; + + if (type_str == "nothing") + type = POINTEDTHING_NOTHING; + else if (type_str == "node") + type = POINTEDTHING_NODE; + else if (type_str == "object") + type = POINTEDTHING_OBJECT; + else + return 0; + + PointedThing pointed; + pointed.type = type; + ClientObjectRef *obj; + + switch (type) { + case POINTEDTHING_NODE: + lua_getfield(L, 2, "under"); + pointed.node_undersurface = check_v3s16(L, -1); + + lua_getfield(L, 2, "above"); + pointed.node_abovesurface = check_v3s16(L, -1); + break; + case POINTEDTHING_OBJECT: + lua_getfield(L, 2, "ref"); + obj = ClientObjectRef::checkobject(L, -1); + pointed.object_id = obj->getClientActiveObject()->getId(); + break; + default: + break; + } + + getClient(L)->interact(action, pointed); + lua_pushboolean(L, true); + return 1; +} + +StringMap *table_to_stringmap(lua_State *L, int index) +{ + StringMap *m = new StringMap; + + lua_pushvalue(L, index); + lua_pushnil(L); + + while (lua_next(L, -2)) { + lua_pushvalue(L, -2); + std::basic_string<char> key = lua_tostring(L, -1); + std::basic_string<char> value = lua_tostring(L, -2); + (*m)[key] = value; + lua_pop(L, 2); + } + + lua_pop(L, 1); + + return m; +} + +// send_inventory_fields(formname, fields) +// Only works if the inventory form was opened beforehand. +int ModApiClient::l_send_inventory_fields(lua_State *L) +{ + std::string formname = luaL_checkstring(L, 1); + StringMap *fields = table_to_stringmap(L, 2); + + getClient(L)->sendInventoryFields(formname, *fields); + return 0; +} + +// send_nodemeta_fields(position, formname, fields) +int ModApiClient::l_send_nodemeta_fields(lua_State *L) +{ + v3s16 pos = check_v3s16(L, 1); + std::string formname = luaL_checkstring(L, 2); + StringMap *m = table_to_stringmap(L, 3); + + getClient(L)->sendNodemetaFields(pos, formname, *m); + return 0; +} + void ModApiClient::Initialize(lua_State *L, int top) { API_FCT(get_current_modname); @@ -441,4 +691,15 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_builtin_path); API_FCT(get_language); API_FCT(get_csm_restrictions); + API_FCT(send_damage); + API_FCT(place_node); + API_FCT(dig_node); + API_FCT(get_inventory); + API_FCT(set_keypress); + API_FCT(drop_selected_item); + API_FCT(get_objects_inside_radius); + API_FCT(make_screenshot); + API_FCT(interact); + API_FCT(send_inventory_fields); + API_FCT(send_nodemeta_fields); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 5dc3efdad..caf21f78e 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -105,6 +105,39 @@ private: // get_csm_restrictions() static int l_get_csm_restrictions(lua_State *L); + // send_damage(damage) + static int l_send_damage(lua_State *L); + + // place_node(pos) + static int l_place_node(lua_State *L); + + // dig_node(pos) + static int l_dig_node(lua_State *L); + + // get_inventory(location) + static int l_get_inventory(lua_State *L); + + // set_keypress(key_setting, pressed) + static int l_set_keypress(lua_State *L); + + // drop_selected_item() + static int l_drop_selected_item(lua_State *L); + + // get_objects_inside_radius(pos, radius) + static int l_get_objects_inside_radius(lua_State *L); + + // make_screenshot() + static int l_make_screenshot(lua_State *L); + + // interact(action, pointed_thing) + static int l_interact(lua_State *L); + + // send_inventory_fields(formname, fields) + static int l_send_inventory_fields(lua_State *L); + + // send_nodemeta_fields(position, formname, fields) + static int l_send_nodemeta_fields(lua_State *L); + public: static void Initialize(lua_State *L, int top); }; diff --git a/src/script/lua_api/l_clientobject.cpp b/src/script/lua_api/l_clientobject.cpp new file mode 100644 index 000000000..d3739639a --- /dev/null +++ b/src/script/lua_api/l_clientobject.cpp @@ -0,0 +1,342 @@ +/* +Dragonfire +Copyright (C) 2020 system32 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "lua_api/l_clientobject.h" +#include "l_internal.h" +#include "common/c_converter.h" +#include "common/c_content.h" +#include "client/client.h" +#include "object_properties.h" +#include "util/pointedthing.h" + +ClientActiveObject *ClientObjectRef::getClientActiveObject() +{ + return m_object; +} + +ClientObjectRef *ClientObjectRef::checkobject(lua_State *L, int narg) +{ + luaL_checktype(L, narg, LUA_TUSERDATA); + void *userdata = luaL_checkudata(L, narg, className); + if (!userdata) + luaL_typerror(L, narg, className); + return *(ClientObjectRef **)userdata; +} + +ClientActiveObject *ClientObjectRef::get_cao(ClientObjectRef *ref) +{ + ClientActiveObject *obj = ref->m_object; + return obj; +} + +GenericCAO *ClientObjectRef::get_generic_cao(ClientObjectRef *ref, lua_State *L) +{ + ClientActiveObject *obj = get_cao(ref); + if (!obj) + return nullptr; + ClientEnvironment &env = getClient(L)->getEnv(); + GenericCAO *gcao = env.getGenericCAO(obj->getId()); + return gcao; +} + +int ClientObjectRef::l_get_pos(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + ClientActiveObject *cao = get_cao(ref); + if (!cao) + return 0; + push_v3f(L, cao->getPosition() / BS); + return 1; +} + +int ClientObjectRef::l_get_velocity(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + push_v3f(L, gcao->getVelocity() / BS); + return 1; +} + +int ClientObjectRef::l_get_acceleration(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + push_v3f(L, gcao->getAcceleration() / BS); + return 1; +} + +int ClientObjectRef::l_get_rotation(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + push_v3f(L, gcao->getRotation()); + return 1; +} + +int ClientObjectRef::l_is_player(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + lua_pushboolean(L, gcao->isPlayer()); + return 1; +} + +int ClientObjectRef::l_is_local_player(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + lua_pushboolean(L, gcao->isLocalPlayer()); + return 1; +} + +int ClientObjectRef::l_get_name(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + lua_pushstring(L, gcao->getName().c_str()); + return 1; +} + +int ClientObjectRef::l_get_attach(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + ClientActiveObject *parent = gcao->getParent(); + if (!parent) + return 0; + push_objectRef(L, parent->getId()); + return 1; +} + +int ClientObjectRef::l_get_nametag(lua_State *L) +{ + log_deprecated(L, "Deprecated call to get_nametag, use get_properties().nametag " + "instead"); + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + ObjectProperties *props = gcao->getProperties(); + lua_pushstring(L, props->nametag.c_str()); + return 1; +} + +int ClientObjectRef::l_get_item_textures(lua_State *L) +{ + log_deprecated(L, "Deprecated call to get_item_textures, use " + "get_properties().textures instead"); + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + ObjectProperties *props = gcao->getProperties(); + lua_newtable(L); + + for (std::string &texture : props->textures) { + lua_pushstring(L, texture.c_str()); + } + return 1; +} + +int ClientObjectRef::l_get_max_hp(lua_State *L) +{ + log_deprecated(L, "Deprecated call to get_max_hp, use get_properties().hp_max " + "instead"); + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + ObjectProperties *props = gcao->getProperties(); + lua_pushnumber(L, props->hp_max); + return 1; +} + +int ClientObjectRef::l_get_properties(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + ObjectProperties *prop = gcao->getProperties(); + push_object_properties(L, prop); + return 1; +} + +int ClientObjectRef::l_set_properties(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + ObjectProperties prop = *gcao->getProperties(); + read_object_properties(L, 2, nullptr, &prop, getClient(L)->idef()); + gcao->setProperties(prop); + return 1; +} + +int ClientObjectRef::l_get_hp(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + lua_pushnumber(L, gcao->getHp()); + return 1; +} + +int ClientObjectRef::l_punch(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0); + getClient(L)->interact(INTERACT_START_DIGGING, pointed); + return 0; +} + +int ClientObjectRef::l_rightclick(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + PointedThing pointed(gcao->getId(), v3f(0, 0, 0), v3s16(0, 0, 0), 0); + getClient(L)->interact(INTERACT_PLACE, pointed); + return 0; +} + +int ClientObjectRef::l_remove(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + ClientActiveObject *cao = get_cao(ref); + if (!cao) + return 0; + getClient(L)->getEnv().removeActiveObject(cao->getId()); + + return 0; +} + +int ClientObjectRef::l_set_nametag_images(lua_State *L) +{ + ClientObjectRef *ref = checkobject(L, 1); + GenericCAO *gcao = get_generic_cao(ref, L); + if (!gcao) + return 0; + gcao->nametag_images.clear(); + if (lua_istable(L, 2)) { + lua_pushnil(L); + while (lua_next(L, 2) != 0) { + gcao->nametag_images.push_back(lua_tostring(L, -1)); + lua_pop(L, 1); + } + } + gcao->updateNametag(); + + return 0; +} + +ClientObjectRef::ClientObjectRef(ClientActiveObject *object) : m_object(object) +{ +} + +void ClientObjectRef::create(lua_State *L, ClientActiveObject *object) +{ + ClientObjectRef *o = new ClientObjectRef(object); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); +} + +void ClientObjectRef::create(lua_State *L, s16 id) +{ + create(L, ((ClientEnvironment *)getEnv(L))->getActiveObject(id)); +} + +void ClientObjectRef::set_null(lua_State *L) +{ + ClientObjectRef *obj = checkobject(L, -1); + obj->m_object = nullptr; +} + +int ClientObjectRef::gc_object(lua_State *L) +{ + ClientObjectRef *obj = *(ClientObjectRef **)(lua_touserdata(L, 1)); + delete obj; + return 0; +} + +// taken from LuaLocalPlayer +void ClientObjectRef::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); // hide metatable from lua getmetatable() + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pop(L, 1); // Drop metatable + + luaL_openlib(L, 0, methods, 0); // fill methodtable + lua_pop(L, 1); // Drop methodtable +} + +const char ClientObjectRef::className[] = "ClientObjectRef"; +luaL_Reg ClientObjectRef::methods[] = {luamethod(ClientObjectRef, get_pos), + luamethod(ClientObjectRef, get_velocity), + luamethod(ClientObjectRef, get_acceleration), + luamethod(ClientObjectRef, get_rotation), + luamethod(ClientObjectRef, is_player), + luamethod(ClientObjectRef, is_local_player), + luamethod(ClientObjectRef, get_name), + luamethod(ClientObjectRef, get_attach), + luamethod(ClientObjectRef, get_nametag), + luamethod(ClientObjectRef, get_item_textures), + luamethod(ClientObjectRef, get_properties), + luamethod(ClientObjectRef, set_properties), + luamethod(ClientObjectRef, get_hp), + luamethod(ClientObjectRef, get_max_hp), luamethod(ClientObjectRef, punch), + luamethod(ClientObjectRef, rightclick), + luamethod(ClientObjectRef, remove), + luamethod(ClientObjectRef, set_nametag_images), {0, 0}}; diff --git a/src/script/lua_api/l_clientobject.h b/src/script/lua_api/l_clientobject.h new file mode 100644 index 000000000..c4c95cb41 --- /dev/null +++ b/src/script/lua_api/l_clientobject.h @@ -0,0 +1,106 @@ +/* +Dragonfire +Copyright (C) 2020 system32 + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "lua_api/l_base.h" +#include "client/clientobject.h" +#include "client/content_cao.h" + +class ClientObjectRef : public ModApiBase +{ +public: + ClientObjectRef(ClientActiveObject *object); + + ~ClientObjectRef() = default; + + ClientActiveObject *getClientActiveObject(); + + static void Register(lua_State *L); + + static void create(lua_State *L, ClientActiveObject *object); + static void create(lua_State *L, s16 id); + + static void set_null(lua_State *L); + + static ClientObjectRef *checkobject(lua_State *L, int narg); + +private: + ClientActiveObject *m_object = nullptr; + static const char className[]; + static luaL_Reg methods[]; + + static ClientActiveObject *get_cao(ClientObjectRef *ref); + static GenericCAO *get_generic_cao(ClientObjectRef *ref, lua_State *L); + + static int gc_object(lua_State *L); + + // get_pos(self) + // returns: {x=num, y=num, z=num} + static int l_get_pos(lua_State *L); + + // get_velocity(self) + static int l_get_velocity(lua_State *L); + + // get_acceleration(self) + static int l_get_acceleration(lua_State *L); + + // get_rotation(self) + static int l_get_rotation(lua_State *L); + + // is_player(self) + static int l_is_player(lua_State *L); + + // is_local_player(self) + static int l_is_local_player(lua_State *L); + + // get_name(self) + static int l_get_name(lua_State *L); + + // get_attach(self) + static int l_get_attach(lua_State *L); + + // get_nametag(self) + static int l_get_nametag(lua_State *L); + + // get_item_textures(self) + static int l_get_item_textures(lua_State *L); + + // get_properties(self) + static int l_get_properties(lua_State *L); + + // set_properties(self, properties) + static int l_set_properties(lua_State *L); + + // get_hp(self) + static int l_get_hp(lua_State *L); + + // get_max_hp(self) + static int l_get_max_hp(lua_State *L); + + // punch(self) + static int l_punch(lua_State *L); + + // rightclick(self) + static int l_rightclick(lua_State *L); + + // remove(self) + static int l_remove(lua_State *L); + + // set_nametag_images(self, images) + static int l_set_nametag_images(lua_State *L); +}; diff --git a/src/script/lua_api/l_env.cpp b/src/script/lua_api/l_env.cpp index 7640f2782..a489d245c 100644 --- a/src/script/lua_api/l_env.cpp +++ b/src/script/lua_api/l_env.cpp @@ -857,7 +857,6 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) int radius = luaL_checkinteger(L, 2); std::vector<content_t> filter; collectNodeIds(L, 3, ndef, filter); - int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; #ifndef SERVER @@ -880,6 +879,165 @@ int ModApiEnvMod::l_find_node_near(lua_State *L) return 0; } +// find_nodes_near(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + auto it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + +// find_nodes_near_under_air(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near_under_air(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + v3s16 psurf(p.X, p.Y + 1, p.Z); + content_t csurf = map.getNode(psurf).getContent(); + if (c == CONTENT_AIR || csurf != CONTENT_AIR) + continue; + auto it = std::find(filter.begin(), filter.end(), c); + if (it != filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + +// find_nodes_near_under_air_except(pos, radius, nodenames, [search_center]) +// nodenames: eg. {"ignore", "group:tree"} or "default:dirt" +int ModApiEnvMod::l_find_nodes_near_under_air_except(lua_State *L) +{ + GET_PLAIN_ENV_PTR; + + const NodeDefManager *ndef = env->getGameDef()->ndef(); + Map &map = env->getMap(); + + v3s16 pos = read_v3s16(L, 1); + int radius = luaL_checkinteger(L, 2); + std::vector<content_t> filter; + collectNodeIds(L, 3, ndef, filter); + int start_radius = (lua_isboolean(L, 4) && readParam<bool>(L, 4)) ? 0 : 1; + +#ifndef SERVER + // Client API limitations + if (Client *client = getClient(L)) + radius = client->CSMClampRadius(pos, radius); +#endif + + std::vector<u32> individual_count; + individual_count.resize(filter.size()); + + lua_newtable(L); + u32 i = 0; + + for (int d = start_radius; d <= radius; d++) { + const std::vector<v3s16> &list = FacePositionCache::getFacePositions(d); + for (const v3s16 &posi : list) { + v3s16 p = pos + posi; + content_t c = map.getNode(p).getContent(); + v3s16 psurf(p.X, p.Y + 1, p.Z); + content_t csurf = map.getNode(psurf).getContent(); + if (c == CONTENT_AIR || csurf != CONTENT_AIR) + continue; + auto it = std::find(filter.begin(), filter.end(), c); + if (it == filter.end()) { + push_v3s16(L, p); + lua_rawseti(L, -2, ++i); + + u32 filt_index = it - filter.begin(); + individual_count[filt_index]++; + } + } + } + lua_createtable(L, 0, filter.size()); + for (u32 i = 0; i < filter.size(); i++) { + lua_pushinteger(L, individual_count[i]); + lua_setfield(L, -2, ndef->get(filter[i]).name.c_str()); + } + return 2; +} + static void checkArea(v3s16 &minp, v3s16 &maxp) { auto volume = VoxelArea(minp, maxp).getVolume(); @@ -1285,7 +1443,7 @@ int ModApiEnvMod::l_delete_area(lua_State *L) // max_jump, max_drop, algorithm) -> table containing path int ModApiEnvMod::l_find_path(lua_State *L) { - GET_ENV_PTR; + Environment *env = getEnv(L); v3s16 pos1 = read_v3s16(L, 1); v3s16 pos2 = read_v3s16(L, 2); @@ -1303,7 +1461,7 @@ int ModApiEnvMod::l_find_path(lua_State *L) algo = PA_DIJKSTRA; } - std::vector<v3s16> path = get_path(&env->getServerMap(), env->getGameDef()->ndef(), pos1, pos2, + std::vector<v3s16> path = get_path(&env->getMap(), env->getGameDef()->ndef(), pos1, pos2, searchdistance, max_jump, max_drop, algo); if (!path.empty()) { @@ -1504,8 +1662,13 @@ void ModApiEnvMod::InitializeClient(lua_State *L, int top) API_FCT(get_node_level); API_FCT(find_nodes_with_meta); API_FCT(find_node_near); + API_FCT(find_nodes_near); + API_FCT(find_nodes_near_under_air); + API_FCT(find_nodes_near_under_air_except); API_FCT(find_nodes_in_area); API_FCT(find_nodes_in_area_under_air); + API_FCT(get_voxel_manip); + API_FCT(find_path); API_FCT(line_of_sight); API_FCT(raycast); } diff --git a/src/script/lua_api/l_env.h b/src/script/lua_api/l_env.h index a7d406d2a..70a8d2398 100644 --- a/src/script/lua_api/l_env.h +++ b/src/script/lua_api/l_env.h @@ -134,6 +134,18 @@ private: // find_node_near(pos, radius, nodenames, search_center) -> pos or nil // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" static int l_find_node_near(lua_State *L); + + // find_nodes_near(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near(lua_State *L); + + // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near_under_air(lua_State *L); + + // find_nodes_near_under_air(pos, radius, nodenames, search_center) -> list of positions + // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" + static int l_find_nodes_near_under_air_except(lua_State *L); // find_nodes_in_area(minp, maxp, nodenames) -> list of positions // nodenames: eg. {"ignore", "group:tree"} or "default:dirt" diff --git a/src/script/lua_api/l_inventoryaction.cpp b/src/script/lua_api/l_inventoryaction.cpp new file mode 100644 index 000000000..f65137465 --- /dev/null +++ b/src/script/lua_api/l_inventoryaction.cpp @@ -0,0 +1,215 @@ +/* +Dragonfire +Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "l_inventoryaction.h" +#include "l_internal.h" +#include "client/client.h" + +int LuaInventoryAction::gc_object(lua_State *L) +{ + LuaInventoryAction *o = *(LuaInventoryAction **)(lua_touserdata(L, 1)); + delete o; + return 0; +} + +int LuaInventoryAction::mt_tostring(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + std::ostringstream os(std::ios::binary); + o->m_action->serialize(os); + lua_pushfstring(L, "InventoryAction(\"%s\")", os.str().c_str()); + return 1; +} + +int LuaInventoryAction::l_apply(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + std::ostringstream os(std::ios::binary); + o->m_action->serialize(os); + + std::istringstream is(os.str(), std::ios_base::binary); + + InventoryAction *a = InventoryAction::deSerialize(is); + + getClient(L)->inventoryAction(a); + return 0; +} + +int LuaInventoryAction::l_from(lua_State *L) +{ + GET_MOVE_ACTION + readFullInventoryLocationInto(L, &act->from_inv, &act->from_list, &act->from_i); + return 0; +} + +int LuaInventoryAction::l_to(lua_State *L) +{ + GET_MOVE_ACTION + readFullInventoryLocationInto(L, &act->to_inv, &act->to_list, &act->to_i); + return 0; +} + +int LuaInventoryAction::l_craft(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + if (o->m_action->getType() != IAction::Craft) + return 0; + + std::string locStr; + InventoryLocation loc; + + locStr = readParam<std::string>(L, 2); + + try { + loc.deSerialize(locStr); + dynamic_cast<ICraftAction *>(o->m_action)->craft_inv = loc; + } catch (SerializationError &) { + } + + return 0; +} + +int LuaInventoryAction::l_set_count(lua_State *L) +{ + LuaInventoryAction *o = checkobject(L, 1); + + s16 count = luaL_checkinteger(L, 2); + + switch (o->m_action->getType()) { + case IAction::Move: + ((IMoveAction *)o->m_action)->count = count; + break; + case IAction::Drop: + ((IDropAction *)o->m_action)->count = count; + break; + case IAction::Craft: + ((ICraftAction *)o->m_action)->count = count; + break; + } + + return 0; +} + +LuaInventoryAction::LuaInventoryAction(const IAction &type) : m_action(nullptr) +{ + switch (type) { + case IAction::Move: + m_action = new IMoveAction(); + break; + case IAction::Drop: + m_action = new IDropAction(); + break; + case IAction::Craft: + m_action = new ICraftAction(); + break; + } +} + +LuaInventoryAction::~LuaInventoryAction() +{ + delete m_action; +} + +void LuaInventoryAction::readFullInventoryLocationInto( + lua_State *L, InventoryLocation *loc, std::string *list, s16 *index) +{ + try { + loc->deSerialize(readParam<std::string>(L, 2)); + std::string l = readParam<std::string>(L, 3); + *list = l; + *index = luaL_checkinteger(L, 4) - 1; + } catch (SerializationError &) { + } +} + +int LuaInventoryAction::create_object(lua_State *L) +{ + IAction type; + std::string typeStr; + + typeStr = readParam<std::string>(L, 1); + + if (typeStr == "move") + type = IAction::Move; + else if (typeStr == "drop") + type = IAction::Drop; + else if (typeStr == "craft") + type = IAction::Craft; + else + return 0; + + LuaInventoryAction *o = new LuaInventoryAction(type); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +int LuaInventoryAction::create(lua_State *L, const IAction &type) +{ + LuaInventoryAction *o = new LuaInventoryAction(type); + *(void **)(lua_newuserdata(L, sizeof(void *))) = o; + luaL_getmetatable(L, className); + lua_setmetatable(L, -2); + return 1; +} + +LuaInventoryAction *LuaInventoryAction::checkobject(lua_State *L, int narg) +{ + return *(LuaInventoryAction **)luaL_checkudata(L, narg, className); +} + +void LuaInventoryAction::Register(lua_State *L) +{ + lua_newtable(L); + int methodtable = lua_gettop(L); + luaL_newmetatable(L, className); + int metatable = lua_gettop(L); + + lua_pushliteral(L, "__metatable"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__index"); + lua_pushvalue(L, methodtable); + lua_settable(L, metatable); + + lua_pushliteral(L, "__gc"); + lua_pushcfunction(L, gc_object); + lua_settable(L, metatable); + + lua_pushliteral(L, "__tostring"); + lua_pushcfunction(L, mt_tostring); + lua_settable(L, metatable); + + lua_pop(L, 1); + + luaL_openlib(L, 0, methods, 0); + lua_pop(L, 1); + + lua_register(L, className, create_object); +} + +const char LuaInventoryAction::className[] = "InventoryAction"; +const luaL_Reg LuaInventoryAction::methods[] = {luamethod(LuaInventoryAction, apply), + luamethod(LuaInventoryAction, from), luamethod(LuaInventoryAction, to), + luamethod(LuaInventoryAction, craft), + luamethod(LuaInventoryAction, set_count), {0, 0}}; diff --git a/src/script/lua_api/l_inventoryaction.h b/src/script/lua_api/l_inventoryaction.h new file mode 100644 index 000000000..a4cc6cbe5 --- /dev/null +++ b/src/script/lua_api/l_inventoryaction.h @@ -0,0 +1,74 @@ +/* +Dragonfire +Copyright (C) 2020 Elias Fleckenstein <eliasfleckenstein@web.de> + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#include "inventorymanager.h" +#include "lua_api/l_base.h" + +#define GET_MOVE_ACTION \ + LuaInventoryAction *o = checkobject(L, 1); \ + if (o->m_action->getType() == IAction::Craft) \ + return 0; \ + MoveAction *act = dynamic_cast<MoveAction *>(o->m_action); + +class LuaInventoryAction : public ModApiBase +{ +private: + InventoryAction *m_action; + + static void readFullInventoryLocationInto(lua_State *L, InventoryLocation *loc, + std::string *list, s16 *index); + + static const char className[]; + static const luaL_Reg methods[]; + + // Exported functions + + // garbage collector + static int gc_object(lua_State *L); + + // __tostring metamethod + static int mt_tostring(lua_State *L); + + // apply(self) + static int l_apply(lua_State *L); + + // from(self, location, list, index) + static int l_from(lua_State *L); + + // to(self, location, list, index) + static int l_to(lua_State *L); + + // craft(self, location) + static int l_craft(lua_State *L); + + // set_count(self, count) + static int l_set_count(lua_State *L); + +public: + LuaInventoryAction(const IAction &type); + ~LuaInventoryAction(); + + // LuaInventoryAction(inventory action type) + // Creates an LuaInventoryAction and leaves it on top of stack + static int create_object(lua_State *L); + // Not callable from Lua + static int create(lua_State *L, const IAction &type); + static LuaInventoryAction *checkobject(lua_State *L, int narg); + static void Register(lua_State *L); +}; diff --git a/src/script/lua_api/l_item.cpp b/src/script/lua_api/l_item.cpp index b58b994d9..9220259ff 100644 --- a/src/script/lua_api/l_item.cpp +++ b/src/script/lua_api/l_item.cpp @@ -28,7 +28,12 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include "inventory.h" #include "log.h" - +#include "script/cpp_api/s_base.h" +#ifndef SERVER +#include "client/client.h" +#include "client/renderingengine.h" +#include "client/shader.h" +#endif // garbage collector int LuaItemStack::gc_object(lua_State *L) @@ -552,9 +557,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) // Get the writable item and node definition managers from the server IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); NodeDefManager *ndef = - getServer(L)->getWritableNodeDefManager(); + getGameDef(L)->getWritableNodeDefManager(); // Check if name is defined std::string name; @@ -602,8 +607,9 @@ int ModApiItemMod::l_register_item_raw(lua_State *L) + itos(MAX_REGISTERED_CONTENT+1) + ") exceeded (" + name + ")"); } + } - + return 0; /* number of results */ } @@ -614,12 +620,12 @@ int ModApiItemMod::l_unregister_item_raw(lua_State *L) std::string name = luaL_checkstring(L, 1); IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); // Unregister the node if (idef->get(name).type == ITEM_NODE) { NodeDefManager *ndef = - getServer(L)->getWritableNodeDefManager(); + getGameDef(L)->getWritableNodeDefManager(); ndef->removeNode(name); } @@ -637,7 +643,7 @@ int ModApiItemMod::l_register_alias_raw(lua_State *L) // Get the writable item definition manager from the server IWritableItemDefManager *idef = - getServer(L)->getWritableItemDefManager(); + getGameDef(L)->getWritableItemDefManager(); idef->registerAlias(name, convert_to); diff --git a/src/script/lua_api/l_localplayer.cpp b/src/script/lua_api/l_localplayer.cpp index 2efb976c7..1da0679d6 100644 --- a/src/script/lua_api/l_localplayer.cpp +++ b/src/script/lua_api/l_localplayer.cpp @@ -17,6 +17,7 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ +#include "l_clientobject.h" #include "l_localplayer.h" #include "l_internal.h" #include "lua_api/l_item.h" @@ -24,7 +25,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/localplayer.h" #include "hud.h" #include "common/c_content.h" +#include "client/client.h" #include "client/content_cao.h" +#include "client/game.h" LuaLocalPlayer::LuaLocalPlayer(LocalPlayer *m) : m_localplayer(m) { @@ -60,6 +63,57 @@ int LuaLocalPlayer::l_get_velocity(lua_State *L) return 1; } +int LuaLocalPlayer::l_set_velocity(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + v3f pos = checkFloatPos(L, 2); + player->setSpeed(pos); + + return 0; +} + +int LuaLocalPlayer::l_get_yaw(lua_State *L) +{ + lua_pushnumber(L, wrapDegrees_0_360(g_game->cam_view.camera_yaw)); + return 1; +} + +int LuaLocalPlayer::l_set_yaw(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + if (lua_isnumber(L, 2)) { + double yaw = lua_tonumber(L, 2); + player->setYaw(yaw); + g_game->cam_view.camera_yaw = yaw; + g_game->cam_view_target.camera_yaw = yaw; + } + + return 0; +} + +int LuaLocalPlayer::l_get_pitch(lua_State *L) +{ + lua_pushnumber(L, -wrapDegrees_180(g_game->cam_view.camera_pitch) ); + return 1; +} + +int LuaLocalPlayer::l_set_pitch(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + if (lua_isnumber(L, 2)) { + double pitch = lua_tonumber(L, 2); + player->setPitch(pitch); + g_game->cam_view.camera_pitch = pitch; + g_game->cam_view_target.camera_pitch = pitch; + } + + return 0; +} + + int LuaLocalPlayer::l_get_hp(lua_State *L) { LocalPlayer *player = getobject(L, 1); @@ -81,10 +135,24 @@ int LuaLocalPlayer::l_get_wield_index(lua_State *L) { LocalPlayer *player = getobject(L, 1); - lua_pushinteger(L, player->getWieldIndex()); + lua_pushinteger(L, player->getWieldIndex() + 1); return 1; } +// set_wield_index(self) +int LuaLocalPlayer::l_set_wield_index(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + u32 index = luaL_checkinteger(L, 2) - 1; + + player->setWieldIndex(index); + g_game->processItemSelection(&g_game->runData.new_playeritem); + ItemStack selected_item, hand_item; + ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item); + g_game->camera->wield(tool_item); + return 0; +} + // get_wielded_item(self) int LuaLocalPlayer::l_get_wielded_item(lua_State *L) { @@ -157,26 +225,30 @@ int LuaLocalPlayer::l_get_physics_override(lua_State *L) { LocalPlayer *player = getobject(L, 1); - lua_newtable(L); - lua_pushnumber(L, player->physics_override_speed); - lua_setfield(L, -2, "speed"); + push_physics_override(L, player->physics_override_speed, player->physics_override_jump, player->physics_override_gravity, player->physics_override_sneak, player->physics_override_sneak_glitch, player->physics_override_new_move); - lua_pushnumber(L, player->physics_override_jump); - lua_setfield(L, -2, "jump"); - - lua_pushnumber(L, player->physics_override_gravity); - lua_setfield(L, -2, "gravity"); - - lua_pushboolean(L, player->physics_override_sneak); - lua_setfield(L, -2, "sneak"); + return 1; +} - lua_pushboolean(L, player->physics_override_sneak_glitch); - lua_setfield(L, -2, "sneak_glitch"); +// set_physics_override(self, override) +int LuaLocalPlayer::l_set_physics_override(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); - lua_pushboolean(L, player->physics_override_new_move); - lua_setfield(L, -2, "new_move"); + player->physics_override_speed = getfloatfield_default( + L, 2, "speed", player->physics_override_speed); + player->physics_override_jump = getfloatfield_default( + L, 2, "jump", player->physics_override_jump); + player->physics_override_gravity = getfloatfield_default( + L, 2, "gravity", player->physics_override_gravity); + player->physics_override_sneak = getboolfield_default( + L, 2, "sneak", player->physics_override_sneak); + player->physics_override_sneak_glitch = getboolfield_default( + L, 2, "sneak_glitch", player->physics_override_sneak_glitch); + player->physics_override_new_move = getboolfield_default( + L, 2, "new_move", player->physics_override_new_move); - return 1; + return 0; } int LuaLocalPlayer::l_get_last_pos(lua_State *L) @@ -261,6 +333,17 @@ int LuaLocalPlayer::l_get_pos(lua_State *L) return 1; } +// set_pos(self, pos) +int LuaLocalPlayer::l_set_pos(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + + v3f pos = checkFloatPos(L, 2); + player->setPosition(pos); + getClient(L)->sendPlayerPos(); + return 0; +} + // get_movement_acceleration(self) int LuaLocalPlayer::l_get_movement_acceleration(lua_State *L) { @@ -400,6 +483,27 @@ int LuaLocalPlayer::l_hud_get(lua_State *L) return 1; } +// get_object(self) +int LuaLocalPlayer::l_get_object(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + ClientEnvironment &env = getClient(L)->getEnv(); + ClientActiveObject *obj = env.getGenericCAO(player->getCAO()->getId()); + + push_objectRef(L, obj->getId()); + + return 1; +} + +// get_hotbar_size(self) +int LuaLocalPlayer::l_get_hotbar_size(lua_State *L) +{ + LocalPlayer *player = getobject(L, 1); + lua_pushnumber(L, player->hud_hotbar_itemcount); + + return 1; +} + LuaLocalPlayer *LuaLocalPlayer::checkobject(lua_State *L, int narg) { luaL_checktype(L, narg, LUA_TUSERDATA); @@ -460,9 +564,15 @@ void LuaLocalPlayer::Register(lua_State *L) const char LuaLocalPlayer::className[] = "LocalPlayer"; const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_velocity), + luamethod(LuaLocalPlayer, set_velocity), + luamethod(LuaLocalPlayer, get_yaw), + luamethod(LuaLocalPlayer, set_yaw), + luamethod(LuaLocalPlayer, get_pitch), + luamethod(LuaLocalPlayer, set_pitch), luamethod(LuaLocalPlayer, get_hp), luamethod(LuaLocalPlayer, get_name), luamethod(LuaLocalPlayer, get_wield_index), + luamethod(LuaLocalPlayer, set_wield_index), luamethod(LuaLocalPlayer, get_wielded_item), luamethod(LuaLocalPlayer, is_attached), luamethod(LuaLocalPlayer, is_touching_ground), @@ -471,6 +581,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, is_climbing), luamethod(LuaLocalPlayer, swimming_vertical), luamethod(LuaLocalPlayer, get_physics_override), + luamethod(LuaLocalPlayer, set_physics_override), // TODO: figure our if these are useful in any way luamethod(LuaLocalPlayer, get_last_pos), luamethod(LuaLocalPlayer, get_last_velocity), @@ -480,6 +591,7 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, get_control), luamethod(LuaLocalPlayer, get_breath), luamethod(LuaLocalPlayer, get_pos), + luamethod(LuaLocalPlayer, set_pos), luamethod(LuaLocalPlayer, get_movement_acceleration), luamethod(LuaLocalPlayer, get_movement_speed), luamethod(LuaLocalPlayer, get_movement), @@ -488,6 +600,8 @@ const luaL_Reg LuaLocalPlayer::methods[] = { luamethod(LuaLocalPlayer, hud_remove), luamethod(LuaLocalPlayer, hud_change), luamethod(LuaLocalPlayer, hud_get), + luamethod(LuaLocalPlayer, get_object), + luamethod(LuaLocalPlayer, get_hotbar_size), luamethod(LuaLocalPlayer, get_move_resistance), diff --git a/src/script/lua_api/l_localplayer.h b/src/script/lua_api/l_localplayer.h index 041545a49..458c824e6 100644 --- a/src/script/lua_api/l_localplayer.h +++ b/src/script/lua_api/l_localplayer.h @@ -35,6 +35,21 @@ private: // get_velocity(self) static int l_get_velocity(lua_State *L); + // set_velocity(self, vel) + static int l_set_velocity(lua_State *L); + + // get_yaw(self) + static int l_get_yaw(lua_State *L); + + // set_yaw(self, yaw) + static int l_set_yaw(lua_State *L); + + // get_pitch(self) + static int l_get_pitch(lua_State *L); + + // set_pitch(self,pitch) + static int l_set_pitch(lua_State *L); + // get_hp(self) static int l_get_hp(lua_State *L); @@ -44,9 +59,15 @@ private: // get_wield_index(self) static int l_get_wield_index(lua_State *L); + // set_wield_index(self) + static int l_set_wield_index(lua_State *L); + // get_wielded_item(self) static int l_get_wielded_item(lua_State *L); + // get_hotbar_size(self) + static int l_get_hotbar_size(lua_State *L); + static int l_is_attached(lua_State *L); static int l_is_touching_ground(lua_State *L); static int l_is_in_liquid(lua_State *L); @@ -55,6 +76,7 @@ private: static int l_swimming_vertical(lua_State *L); static int l_get_physics_override(lua_State *L); + static int l_set_physics_override(lua_State *L); static int l_get_override_pos(lua_State *L); @@ -72,6 +94,9 @@ private: // get_pos(self) static int l_get_pos(lua_State *L); + // set_pos(self, pos) + static int l_set_pos(lua_State *L); + // get_movement_acceleration(self) static int l_get_movement_acceleration(lua_State *L); @@ -97,6 +122,9 @@ private: static int l_get_move_resistance(lua_State *L); + // get_object(self) + static int l_get_object(lua_State *L); + LocalPlayer *m_localplayer = nullptr; public: diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 4d9fa5b14..411250a0b 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -714,6 +714,10 @@ bool ModApiMainMenu::mayModifyPath(std::string path) if (fs::PathStartsWith(path, path_user + DIR_DELIM "client")) return true; + if (fs::PathStartsWith(path, path_user + DIR_DELIM "clientmods")) + return true; + if (fs::PathStartsWith(path, path_user + DIR_DELIM "textures")) + return true; if (fs::PathStartsWith(path, path_user + DIR_DELIM "games")) return true; if (fs::PathStartsWith(path, path_user + DIR_DELIM "mods")) diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 4b0b45887..e8105dd75 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -336,6 +336,7 @@ int ModApiServer::l_disconnect_player(lua_State *L) return 1; } +// remove_player(name) int ModApiServer::l_remove_player(lua_State *L) { NO_MAP_LOCK_REQUIRED; diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index 97068ce4c..fa749c2e5 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -640,6 +640,8 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(compress); API_FCT(decompress); + API_FCT(request_insecure_environment); + API_FCT(encode_base64); API_FCT(decode_base64); @@ -647,6 +649,9 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(sha1); API_FCT(colorspec_to_colorstring); API_FCT(colorspec_to_bytes); + + LuaSettings::create(L, g_settings, g_settings_path); + lua_setfield(L, top, "settings"); } void ModApiUtil::InitializeAsync(lua_State *L, int top) |