How to sort my inventory array of resources by name

Godot Version

v4.4.stable.official.4c311cbee

Question

I am trying to sort my inventory items by name. All routes I take result in an error that I cannot figure out, not all errors being the same. I am a few months in and slowly understanding gdscript. Any help would be appreciated!

My inventory is fully functional, including adding items, removing items, splitting stacks, etc. Just trying to add a sort function now.

The inventory array is of “SlotData” resource (contains quantity and ItemData resource)
ItemData resource contains name, texture, and other item linked variables.
Typically when accessing the name I would use “slot_data.item_data.name”

My current code (generated from Google AI overview)

@export var slots : Array [SlotData]

func sort_by_name_trigger(): #triggered by the "y" key to start sorting
	slots.sort_custom(_sort_slots_by_item_name)

func _sort_slots_by_item_name(slot_a: SlotData, slot_b: SlotData) -> bool:
	if slot_a.item_data and slot_b.item_data:
		return slot_a.item_data.name < slot_b.item_data.name  # Sort ascending by name
	elif slot_a.item_data:
		return true  # Slot with item comes before empty slot
	else:
		return false  # Empty slot comes after slot with item

currently I am getting an error, and I am assuming it is trying to access a null reference.
(Invalid access to property or key ‘item_data’ on a base object of type 'Nil)
There are 7 of the 40 slots containing items of varying types.

Your sorting functions looks good. I reckon it’s the SlotData that’s throwing the error. Debug your datatype. I think it’s likely that an empty slot is trowing the NULL. Make sure that empty slots are also a SlotData object, or change the logic to checks is SlotData exists before accessing .item_data.

1 Like

Thanks for the reply! After posting this, I noticed slot_b was null, causing the error. I couldn’t get back on to add it to the original message, as It was pending approval, being my first post. I will say all slots are null unless there was an item located at that slot. See print out of the first 10 slots below, as the rest of the 40 slots are null. Note that the 5 null slots do not show up on the forum message, but are there.

<Resource#-9223372002595699332>
<Resource#-9223372002578922114>
<Resource#-9223372002562144896>
<Resource#-9223372002545367681>
<Resource#-9223372002528590462>




I’m assuming I should add another if statement to say if == null then “do something”? In that case I can try the following (guessing, as I am still not real familiar of how the custom sort works yet)

if a == null and b != null then b < a (sends a to the end of the list)
if a != null and b == null then b > a (sends b to the end of the list)
if a == null and b == null then a > b (as it don’t matter which is listed first)

I prefer not to write data in my empty slots, as this is how the code knows where items are.

What does SlotData contain? You need to check if slot_a is null, can slot_a.item_data ever be null? If not then you could use this to check for null elements in the array.

func _sort_slots_by_item_name(slot_a: SlotData, slot_b: SlotData) -> bool:
	if slot_a and slot_b:
		return slot_a.item_data.name < slot_b.item_data.name  # Sort ascending by name
	elif slot_a:
		return true  # Slot with item comes before empty slot
	else:
		return false  # Empty slot comes after slot with item

SlotData contains only the quantity and ItemData.

I am assuming it steps through all the slots and compares them to the next slot. In this case, if there are empty slots scattered in the inventory anywhere, you could have either a or b null and any time.

Yes but checking if a slot is empty is slot_a != null, not slot_a.item_data != null. the latter is trying to access .item_data from a null value.

1 Like

This works, adding slot_a and slot_b to the beginning, to verify they are both not null, then adding slot_a and !slot_b to the elif statement:

if slot_a and slot_b and slot_a.item_data and slot_b.item_data:
	return slot_a.item_data.name < slot_b.item_data.name  # Sort ascending by name
elif slot_a and !slot_b and slot_a.item_data:
	return true  # Slot with item comes before empty slot
else:
	return false  # Empty slot comes after slot with item

Thanks for the help from both of you!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.