Clamp hotbar selection to slots that exist (#14869)

This commit is contained in:
1F616EMO~nya 2024-08-12 21:35:13 +08:00 committed by GitHub
parent 39c2af9710
commit 98e51a0159
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 51 additions and 11 deletions

View File

@ -8225,7 +8225,9 @@ child will follow movement and rotation of that bone.
* See `hud_set_flags` for a list of flags that can be toggled. * See `hud_set_flags` for a list of flags that can be toggled.
* `hud_set_hotbar_itemcount(count)`: sets number of items in builtin hotbar * `hud_set_hotbar_itemcount(count)`: sets number of items in builtin hotbar
* `count`: number of items, must be between `1` and `32` * `count`: number of items, must be between `1` and `32`
* If `count` exceeds the `"main"` list size, the list size will be used instead.
* `hud_get_hotbar_itemcount()`: returns number of visible items * `hud_get_hotbar_itemcount()`: returns number of visible items
* This value is also clamped by the `"main"` list size.
* `hud_set_hotbar_image(texturename)` * `hud_set_hotbar_image(texturename)`
* sets background image for hotbar * sets background image for hotbar
* `hud_get_hotbar_image()`: returns texturename * `hud_get_hotbar_image()`: returns texturename

View File

@ -84,3 +84,25 @@ local function run_player_add_pos_tests(player)
end end
unittests.register("test_player_add_pos", run_player_add_pos_tests, {player=true}) unittests.register("test_player_add_pos", run_player_add_pos_tests, {player=true})
--
-- Hotbar selection clamp
--
local function run_player_hotbar_clamp_tests(player)
local inv = player:get_inventory()
local old_inv_size = inv:get_size("main")
local old_inv_list = inv:get_list("main") -- Avoid accidentally removing item
local old_bar_size = player:hud_get_hotbar_itemcount()
inv:set_size("main", 5)
player:hud_set_hotbar_itemcount(2)
assert(player:hud_get_hotbar_itemcount() == 2)
player:hud_set_hotbar_itemcount(6)
assert(player:hud_get_hotbar_itemcount() == 5)
inv:set_size("main", old_inv_size)
inv:set_list("main", old_inv_list)
player:hud_set_hotbar_itemcount(old_bar_size)
end
unittests.register("test_player_hotbar_clamp", run_player_hotbar_clamp_tests, {player=true})

View File

@ -2188,12 +2188,14 @@ void Game::processItemSelection(u16 *new_playeritem)
{ {
LocalPlayer *player = client->getEnv().getLocalPlayer(); LocalPlayer *player = client->getEnv().getLocalPlayer();
*new_playeritem = player->getWieldIndex();
u16 max_item = player->getMaxHotbarItemcount();
if (max_item == 0)
return;
max_item -= 1;
/* Item selection using mouse wheel /* Item selection using mouse wheel
*/ */
*new_playeritem = player->getWieldIndex();
u16 max_item = MYMIN(PLAYER_INVENTORY_SIZE - 1,
player->hud_hotbar_itemcount - 1);
s32 wheel = input->getMouseWheel(); s32 wheel = input->getMouseWheel();
if (!m_enable_hotbar_mouse_wheel) if (!m_enable_hotbar_mouse_wheel)
wheel = 0; wheel = 0;

View File

@ -783,7 +783,7 @@ void Hud::drawHotbar(u16 playeritem)
v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y); v2s32 centerlowerpos(m_displaycenter.X, m_screensize.Y);
s32 hotbar_itemcount = player->hud_hotbar_itemcount; s32 hotbar_itemcount = player->getMaxHotbarItemcount();
s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2); s32 width = hotbar_itemcount * (m_hotbar_imagesize + m_padding * 2);
v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3); v2s32 pos = centerlowerpos - v2s32(width / 2, m_hotbar_imagesize + m_padding * 3);

View File

@ -852,11 +852,11 @@ void Server::handleCommand_PlayerItem(NetworkPacket* pkt)
*pkt >> item; *pkt >> item;
if (item >= player->getHotbarItemcount()) { if (item >= player->getMaxHotbarItemcount()) {
actionstream << "Player: " << player->getName() actionstream << "Player: " << player->getName()
<< " tried to access item=" << item << " tried to access item=" << item
<< " out of hotbar_itemcount=" << " out of hotbar_itemcount="
<< player->getHotbarItemcount() << player->getMaxHotbarItemcount()
<< "; ignoring." << std::endl; << "; ignoring." << std::endl;
return; return;
} }
@ -983,11 +983,11 @@ void Server::handleCommand_Interact(NetworkPacket *pkt)
// Update wielded item // Update wielded item
if (item_i >= player->getHotbarItemcount()) { if (item_i >= player->getMaxHotbarItemcount()) {
actionstream << "Player: " << player->getName() actionstream << "Player: " << player->getName()
<< " tried to access item=" << item_i << " tried to access item=" << item_i
<< " out of hotbar_itemcount=" << " out of hotbar_itemcount="
<< player->getHotbarItemcount() << player->getMaxHotbarItemcount()
<< "; ignoring." << std::endl; << "; ignoring." << std::endl;
return; return;
} }

View File

@ -88,6 +88,11 @@ void Player::setWieldIndex(u16 index)
m_wield_index = MYMIN(index, mlist ? mlist->getSize() : 0); m_wield_index = MYMIN(index, mlist ? mlist->getSize() : 0);
} }
u16 Player::getWieldIndex()
{
return std::min(m_wield_index, getMaxHotbarItemcount());
}
ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const ItemStack &Player::getWieldedItem(ItemStack *selected, ItemStack *hand) const
{ {
assert(selected); assert(selected);
@ -157,6 +162,12 @@ void Player::clearHud()
} }
} }
u16 Player::getMaxHotbarItemcount()
{
InventoryList *mainlist = inventory.getList("main");
return mainlist ? std::min(mainlist->getSize(), (u32) hud_hotbar_itemcount) : 0;
}
#ifndef SERVER #ifndef SERVER
u32 PlayerControl::getKeysPressed() const u32 PlayerControl::getKeysPressed() const

View File

@ -223,7 +223,7 @@ public:
// Returns non-empty `selected` ItemStack. `hand` is a fallback, if specified // Returns non-empty `selected` ItemStack. `hand` is a fallback, if specified
ItemStack &getWieldedItem(ItemStack *selected, ItemStack *hand) const; ItemStack &getWieldedItem(ItemStack *selected, ItemStack *hand) const;
void setWieldIndex(u16 index); void setWieldIndex(u16 index);
u16 getWieldIndex() const { return m_wield_index; } u16 getWieldIndex();
bool setFov(const PlayerFovSpec &spec) bool setFov(const PlayerFovSpec &spec)
{ {
@ -247,6 +247,9 @@ public:
u32 hud_flags; u32 hud_flags;
s32 hud_hotbar_itemcount; s32 hud_hotbar_itemcount;
// Get actual usable number of hotbar items (clamped to size of "main" list)
u16 getMaxHotbarItemcount();
protected: protected:
char m_name[PLAYERNAME_SIZE]; char m_name[PLAYERNAME_SIZE];
v3f m_speed; // velocity; in BS-space v3f m_speed; // velocity; in BS-space

View File

@ -1842,7 +1842,7 @@ int ObjectRef::l_hud_get_hotbar_itemcount(lua_State *L)
if (player == nullptr) if (player == nullptr)
return 0; return 0;
lua_pushinteger(L, player->getHotbarItemcount()); lua_pushinteger(L, player->getMaxHotbarItemcount());
return 1; return 1;
} }