Skip to content

Sort button attempt 2 - #3194

Open
Crepestrom wants to merge 71 commits into
PixelGuys:masterfrom
Crepestrom:Sort-Button-2
Open

Sort button attempt 2#3194
Crepestrom wants to merge 71 commits into
PixelGuys:masterfrom
Crepestrom:Sort-Button-2

Conversation

@Crepestrom

@Crepestrom Crepestrom commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

Sort button now functions as normal

Before sorting it will compress all items into their max stacks and push them all to the lowest index getting rid of any holes

Then the sort button will first seperate items into procederal items and nonprocedural items
then they will be sorted by tag
items that share the same first tag will be internally sorted by their second tag and so on and so forth
procedural items are sorted by durability

image

Also allows buttons to be hidden
if a button is hidden the icon within it is extended to the size of the whole button (its scaled up).

@Crepestrom Crepestrom mentioned this pull request Jun 8, 2026

@Wunka Wunka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still think that std.sort is probably way nicer and easier. Here is an example (not tested) based on your current code (but of course not completly mapped and I with an added getTags method for the Item struct):

pub fn sortItems(source: ClientInventory, ignoredSlotCount: usize) void {
	compressItems(source);
	const ctx: SortContext = .{.inv = source};
	std.sort.insertionContext(ignoredSlotCount, source.super._items.len, ctx);
}

const SortContext = struct {
	inv: ClientInventory,

	pub fn lessThan(ctx: @This(), a: usize, b: usize) bool {
		const itemA = ctx.inv.getItem(a);
		const itemB = ctx.inv.getItem(b);

		if(itemA == .null) return false;
		if(itemB == .null) return true;

		const itemATags = itemA.getTags().?;
		const itemBTags = itemB.getTags().?;

		for(0..@min(itemATags.len, itemBTags.len)) |i| {
			if(itemATags[i] == itemBTags[i]) continue;
			return std.mem.lessThan(u8, itemATags[i].getName(), itemBTags[i].getName());
		}
		if(itemATags.len != itemBTags.len) return itemATags.len < itemBTags.len;

		return std.mem.lessThan(u8, itemA.id().?, itemB.id().?);
	}

	pub fn swap(ctx: @This(), a: usize, b: usize) void {
		main.sync.client.executeCommand(.{.depositOrSwap = .{
			.dest = .{.inv = ctx.inv.super, .slot = @intCast(a)}, 
			.source = .{.inv = ctx.inv.super, .slot = @intCast(b)},
		}});
	}
};

@Crepestrom
Crepestrom marked this pull request as ready for review June 9, 2026 21:16
@Crepestrom

Copy link
Copy Markdown
Contributor Author

also fixes #3195

@Wunka Wunka moved this to Low Priority in PRs to review Jun 10, 2026

@IntegratedQuantum IntegratedQuantum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

About the UI: An icon like this is hard to understand, there is no such thing as a universal sorting icon, and a funnel is often used for filtering.
I think Terraria has a simple and intuitive UI for this:

Image

Comment thread src/Inventory.zig
Comment thread src/Inventory.zig Outdated
Comment thread src/Inventory.zig Outdated
Comment thread src/Inventory.zig Outdated
@IntegratedQuantum IntegratedQuantum moved this from Low Priority to In review in PRs to review Jun 11, 2026
@Crepestrom

Copy link
Copy Markdown
Contributor Author

I still think that std.sort is probably way nicer and easier. Here is an example (not tested) based on your current code (but of course not completly mapped and I with an added getTags method for the Item struct):

pub fn sortItems(source: ClientInventory, ignoredSlotCount: usize) void {
	compressItems(source);
	const ctx: SortContext = .{.inv = source};
	std.sort.insertionContext(ignoredSlotCount, source.super._items.len, ctx);
}

