Skip to content

Commit

Permalink
Bogosort compat (#32)
Browse files Browse the repository at this point in the history
* update bogosorter api

* fix widgets using deprecated draw method

* open client screens on next tick

* fix sync value collecting

* add sort buttons to sortable slot groups

* enable test guis via config
  • Loading branch information
brachy84 authored Sep 29, 2023
1 parent 52cec98 commit 394748b
Show file tree
Hide file tree
Showing 24 changed files with 618 additions and 36 deletions.
139 changes: 139 additions & 0 deletions src/api/java/com/cleanroommc/bogosorter/api/IBogoSortAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package com.cleanroommc.bogosorter.api;

import net.minecraft.inventory.Container;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTBase;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import java.util.Comparator;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.function.Function;

public interface IBogoSortAPI {

static IBogoSortAPI getInstance() {
throw new UnsupportedOperationException();
}

/**
* Register a function that converts a {@link Slot} to a {@link ISlot}. Useful if modders messed up.
*
* @param clazz slot class
* @param function converter function
* @param <T> slot type
*/
<T extends Slot> void addSlotGetter(Class<T> clazz, Function<T, ISlot> function);

/**
* Registers a function which handles slot insertions in a custom way.
*
* @param clazz container class
* @param insertable custom insertion function
*/
void addCustomInsertable(Class<? extends Container> clazz, ICustomInsertable insertable);

/**
* Adds sorting compat for a container class
*
* @param clazz container class
* @param builder sorting compat builder
* @param <T> container type
*/
<T extends Container> void addCompat(Class<T> clazz, BiConsumer<T, ISortingContextBuilder> builder);

/**
* Adds sorting compat for a container class.
* Is useful when you don't have access to the super class of {@link T}
*
* @param clazz container class
* @param builder sorting compat builder
* @param <T> container type
*/
<T> void addCompatSimple(Class<T> clazz, BiConsumer<T, ISortingContextBuilder> builder);

/**
* Registers a function to figure out where to place player inventory sort buttons.
*
* @param clazz class of the container
* @param buttonPos pos function or null if no buttons are desired
* @throws IllegalArgumentException if the class is not of a container
*/
void addPlayerSortButtonPosition(Class<?> clazz, IPosSetter buttonPos);

/**
* Removes sorting compat for a container class
*
* @param clazz container class
* @param <T> container type
*/
<T extends Container> void removeCompat(Class<T> clazz);

/**
* Registers a sorting rule for items
*
* @param itemComparator comparator
*/
void registerItemSortingRule(String key, Comparator<ItemStack> itemComparator);

/**
* Registers a sorting rule for NBT tags
*
* @param tagPath path of the nbt tag. Separate sub tags with '/'
* @param comparator comparator sorting the tags based on tagPath
*/
void registerNbtSortingRule(String key, String tagPath, Comparator<NBTBase> comparator);

/**
* Registers a sorting rule for NBT tags
*
* @param tagPath path of the nbt tag. Separate sub tags with '/'
* @param expectedType the expected NBT tag id. Will be automatically compared
* @see net.minecraftforge.common.util.Constants.NBT for expectedType
*/
void registerNbtSortingRule(String key, String tagPath, int expectedType);

/**
* Registers a sorting rule for NBT tags
*
* @param tagPath path of the nbt tag. Separate sub tags with '/'
* @param expectedType the expected NBT tag id
* @param comparator comparator of the type converted by converter
* @param converter converts the tag found at the tagPath for the comparator
* @see net.minecraftforge.common.util.Constants.NBT for expectedType
*/
<T> void registerNbtSortingRule(String key, String tagPath, int expectedType, Comparator<T> comparator, Function<NBTBase, T> converter);

/**
* Opens the bogosort config gui
*/
@SideOnly(Side.CLIENT)
void openConfigGui();

/**
* Tries to sort a slot group with the given slot.
*
* @param slot slot of slot group to sort
* @return if the slot group will be sorted (on server side)
*/
@SideOnly(Side.CLIENT)
boolean sortSlotGroup(Slot slot);

/**
* Turns a slot into a generic interface slot
*
* @param slot slot
* @return generic slot
*/
ISlot getSlot(Slot slot);

/**
* Transforms a list of slots using {@link #getSlot(Slot)}
*
* @param slots list of slots
* @return list of generic slots
*/
List<ISlot> getSlots(List<Slot> slots);
}
74 changes: 74 additions & 0 deletions src/api/java/com/cleanroommc/bogosorter/api/IButtonPos.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.cleanroommc.bogosorter.api;

/**
* Determines the true sort button pos for slot groups.
*/
public interface IButtonPos {

void setEnabled(boolean enabled);

/**
* Sets position where the buttons will be placed.
*
* @param x x pos
* @param y y pos
*/
void setPos(int x, int y);

/**
* Sets the alignment of the buttons. Determines where the buttons are placed relative to the pos.
* For example if the alignment is bottom left, then the pos will be the bottom left corner of the buttons.
*
* @param alignment alignment
*/
void setAlignment(Alignment alignment);

/**
* Sets the layout of the buttons. Horizontal is next to each other and vertical is on top of each other.
*
* @param layout layout
*/
void setLayout(Layout layout);

default void setTopLeft() {
setAlignment(Alignment.TOP_LEFT);
}

default void setTopRight() {
setAlignment(Alignment.TOP_RIGHT);
}

default void setBottomLeft() {
setAlignment(Alignment.BOTTOM_LEFT);
}

default void setBottomRight() {
setAlignment(Alignment.BOTTOM_RIGHT);
}

default void setHorizontal() {
setLayout(Layout.HORIZONTAL);
}

default void setVertical() {
setLayout(Layout.VERTICAL);
}

boolean isEnabled();

int getX();

int getY();

Alignment getAlignment();

Layout getLayout();

enum Alignment {
TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT
}

enum Layout {
HORIZONTAL, VERTICAL
}
}
11 changes: 11 additions & 0 deletions src/api/java/com/cleanroommc/bogosorter/api/ICustomInsertable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.cleanroommc.bogosorter.api;

import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;

import java.util.List;

public interface ICustomInsertable {

ItemStack insert(Container container, List<ISlot> slots, ItemStack itemStack, boolean emptyOnly);
}
37 changes: 37 additions & 0 deletions src/api/java/com/cleanroommc/bogosorter/api/IPosSetter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.cleanroommc.bogosorter.api;

/**
* A function to set the sort button pos of {@link ISlotGroup}'s.
*/
@FunctionalInterface
public interface IPosSetter {

IPosSetter TOP_RIGHT_HORIZONTAL = (slotGroup, buttonPos) -> {
if (slotGroup.getSlots().size() < slotGroup.getRowSize()) {
buttonPos.setPos(-1000, -1000);
} else {
ISlot topRight = slotGroup.getSlots().get(slotGroup.getRowSize() - 1);
buttonPos.setPos(topRight.bogo$getX() + 17, topRight.bogo$getY() - 2);
}
};

IPosSetter TOP_RIGHT_VERTICAL = (slotGroup, buttonPos) -> {
if (slotGroup.getSlots().size() < slotGroup.getRowSize()) {
buttonPos.setPos(-1000, -1000);
} else {
ISlot topRight = slotGroup.getSlots().get(slotGroup.getRowSize() - 1);
buttonPos.setVertical();
buttonPos.setTopLeft();
buttonPos.setPos(topRight.bogo$getX() + 18, topRight.bogo$getY() - 1);
}
};

/**
* Called every frame, to make sure the buttons are always in the right position.
* Call setters on {@link IButtonPos} here.
*
* @param slotGroup slot group of the buttons
* @param buttonPos the mutable button pos
*/
void setButtonPos(ISlotGroup slotGroup, IButtonPos buttonPos);
}
41 changes: 41 additions & 0 deletions src/api/java/com/cleanroommc/bogosorter/api/ISlot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.cleanroommc.bogosorter.api;

import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.Slot;
import net.minecraft.item.ItemStack;

/**
* A custom slot interface. Useful if mods have a slot that does not implement the necessary methods.
* {@link Slot} implements this interface via mixin.
*/
public interface ISlot {

Slot bogo$getRealSlot();

int bogo$getX();

int bogo$getY();

int bogo$getSlotNumber();

int bogo$getSlotIndex();

IInventory bogo$getInventory();

void bogo$putStack(ItemStack itemStack);

ItemStack bogo$getStack();

int bogo$getMaxStackSize(ItemStack itemStack);

int bogo$getItemStackLimit(ItemStack itemStack);

boolean bogo$isEnabled();

boolean bogo$isItemValid(ItemStack stack);

boolean bogo$canTakeStack(EntityPlayer player);

void bogo$onSlotChanged();
}
59 changes: 59 additions & 0 deletions src/api/java/com/cleanroommc/bogosorter/api/ISlotGroup.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package com.cleanroommc.bogosorter.api;

import java.util.List;

/**
* A slot group is a list of slots which is organized in a rectangle.
* It doesn't necessarily need to be a rectangle, but you might run into issues if the shape is more complex.
*/
public interface ISlotGroup {

/**
* An unmodifiable view of all the slots of this group.
*
* @return all slots
*/
List<ISlot> getSlots();

/**
* Returns how many slots are in row. This is mostly used to determine the button position with
* {@link IPosSetter#TOP_RIGHT_VERTICAL} and {@link IPosSetter#TOP_RIGHT_HORIZONTAL}. If the slot group shape is
* not rectangular, try to return the row size of the first row.
*
* @return slots per row
*/
int getRowSize();

/**
* Returns the priority that this group takes when items are transferred via shortcuts.
*
* @return priority
*/
int getPriority();

/**
* Returns if this slot groups only consists of player inventory slots. It does not need to be the full player
* inventory. The player hotbar is usually not part of this.
*
* @return if all slots are part of the player inventory
*/
boolean isPlayerInventory();

/**
* Sets the priority of this slot group. Can determine where items are transferred first with shortcuts.
* Returns itself to be used in a builder like manner.
*
* @param priority priority
* @return this
*/
ISlotGroup priority(int priority);

/**
* Sets a custom function to determine the position of sort buttons. Default is top right corner.
* Returns itself to be used in a builder like manner.
*
* @param posSetter pos function or null if no buttons are desired
* @return this
*/
ISlotGroup buttonPosSetter(IPosSetter posSetter);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,29 @@
package com.cleanroommc.bogosorter.api;

import java.util.function.BiConsumer;

/**
* implement on {@link net.minecraft.inventory.Container}
* This interface marks a {@link net.minecraft.inventory.Container} as sortable.
* Implementing this interface takes priority over {@link IBogoSortAPI#addCompat(Class, BiConsumer)} and
* {@link IBogoSortAPI#addPlayerSortButtonPosition(Class, IPosSetter)}, but has the same effect.
*/
public interface ISortableContainer {

/**
* Is called when the container is opened. Add slot groups this container adds here.
* Do not add the player inventory here (except if Bogosorter doesn't do it automatically).
*
* @param builder builder to build slot groups
*/
void buildSortingContext(ISortingContextBuilder builder);

/**
* Determines where the buttons of the player inventory (if exists) should be placed.
* Returning null will result in no sort buttons.
*
* @return player inventory sort button position function
*/
default IPosSetter getPlayerButtonPosSetter() {
return IPosSetter.TOP_RIGHT_HORIZONTAL;
}
}
Loading

0 comments on commit 394748b

Please sign in to comment.