]> git.lizzy.rs Git - dragonfireclient.git/blobdiff - src/script/lua_api/l_client.cpp
Merge branch 'master' of https://github.com/minetest/minetest
[dragonfireclient.git] / src / script / lua_api / l_client.cpp
index aaced7cd0a09ab8343683ff5632dbf9573f35318..265c7d3fc6bbe189b497a6ef0432953a1eaf4c0c 100644 (file)
@@ -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);
 }