const SortContext = struct {
	inv: ClientInventory,

	pub fn lessThan(ctx: @This(), a: usize, b: usize) bool {
		const itemA = ctx.inv.getItem(a);
		const itemB = ctx.inv.getItem(b);

		if(itemA == .null) return false;
		if(itemB == .null) return true;

		const itemATags = itemA.getTags().?;
		const itemBTags = itemB.getTags().?;

		for(0..@min(itemATags.len, itemBTags.len)) |i| {
			if(itemATags[i] == itemBTags[i]) continue;
			return std.mem.lessThan(u8, itemATags[i].getName(), itemBTags[i].getName());
		}
		if(itemATags.len != itemBTags.len) return itemATags.len < itemBTags.len;

		return std.mem.lessThan(u8, itemA.id().?, itemB.id().?);
	}

	pub fn swap(ctx: @This(), a: usize, b: usize) void {
		main.sync.client.executeCommand(.{.depositOrSwap = .{
			.dest = .{.inv = ctx.inv.super, .slot = @intCast(a)}, 
			.source = .{.inv = ctx.inv.super, .slot = @intCast(b)},
		}});
	}
};

I realized how to turn tags into numbers so I’m gonna try this

@Crepestrom

Copy link
Copy Markdown
Contributor Author

is ready for rereview

@Wunka Wunka left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice. Now the code looks much better

Comment thread src/Inventory.zig Outdated
Comment thread src/Inventory.zig Outdated
Comment thread src/Inventory.zig
@IntegratedQuantum IntegratedQuantum moved this from In review to WIP/not ready for review in PRs to review Jun 12, 2026
@Crepestrom Crepestrom changed the title Sort button 2 Sort button attempt 2 Jun 13, 2026

@IntegratedQuantum IntegratedQuantum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before my next review please figure out how to get leak checking working. It still leaks.
To use leak checking you need to build in debug mode, test your feature, and then you need to exit the game normally (do not kill it through Ctrl+C or whatever), then you will see the leaks in the terminal output.
Please ask someone for help if you can't figure it out on your own. But we cannot have you as a contributor if every time I review I need to run the leak check for you.

Comment thread src/gui/windows/chest.zig
@Crepestrom

Copy link
Copy Markdown
Contributor Author

ok what allocator is leaking?
ill see if i can fix that check

@du82

du82 commented Jul 23, 2026

Copy link
Copy Markdown

I don't think the sort button should be that big. The UI / UX is pretty bad on it. Maybe it should live in the toolbar as a small filter icon

@Wunka

Wunka commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

I don't think the sort button should be that big. The UI / UX is pretty bad on it. Maybe it should live in the toolbar as a small filter icon

Are you looking at the old pictures?

@IntegratedQuantum IntegratedQuantum left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how you missed it, but it's still leaking.

Also stack merging doesn't work properly:
Image
when clicking the button becomes
Image

Comment thread src/gui/components/Button.zig Outdated
Comment thread src/assets.zig Outdated
const index = items.BaseItemIndex.fromId(stringId).?;
const item = &items.itemList[@intFromEnum(index)];
item.block = block;
const combinedTags = std.mem.concat(main.worldArena.allocator, Tag, &.{blocks.parseBlock(stringId).tags(), item.tags}) catch unreachable;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm still not sure if we want this.
Also it's not needed now that sorting no longer uses tags

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment thread src/items.zig Outdated
}
}

pub fn getTags(self: Item) []const Tag {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not used

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment thread src/Inventory.zig Outdated
return std.mem.lessThan(u8, itemA.id().?, itemB.id().?);
}

pub fn swap(ctx: *@This(), a: usize, b: usize) void {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed

Comment thread src/Inventory.zig
var SortList = main.ListManaged(usize).init(main.stackAllocator);
var intermediaryList = main.ListManaged(usize).init(main.stackAllocator);
defer SortList.deinit();
defer intermediaryList.deinit();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

defer should always be directly after the line that does the init

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

moved

Comment thread src/Inventory.zig Outdated
pub fn sortItems(source: ClientInventory, options: SortOptions) void {
compressItems(source, options);
const InventorySize: usize = source.super.size() - options.ignoredSlotCount;
var SortList = main.ListManaged(usize).init(main.stackAllocator);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
var SortList = main.ListManaged(usize).init(main.stackAllocator);
var sortList = main.ListManaged(usize).init(main.stackAllocator);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renamed

@IntegratedQuantum IntegratedQuantum moved this from Low Priority to In review in PRs to review Jul 30, 2026
@IntegratedQuantum

Copy link
Copy Markdown
Member

I don't see any changes since my last review. Did you forget to push?

@Crepestrom

Copy link
Copy Markdown
Contributor Author

testing finished

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

5 participants