Force set/get_wielded_item() to access to itemstack of current used hand

This commit is contained in:
Andrey2470T 2024-03-09 16:50:28 +03:00
parent 147e481b2b
commit 8167c04b83
7 changed files with 140 additions and 44 deletions

View File

@ -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:

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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);