mirror of
https://github.com/luanti-org/luanti.git
synced 2025-06-27 16:36:03 +00:00
Add new hotbar_slot_selected lua callback
This commit is contained in:
parent
1f9a3b5875
commit
7425126f6b
8 changed files with 169 additions and 2 deletions
|
@ -618,6 +618,7 @@ core.registered_allow_player_inventory_actions, core.register_allow_player_inven
|
|||
core.registered_on_rightclickplayers, core.register_on_rightclickplayer = make_registration()
|
||||
core.registered_on_liquid_transformed, core.register_on_liquid_transformed = make_registration()
|
||||
core.registered_on_mapblocks_changed, core.register_on_mapblocks_changed = make_registration()
|
||||
core.registered_on_hotbar_slot_selected, core.register_on_hotbar_slot_selected = make_registration()
|
||||
|
||||
-- A bunch of registrations are read by the C++ side once on env init, so we cannot
|
||||
-- allow them to change afterwards (see s_env.cpp).
|
||||
|
|
|
@ -6331,6 +6331,14 @@ Call these functions only at load time!
|
|||
The set is a table where the keys are hashes and the values are `true`.
|
||||
* `modified_block_count` is the number of entries in the set.
|
||||
* Note: callbacks must be registered at mod load time.
|
||||
* `core.register_on_hotbar_slot_selected(function(player, inventory, list_name, hotbar_slot, prev_hotbar_slot, is_from_scrolling))`
|
||||
* Called when the player selects a hotbar slot, including re-selecting current slot
|
||||
* `player`: `ObjectRef` - Player that selected their hotbar slot
|
||||
* `inventory`: type `InvRef`
|
||||
* `list_name`: string - the name of the hotbar list
|
||||
* `hotbar_slot`: integer - the newly selected hotbar slot
|
||||
* `prev_hotbar_slot`: integer - the previously selected hotbar slot, can be the same as `hotbar_slot` if the player selected the same slot
|
||||
* `is_from_scrolling`: boolean - true if the input came from a scroll action, or the prev/next slot input keys
|
||||
|
||||
Setting-related
|
||||
---------------
|
||||
|
@ -7890,6 +7898,7 @@ For historical reasons, the use of an -s suffix in these names is inconsistent.
|
|||
* `core.registered_on_modchannel_message`
|
||||
* `core.registered_on_liquid_transformed`
|
||||
* `core.registered_on_mapblocks_changed`
|
||||
* `core.registered_on_hotbar_slot_selected`
|
||||
|
||||
Class reference
|
||||
===============
|
||||
|
|
|
@ -2036,6 +2036,9 @@ void Game::processItemSelection(u16 *new_playeritem)
|
|||
if (max_item == 0)
|
||||
return;
|
||||
max_item -= 1;
|
||||
u16 prev_playeritem = *new_playeritem;
|
||||
bool player_input_happened = false;
|
||||
bool change_was_from_scrolling = false;
|
||||
|
||||
/* Item selection using mouse wheel
|
||||
*/
|
||||
|
@ -2053,6 +2056,10 @@ void Game::processItemSelection(u16 *new_playeritem)
|
|||
if (wasKeyDown(KeyType::HOTBAR_PREV))
|
||||
dir = 1;
|
||||
|
||||
if (dir != 0) {
|
||||
player_input_happened = true;
|
||||
change_was_from_scrolling = true;
|
||||
}
|
||||
if (dir < 0)
|
||||
*new_playeritem = *new_playeritem < max_item ? *new_playeritem + 1 : 0;
|
||||
else if (dir > 0)
|
||||
|
@ -2064,18 +2071,37 @@ void Game::processItemSelection(u16 *new_playeritem)
|
|||
for (u16 i = 0; i <= max_item; i++) {
|
||||
if (wasKeyDown((GameKeyType) (KeyType::SLOT_1 + i))) {
|
||||
*new_playeritem = i;
|
||||
player_input_happened = true;
|
||||
change_was_from_scrolling = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_touchcontrols) {
|
||||
std::optional<u16> selection = g_touchcontrols->getHotbarSelection();
|
||||
if (selection)
|
||||
if (selection) {
|
||||
*new_playeritem = *selection;
|
||||
player_input_happened = true;
|
||||
change_was_from_scrolling = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Clamp selection again in case it wasn't changed but max_item was
|
||||
*new_playeritem = MYMIN(*new_playeritem, max_item);
|
||||
|
||||
if (player_input_happened) {
|
||||
if (prev_playeritem != *new_playeritem) {
|
||||
client->setPlayerItem(*new_playeritem);
|
||||
}
|
||||
// notify server of hotbar item selected
|
||||
IHotbarSlotSelectedAction* a = new IHotbarSlotSelectedAction();
|
||||
a->inv.setCurrentPlayer();
|
||||
a->list = "main";
|
||||
a->selected_slot = *new_playeritem;
|
||||
a->prev_selected_slot = prev_playeritem;
|
||||
a->from_scroll = change_was_from_scrolling;
|
||||
client->inventoryAction(a);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -104,6 +104,8 @@ InventoryAction *InventoryAction::deSerialize(std::istream &is)
|
|||
a = new IDropAction(is);
|
||||
} else if (type == "Craft") {
|
||||
a = new ICraftAction(is);
|
||||
} else if (type == "HotbarSlotSelected") {
|
||||
a = new IHotbarSlotSelectedAction(is);
|
||||
}
|
||||
|
||||
return a;
|
||||
|
@ -1017,3 +1019,54 @@ bool getCraftingResult(Inventory *inv, ItemStack &result,
|
|||
return found;
|
||||
}
|
||||
|
||||
/*
|
||||
IHotbarSlotSelectedAction
|
||||
*/
|
||||
|
||||
IHotbarSlotSelectedAction::IHotbarSlotSelectedAction(std::istream& is)
|
||||
{
|
||||
std::string ts;
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
inv.deSerialize(ts);
|
||||
|
||||
std::getline(is, list, ' ');
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
selected_slot = stoi(ts);
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
prev_selected_slot = stoi(ts);
|
||||
|
||||
std::getline(is, ts, ' ');
|
||||
from_scroll = stoi(ts);
|
||||
}
|
||||
|
||||
void IHotbarSlotSelectedAction::apply(InventoryManager* mgr, ServerActiveObject* player, IGameDef* gamedef)
|
||||
{
|
||||
Inventory* inv_hotbar = mgr->getInventory(inv);
|
||||
|
||||
if (!inv_hotbar) {
|
||||
warningstream << "IHotbarSlotSelectedAction::apply(): FAIL: source inventory not found: "
|
||||
<< "inv=\"" << inv.dump() << "\"" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
InventoryList* list_wield = inv_hotbar->getList(list);
|
||||
|
||||
/*
|
||||
If the list doesn't exist
|
||||
*/
|
||||
if (!list_wield) {
|
||||
warningstream << "IHotbarSlotSelectedAction::apply(): FAIL: source list not found: "
|
||||
<< "list=\"" << list << "\"" << std::endl;
|
||||
return;
|
||||
}
|
||||
ServerScripting* sa = PLAYER_TO_SA(player);
|
||||
sa->on_hotbar_slot_selected(player, inv, list, selected_slot, prev_selected_slot, from_scroll);
|
||||
}
|
||||
|
||||
void IHotbarSlotSelectedAction::clientApply(InventoryManager* mgr, IGameDef* gamedef)
|
||||
{
|
||||
// Optional operation that is run on the client to make lag less apparent.
|
||||
}
|
||||
|
|
|
@ -109,7 +109,8 @@ public:
|
|||
enum class IAction : u16 {
|
||||
Move,
|
||||
Drop,
|
||||
Craft
|
||||
Craft,
|
||||
HotbarSlotSelected,
|
||||
};
|
||||
|
||||
struct InventoryAction
|
||||
|
@ -247,3 +248,35 @@ struct ICraftAction : public InventoryAction
|
|||
bool getCraftingResult(Inventory *inv, ItemStack &result,
|
||||
std::vector<ItemStack> &output_replacements,
|
||||
bool decrementInput, IGameDef *gamedef);
|
||||
|
||||
struct IHotbarSlotSelectedAction : public InventoryAction
|
||||
{
|
||||
InventoryLocation inv;
|
||||
std::string list;
|
||||
s16 selected_slot = -1;
|
||||
s16 prev_selected_slot = -1;
|
||||
bool from_scroll = false;
|
||||
|
||||
IHotbarSlotSelectedAction() = default;
|
||||
|
||||
IHotbarSlotSelectedAction(std::istream& is);
|
||||
|
||||
IAction getType() const
|
||||
{
|
||||
return IAction::HotbarSlotSelected;
|
||||
}
|
||||
|
||||
void serialize(std::ostream& os) const
|
||||
{
|
||||
os<<"HotbarSlotSelected ";
|
||||
os<<inv.dump()<<" ";
|
||||
os<<list<<" ";
|
||||
os<<selected_slot<<" ";
|
||||
os<<prev_selected_slot<<" ";
|
||||
os<<(from_scroll ? "1" : "0");
|
||||
}
|
||||
|
||||
void apply(InventoryManager* mgr, ServerActiveObject* player, IGameDef* gamedef);
|
||||
|
||||
void clientApply(InventoryManager* mgr, IGameDef* gamedef);
|
||||
};
|
||||
|
|
|
@ -734,6 +734,14 @@ void Server::handleCommand_InventoryAction(NetworkPacket* pkt)
|
|||
|
||||
if (!check_inv_access(ca->craft_inv))
|
||||
return;
|
||||
}
|
||||
/*
|
||||
Handle HotbarSlotSelected action special cases
|
||||
*/
|
||||
else if (a->getType() == IAction::HotbarSlotSelected) {
|
||||
IHotbarSlotSelectedAction *ha = (IHotbarSlotSelectedAction*)a.get();
|
||||
ha->inv.applyCurrentPlayer(player->getName());
|
||||
// Note: `IHotbarSlotSelectedAction::clientApply` is empty, thus nothing to revert.
|
||||
} else {
|
||||
// Unknown action. Ignored.
|
||||
return;
|
||||
|
|
|
@ -236,6 +236,35 @@ void ScriptApiPlayer::on_authplayer(const std::string &name, const std::string &
|
|||
runCallbacks(3, RUN_CALLBACKS_MODE_FIRST);
|
||||
}
|
||||
|
||||
void ScriptApiPlayer::on_hotbar_slot_selected(
|
||||
ServerActiveObject* player,
|
||||
InventoryLocation& loc,
|
||||
const std::string &list,
|
||||
int hotbar_slot,
|
||||
int prev_hotbar_slot,
|
||||
bool is_from_scroll
|
||||
)
|
||||
{
|
||||
SCRIPTAPI_PRECHECKHEADER
|
||||
|
||||
lua_getglobal(L, "core");
|
||||
lua_getfield(L, -1, "registered_on_hotbar_slot_selected");
|
||||
// param 1
|
||||
objectrefGetOrCreate(L, player);
|
||||
// param 2
|
||||
InvRef::create(L, loc);
|
||||
// param 3
|
||||
lua_pushstring(L, list.c_str());
|
||||
// param 4
|
||||
lua_pushinteger(L, hotbar_slot + 1);
|
||||
// param 5
|
||||
lua_pushinteger(L, prev_hotbar_slot + 1);
|
||||
// param 6
|
||||
lua_pushboolean(L, is_from_scroll);
|
||||
|
||||
runCallbacks(6, RUN_CALLBACKS_MODE_LAST);
|
||||
}
|
||||
|
||||
void ScriptApiPlayer::pushMoveArguments(
|
||||
const MoveAction &ma, int count,
|
||||
ServerActiveObject *player)
|
||||
|
|
|
@ -38,6 +38,14 @@ public:
|
|||
void on_playerReceiveFields(ServerActiveObject *player,
|
||||
const std::string &formname, const StringMap &fields);
|
||||
void on_authplayer(const std::string &name, const std::string &ip, bool is_success);
|
||||
void on_hotbar_slot_selected(
|
||||
ServerActiveObject* player,
|
||||
InventoryLocation& loc,
|
||||
const std::string& list,
|
||||
int hotbar_slot,
|
||||
int prev_hotbar_slot,
|
||||
bool is_from_scroll
|
||||
);
|
||||
|
||||
// Player inventory callbacks
|
||||
// Return number of accepted items to be moved
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue