Fix individual decor inventory identity (#128)

This commit is contained in:
Alexander Sellite 2026-09-02 09:51:33 -04:00
parent cab313d69d
commit 5aa723de54
6 changed files with 276 additions and 113 deletions

View file

@ -66,24 +66,44 @@ func setup(
_validate_assignments() _validate_assignments()
func assign_item(slot_index: int, item_id: StringName) -> bool: func assign_item(
slot_index: int,
item_id: StringName,
entry_key: String = "",
) -> bool:
if not _is_slot_valid(slot_index) or not _can_assign(item_id): if not _is_slot_valid(slot_index) or not _can_assign(item_id):
return false return false
if _inventory_layout != null:
if not entry_key.is_empty():
var entry := _inventory_layout.get_entry_by_key(entry_key)
if (
entry.is_empty()
or int(entry.get("kind", -1))
!= PlayerInventoryLayout.EntryKind.ITEM
or StringName(str(entry.get("identity", ""))) != item_id
):
return false
if not _inventory_layout.move_entry_by_key(
entry_key,
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
):
return false
else:
if not _inventory_layout.move_entry(
PlayerInventoryLayout.EntryKind.ITEM,
item_id,
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
):
return false
_synchronize_assignments_from_layout()
return true
if _slots[slot_index] == item_id: if _slots[slot_index] == item_id:
return true return true
var source_index: int = _slots.find(item_id) var source_index: int = _slots.find(item_id)
var displaced_item: StringName = _slots[slot_index] var displaced_item: StringName = _slots[slot_index]
var displaced_fish: StringName = _fish_slots[slot_index] var displaced_fish: StringName = _fish_slots[slot_index]
if (
_inventory_layout != null
and not _inventory_layout.move_entry(
PlayerInventoryLayout.EntryKind.ITEM,
item_id,
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
)
):
return false
var selected_slot_was_affected: bool = slot_index == _selected_slot var selected_slot_was_affected: bool = slot_index == _selected_slot
if source_index >= 0 and source_index != slot_index: if source_index >= 0 and source_index != slot_index:
_slots[source_index] = displaced_item _slots[source_index] = displaced_item
@ -102,21 +122,21 @@ func assign_item(slot_index: int, item_id: StringName) -> bool:
func assign_fish(slot_index: int, catch_id: StringName) -> bool: func assign_fish(slot_index: int, catch_id: StringName) -> bool:
if not _is_slot_valid(slot_index) or not _can_assign_fish(catch_id): if not _is_slot_valid(slot_index) or not _can_assign_fish(catch_id):
return false return false
if _inventory_layout != null:
if not _inventory_layout.move_entry(
PlayerInventoryLayout.EntryKind.CATCH,
catch_id,
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
):
return false
_synchronize_assignments_from_layout()
return true
if _fish_slots[slot_index] == catch_id: if _fish_slots[slot_index] == catch_id:
return true return true
var source_index: int = _fish_slots.find(catch_id) var source_index: int = _fish_slots.find(catch_id)
var displaced_item: StringName = _slots[slot_index] var displaced_item: StringName = _slots[slot_index]
var displaced_fish: StringName = _fish_slots[slot_index] var displaced_fish: StringName = _fish_slots[slot_index]
if (
_inventory_layout != null
and not _inventory_layout.move_entry(
PlayerInventoryLayout.EntryKind.CATCH,
catch_id,
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
)
):
return false
var selected_slot_was_affected: bool = slot_index == _selected_slot var selected_slot_was_affected: bool = slot_index == _selected_slot
if source_index >= 0 and source_index != slot_index: if source_index >= 0 and source_index != slot_index:
_slots[source_index] = displaced_item _slots[source_index] = displaced_item
@ -146,6 +166,9 @@ func clear_slot(slot_index: int) -> bool:
and not _inventory_layout.return_hotbar_entry_to_inventory(slot_index) and not _inventory_layout.return_hotbar_entry_to_inventory(slot_index)
): ):
return false return false
if _inventory_layout != null:
_synchronize_assignments_from_layout()
return true
_slots[slot_index] = StringName() _slots[slot_index] = StringName()
_fish_slots[slot_index] = StringName() _fish_slots[slot_index] = StringName()
slots_changed.emit() slots_changed.emit()
@ -162,38 +185,30 @@ func swap_slots(from_index: int, to_index: int) -> bool:
): ):
return false return false
if _inventory_layout != null: if _inventory_layout != null:
var kind: PlayerInventoryLayout.EntryKind var source_key := _inventory_layout.get_key_at(
var identity: StringName PlayerInventoryLayout.InventoryContainer.HOTBAR,
if not _fish_slots[from_index].is_empty(): from_index,
kind = PlayerInventoryLayout.EntryKind.CATCH )
identity = _fish_slots[from_index] var target_key := _inventory_layout.get_key_at(
elif not _slots[from_index].is_empty(): PlayerInventoryLayout.InventoryContainer.HOTBAR,
kind = PlayerInventoryLayout.EntryKind.ITEM to_index,
identity = _slots[from_index] )
else: if source_key.is_empty() and target_key.is_empty():
kind = ( return false
PlayerInventoryLayout.EntryKind.CATCH var moved_key: String = (
if not _fish_slots[to_index].is_empty() source_key if not source_key.is_empty() else target_key
else PlayerInventoryLayout.EntryKind.ITEM )
) var destination: int = (
identity = ( to_index if not source_key.is_empty() else from_index
_fish_slots[to_index] )
if not _fish_slots[to_index].is_empty() if not _inventory_layout.move_entry_by_key(
else _slots[to_index] moved_key,
) PlayerInventoryLayout.InventoryContainer.HOTBAR,
var temporary_index: int = from_index destination,
from_index = to_index
to_index = temporary_index
if (
identity.is_empty()
or not _inventory_layout.move_entry(
kind,
identity,
PlayerInventoryLayout.InventoryContainer.HOTBAR,
to_index,
)
): ):
return false return false
_synchronize_assignments_from_layout()
return true
var temporary: StringName = _slots[from_index] var temporary: StringName = _slots[from_index]
_slots[from_index] = _slots[to_index] _slots[from_index] = _slots[to_index]
_slots[to_index] = temporary _slots[to_index] = temporary
@ -213,40 +228,19 @@ func move_slot_to_container(
) -> bool: ) -> bool:
if not _is_slot_valid(slot_index) or _inventory_layout == null: if not _is_slot_valid(slot_index) or _inventory_layout == null:
return false return false
var kind: PlayerInventoryLayout.EntryKind var entry_key := _inventory_layout.get_key_at(
var identity: StringName PlayerInventoryLayout.InventoryContainer.HOTBAR,
if not _fish_slots[slot_index].is_empty(): slot_index,
kind = PlayerInventoryLayout.EntryKind.CATCH )
identity = _fish_slots[slot_index] if entry_key.is_empty():
elif not _slots[slot_index].is_empty():
kind = PlayerInventoryLayout.EntryKind.ITEM
identity = _slots[slot_index]
else:
return false return false
if not _inventory_layout.move_entry( if not _inventory_layout.move_entry_by_key(
kind, entry_key,
identity,
target_container, target_container,
target_slot, target_slot,
): ):
return false return false
_slots[slot_index] = StringName() _synchronize_assignments_from_layout()
_fish_slots[slot_index] = StringName()
var replacement := _inventory_layout.get_entry_at(
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
)
if not replacement.is_empty():
var replacement_identity := StringName(
str(replacement.get("identity", ""))
)
if int(replacement.get("kind", -1)) == PlayerInventoryLayout.EntryKind.CATCH:
_fish_slots[slot_index] = replacement_identity
else:
_slots[slot_index] = replacement_identity
slots_changed.emit()
if slot_index == _selected_slot:
_emit_selected_assignment()
return true return true
@ -288,6 +282,22 @@ func get_item_id(slot_index: int) -> StringName:
return _slots[slot_index] if _is_slot_valid(slot_index) else StringName() return _slots[slot_index] if _is_slot_valid(slot_index) else StringName()
func get_item_entry_key(slot_index: int) -> String:
if not _is_slot_valid(slot_index) or _inventory_layout == null:
return ""
var entry := _inventory_layout.get_entry_at(
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
)
if int(entry.get("kind", -1)) != PlayerInventoryLayout.EntryKind.ITEM:
return ""
return str(entry.get("key", ""))
func get_selected_item_entry_key() -> String:
return get_item_entry_key(_selected_slot)
func get_fish_catch_id(slot_index: int) -> StringName: func get_fish_catch_id(slot_index: int) -> StringName:
return ( return (
_fish_slots[slot_index] _fish_slots[slot_index]
@ -339,6 +349,12 @@ func replace_state(
fish_slots: Array[StringName] = [], fish_slots: Array[StringName] = [],
synchronize_layout: bool = true, synchronize_layout: bool = true,
) -> bool: ) -> bool:
if _inventory_layout != null and not synchronize_layout:
_selected_slot = clampi(selected_slot, 0, SLOT_COUNT - 1)
_synchronize_assignments_from_layout(false)
slots_changed.emit()
_emit_selected_assignment()
return true
if ( if (
synchronize_layout and _inventory_layout != null synchronize_layout and _inventory_layout != null
and not _inventory_layout.return_all_hotbar_entries_to_inventory() and not _inventory_layout.return_all_hotbar_entries_to_inventory()
@ -355,9 +371,17 @@ func replace_state(
var item_id: StringName = slots[index] var item_id: StringName = slots[index]
if item_id.is_empty(): if item_id.is_empty():
continue continue
if _can_assign(item_id) and not seen_assignments.has(item_id): var permits_duplicates: bool = (
_inventory_layout != null
and _inventory_layout.uses_individual_item_slots(item_id)
)
if (
_can_assign(item_id)
and (permits_duplicates or not seen_assignments.has(item_id))
):
normalized[index] = item_id normalized[index] = item_id
seen_assignments[item_id] = true if not permits_duplicates:
seen_assignments[item_id] = true
var seen_fish: Dictionary[StringName, bool] = {} var seen_fish: Dictionary[StringName, bool] = {}
for index: int in range(mini(fish_slots.size(), SLOT_COUNT)): for index: int in range(mini(fish_slots.size(), SLOT_COUNT)):
if not normalized[index].is_empty(): if not normalized[index].is_empty():
@ -370,21 +394,23 @@ func replace_state(
_fish_slots = normalized_fish _fish_slots = normalized_fish
if _inventory_layout != null and synchronize_layout: if _inventory_layout != null and synchronize_layout:
for index: int in SLOT_COUNT: for index: int in SLOT_COUNT:
if not _slots[index].is_empty(): if not normalized[index].is_empty():
_inventory_layout.move_entry( _inventory_layout.move_entry(
PlayerInventoryLayout.EntryKind.ITEM, PlayerInventoryLayout.EntryKind.ITEM,
_slots[index], normalized[index],
PlayerInventoryLayout.InventoryContainer.HOTBAR, PlayerInventoryLayout.InventoryContainer.HOTBAR,
index, index,
) )
elif not _fish_slots[index].is_empty(): elif not normalized_fish[index].is_empty():
_inventory_layout.move_entry( _inventory_layout.move_entry(
PlayerInventoryLayout.EntryKind.CATCH, PlayerInventoryLayout.EntryKind.CATCH,
_fish_slots[index], normalized_fish[index],
PlayerInventoryLayout.InventoryContainer.HOTBAR, PlayerInventoryLayout.InventoryContainer.HOTBAR,
index, index,
) )
_selected_slot = clampi(selected_slot, 0, SLOT_COUNT - 1) _selected_slot = clampi(selected_slot, 0, SLOT_COUNT - 1)
if _inventory_layout != null:
_synchronize_assignments_from_layout(false)
slots_changed.emit() slots_changed.emit()
_emit_selected_assignment() _emit_selected_assignment()
return true return true
@ -434,6 +460,9 @@ func _can_assign_fish(catch_id: StringName) -> bool:
func _validate_assignments() -> void: func _validate_assignments() -> void:
if _inventory_layout != null:
_synchronize_assignments_from_layout()
return
var changed: bool = false var changed: bool = false
for index: int in range(SLOT_COUNT): for index: int in range(SLOT_COUNT):
if not _slots[index].is_empty() and not _can_assign(_slots[index]): if not _slots[index].is_empty() and not _can_assign(_slots[index]):
@ -450,6 +479,37 @@ func _validate_assignments() -> void:
_emit_selected_assignment() _emit_selected_assignment()
func _synchronize_assignments_from_layout(emit_changes: bool = true) -> void:
if _inventory_layout == null:
return
var synchronized_items: Array[StringName] = []
synchronized_items.resize(SLOT_COUNT)
synchronized_items.fill(StringName())
var synchronized_fish: Array[StringName] = []
synchronized_fish.resize(SLOT_COUNT)
synchronized_fish.fill(StringName())
for slot_index: int in SLOT_COUNT:
var entry := _inventory_layout.get_entry_at(
PlayerInventoryLayout.InventoryContainer.HOTBAR,
slot_index,
)
if entry.is_empty():
continue
var identity := StringName(str(entry.get("identity", "")))
if int(entry.get("kind", -1)) == PlayerInventoryLayout.EntryKind.CATCH:
synchronized_fish[slot_index] = identity
else:
synchronized_items[slot_index] = identity
var changed: bool = (
synchronized_items != _slots or synchronized_fish != _fish_slots
)
_slots = synchronized_items
_fish_slots = synchronized_fish
if changed and emit_changes:
slots_changed.emit()
_emit_selected_assignment()
func _on_bag_contents_changed() -> void: func _on_bag_contents_changed() -> void:
_validate_assignments() _validate_assignments()

View file

@ -41,6 +41,7 @@ var _placements: Dictionary[String, Dictionary] = {}
var _prepared_item_placements: Dictionary[StringName, Array] = {} var _prepared_item_placements: Dictionary[StringName, Array] = {}
var _reconciling: bool = false var _reconciling: bool = false
var _backpack_level: int = 0 var _backpack_level: int = 0
var _item_entry_being_consumed: String = ""
func setup( func setup(
@ -274,6 +275,14 @@ func get_entry(kind: EntryKind, identity: StringName) -> Dictionary:
return _placements.get(key, {}).duplicate(true) return _placements.get(key, {}).duplicate(true)
func get_entry_by_key(key: String) -> Dictionary:
if key.is_empty() or not _placements.has(key):
return {}
var entry: Dictionary = _placements[key].duplicate(true)
entry["key"] = key
return entry
func get_container(kind: EntryKind, identity: StringName) -> int: func get_container(kind: EntryKind, identity: StringName) -> int:
return int( return int(
get_entry(kind, identity).get("container", -1) get_entry(kind, identity).get("container", -1)
@ -333,6 +342,25 @@ func move_entry_by_key(
return true return true
func consume_individual_item_entry(key: String) -> bool:
if _bag == null or _reconciling or not _item_entry_being_consumed.is_empty():
return false
var entry: Dictionary = _placements.get(key, {})
if (
entry.is_empty()
or int(entry.get("kind", -1)) != EntryKind.ITEM
or int(entry.get("unit", -1)) < 0
):
return false
var item_id := StringName(str(entry.get("identity", "")))
if item_id.is_empty() or not _uses_individual_item_slots(item_id):
return false
_item_entry_being_consumed = key
var removed: bool = _bag.remove_item(item_id, 1)
_item_entry_being_consumed = ""
return removed and not _placements.has(key)
func move_entry_to_first_free( func move_entry_to_first_free(
kind: EntryKind, kind: EntryKind,
identity: StringName, identity: StringName,
@ -588,6 +616,8 @@ func _add_expected_individual_items(
for key: String in existing_keys: for key: String in existing_keys:
if retained >= quantity: if retained >= quantity:
break break
if key == _item_entry_being_consumed:
continue
var placement: Dictionary = _placements[key] var placement: Dictionary = _placements[key]
var unit: int = int(placement.get("unit", -1)) var unit: int = int(placement.get("unit", -1))
if unit < 0 or used_units.has(unit): if unit < 0 or used_units.has(unit):
@ -795,6 +825,10 @@ func _uses_individual_item_slots(item_id: StringName) -> bool:
return DecorCatalogType.has_product(item_id) return DecorCatalogType.has_product(item_id)
func uses_individual_item_slots(item_id: StringName) -> bool:
return _uses_individual_item_slots(item_id)
func _item_entry_keys(item_id: StringName) -> Array[String]: func _item_entry_keys(item_id: StringName) -> Array[String]:
var result: Array[String] = [] var result: Array[String] = []
for key: String in _placements: for key: String in _placements:

View file

@ -128,10 +128,21 @@ func place_local_decor(
not can_local_decorate() not can_local_decorate()
or has_pending_local_decor_mutation() or has_pending_local_decor_mutation()
or _bag == null or _bag == null
or _inventory_layout == null
or _hotbar == null
or _bag.get_quantity(decor_id) <= 0 or _bag.get_quantity(decor_id) <= 0
or _world_service == null or _world_service == null
): ):
return "" return ""
var selected_entry_key: String = _hotbar.get_selected_item_entry_key()
var selected_entry: Dictionary = _inventory_layout.get_entry_by_key(
selected_entry_key
)
if (
selected_entry.is_empty()
or StringName(str(selected_entry.get("identity", ""))) != decor_id
):
return ""
var owner_fingerprint: String = ( var owner_fingerprint: String = (
_session.get_local_identity_fingerprint() _session.get_local_identity_fingerprint()
) )
@ -162,7 +173,9 @@ func place_local_decor(
if instance_id.is_empty(): if instance_id.is_empty():
_suppress_local_submission = false _suppress_local_submission = false
return "" return ""
if not _bag.remove_item(decor_id, 1): if not _inventory_layout.consume_individual_item_entry(
selected_entry_key
):
_local_home.remove_placement(instance_id) _local_home.remove_placement(instance_id)
_suppress_local_submission = false _suppress_local_submission = false
return "" return ""
@ -188,17 +201,9 @@ func remove_local_decor(instance_id: String) -> bool:
if transaction.is_empty(): if transaction.is_empty():
return false return false
var decor_id := StringName(str(placement["decor_id"])) var decor_id := StringName(str(placement["decor_id"]))
var target_hotbar_slot: int = _hotbar.find_item_slot(decor_id) var target_hotbar_slot: int = _hotbar.find_first_empty_slot()
if target_hotbar_slot < 0:
target_hotbar_slot = _hotbar.find_first_empty_slot()
var prepared_hotbar_placement: bool = false var prepared_hotbar_placement: bool = false
if ( if target_hotbar_slot >= 0:
target_hotbar_slot >= 0
and _inventory_layout.get_container(
PlayerInventoryLayout.EntryKind.ITEM,
decor_id,
) < 0
):
prepared_hotbar_placement = ( prepared_hotbar_placement = (
_inventory_layout.prepare_new_item_placement( _inventory_layout.prepare_new_item_placement(
decor_id, decor_id,
@ -215,8 +220,7 @@ func remove_local_decor(instance_id: String) -> bool:
if prepared_hotbar_placement: if prepared_hotbar_placement:
_inventory_layout.cancel_prepared_item_placement(decor_id) _inventory_layout.cancel_prepared_item_placement(decor_id)
return false return false
if target_hotbar_slot >= 0: if prepared_hotbar_placement:
_hotbar.assign_item(target_hotbar_slot, decor_id)
_hotbar.select_slot(target_hotbar_slot) _hotbar.select_slot(target_hotbar_slot)
_suppress_local_submission = true _suppress_local_submission = true
if not _local_home.remove_placement(instance_id): if not _local_home.remove_placement(instance_id):
@ -980,15 +984,16 @@ func _restore_decor_item_to_bag(
if _bag == null: if _bag == null:
return false return false
var prepared_slot: int = -1 var prepared_slot: int = -1
if ( if _inventory_layout != null and _hotbar != null:
_inventory_layout != null
and _hotbar != null
and _inventory_layout.get_container(
PlayerInventoryLayout.EntryKind.ITEM, decor_id
) < 0
):
var candidate_slot: int = preferred_hotbar_slot var candidate_slot: int = preferred_hotbar_slot
if candidate_slot < 0: if (
candidate_slot < 0
or candidate_slot >= PlayerHotbar.SLOT_COUNT
or not _inventory_layout.get_key_at(
PlayerInventoryLayout.InventoryContainer.HOTBAR,
candidate_slot,
).is_empty()
):
candidate_slot = _hotbar.find_first_empty_slot() candidate_slot = _hotbar.find_first_empty_slot()
if candidate_slot >= 0 and _inventory_layout.prepare_new_item_placement( if candidate_slot >= 0 and _inventory_layout.prepare_new_item_placement(
decor_id, decor_id,
@ -1000,10 +1005,8 @@ func _restore_decor_item_to_bag(
if not restored: if not restored:
if prepared_slot >= 0: if prepared_slot >= 0:
_inventory_layout.cancel_prepared_item_placement(decor_id) _inventory_layout.cancel_prepared_item_placement(decor_id)
if _bag.get_owned_item(decor_id) == null: restored = _bag.add_item_to_storage(decor_id, 1)
restored = _bag.add_item_to_storage(decor_id, 1)
if restored and prepared_slot >= 0: if restored and prepared_slot >= 0:
_hotbar.assign_item(prepared_slot, decor_id)
_hotbar.select_slot(prepared_slot) _hotbar.select_slot(prepared_slot)
return restored return restored

View file

@ -104,7 +104,62 @@ func _run() -> void:
assert(layout.restore_from_save_data(decor_layout_save)) assert(layout.restore_from_save_data(decor_layout_save))
assert(layout.get_inventory_count() == 2) assert(layout.get_inventory_count() == 2)
assert(layout.get_storage_count() == 1) assert(layout.get_storage_count() == 1)
assert(bag.remove_item(&"basic_cube", 3)) var restored_inventory_decor := layout.get_entries(
PlayerInventoryLayout.InventoryContainer.INVENTORY
)
var hotbar_decor_key: String = str(
restored_inventory_decor[0].get("key", "")
)
assert(hotbar.assign_item(0, &"basic_cube", hotbar_decor_key))
assert(hotbar.get_item_entry_key(0) == hotbar_decor_key)
var second_hotbar_decor_key: String = str(
layout.get_entries(
PlayerInventoryLayout.InventoryContainer.INVENTORY
)[0].get("key", "")
)
assert(second_hotbar_decor_key != hotbar_decor_key)
assert(hotbar.assign_item(1, &"basic_cube", second_hotbar_decor_key))
assert(hotbar.get_item_id(0) == &"basic_cube")
assert(hotbar.get_item_id(1) == &"basic_cube")
assert(hotbar.get_item_entry_key(1) == second_hotbar_decor_key)
assert(
str(layout.get_entry_by_key(moved_decor_key).get("key", ""))
== moved_decor_key
)
assert(
int(layout.get_entry_by_key(moved_decor_key).get("container", -1))
== PlayerInventoryLayout.InventoryContainer.STORAGE
)
assert(hotbar.move_slot_to_container(
0,
PlayerInventoryLayout.InventoryContainer.INVENTORY,
5,
))
assert(hotbar.get_item_id(0).is_empty())
assert(hotbar.get_item_entry_key(1) == second_hotbar_decor_key)
assert(
str(
layout.get_entry_at(
PlayerInventoryLayout.InventoryContainer.INVENTORY, 5
).get("key", "")
)
== hotbar_decor_key
)
assert(
int(layout.get_entry_by_key(moved_decor_key).get("container", -1))
== PlayerInventoryLayout.InventoryContainer.STORAGE
)
assert(hotbar.assign_item(0, &"basic_cube", hotbar_decor_key))
assert(layout.consume_individual_item_entry(hotbar_decor_key))
assert(bag.get_quantity(&"basic_cube") == 2)
assert(layout.get_entry_by_key(hotbar_decor_key).is_empty())
assert(hotbar.get_item_id(0).is_empty())
assert(hotbar.get_item_entry_key(1) == second_hotbar_decor_key)
assert(
int(layout.get_entry_by_key(moved_decor_key).get("container", -1))
== PlayerInventoryLayout.InventoryContainer.STORAGE
)
assert(bag.remove_item(&"basic_cube", 2))
assert(layout.get_inventory_count() == 0) assert(layout.get_inventory_count() == 0)
assert(layout.get_storage_count() == 0) assert(layout.get_storage_count() == 0)

View file

@ -401,7 +401,8 @@ func _drop_data(_at_position: Vector2, data: Variant) -> void:
else: else:
_hotbar.assign_item( _hotbar.assign_item(
slot_index, slot_index,
StringName(str(payload["item_id"])) StringName(str(payload["item_id"])),
str(payload.get("entry_key", "")),
) )

View file

@ -310,6 +310,7 @@ var _controller_hotbar_assignment_kind: PlayerHotbarType.AssignmentKind = (
PlayerHotbarType.AssignmentKind.EMPTY PlayerHotbarType.AssignmentKind.EMPTY
) )
var _controller_hotbar_identity: StringName var _controller_hotbar_identity: StringName
var _controller_hotbar_entry_key: String = ""
var _controller_storage_identity: StringName var _controller_storage_identity: StringName
var _controller_previous_hotbar_slot: int = 0 var _controller_previous_hotbar_slot: int = 0
var _controller_previous_storage_slot: int = 0 var _controller_previous_storage_slot: int = 0
@ -1036,6 +1037,7 @@ func _try_begin_controller_hotbar_placement() -> bool:
PlayerHotbarType.AssignmentKind.EMPTY PlayerHotbarType.AssignmentKind.EMPTY
) )
var identity: StringName var identity: StringName
var entry_key: String = ""
if _current_section == Section.COOLER: if _current_section == Section.COOLER:
var fish_node := focus_owner as CoolerFishSpriteType var fish_node := focus_owner as CoolerFishSpriteType
if fish_node == null or fish_node.catch_id.is_empty(): if fish_node == null or fish_node.catch_id.is_empty():
@ -1047,6 +1049,7 @@ func _try_begin_controller_hotbar_placement() -> bool:
if slot == null or slot.entry_identity.is_empty(): if slot == null or slot.entry_identity.is_empty():
return false return false
identity = slot.entry_identity identity = slot.entry_identity
entry_key = slot.entry_key
if slot.entry_kind == PlayerInventoryLayout.EntryKind.CATCH: if slot.entry_kind == PlayerInventoryLayout.EntryKind.CATCH:
assignment_kind = PlayerHotbarType.AssignmentKind.FISH assignment_kind = PlayerHotbarType.AssignmentKind.FISH
else: else:
@ -1059,7 +1062,9 @@ func _try_begin_controller_hotbar_placement() -> bool:
assignment_kind = PlayerHotbarType.AssignmentKind.ITEM assignment_kind = PlayerHotbarType.AssignmentKind.ITEM
else: else:
return false return false
return _begin_controller_hotbar_placement(assignment_kind, identity) return _begin_controller_hotbar_placement(
assignment_kind, identity, entry_key
)
func _begin_controller_hotbar_placement_for_item(item_id: StringName) -> bool: func _begin_controller_hotbar_placement_for_item(item_id: StringName) -> bool:
@ -1078,6 +1083,7 @@ func _begin_controller_hotbar_placement_for_item(item_id: StringName) -> bool:
func _begin_controller_hotbar_placement( func _begin_controller_hotbar_placement(
assignment_kind: PlayerHotbarType.AssignmentKind, assignment_kind: PlayerHotbarType.AssignmentKind,
identity: StringName, identity: StringName,
entry_key: String = "",
) -> bool: ) -> bool:
if _hotbar == null or identity.is_empty(): if _hotbar == null or identity.is_empty():
return false return false
@ -1085,6 +1091,7 @@ func _begin_controller_hotbar_placement(
_controller_source_identity = identity _controller_source_identity = identity
_controller_hotbar_assignment_kind = assignment_kind _controller_hotbar_assignment_kind = assignment_kind
_controller_hotbar_identity = identity _controller_hotbar_identity = identity
_controller_hotbar_entry_key = entry_key
_controller_previous_hotbar_slot = _hotbar.get_selected_slot() _controller_previous_hotbar_slot = _hotbar.get_selected_slot()
var initial_slot: int = _find_controller_hotbar_assignment( var initial_slot: int = _find_controller_hotbar_assignment(
assignment_kind, assignment_kind,
@ -1193,6 +1200,7 @@ func _confirm_controller_hotbar_placement() -> void:
assigned = _hotbar.assign_item( assigned = _hotbar.assign_item(
slot_index, slot_index,
_controller_hotbar_identity, _controller_hotbar_identity,
_controller_hotbar_entry_key,
) )
if assigned: if assigned:
_release_controller_ownership(true, false) _release_controller_ownership(true, false)
@ -1212,6 +1220,7 @@ func _return_controller_hotbar_placement_to_storage() -> bool:
_controller_ownership = ControllerOwnership.STORAGE_PLACEMENT _controller_ownership = ControllerOwnership.STORAGE_PLACEMENT
_controller_hotbar_assignment_kind = PlayerHotbarType.AssignmentKind.EMPTY _controller_hotbar_assignment_kind = PlayerHotbarType.AssignmentKind.EMPTY
_controller_hotbar_identity = StringName() _controller_hotbar_identity = StringName()
_controller_hotbar_entry_key = ""
_apply_inventory_controller_zone_focus_modes() _apply_inventory_controller_zone_focus_modes()
_configure_bag_storage_slot_focus() _configure_bag_storage_slot_focus()
var target_index: int = clampi( var target_index: int = clampi(
@ -1237,6 +1246,7 @@ func _release_controller_ownership(
_controller_source_identity = StringName() _controller_source_identity = StringName()
_controller_hotbar_assignment_kind = PlayerHotbarType.AssignmentKind.EMPTY _controller_hotbar_assignment_kind = PlayerHotbarType.AssignmentKind.EMPTY
_controller_hotbar_identity = StringName() _controller_hotbar_identity = StringName()
_controller_hotbar_entry_key = ""
_controller_storage_identity = StringName() _controller_storage_identity = StringName()
if prior_ownership == ControllerOwnership.NOTEPAD_ACTIONS: if prior_ownership == ControllerOwnership.NOTEPAD_ACTIONS:
_set_inventory_notepad_visible(source_section, false) _set_inventory_notepad_visible(source_section, false)