mirror of https://github.com/minetest/minetest.git
Force set/get_wielded_item() to access to itemstack of current used hand
This commit is contained in:
parent
147e481b2b
commit
8167c04b83
|
@ -29,6 +29,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include <array>
|
||||
#include <list>
|
||||
#include <optional>
|
||||
#include "player.h"
|
||||
|
||||
class LocalPlayer;
|
||||
struct MapDrawControl;
|
||||
|
@ -72,8 +73,6 @@ struct Nametag
|
|||
}
|
||||
};
|
||||
|
||||
enum HandIndex { MAINHAND = 0, OFFHAND = 1 };
|
||||
|
||||
class WieldNode
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -776,10 +776,10 @@ protected:
|
|||
const core::line3d<f32> &shootline, bool liquids_pointable,
|
||||
const std::optional<Pointabilities> &pointabilities,
|
||||
bool look_for_object, const v3s16 &camera_offset);
|
||||
void handlePointingAtNothing(const ItemStack &playerItem);
|
||||
void handlePointingAtNothing(HandIndex used_hand);
|
||||
void handlePointingAtNode(const PointedThing &pointed,
|
||||
const ItemStack &selected_item, const ItemStack &hand_item,
|
||||
const ItemStack &place_item, f32 dtime);
|
||||
HandIndex used_hand, f32 dtime);
|
||||
void handlePointingAtObject(const PointedThing &pointed, const ItemStack &playeritem,
|
||||
const v3f &player_position, bool show_debug);
|
||||
void handleDigging(const PointedThing &pointed, const v3s16 &nodepos,
|
||||
|
@ -3342,8 +3342,6 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||
!runData.btn_down_for_dig,
|
||||
camera_offset);
|
||||
|
||||
player->getOffhandWieldedItem(&offhand_item, &place_item, itemdef_manager, pointed);
|
||||
|
||||
if (pointed != runData.pointed_old)
|
||||
infostream << "Pointing at " << pointed.dump() << std::endl;
|
||||
|
||||
|
@ -3409,12 +3407,14 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||
else
|
||||
runData.repeat_place_timer = 0;
|
||||
|
||||
HandIndex cur_used_hand = player->getCurrentUsedHand(itemdef_manager, pointed);
|
||||
|
||||
if (selected_def.usable && isKeyDown(KeyType::DIG)) {
|
||||
if (wasKeyPressed(KeyType::DIG) && (!client->modsLoaded() ||
|
||||
!client->getScript()->on_item_use(selected_item, pointed)))
|
||||
client->interact(INTERACT_USE, pointed);
|
||||
} else if (pointed.type == POINTEDTHING_NODE) {
|
||||
handlePointingAtNode(pointed, selected_item, hand_item, place_item, dtime);
|
||||
handlePointingAtNode(pointed, selected_item, hand_item, cur_used_hand, dtime);
|
||||
} else if (pointed.type == POINTEDTHING_OBJECT) {
|
||||
v3f player_position = player->getPosition();
|
||||
bool basic_debug_allowed = client->checkPrivilege("debug") || (player->hud_flags & HUD_FLAG_BASIC_DEBUG);
|
||||
|
@ -3427,7 +3427,7 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud)
|
|||
if (wasKeyPressed(KeyType::DIG) && client->modsLoaded())
|
||||
client->getScript()->on_item_use(selected_item, pointed);
|
||||
} else if (wasKeyPressed(KeyType::PLACE)) {
|
||||
handlePointingAtNothing(place_item);
|
||||
handlePointingAtNothing(cur_used_hand);
|
||||
}
|
||||
|
||||
runData.pointed_old = pointed;
|
||||
|
@ -3548,7 +3548,7 @@ PointedThing Game::updatePointedThing(
|
|||
}
|
||||
|
||||
|
||||
void Game::handlePointingAtNothing(const ItemStack &playerItem)
|
||||
void Game::handlePointingAtNothing(HandIndex used_hand)
|
||||
{
|
||||
infostream << "Attempted to place item while pointing at nothing" << std::endl;
|
||||
PointedThing fauxPointed;
|
||||
|
@ -3559,7 +3559,7 @@ void Game::handlePointingAtNothing(const ItemStack &playerItem)
|
|||
|
||||
void Game::handlePointingAtNode(const PointedThing &pointed,
|
||||
const ItemStack &selected_item, const ItemStack &hand_item,
|
||||
const ItemStack &place_item, f32 dtime)
|
||||
HandIndex used_hand, f32 dtime)
|
||||
{
|
||||
v3s16 nodepos = pointed.node_undersurface;
|
||||
v3s16 neighborpos = pointed.node_abovesurface;
|
||||
|
@ -3593,14 +3593,14 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
|
|||
if ((wasKeyPressed(KeyType::PLACE) ||
|
||||
runData.repeat_place_timer >= m_repeat_place_time) &&
|
||||
client->checkPrivilege("interact")) {
|
||||
LocalPlayer *player = client->getEnv().getLocalPlayer();
|
||||
player->current_used_hand = used_hand;
|
||||
|
||||
runData.repeat_place_timer = 0;
|
||||
infostream << "Place button pressed while looking at ground" << std::endl;
|
||||
|
||||
// Placing animation (always shown for feedback)
|
||||
if (place_item == selected_item)
|
||||
camera->setDigging(1, MAINHAND);
|
||||
else
|
||||
camera->setDigging(1, OFFHAND);
|
||||
camera->setDigging(1, used_hand);
|
||||
|
||||
soundmaker->m_player_rightpunch_sound = SoundSpec();
|
||||
|
||||
|
@ -3608,12 +3608,22 @@ void Game::handlePointingAtNode(const PointedThing &pointed,
|
|||
// make that happen
|
||||
// And also set the sound and send the interact
|
||||
// But first check for meta formspec and rightclickable
|
||||
ItemStack place_item;
|
||||
|
||||
if (used_hand == MAINHAND)
|
||||
player->getWieldedItem(&place_item, nullptr);
|
||||
else
|
||||
player->getOffhandWieldedItem(&place_item);
|
||||
|
||||
auto &def = place_item.getDefinition(itemdef_manager);
|
||||
bool placed = nodePlacement(def, place_item, nodepos, neighborpos,
|
||||
pointed, meta);
|
||||
|
||||
if (placed && client->modsLoaded())
|
||||
client->getScript()->on_placenode(pointed, def);
|
||||
|
||||
// Resets the hand index after 'on_place' callback run.
|
||||
player->current_used_hand = MAINHAND;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4154,7 +4164,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
|
|||
ItemStack selected_item, hand_item, offhand_item;
|
||||
ItemStack &tool_item = player->getWieldedItem(&selected_item, &hand_item);
|
||||
camera->wield(tool_item, MAINHAND);
|
||||
player->getOffhandWieldedItem(&offhand_item, nullptr, itemdef_manager, PointedThing());
|
||||
player->getOffhandWieldedItem(&offhand_item);
|
||||
camera->wield(offhand_item, OFFHAND);
|
||||
}
|
||||
|
||||
|
|
|
@ -919,12 +919,10 @@ static inline void getWieldedItem(const PlayerSAO *playersao, std::optional<Item
|
|||
playersao->getWieldedItem(&(*ret));
|
||||
}
|
||||
|
||||
static inline bool getOffhandWieldedItem(const PlayerSAO *playersao, std::optional<ItemStack> &offhand,
|
||||
std::optional<ItemStack> &place, IItemDefManager *idef, const PointedThing &pointed)
|
||||
static inline void getOffhandWieldedItem(const PlayerSAO *playersao, std::optional<ItemStack> &offhand)
|
||||
{
|
||||
offhand = ItemStack();
|
||||
place = ItemStack();
|
||||
return playersao->getOffhandWieldedItem(&(*offhand), &(*place), idef, pointed);
|
||||
playersao->getOffhandWieldedItem(&(*offhand));
|
||||
}
|
||||
|
||||
void Server::handleCommand_Interact(NetworkPacket *pkt)
|
||||
|
@ -1237,7 +1235,14 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
|||
case INTERACT_PLACE: {
|
||||
std::optional<ItemStack> main_item, offhand_item, place_item;
|
||||
getWieldedItem(playersao, main_item);
|
||||
bool use_offhand = getOffhandWieldedItem(playersao, offhand_item, place_item, m_itemdef, pointed);
|
||||
getOffhandWieldedItem(playersao, offhand_item);
|
||||
|
||||
HandIndex used_hand = playersao->getCurrentUsedHand(m_itemdef, pointed);
|
||||
|
||||
if (used_hand == MAINHAND)
|
||||
place_item = main_item;
|
||||
else
|
||||
place_item = offhand_item;
|
||||
|
||||
// Reset build time counter
|
||||
if (pointed.type == POINTEDTHING_NODE &&
|
||||
|
@ -1259,22 +1264,30 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
|||
<< pointed_object->getDescription() << std::endl;
|
||||
|
||||
// Do stuff
|
||||
if (m_script->item_OnSecondaryUse(use_offhand ? offhand_item : main_item, playersao, pointed)) {
|
||||
if (use_offhand
|
||||
playersao->getPlayer()->current_used_hand = used_hand;
|
||||
if (m_script->item_OnSecondaryUse(used_hand == MAINHAND ? main_item : offhand_item, playersao, pointed)) {
|
||||
if (used_hand == OFFHAND
|
||||
? (offhand_item.has_value() && playersao->setOffhandWieldedItem(*offhand_item))
|
||||
: (main_item.has_value() && playersao->setWieldedItem(*main_item)))
|
||||
SendInventory(player, true);
|
||||
}
|
||||
|
||||
pointed_object->rightClick(playersao);
|
||||
} else if (m_script->item_OnPlace(use_offhand ? offhand_item : main_item, playersao, pointed)) {
|
||||
// Placement was handled in lua
|
||||
playersao->getPlayer()->current_used_hand = MAINHAND;
|
||||
|
||||
// Apply returned ItemStack
|
||||
if (use_offhand
|
||||
? (offhand_item.has_value() && playersao->setOffhandWieldedItem(*offhand_item))
|
||||
: (main_item.has_value() && playersao->setWieldedItem(*main_item)))
|
||||
pointed_object->rightClick(playersao);
|
||||
}
|
||||
else {
|
||||
playersao->getPlayer()->current_used_hand = used_hand;
|
||||
if (m_script->item_OnPlace(used_hand == MAINHAND ? main_item : offhand_item, playersao, pointed)) {
|
||||
// Placement was handled in lua
|
||||
|
||||
// Apply returned ItemStack
|
||||
if (used_hand == OFFHAND
|
||||
? (offhand_item.has_value() && playersao->setOffhandWieldedItem(*offhand_item))
|
||||
: (main_item.has_value() && playersao->setWieldedItem(*main_item)))
|
||||
SendInventory(player, true);
|
||||
}
|
||||
playersao->getPlayer()->current_used_hand = MAINHAND;
|
||||
}
|
||||
|
||||
if (pointed.type != POINTEDTHING_NODE)
|
||||
|
@ -1318,20 +1331,28 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
|
|||
case INTERACT_ACTIVATE: {
|
||||
std::optional<ItemStack> main_item, offhand_item, place_item;
|
||||
getWieldedItem(playersao, main_item);
|
||||
bool use_offhand = getOffhandWieldedItem(playersao, offhand_item, place_item, m_itemdef, pointed);
|
||||
getOffhandWieldedItem(playersao, offhand_item);
|
||||
HandIndex used_hand = playersao->getCurrentUsedHand(m_itemdef, pointed);
|
||||
|
||||
if (used_hand == MAINHAND)
|
||||
place_item = main_item;
|
||||
else
|
||||
place_item = offhand_item;
|
||||
|
||||
actionstream << player->getName() << " activates "
|
||||
<< place_item->name << std::endl;
|
||||
|
||||
pointed.type = POINTEDTHING_NOTHING; // can only ever be NOTHING
|
||||
|
||||
if (m_script->item_OnSecondaryUse(use_offhand ? offhand_item : main_item, playersao, pointed)) {
|
||||
playersao->getPlayer()->current_used_hand = used_hand;
|
||||
if (m_script->item_OnSecondaryUse(used_hand == MAINHAND ? main_item : offhand_item, playersao, pointed)) {
|
||||
// Apply returned ItemStack
|
||||
if (use_offhand
|
||||
if (used_hand == OFFHAND
|
||||
? (offhand_item.has_value() && playersao->setOffhandWieldedItem(*offhand_item))
|
||||
: (main_item.has_value() && playersao->setWieldedItem(*main_item)))
|
||||
SendInventory(player, true);
|
||||
}
|
||||
playersao->getPlayer()->current_used_hand = MAINHAND;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ Player::Player(const char *name, IItemDefManager *idef):
|
|||
craft->setWidth(3);
|
||||
inventory.addList("craftpreview", 1);
|
||||
inventory.addList("craftresult", 1);
|
||||
inventory.addList("offhand", 1);
|
||||
inventory.setModified(false);
|
||||
|
||||
// Can be redefined via Lua
|
||||
|
@ -95,8 +96,12 @@ ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const
|
|||
const InventoryList *mlist = inventory.getList("main"); // TODO: Make this generic
|
||||
const InventoryList *hlist = inventory.getList("hand");
|
||||
|
||||
if (mlist && m_wield_index < mlist->getSize())
|
||||
*selected = mlist->getItem(m_wield_index);
|
||||
if (current_used_hand == MAINHAND) {
|
||||
if (mlist && m_wield_index < mlist->getSize())
|
||||
*selected = mlist->getItem(m_wield_index);
|
||||
}
|
||||
else
|
||||
getOffhandWieldedItem(selected);
|
||||
|
||||
if (hand && hlist)
|
||||
*hand = hlist->getItem(0);
|
||||
|
@ -105,7 +110,45 @@ ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const
|
|||
return (hand && selected->name.empty()) ? *hand : *selected;
|
||||
}
|
||||
|
||||
bool Player::getOffhandWieldedItem(ItemStack *offhand, ItemStack *place, IItemDefManager *idef, const PointedThing &pointed) const
|
||||
void Player::getOffhandWieldedItem(ItemStack *offhand) const
|
||||
{
|
||||
assert(offhand);
|
||||
|
||||
const InventoryList *olist = inventory.getList("offhand");
|
||||
|
||||
if (olist)
|
||||
*offhand = olist->getItem(0);
|
||||
}
|
||||
|
||||
HandIndex Player::getCurrentUsedHand(IItemDefManager *idef, const PointedThing &pointed) const
|
||||
{
|
||||
ItemStack main, offhand;
|
||||
|
||||
getWieldedItem(&main, nullptr);
|
||||
getOffhandWieldedItem(&offhand);
|
||||
|
||||
const ItemDefinition &main_def = main.getDefinition(idef);
|
||||
const ItemDefinition &offhand_def = offhand.getDefinition(idef);
|
||||
|
||||
bool main_usable, offhand_usable;
|
||||
|
||||
// figure out which item to use for placements
|
||||
|
||||
if (pointed.type == POINTEDTHING_NODE) {
|
||||
// an item can be used on nodes if it has a place handler or prediction
|
||||
main_usable = main_def.has_on_place || main_def.node_placement_prediction != "";
|
||||
offhand_usable = offhand_def.has_on_place || offhand_def.node_placement_prediction != "";
|
||||
} else {
|
||||
// an item can be used on anything else if it has a secondary use handler
|
||||
main_usable = main_def.has_on_secondary_use;
|
||||
offhand_usable = offhand_def.has_on_secondary_use;
|
||||
}
|
||||
|
||||
// main hand has priority
|
||||
return (HandIndex)(offhand_usable && !main_usable);
|
||||
}
|
||||
|
||||
/*bool Player::getOffhandWieldedItem(ItemStack *offhand, ItemStack *place, IItemDefManager *idef, const PointedThing &pointed) const
|
||||
{
|
||||
assert(offhand);
|
||||
|
||||
|
@ -143,7 +186,7 @@ bool Player::getOffhandWieldedItem(ItemStack *offhand, ItemStack *place, IItemDe
|
|||
*place = use_offhand ? *offhand : main;
|
||||
|
||||
return use_offhand;
|
||||
}
|
||||
}*/
|
||||
|
||||
u32 Player::addHud(HudElement *toadd)
|
||||
{
|
||||
|
|
|
@ -35,6 +35,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define PLAYERNAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"
|
||||
#define PLAYERNAME_ALLOWED_CHARS_USER_EXPL "'a' to 'z', 'A' to 'Z', '0' to '9', '-', '_'"
|
||||
|
||||
enum HandIndex { MAINHAND = 0, OFFHAND = 1 };
|
||||
|
||||
struct PlayerFovSpec
|
||||
{
|
||||
f32 fov;
|
||||
|
@ -224,8 +226,9 @@ public:
|
|||
// item currently in secondary hand is returned in `offhand`
|
||||
// item to use for place / secondary_use (either main or offhand) is (optionally) returned in `place`
|
||||
// return value: whether to use main or offhand for placing
|
||||
bool getOffhandWieldedItem(ItemStack *offhand, ItemStack *place,
|
||||
IItemDefManager *idef, const PointedThing &pointed) const;
|
||||
void getOffhandWieldedItem(ItemStack *offhand) const;
|
||||
|
||||
HandIndex getCurrentUsedHand(IItemDefManager *idef, const PointedThing &pointed) const;
|
||||
|
||||
void setWieldIndex(u16 index);
|
||||
u16 getWieldIndex() const { return m_wield_index; }
|
||||
|
@ -252,6 +255,8 @@ public:
|
|||
u32 hud_flags;
|
||||
s32 hud_hotbar_itemcount;
|
||||
|
||||
HandIndex current_used_hand { MAINHAND };
|
||||
|
||||
protected:
|
||||
char m_name[PLAYERNAME_SIZE];
|
||||
v3f m_speed; // velocity; in BS-space
|
||||
|
|
|
@ -570,16 +570,32 @@ ItemStack PlayerSAO::getWieldedItem(ItemStack *selected, ItemStack *hand) const
|
|||
return m_player->getWieldedItem(selected, hand);
|
||||
}
|
||||
|
||||
bool PlayerSAO::getOffhandWieldedItem(ItemStack *offhand, ItemStack *place, IItemDefManager *itemdef_manager, PointedThing pointed) const
|
||||
void PlayerSAO::getOffhandWieldedItem(ItemStack *offhand) const
|
||||
{
|
||||
return m_player->getOffhandWieldedItem(offhand, place, itemdef_manager, pointed);
|
||||
m_player->getOffhandWieldedItem(offhand);
|
||||
}
|
||||
|
||||
HandIndex PlayerSAO::getCurrentUsedHand(IItemDefManager *idef, const PointedThing &pointed) const
|
||||
{
|
||||
return m_player->getCurrentUsedHand(idef, pointed);
|
||||
}
|
||||
|
||||
bool PlayerSAO::setWieldedItem(const ItemStack &item)
|
||||
{
|
||||
InventoryList *mlist = m_player->inventory.getList(getWieldList());
|
||||
if (mlist) {
|
||||
mlist->changeItem(m_player->getWieldIndex(), item);
|
||||
InventoryList *list;
|
||||
u16 list_index;
|
||||
|
||||
if (m_player->current_used_hand == MAINHAND) {
|
||||
list = m_player->inventory.getList(getWieldList());
|
||||
list_index = m_player->getWieldIndex();
|
||||
}
|
||||
else {
|
||||
list = m_player->inventory.getList("offhand");
|
||||
list_index = 0;
|
||||
}
|
||||
|
||||
if (list) {
|
||||
list->changeItem(list_index, item);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -26,6 +26,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "unit_sao.h"
|
||||
#include "util/numeric.h"
|
||||
#include "util/pointedthing.h"
|
||||
#include "player.h"
|
||||
|
||||
class IItemDefManager;
|
||||
|
||||
|
@ -137,7 +138,8 @@ public:
|
|||
std::string getWieldList() const override { return "main"; }
|
||||
u16 getWieldIndex() const override;
|
||||
ItemStack getWieldedItem(ItemStack *selected, ItemStack *hand = nullptr) const override;
|
||||
bool getOffhandWieldedItem(ItemStack *offhand, ItemStack *place, IItemDefManager *itemdef_manager, PointedThing pointed) const;
|
||||
void getOffhandWieldedItem(ItemStack *offhand) const;
|
||||
HandIndex getCurrentUsedHand(IItemDefManager *idef, const PointedThing &pointed) const;
|
||||
bool setWieldedItem(const ItemStack &item) override;
|
||||
bool setOffhandWieldedItem(const ItemStack &item);
|
||||
|
||||
|
|
Loading…
Reference in New Issue