Sort button 2#3194
Conversation
Wunka
left a comment
There was a problem hiding this comment.
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)},
}});
}
};|
also fixes #3195 |
|
|
||
| pub fn compressItems(source: ClientInventory) void { | ||
| for (source.super._items, 0..) |invStack, slot| { | ||
| for (source.super._items, 0..) |checkedInvStack, checkedSlot| { |
There was a problem hiding this comment.
If the item is filled with mostly the same items, this will spawn O(n²) inventory commands. That is excessive.
There was a problem hiding this comment.
ok i made it a bit more effecient
I realized how to turn tags into numbers so I’m gonna try this |
|
is ready for rereview |
Wunka
left a comment
There was a problem hiding this comment.
Nice. Now the code looks much better
| pub fn getTagsFromItem(givenItem: Item) []const Tag { | ||
| if (givenItem == .null) { | ||
| return &[_]Tag{}; | ||
| } else if (givenItem == .proceduralItem) { | ||
| return givenItem.proceduralItem.type.tags(); | ||
| } else if (givenItem == .baseItem) { | ||
| return givenItem.baseItem.tags(); | ||
| } else { | ||
| std.log.err("getSortingTag: Could not find item class {}", .{givenItem}); | ||
| return &[_]Tag{}; | ||
| } | ||
| } |
There was a problem hiding this comment.
This should be in the Item struct and use a switch(self) so you don't need the else at the end
| 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; |
There was a problem hiding this comment.
this is probably not the best thing (I know it is from me but it was at that time made up on the spot). We probably need to enforce that the tags are sorted so that for example when ItemA has a,b tags and ItemB has c,a,b It gets compared with a,b and a,b,c. Either by sorting them when we load the tags or here. Or some other way.
There was a problem hiding this comment.
If I do this I think it would cause read order issues if I make it check if the first tag of ItemA exists in ItemB because they could have different orders
I could fix this with forcing them to read based on the enum int value but I like what I have now because it gives control to developers on how items are catogorized and sorted
you could create tags that are used in nothing but sorting so that all flowers are sorted together under the category of cuttable
There was a problem hiding this comment.
If I do this I think it would cause read order issues if I make it check if the first tag of ItemA exists in ItemB because they could have different orders I could fix this with forcing them to read based on the enum int value but I like what I have now because it gives control to developers on how items are catogorized and sorted
you could create tags that are used in nothing but sorting so that all flowers are sorted together under the category of cuttable
We didn't mean that. We meant that the tags should be already sorted so what you at the start said doesn't need to be done. This sorting algorithm could then also be changed by a user if they want to.
You just need to add in src/tag.zig
pub fn loadTagsFromZon(_allocator: main.heap.NeverFailingAllocator, zon: main.ZonElement) []Tag {
const result = _allocator.alloc(Tag, zon.toSlice().len);
for (zon.toSlice(), 0..) |tagZon, i| {
result[i] = Tag.find(tagZon.as([]const u8) orelse blk: {
std.log.err("Tag array field {s} has incorrect type, expected string", .{@tagName(tagZon)});
break :blk "incorrect";
});
}
+ // some kind of sorting before returning the result
return result;
}There was a problem hiding this comment.
I don’t understand what you mean by sorting the tags
There was a problem hiding this comment.
Oh I see
You mean so that
C A B
B A C
C B A
all get sorted together A B C
Right?
There was a problem hiding this comment.
Oh I see You mean so that C A B B A C C B A
all get sorted together A B C Right?
yes exactly.
There was a problem hiding this comment.
No
Id rather give the developer control on sorting rather than enforce is based on the order tags were read into memory
Even if that means mistakes can make sorting look weird
There was a problem hiding this comment.
But the sorting of the tags is also clientside. So it can also be changed.
| } | ||
| if (itemATags.len != itemBTags.len) return itemATags.len < itemBTags.len; | ||
|
|
||
| return std.mem.lessThan(u8, itemA.id().?, itemB.id().?); |
There was a problem hiding this comment.
I think it would be nice to add here that proceduralItems are sorted by durability, when even the id is the same.

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