Added ThroughWalls, InventoryActions API and AutoTotem

This commit is contained in:
Elias Fleckenstein 2020-10-19 13:09:38 +02:00
parent 35da7306dc
commit f1ff05bf59
14 changed files with 408 additions and 48 deletions

View File

@ -1,47 +1,57 @@
local placed_crystal
local switched_to_totem = 0
local used_sneak = true
local totem_move_action = InventoryAction("move")
totem_move_action:to("current_player", "main", 8)
core.register_globalstep(function(dtime)
if not minetest.settings:get_bool("crystal_pvp") then return end
local player = core.localplayer
if not player then return end
local control = player:get_control()
local pointed = core.get_pointed_thing()
local item = player:get_wielded_item():get_name()
if placed_crystal then
if core.switch_to_item("mobs_mc:totem") then
switched_to_totem = 5
end
placed_crystal = false
elseif switched_to_totem > 0 then
if item ~= "mobs_mc:totem" then
switched_to_totem = 0
elseif pointed and pointed.type == "object" then
pointed.ref:punch()
switched_to_totem = 0
if core.settings:get_bool("crystal_pvp") then
if placed_crystal then
if core.switch_to_item("mobs_mc:totem") then
switched_to_totem = 5
end
placed_crystal = false
elseif switched_to_totem > 0 then
if item ~= "mobs_mc:totem" then
switched_to_totem = 0
elseif pointed and pointed.type == "object" then
pointed.ref:punch()
switched_to_totem = 0
else
switched_to_totem = switched_to_totem
end
elseif control.RMB and item == "mcl_end:crystal" then
placed_crystal = true
elseif control.sneak then
if pointed and pointed.type == "node" and not used_sneak then
local pos = core.get_pointed_thing_position(pointed)
local node = core.get_node_or_nil(pos)
if node and (node.name == "mcl_core:obsidian" or node.name == "mcl_core:bedrock") then
core.switch_to_item("mcl_end:crystal")
core.place_node(pos)
placed_crystal = true
end
end
used_sneak = true
else
switched_to_totem = switched_to_totem
used_sneak = false
end
elseif control.RMB and item == "mcl_end:crystal" then
placed_crystal = true
elseif control.sneak then
if used_sneak then
core.switch_to_item("mobs_mc:totem")
return
end
core.switch_to_item("mcl_end:crystal")
if pointed and pointed.type == "node" then
local pos = core.get_pointed_thing_position(pointed)
local node = core.get_node_or_nil(pos)
if node and (node.name == "mcl_core:obsidian" or node.name == "mcl_core:bedrock") then
core.place_node(pos)
placed_crystal = true
end
if core.settings:get_bool("autototem") then
local totem_stack = core.get_inventory("current_player").main[9]
if totem_stack and totem_stack:get_name() ~= "mobs_mc:totem" then
local totem_index = core.find_item("mobs_mc:totem")
if totem_index then
totem_move_action:from("current_player", "main", totem_index - 1)
totem_move_action:apply()
player:set_wield_index(8)
end
end
used_sneak = true
else
used_sneak = false
end
end)

View File

@ -5,6 +5,8 @@ core.cheats = {
["FastHit"] = "spamclick",
["AttachmentFloat"] = "float_above_parent",
["CrystalPvP"] = "crystal_pvp",
["AutoTotem"] = "autototem",
["ThroughWalls"] = "dont_point_nodes",
},
["Movement"] = {
["Freecam"] = "freecam",

View File

@ -1,5 +1,6 @@
local elapsed_time = 0
local tick_time = 0.05
local drop_action = InventoryAction("drop")
core.register_globalstep(function(dtime)
-- AutoEject
@ -9,11 +10,8 @@ core.register_globalstep(function(dtime)
local inventory = core.get_inventory("current_player")
for index, stack in pairs(inventory.main) do
if table.indexof(list, stack:get_name()) ~= -1 then
local old_index = player:get_wield_index()
player:set_wield_index(index - 1)
core.drop_selected_item()
player:set_wield_index(old_index)
return
drop_action:from("current_player", "main", index - 1)
drop_action:apply()
end
end
end

View File

@ -21,20 +21,27 @@ function core.parse_relative_pos(param)
return success, pos
end
function core.switch_to_item(item)
function core.find_item(item)
for index, stack in ipairs(core.get_inventory("current_player").main) do
if stack:get_name() == item then
core.localplayer:set_wield_index(index - 1)
return true
return index
end
end
return false
end
function core.switch_to_item(item)
local i = core.find_item(item)
if i then
core.localplayer:set_wield_index(i - 1)
return true
else
return false
end
end
function core.get_pointed_thing()
local pos = core.camera:get_pos()
local pos2 = vector.add(pos, vector.multiply(core.camera:get_look_dir(), 5))
local ray = core.raycast(pos, pos2, true, true)
local ray = core.raycast(pos, pos2, true, core.settings:get_bool("point_liquids") or core.get_item_def(core.localplayer:get_wielded_item():get_name()).liquids_pointable)
return ray:next()
end

View File

@ -1012,6 +1012,9 @@ Passed to `HTTPApiTable.fetch` callback. Returned by
* e.g. minetest.set_keypress("jump", true) will cause te player to jump until minetest.set_keypress("jump", false) is called or the player presses & releases the space bar himself
* `minetest.get_inventory(location)`
* Returns the inventory at location
* `minetest.find_item(item)`
* finds and an item in the inventory
* returns index on success or nil if item is not found
* `minetest.switch_to_item(item)`
* `item` is an Itemstring
* searches to item in inventory, sets the wield index to it if found
@ -1706,3 +1709,46 @@ Same as `image`, but does not accept a `position`; the position is instead deter
-- ^ Uses texture (string)
}
### InventoryAction
A reference to a C++ InventoryAction. You can move, drop and craft items in all accessible inventories using InventoryActions.
#### methods
* `InventoryAction(type)`:
* creates a new InventoryAction
* type is on of "move", "drop", or "craft", else returns nil
* `apply()`:
* applies the InventoryAction (InventoryActions can be applied multible times)
* `from(inventorylocation, listname, stack)`
* this is valid for move or drop actions
* when `apply()` is called items are moved / dropped from `listname` `inventorylocation` in` at `stack`
* `to(inventorylocation, listname, stack)`
* this is valid for move actions
* when `apply()` is called items are moved to `listname` in`inventorylocation` at `stack`
* `craft(inventoryaction)`
* this is valid for craft actions
* when `apply()` is called a craft event for this inventory will be triggered
* `set_count(count)`
* this is valid for all actions
* it specifies how many items to drop / craft / move
* `0` means move all items
* default count: `0`
#### example
`local move_act = InventoryAction("move")
move_act:from("current_player", "main", 0)
move_act:to("current_player", "craft", 0)
move_act:set_count(1)
local craft_act = InventoryAction("craft")
craft_act:craft("current_player")
local drop_act = InventoryAction("drop")
drop_act:from("current_player", "craft", 0)
move_act:apply()
craft_act:apply()
drop_act:apply()
`
* e.g. In first hotbar slot there are tree logs: Move one to craft field, then craft wood out of it and immediately drop it

View File

@ -2458,7 +2458,7 @@ PointedThing Game::updatePointedThing(
runData.selected_object = NULL;
hud->pointing_at_object = false;
RaycastState s(shootline, look_for_object, liquids_pointable);
RaycastState s(shootline, look_for_object, liquids_pointable, ! g_settings->getBool("dont_point_nodes"));
PointedThing result;
env.continueRaycast(&s, &result);
if (result.type == POINTEDTHING_OBJECT) {

View File

@ -109,6 +109,8 @@ void set_default_settings(Settings *settings)
settings->setDefault("autotnt", "false");
settings->setDefault("replace", "false");
settings->setDefault("crystal_pvp", "false");
settings->setDefault("autototem", "false");
settings->setDefault("dont_point_nodes", "false");
// Keymap
settings->setDefault("remote_port", "30000");

View File

@ -106,8 +106,10 @@ bool Environment::line_of_sight(v3f pos1, v3f pos2, v3s16 *p)
Check if a node is pointable
*/
inline static bool isPointableNode(const MapNode &n,
const NodeDefManager *nodedef , bool liquids_pointable)
const NodeDefManager *nodedef , bool liquids_pointable, bool nodes_pointable)
{
if (! nodes_pointable)
return false;
const ContentFeatures &features = nodedef->get(n);
return features.pointable ||
((liquids_pointable || g_settings->getBool("point_liquids")) && features.isLiquid());
@ -180,7 +182,7 @@ void Environment::continueRaycast(RaycastState *state, PointedThing *result)
n = map.getNode(np, &is_valid_position);
if (!(is_valid_position && isPointableNode(n, nodedef,
state->m_liquids_pointable))) {
state->m_liquids_pointable, state->m_nodes_pointable))) {
continue;
}

View File

@ -57,12 +57,13 @@ bool RaycastSort::operator() (const PointedThing &pt1,
RaycastState::RaycastState(const core::line3d<f32> &shootline,
bool objects_pointable, bool liquids_pointable) :
bool objects_pointable, bool liquids_pointable, bool nodes_pointable) :
m_shootline(shootline),
m_iterator(shootline.start / BS, shootline.getVector() / BS),
m_previous_node(m_iterator.m_current_node_pos),
m_objects_pointable(objects_pointable),
m_liquids_pointable(liquids_pointable)
m_liquids_pointable(liquids_pointable),
m_nodes_pointable(nodes_pointable)
{
}

View File

@ -38,7 +38,7 @@ public:
* @param liquids pointable if false, liquid nodes won't be found
*/
RaycastState(const core::line3d<f32> &shootline, bool objects_pointable,
bool liquids_pointable);
bool liquids_pointable, bool nodes_pointable = true);
//! Shootline of the raycast.
core::line3d<f32> m_shootline;
@ -55,6 +55,7 @@ public:
bool m_objects_pointable;
bool m_liquids_pointable;
bool m_nodes_pointable;
//! The code needs to search these nodes around the center node.
core::aabbox3d<s16> m_search_range { 0, 0, 0, 0, 0, 0 };

View File

@ -6,6 +6,7 @@ set(common_SCRIPT_LUA_API_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/l_env.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_http.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_inventory.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_inventoryaction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_item.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_itemstackmeta.cpp
${CMAKE_CURRENT_SOURCE_DIR}/l_mapgen.cpp

View File

@ -0,0 +1,216 @@
/*
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);
} 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}
};

View File

@ -0,0 +1,72 @@
/*
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);
};

View File

@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "lua_api/l_client.h"
#include "lua_api/l_clientobject.h"
#include "lua_api/l_env.h"
#include "lua_api/l_inventoryaction.h"
#include "lua_api/l_item.h"
#include "lua_api/l_itemstackmeta.h"
#include "lua_api/l_minimap.h"
@ -80,6 +81,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top)
ModChannelRef::Register(L);
LuaSettings::Register(L);
ClientObjectRef::Register(L);
LuaInventoryAction::Register(L);
ModApiItemMod::Initialize(L, top);
ModApiUtil::InitializeClient(L, top);