├── repositories.gradle ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── src ├── main │ ├── resources │ │ ├── assets │ │ │ └── bogosorter │ │ │ │ ├── textures │ │ │ │ └── gui │ │ │ │ │ ├── sort.png │ │ │ │ │ ├── dropoff.png │ │ │ │ │ ├── settings.png │ │ │ │ │ ├── base_button.png │ │ │ │ │ ├── arrow_down_up.png │ │ │ │ │ └── toggle_config.png │ │ │ │ └── lang │ │ │ │ ├── zh_cn.lang │ │ │ │ ├── ja_jp.lang │ │ │ │ ├── ko_kr.lang │ │ │ │ ├── en_us.lang │ │ │ │ ├── ru_ru.lang │ │ │ │ └── pt_br.lang │ │ ├── mixin.bogosorter.quark.json │ │ ├── mixin.bogosorter.rftools.json │ │ ├── mixin.bogosorter.charset.json │ │ ├── mixin.bogosorter.simplybackpacks.json │ │ ├── mixin.bogosorter.colossalchests.json │ │ ├── mixin.bogosorter.galacticraftcore.json │ │ ├── mixin.bogosorter.galacticraftplanets.json │ │ ├── mixin.bogosorter.ironchest.json │ │ ├── mixin.bogosorter.thermalexpansion.json │ │ ├── mixin.bogosorter.avaritiaddons.json │ │ ├── mixin.bogosorter.gregtechceu.json │ │ ├── mixin.bogosorter.improvedbackpacks.json │ │ ├── mixin.bogosorter.hbm.json │ │ ├── mixin.bogosorter.enderio.json │ │ ├── pack.mcmeta │ │ ├── mcmod.info │ │ └── mixin.bogosorter.json │ └── java │ │ └── com │ │ └── cleanroommc │ │ └── bogosorter │ │ ├── compat │ │ ├── gtce │ │ │ ├── IModularSortable.java │ │ │ └── SortableSlotWidget.java │ │ ├── FixedLimitSlot.java │ │ ├── InfinitySlotWrapper.java │ │ ├── screen │ │ │ └── WarningScreen.java │ │ └── SlotDelegate.java │ │ ├── common │ │ ├── sort │ │ │ ├── IGuiContainerAccessor.java │ │ │ ├── ClientItemSortRule.java │ │ │ ├── ClientSortData.java │ │ │ ├── color │ │ │ │ └── ColorUtil.java │ │ │ ├── ItemSortContainer.java │ │ │ ├── NbtSortRule.java │ │ │ ├── SlotGroup.java │ │ │ ├── ButtonPos.java │ │ │ └── DefaultRules.java │ │ ├── config │ │ │ ├── ColoredIcon.java │ │ │ ├── ConfigReloadCommand.java │ │ │ ├── BogoSortCommandTree.java │ │ │ ├── PlayerConfig.java │ │ │ └── Serializer.java │ │ ├── network │ │ │ ├── SReloadConfig.java │ │ │ ├── SRefillSound.java │ │ │ ├── CConfigSync.java │ │ │ ├── IPacket.java │ │ │ ├── CHotbarSwap.java │ │ │ ├── CSlotSync.java │ │ │ ├── CShortcut.java │ │ │ ├── NetworkUtils.java │ │ │ ├── NetworkHandler.java │ │ │ └── CSort.java │ │ ├── SortConfigChangeEvent.java │ │ ├── refill │ │ │ └── DamageHelper.java │ │ ├── McUtils.java │ │ └── HotbarSwap.java │ │ ├── api │ │ ├── ICustomInsertable.java │ │ ├── ISlot.java │ │ ├── ISortableContainer.java │ │ ├── IPosSetter.java │ │ ├── SortRule.java │ │ ├── IButtonPos.java │ │ ├── ISlotGroup.java │ │ ├── ISortingContextBuilder.java │ │ └── IBogoSortAPI.java │ │ ├── core │ │ ├── mixin │ │ │ ├── ItemStackAccessor.java │ │ │ ├── avaritiaddons │ │ │ │ ├── InfinityMatchingAccessor.java │ │ │ │ └── ContainerInfinityChestMixin.java │ │ │ ├── enderio │ │ │ │ ├── EIOContainerAccessor.java │ │ │ │ ├── StorageUpgradeAccessor.java │ │ │ │ ├── MixinVacuumChest.java │ │ │ │ ├── MixinBuffer.java │ │ │ │ └── MixinEIOStorage.java │ │ │ ├── colossalchests │ │ │ │ └── ContainerColossalChestAccessor.java │ │ │ ├── GuiEditSignMixin.java │ │ │ ├── simplybackpacks │ │ │ │ └── BackpackContainerMixin.java │ │ │ ├── hbm │ │ │ │ ├── MixinContainerCrateDesh.java │ │ │ │ ├── MixinContainerCrateIron.java │ │ │ │ ├── MixinContainerCrateSteel.java │ │ │ │ └── MixinContainerCrateTungsten.java │ │ │ ├── charset │ │ │ │ └── MixinContainerChestCharset.java │ │ │ ├── quark │ │ │ │ └── AutomaticToolRestockMixin.java │ │ │ ├── gtceu │ │ │ │ ├── MixinModularUI.java │ │ │ │ ├── MixinToolHelper.java │ │ │ │ ├── MixinToolMetaItem.java │ │ │ │ └── MixinMetaTileEntityCrate.java │ │ │ ├── improvedbackpacks │ │ │ │ ├── ContainerBackpackMixin.java │ │ │ │ └── ContainerBlockBackpackMixin.java │ │ │ ├── GuiContainerMixin.java │ │ │ ├── thermal │ │ │ │ ├── MixinContainerStrongbox.java │ │ │ │ └── MixinContainerSatchel.java │ │ │ ├── MixinMinecraft.java │ │ │ ├── CreativeSlotMixin.java │ │ │ ├── MixinItemStack.java │ │ │ ├── galacticraft │ │ │ │ ├── core │ │ │ │ │ └── MixinContainerRocketInventory.java │ │ │ │ └── planets │ │ │ │ │ └── MixinEntitySlimeling.java │ │ │ ├── rftools │ │ │ │ └── GuiStorageScannerMixin.java │ │ │ ├── MixinContainerHorseInventory.java │ │ │ ├── ironchests │ │ │ │ ├── MixinIronShulkerContainer.java │ │ │ │ └── MixinIronChestContainer.java │ │ │ ├── MixinEntityLivingBase.java │ │ │ └── SlotMixin.java │ │ ├── CatServerHelper.java │ │ ├── BogoSorterTransformer.java │ │ ├── BogoSorterCore.java │ │ └── visitor │ │ │ ├── EntityPlayerVisitor.java │ │ │ └── PIMVisitor.java │ │ └── LateMixin.java └── api │ └── java │ ├── com │ ├── creativemd │ │ ├── littletiles │ │ │ └── client │ │ │ │ └── render │ │ │ │ ├── cache │ │ │ │ └── LayeredRenderBoxCache.java │ │ │ │ └── tile │ │ │ │ └── LittleRenderBox.java │ │ └── creativecore │ │ │ └── client │ │ │ └── mods │ │ │ └── optifine │ │ │ └── OptifineHelper.java │ └── enderio │ │ └── core │ │ └── common │ │ └── interfaces │ │ └── IOverlayRenderAware.java │ ├── crazypants │ └── enderio │ │ └── api │ │ └── tool │ │ ├── IHideFacades.java │ │ ├── ITool.java │ │ └── IConduitControl.java │ ├── cofh │ └── api │ │ └── item │ │ └── IToolHammer.java │ ├── forestry │ └── api │ │ └── arboriculture │ │ └── IToolGrafter.java │ └── buildcraft │ └── api │ └── tools │ └── IToolWrench.java ├── bansoukou └── gregtech-1.12.2-1.17.1.770 │ └── gregtech │ ├── api │ └── gui │ │ ├── ModularUI.class │ │ ├── impl │ │ └── ModularUIContainer.class │ │ └── widgets │ │ └── SortableSlotWidget.class │ └── common │ └── metatileentities │ └── storage │ └── MetaTileEntityChest.class ├── .gitignore ├── gradle.properties ├── settings.gradle ├── README.md ├── gradlew.bat └── .github └── workflows └── build.yaml /repositories.gradle: -------------------------------------------------------------------------------- 1 | // Add any additional repositories for your dependencies here 2 | 3 | repositories { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/textures/gui/sort.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/src/main/resources/assets/bogosorter/textures/gui/sort.png -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/textures/gui/dropoff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/src/main/resources/assets/bogosorter/textures/gui/dropoff.png -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/textures/gui/settings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/src/main/resources/assets/bogosorter/textures/gui/settings.png -------------------------------------------------------------------------------- /src/api/java/com/creativemd/littletiles/client/render/cache/LayeredRenderBoxCache.java: -------------------------------------------------------------------------------- 1 | package com.creativemd.littletiles.client.render.cache; 2 | 3 | public class LayeredRenderBoxCache { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/textures/gui/base_button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/src/main/resources/assets/bogosorter/textures/gui/base_button.png -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/textures/gui/arrow_down_up.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/src/main/resources/assets/bogosorter/textures/gui/arrow_down_up.png -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/textures/gui/toggle_config.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/src/main/resources/assets/bogosorter/textures/gui/toggle_config.png -------------------------------------------------------------------------------- /bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/api/gui/ModularUI.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/api/gui/ModularUI.class -------------------------------------------------------------------------------- /src/api/java/com/creativemd/littletiles/client/render/tile/LittleRenderBox.java: -------------------------------------------------------------------------------- 1 | package com.creativemd.littletiles.client.render.tile; 2 | 3 | public class LittleRenderBox { 4 | public boolean needsResorting; 5 | } 6 | -------------------------------------------------------------------------------- /bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/api/gui/impl/ModularUIContainer.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/api/gui/impl/ModularUIContainer.class -------------------------------------------------------------------------------- /bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/api/gui/widgets/SortableSlotWidget.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/api/gui/widgets/SortableSlotWidget.class -------------------------------------------------------------------------------- /src/api/java/com/creativemd/creativecore/client/mods/optifine/OptifineHelper.java: -------------------------------------------------------------------------------- 1 | package com.creativemd.creativecore.client.mods.optifine; 2 | 3 | public interface OptifineHelper { 4 | static boolean isActive() { 5 | return false; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/common/metatileentities/storage/MetaTileEntityChest.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CleanroomMC/InventoryBogoSorter/HEAD/bansoukou/gregtech-1.12.2-1.17.1.770/gregtech/common/metatileentities/storage/MetaTileEntityChest.class -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/compat/gtce/IModularSortable.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.compat.gtce; 2 | 3 | public interface IModularSortable { 4 | 5 | void addSortArea(String key, int rowSize); 6 | 7 | int getRowSize(String key); 8 | } 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # eclipse 2 | bin 3 | *.launch 4 | .settings 5 | .metadata 6 | .classpath 7 | .project 8 | 9 | # idea 10 | out 11 | *.ipr 12 | *.iws 13 | *.iml 14 | .idea 15 | 16 | # gradle 17 | build 18 | .gradle 19 | 20 | # other 21 | eclipse 22 | run 23 | 24 | .shelf 25 | logs 26 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip 4 | networkTimeout=10000 5 | validateDistributionUrl=true 6 | zipStoreBase=GRADLE_USER_HOME 7 | zipStorePath=wrapper/dists 8 | -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.quark.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.quark", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "AutomaticToolRestockMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.rftools.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.rftools", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "client": [ 8 | "GuiStorageScannerMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.charset.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.charset", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinContainerChestCharset" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.simplybackpacks.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.simplybackpacks", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "BackpackContainerMixin" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.colossalchests.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.colossalchests", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "ContainerColossalChestAccessor" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.galacticraftcore.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.galacticraft.core", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinContainerRocketInventory" 9 | ] 10 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.galacticraftplanets.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.galacticraft.planets", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinEntitySlimeling" 9 | ] 10 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | 2 | # Gradle Settings 3 | # Effectively applies the '--stacktrace' flag by default 4 | org.gradle.logging.stacktrace = all 5 | # Sets default memory used for gradle commands. Can be overridden by user or command line properties. 6 | # This is required to provide enough memory for the Minecraft decompilation process. 7 | org.gradle.jvmargs = -Xmx3G 8 | -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.ironchest.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.ironchests", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinIronChestContainer", 9 | "MixinIronShulkerContainer" 10 | ] 11 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.thermalexpansion.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.thermal", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinContainerSatchel", 9 | "MixinContainerStrongbox" 10 | ] 11 | } -------------------------------------------------------------------------------- /src/api/java/com/enderio/core/common/interfaces/IOverlayRenderAware.java: -------------------------------------------------------------------------------- 1 | package com.enderio.core.common.interfaces; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | import javax.annotation.Nonnull; 6 | 7 | public interface IOverlayRenderAware { 8 | 9 | public void renderItemOverlayIntoGUI(@Nonnull ItemStack stack, int xPosition, int yPosition); 10 | 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/IGuiContainerAccessor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | 5 | import java.util.List; 6 | 7 | public interface IGuiContainerAccessor { 8 | 9 | List getButtons(); 10 | 11 | int getGuiTop(); 12 | 13 | int getGuiLeft(); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.avaritiaddons.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.avaritiaddons", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "ContainerInfinityChestMixin", 9 | "InfinityMatchingAccessor" 10 | ] 11 | } -------------------------------------------------------------------------------- /src/api/java/crazypants/enderio/api/tool/IHideFacades.java: -------------------------------------------------------------------------------- 1 | package crazypants.enderio.api.tool; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.item.ItemStack; 5 | 6 | import javax.annotation.Nonnull; 7 | 8 | public interface IHideFacades { 9 | 10 | boolean shouldHideFacades(@Nonnull ItemStack stack, @Nonnull EntityPlayer player); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.gregtechceu.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.gtceu", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinMetaTileEntityCrate", 9 | "MixinModularUI", 10 | "MixinToolHelper" 11 | ] 12 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.improvedbackpacks.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.improvedbackpacks", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "ContainerBackpackMixin", 9 | "ContainerBlockBackpackMixin" 10 | ] 11 | } -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/ICustomInsertable.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import net.minecraft.inventory.Container; 4 | import net.minecraft.item.ItemStack; 5 | 6 | import java.util.List; 7 | 8 | public interface ICustomInsertable { 9 | 10 | ItemStack insert(Container container, List slots, ItemStack itemStack, boolean emptyOnly); 11 | } 12 | -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.hbm.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.hbm", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "MixinContainerCrateDesh", 9 | "MixinContainerCrateIron", 10 | "MixinContainerCrateSteel", 11 | "MixinContainerCrateTungsten" 12 | ] 13 | } -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.enderio.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin.enderio", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "EIOContainerAccessor", 9 | "MixinBuffer", 10 | "MixinEIOStorage", 11 | "MixinVacuumChest", 12 | "StorageUpgradeAccessor" 13 | ] 14 | } -------------------------------------------------------------------------------- /src/main/resources/pack.mcmeta: -------------------------------------------------------------------------------- 1 | { 2 | "pack": { 3 | "description": "examplemod resources", 4 | "pack_format": 3, 5 | "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)." 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/main/resources/mcmod.info: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "modid": "bogosorter", 4 | "name": "Inventory Bogo Sorter", 5 | "description": "A highly configurable and advanced inventory sorter mod", 6 | "version": "${version}", 7 | "mcversion": "${mcversion}", 8 | "url": "", 9 | "updateUrl": "", 10 | "authorList": ["brachy84"], 11 | "credits": "Autor of InventoryTweaks", 12 | "logoFile": "", 13 | "screenshots": [], 14 | "dependencies": [] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/ItemStackAccessor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import net.minecraft.item.ItemStack; 4 | import net.minecraft.nbt.NBTTagCompound; 5 | 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.gen.Accessor; 8 | 9 | @Mixin(value = ItemStack.class, remap = false) 10 | public interface ItemStackAccessor { 11 | 12 | @Accessor 13 | NBTTagCompound getCapNBT(); 14 | } 15 | -------------------------------------------------------------------------------- /src/api/java/crazypants/enderio/api/tool/ITool.java: -------------------------------------------------------------------------------- 1 | package crazypants.enderio.api.tool; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.util.EnumHand; 5 | import net.minecraft.util.math.BlockPos; 6 | 7 | import javax.annotation.Nonnull; 8 | 9 | public interface ITool extends IHideFacades { 10 | 11 | boolean canUse(@Nonnull EnumHand stack, @Nonnull EntityPlayer player, @Nonnull BlockPos pos); 12 | 13 | void used(@Nonnull EnumHand stack, @Nonnull EntityPlayer player, @Nonnull BlockPos pos); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/resources/mixin.bogosorter.json: -------------------------------------------------------------------------------- 1 | { 2 | "package": "com.cleanroommc.bogosorter.core.mixin", 3 | "refmap": "mixins.bogosorter.refmap.json", 4 | "target": "@env(DEFAULT)", 5 | "minVersion": "0.8", 6 | "compatibilityLevel": "JAVA_8", 7 | "mixins": [ 8 | "ItemStackAccessor", 9 | "MixinContainerHorseInventory", 10 | "MixinEntityLivingBase", 11 | "MixinItemStack", 12 | "SlotMixin" 13 | ], 14 | "client": [ 15 | "CreativeSlotMixin", 16 | "GuiContainerMixin", 17 | "GuiEditSignMixin", 18 | "MixinMinecraft" 19 | ] 20 | } -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/avaritiaddons/InfinityMatchingAccessor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.avaritiaddons; 2 | 3 | import net.minecraft.item.ItemStack; 4 | 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Invoker; 7 | import wanion.avaritiaddons.block.chest.infinity.InfinityMatching; 8 | 9 | @Mixin(value = InfinityMatching.class, remap = false) 10 | public interface InfinityMatchingAccessor { 11 | 12 | @Invoker 13 | void invokeSetStack(ItemStack itemStack, int count); 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/enderio/EIOContainerAccessor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.enderio; 2 | 3 | import crazypants.enderio.base.machine.baselegacy.AbstractInventoryMachineEntity; 4 | import crazypants.enderio.base.machine.gui.AbstractMachineContainer; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.gen.Accessor; 7 | 8 | @Mixin(value = AbstractMachineContainer.class, remap = false) 9 | public interface EIOContainerAccessor { 10 | 11 | @Accessor 12 | E getTe(); 13 | } 14 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/enderio/StorageUpgradeAccessor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.enderio; 2 | 3 | import net.minecraft.inventory.EntityEquipmentSlot; 4 | 5 | import crazypants.enderio.base.item.darksteel.upgrade.storage.StorageUpgrade; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.gen.Invoker; 8 | 9 | @Mixin(value = StorageUpgrade.class, remap = false) 10 | public interface StorageUpgradeAccessor { 11 | 12 | @Invoker 13 | static int invokeCols(EntityEquipmentSlot slot) { 14 | return 0; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/colossalchests/ContainerColossalChestAccessor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.colossalchests; 2 | 3 | import net.minecraft.inventory.Slot; 4 | 5 | import org.cyclops.colossalchests.inventory.container.ContainerColossalChest; 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.gen.Accessor; 8 | 9 | import java.util.List; 10 | 11 | @Mixin(value = ContainerColossalChest.class, remap = false) 12 | public interface ContainerColossalChestAccessor { 13 | 14 | @Accessor 15 | List getChestSlots(); 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/api/java/cofh/api/item/IToolHammer.java: -------------------------------------------------------------------------------- 1 | package cofh.api.item; 2 | 3 | import net.minecraft.entity.Entity; 4 | import net.minecraft.entity.EntityLivingBase; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.util.math.BlockPos; 7 | 8 | public interface IToolHammer { 9 | 10 | boolean isUsable(ItemStack item, EntityLivingBase user, BlockPos pos); 11 | 12 | boolean isUsable(ItemStack item, EntityLivingBase user, Entity entity); 13 | 14 | void toolUsed(ItemStack item, EntityLivingBase user, BlockPos pos); 15 | 16 | void toolUsed(ItemStack item, EntityLivingBase user, Entity entity); 17 | } 18 | -------------------------------------------------------------------------------- /src/api/java/crazypants/enderio/api/tool/IConduitControl.java: -------------------------------------------------------------------------------- 1 | package crazypants.enderio.api.tool; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.item.ItemStack; 5 | 6 | import javax.annotation.Nonnull; 7 | 8 | public interface IConduitControl { 9 | 10 | /** 11 | * Controls whether the overlay is shown and the player can change the display mode. 12 | * 13 | * @param stack The itemstack 14 | * @param player The player holding the itemstack 15 | * @return True if the overlay should be rendered and the player should be able to change modes. False otherwise. 16 | */ 17 | boolean showOverlay(@Nonnull ItemStack stack, @Nonnull EntityPlayer player); 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/GuiEditSignMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import net.minecraft.client.gui.inventory.GuiEditSign; 4 | import net.minecraft.tileentity.TileEntitySign; 5 | 6 | import org.spongepowered.asm.mixin.Mixin; 7 | import org.spongepowered.asm.mixin.injection.At; 8 | import org.spongepowered.asm.mixin.injection.Inject; 9 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 10 | 11 | @Mixin(GuiEditSign.class) 12 | public class GuiEditSignMixin { 13 | 14 | @Inject(method = "", at = @At("RETURN")) 15 | public void init(TileEntitySign teSign, CallbackInfo ci) { 16 | ((GuiEditSign) (Object) this).setFocused(true); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/simplybackpacks/BackpackContainerMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.simplybackpacks; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import com.flanks255.simplybackpacks.gui.BackpackContainer; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | 10 | @Mixin(value = BackpackContainer.class, remap = false) 11 | public class BackpackContainerMixin implements ISortableContainer { 12 | 13 | @Shadow 14 | private int slotcount; 15 | 16 | @Override 17 | public void buildSortingContext(ISortingContextBuilder builder) { 18 | builder.addSlotGroup(0, slotcount, slotcount == 18 ? 9 : 11); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/ClientItemSortRule.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.api.SortRule; 4 | 5 | import net.minecraft.item.ItemStack; 6 | 7 | import java.util.Comparator; 8 | 9 | public class ClientItemSortRule extends SortRule { 10 | 11 | private final Comparator serverComparator; 12 | 13 | public ClientItemSortRule(String key, Comparator comparator, Comparator serverComparator) { 14 | super(key, comparator); 15 | this.serverComparator = serverComparator; 16 | } 17 | 18 | public int compareServer(ItemSortContainer o1, ItemSortContainer o2) { 19 | return isInverted() ? serverComparator.compare(o2, o1) : serverComparator.compare(o1, o2); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/hbm/MixinContainerCrateDesh.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.hbm; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import com.hbm.inventory.container.ContainerCrateDesh; 7 | import com.hbm.tileentity.machine.TileEntityCrateDesh; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | @Mixin(value = ContainerCrateDesh.class, remap = false) 12 | public class MixinContainerCrateDesh implements ISortableContainer { 13 | 14 | @Shadow 15 | private TileEntityCrateDesh crate; 16 | 17 | @Override 18 | public void buildSortingContext(ISortingContextBuilder builder) { 19 | builder.addSlotGroup(0, crate.inventory.getSlots(), 13); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/hbm/MixinContainerCrateIron.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.hbm; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import com.hbm.inventory.container.ContainerCrateIron; 7 | import com.hbm.tileentity.machine.TileEntityCrateIron; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | @Mixin(value = ContainerCrateIron.class, remap = false) 12 | public class MixinContainerCrateIron implements ISortableContainer { 13 | 14 | @Shadow 15 | private TileEntityCrateIron diFurnace; 16 | 17 | @Override 18 | public void buildSortingContext(ISortingContextBuilder builder) { 19 | builder.addSlotGroup(0, diFurnace.inventory.getSlots(), 9); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/hbm/MixinContainerCrateSteel.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.hbm; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import com.hbm.inventory.container.ContainerCrateSteel; 7 | import com.hbm.tileentity.machine.TileEntityCrateSteel; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | @Mixin(value = ContainerCrateSteel.class, remap = false) 12 | public class MixinContainerCrateSteel implements ISortableContainer { 13 | 14 | @Shadow 15 | private TileEntityCrateSteel diFurnace; 16 | 17 | @Override 18 | public void buildSortingContext(ISortingContextBuilder builder) { 19 | builder.addSlotGroup(0, diFurnace.inventory.getSlots(), 9); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/hbm/MixinContainerCrateTungsten.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.hbm; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import com.hbm.inventory.container.ContainerCrateTungsten; 7 | import com.hbm.tileentity.machine.TileEntityCrateTungsten; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.Shadow; 10 | 11 | @Mixin(value = ContainerCrateTungsten.class, remap = false) 12 | public class MixinContainerCrateTungsten implements ISortableContainer { 13 | 14 | @Shadow 15 | private TileEntityCrateTungsten crate; 16 | 17 | @Override 18 | public void buildSortingContext(ISortingContextBuilder builder) { 19 | builder.addSlotGroup(0, crate.inventory.getSlots(), 8); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/CatServerHelper.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | 5 | public class CatServerHelper { 6 | 7 | private static boolean loaded = false; 8 | private static boolean init = false; 9 | 10 | public static boolean isCatServerLoaded() { 11 | if (!init) { 12 | loaded = classExists("catserver.server.CatServerLaunch"); 13 | if (loaded) BogoSorter.LOGGER.info("### Detected CatServer ###"); 14 | init = true; 15 | } 16 | return loaded; 17 | } 18 | 19 | public static boolean classExists(String name) { 20 | try { 21 | Class.forName(name, false, CatServerHelper.class.getClassLoader()); 22 | return true; 23 | } catch (Exception ignored) { 24 | return false; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/enderio/MixinVacuumChest.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.enderio; 2 | 3 | import com.cleanroommc.bogosorter.api.IPosSetter; 4 | import com.cleanroommc.bogosorter.api.ISortableContainer; 5 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 6 | 7 | import crazypants.enderio.machines.machine.vacuum.chest.ContainerVacuumChest; 8 | import org.jetbrains.annotations.Nullable; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | 11 | @Mixin(ContainerVacuumChest.class) 12 | public class MixinVacuumChest implements ISortableContainer { 13 | 14 | @Override 15 | public void buildSortingContext(ISortingContextBuilder builder) { 16 | builder.addSlotGroup(1, 28, 9); 17 | } 18 | 19 | @Override 20 | public @Nullable IPosSetter getPlayerButtonPosSetter() { 21 | return IPosSetter.TOP_RIGHT_VERTICAL; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/config/ColoredIcon.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.config; 2 | 3 | import com.cleanroommc.modularui.api.drawable.IDrawable; 4 | import com.cleanroommc.modularui.drawable.UITexture; 5 | import com.cleanroommc.modularui.screen.viewport.GuiContext; 6 | import com.cleanroommc.modularui.theme.WidgetTheme; 7 | import com.cleanroommc.modularui.utils.Color; 8 | 9 | public class ColoredIcon implements IDrawable { 10 | 11 | private final UITexture drawable; 12 | private final int color; 13 | 14 | public ColoredIcon(UITexture drawable, int color) { 15 | this.drawable = drawable; 16 | this.color = color; 17 | } 18 | 19 | @Override 20 | public void draw(GuiContext context, int x, int y, int width, int height, WidgetTheme widgetTheme) { 21 | Color.setGlColor(this.color); 22 | this.drawable.draw(x, y, width, height); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | // RetroFuturaGradle 5 | name 'GTNH Maven' 6 | url 'https://nexus.gtnewhorizons.com/repository/public/' 7 | //noinspection GroovyAssignabilityCheck 8 | mavenContent { 9 | includeGroup 'com.gtnewhorizons' 10 | includeGroup 'com.gtnewhorizons.retrofuturagradle' 11 | } 12 | } 13 | gradlePluginPortal() 14 | mavenCentral() 15 | mavenLocal() 16 | } 17 | } 18 | 19 | plugins { 20 | id 'com.diffplug.blowdryerSetup' version '1.7.0' 21 | // Automatic toolchain provisioning 22 | id 'org.gradle.toolchains.foojay-resolver-convention' version '0.7.0' 23 | } 24 | 25 | blowdryerSetup { 26 | repoSubfolder 'spotless' 27 | github 'GregTechCEu/Buildscripts', 'tag', 'v1.0.7' 28 | } 29 | 30 | rootProject.name = rootProject.projectDir.getName() 31 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/charset/MixinContainerChestCharset.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.charset; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import pl.asie.charset.module.storage.chests.ContainerChestCharset; 10 | import pl.asie.charset.module.storage.chests.TileEntityChestCharset; 11 | 12 | @Mixin(value = ContainerChestCharset.class, remap = false) 13 | public class MixinContainerChestCharset implements ISortableContainer { 14 | 15 | @Shadow 16 | @Final 17 | protected TileEntityChestCharset tile; 18 | 19 | @Override 20 | public void buildSortingContext(ISortingContextBuilder builder) { 21 | builder.addSlotGroup(0, tile.getSlots(), 9); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/compat/FixedLimitSlot.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.compat; 2 | 3 | import net.minecraft.inventory.Slot; 4 | import net.minecraft.item.ItemStack; 5 | 6 | /** 7 | * @author ZZZank 8 | */ 9 | public class FixedLimitSlot extends SlotDelegate { 10 | 11 | private final int sizeLimit; 12 | 13 | public FixedLimitSlot(Slot slot, int sizeLimit) { 14 | super(slot); 15 | if (sizeLimit <= 0) { 16 | throw new IllegalArgumentException(String.format( 17 | "size limit '%s' not valid, must be positive number", 18 | sizeLimit 19 | )); 20 | } 21 | this.sizeLimit = sizeLimit; 22 | } 23 | 24 | @Override 25 | public int bogo$getItemStackLimit(ItemStack itemStack) { 26 | return sizeLimit; 27 | } 28 | 29 | @Override 30 | public int bogo$getMaxStackSize(ItemStack itemStack) { 31 | return sizeLimit; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/quark/AutomaticToolRestockMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.quark; 2 | 3 | import com.cleanroommc.bogosorter.common.config.PlayerConfig; 4 | 5 | import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent; 6 | 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | import vazkii.quark.management.feature.AutomaticToolRestock; 12 | 13 | @Mixin(value = AutomaticToolRestock.class, remap = false) 14 | public class AutomaticToolRestockMixin { 15 | 16 | @Inject(method = "onToolBreak", at = @At("HEAD"), cancellable = true) 17 | public void onToolBreak(PlayerDestroyItemEvent event, CallbackInfo ci) { 18 | if (PlayerConfig.get(event.getEntityPlayer()).enableAutoRefill) { 19 | ci.cancel(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/gtceu/MixinModularUI.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.gtceu; 2 | 3 | import com.cleanroommc.bogosorter.compat.gtce.IModularSortable; 4 | 5 | import gregtech.api.gui.ModularUI; 6 | import it.unimi.dsi.fastutil.objects.Object2IntMap; 7 | import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Unique; 11 | 12 | @Mixin(value = ModularUI.class, remap = false) 13 | public class MixinModularUI implements IModularSortable { 14 | 15 | @Unique 16 | @Final 17 | private final Object2IntMap rowSizes = new Object2IntOpenHashMap<>(); 18 | 19 | @Override 20 | public void addSortArea(String key, int rowSize) { 21 | rowSizes.put(key, rowSize); 22 | } 23 | 24 | @Override 25 | public int getRowSize(String key) { 26 | return rowSizes.getInt(key); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/improvedbackpacks/ContainerBackpackMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.improvedbackpacks; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import ru.poopycoders.improvedbackpacks.inventory.InventoryBackpack; 10 | import ru.poopycoders.improvedbackpacks.inventory.containers.ContainerBackpack; 11 | 12 | @Mixin(value = ContainerBackpack.class, remap = false) 13 | public class ContainerBackpackMixin implements ISortableContainer { 14 | 15 | @Shadow 16 | @Final 17 | private InventoryBackpack backpackInventory; 18 | 19 | @Override 20 | public void buildSortingContext(ISortingContextBuilder builder) { 21 | builder.addSlotGroup(0, backpackInventory.getSizeInventory(), 9); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/GuiContainerMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import com.cleanroommc.bogosorter.common.sort.IGuiContainerAccessor; 4 | 5 | import net.minecraft.client.gui.GuiButton; 6 | import net.minecraft.client.gui.GuiScreen; 7 | import net.minecraft.client.gui.inventory.GuiContainer; 8 | 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | import java.util.List; 13 | 14 | @Mixin(GuiContainer.class) 15 | public class GuiContainerMixin extends GuiScreen implements IGuiContainerAccessor { 16 | 17 | @Shadow 18 | protected int guiTop; 19 | 20 | @Shadow 21 | protected int guiLeft; 22 | 23 | @Override 24 | public List getButtons() { 25 | return buttonList; 26 | } 27 | 28 | @Override 29 | public int getGuiTop() { 30 | return guiTop; 31 | } 32 | 33 | @Override 34 | public int getGuiLeft() { 35 | return guiLeft; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/improvedbackpacks/ContainerBlockBackpackMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.improvedbackpacks; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import org.spongepowered.asm.mixin.Final; 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.Shadow; 9 | import ru.poopycoders.improvedbackpacks.inventory.containers.ContainerBlockBackpack; 10 | import ru.poopycoders.improvedbackpacks.tiles.TileEntityBackpack; 11 | 12 | @Mixin(value = ContainerBlockBackpack.class, remap = false) 13 | public class ContainerBlockBackpackMixin implements ISortableContainer { 14 | 15 | 16 | @Shadow 17 | @Final 18 | private TileEntityBackpack tileEntityBackpack; 19 | 20 | @Override 21 | public void buildSortingContext(ISortingContextBuilder builder) { 22 | builder.addSlotGroup(0, tileEntityBackpack.getSizeInventory(), 9); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/thermal/MixinContainerStrongbox.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.thermal; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import net.minecraft.inventory.Container; 7 | 8 | import cofh.thermalexpansion.gui.container.storage.ContainerStrongbox; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | @Mixin(value = ContainerStrongbox.class, remap = false) 13 | public abstract class MixinContainerStrongbox implements ISortableContainer { 14 | 15 | @Shadow 16 | int rowSize; 17 | 18 | @Shadow 19 | int storageIndex; 20 | 21 | @SuppressWarnings("all") 22 | @Override 23 | public void buildSortingContext(ISortingContextBuilder builder) { 24 | if (storageIndex != 0) { 25 | builder.addSlotGroup(36, ((Container) (Object) this).inventorySlots.size(), rowSize); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/MixinMinecraft.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import com.cleanroommc.bogosorter.common.HotbarSwap; 4 | 5 | import net.minecraft.client.Minecraft; 6 | import net.minecraft.client.entity.EntityPlayerSP; 7 | import net.minecraft.entity.player.InventoryPlayer; 8 | 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Redirect; 13 | 14 | @Mixin(Minecraft.class) 15 | public class MixinMinecraft { 16 | 17 | @Shadow 18 | public EntityPlayerSP player; 19 | 20 | @Redirect(method = "runTickMouse", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/player/InventoryPlayer;changeCurrentItem(I)V")) 21 | public void mouseInput(InventoryPlayer instance, int direction) { 22 | if (!HotbarSwap.doCancelHotbarSwap()) { 23 | player.inventory.changeCurrentItem(direction); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/CreativeSlotMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import net.minecraft.client.gui.inventory.GuiContainerCreative; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.inventory.Slot; 6 | 7 | import org.spongepowered.asm.mixin.Mixin; 8 | import org.spongepowered.asm.mixin.injection.At; 9 | import org.spongepowered.asm.mixin.injection.Inject; 10 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 11 | 12 | @Mixin(targets = "net.minecraft.client.gui.inventory.GuiContainerCreative$CreativeSlot") 13 | public class CreativeSlotMixin extends Slot { 14 | 15 | private CreativeSlotMixin(IInventory inventoryIn, int index, int xPosition, int yPosition) { 16 | super(inventoryIn, index, xPosition, yPosition); 17 | } 18 | 19 | @Inject(method = "", at = @At("TAIL")) 20 | public void constructor(GuiContainerCreative this$0, Slot p_i46313_2_, int index, CallbackInfo ci) { 21 | slotNumber = p_i46313_2_.slotNumber; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/SReloadConfig.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.common.SortConfigChangeEvent; 4 | import com.cleanroommc.bogosorter.common.config.PlayerConfig; 5 | import com.cleanroommc.bogosorter.common.config.Serializer; 6 | 7 | import net.minecraft.client.network.NetHandlerPlayClient; 8 | import net.minecraft.network.PacketBuffer; 9 | import net.minecraftforge.common.MinecraftForge; 10 | 11 | import java.io.IOException; 12 | 13 | public class SReloadConfig implements IPacket { 14 | 15 | @Override 16 | public void encode(PacketBuffer buf) throws IOException { 17 | } 18 | 19 | @Override 20 | public void decode(PacketBuffer buf) throws IOException { 21 | } 22 | 23 | @Override 24 | public IPacket executeClient(NetHandlerPlayClient handler) { 25 | Serializer.loadConfig(); 26 | PlayerConfig.syncToServer(); 27 | MinecraftForge.EVENT_BUS.post(new SortConfigChangeEvent()); 28 | return null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/SRefillSound.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import net.minecraft.client.Minecraft; 4 | import net.minecraft.client.audio.PositionedSoundRecord; 5 | import net.minecraft.client.network.NetHandlerPlayClient; 6 | import net.minecraft.init.SoundEvents; 7 | import net.minecraft.network.PacketBuffer; 8 | import net.minecraftforge.fml.relauncher.Side; 9 | import net.minecraftforge.fml.relauncher.SideOnly; 10 | 11 | import java.io.IOException; 12 | 13 | public class SRefillSound implements IPacket { 14 | 15 | @Override 16 | public void encode(PacketBuffer buf) throws IOException { 17 | } 18 | 19 | @Override 20 | public void decode(PacketBuffer buf) throws IOException { 21 | } 22 | 23 | @SideOnly(Side.CLIENT) 24 | @Override 25 | public IPacket executeClient(NetHandlerPlayClient handler) { 26 | Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getRecord(SoundEvents.ENTITY_CHICKEN_EGG, 1, 1)); 27 | return null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/MixinItemStack.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import com.cleanroommc.bogosorter.common.refill.DamageHelper; 4 | 5 | import net.minecraft.entity.player.EntityPlayerMP; 6 | import net.minecraft.item.ItemStack; 7 | 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Inject; 11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 12 | 13 | import java.util.Random; 14 | 15 | @Mixin(ItemStack.class) 16 | public abstract class MixinItemStack { 17 | 18 | @Inject(method = "attemptDamageItem", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;setItemDamage(I)V", shift = At.Shift.AFTER), cancellable = true) 19 | private void damageItem(int amount, Random rand, EntityPlayerMP player, CallbackInfoReturnable cir) { 20 | if (player != null) { 21 | DamageHelper.damageItemHook(player, (ItemStack) (Object) this); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/thermal/MixinContainerSatchel.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.thermal; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import net.minecraft.inventory.Container; 7 | 8 | import cofh.thermalexpansion.gui.container.storage.ContainerSatchel; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | @Mixin(value = ContainerSatchel.class, remap = false) 13 | public abstract class MixinContainerSatchel implements ISortableContainer { 14 | 15 | @Shadow 16 | int rowSize; 17 | 18 | @Shadow 19 | boolean isCreative; 20 | 21 | @Shadow 22 | boolean isVoid; 23 | 24 | @SuppressWarnings("all") 25 | @Override 26 | public void buildSortingContext(ISortingContextBuilder builder) { 27 | if (!isCreative && !isVoid) { 28 | builder.addSlotGroup(36, ((Container) (Object) this).inventorySlots.size(), rowSize); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/CConfigSync.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.common.config.PlayerConfig; 4 | 5 | import net.minecraft.network.NetHandlerPlayServer; 6 | import net.minecraft.network.PacketBuffer; 7 | 8 | import io.netty.buffer.Unpooled; 9 | 10 | import java.io.IOException; 11 | 12 | public class CConfigSync implements IPacket { 13 | 14 | private PacketBuffer packet; 15 | 16 | @Override 17 | public void encode(PacketBuffer buf) throws IOException { 18 | packet = new PacketBuffer(Unpooled.buffer()); 19 | PlayerConfig.getClient().writePacket(packet); 20 | NetworkUtils.writePacketBuffer(buf, packet); 21 | } 22 | 23 | @Override 24 | public void decode(PacketBuffer buf) throws IOException { 25 | packet = NetworkUtils.readPacketBuffer(buf); 26 | } 27 | 28 | @Override 29 | public IPacket executeServer(NetHandlerPlayServer handler) { 30 | PlayerConfig.get(handler.player).readPacket(packet); 31 | return null; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/galacticraft/core/MixinContainerRocketInventory.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.galacticraft.core; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import micdoodle8.mods.galacticraft.api.entity.IRocketType; 7 | import micdoodle8.mods.galacticraft.core.inventory.ContainerRocketInventory; 8 | import org.spongepowered.asm.mixin.Final; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | import org.spongepowered.asm.mixin.Shadow; 11 | 12 | @Mixin(value = ContainerRocketInventory.class, remap = false) 13 | public class MixinContainerRocketInventory implements ISortableContainer { 14 | 15 | @Shadow 16 | @Final 17 | private IRocketType.EnumRocketType rocketType; 18 | 19 | @Override 20 | public void buildSortingContext(ISortingContextBuilder builder) { 21 | int inventorySpace = rocketType.getInventorySpace() - 2; 22 | if (inventorySpace > 2) { 23 | builder.addSlotGroup(0, inventorySpace, 9); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/api/java/forestry/api/arboriculture/IToolGrafter.java: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | * Copyright 2011-2014 SirSengir 3 | * 4 | * This work (the API) is licensed under the "MIT" License, see LICENSE.txt for details. 5 | ******************************************************************************/ 6 | package forestry.api.arboriculture; 7 | 8 | import net.minecraft.entity.player.EntityPlayer; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.util.math.BlockPos; 11 | import net.minecraft.world.World; 12 | 13 | public interface IToolGrafter { 14 | /** 15 | * Called by leaves to determine the increase in sapling droprate. 16 | * 17 | * @param stack ItemStack containing the grafter. 18 | * @param world Minecraft world the player and the target block inhabit. 19 | * @param pos Coordinate of the broken leaf block. 20 | * @return Float representing the factor the usual drop chance is to be multiplied by. 21 | */ 22 | float getSaplingModifier(ItemStack stack, World world, EntityPlayer player, BlockPos pos); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/rftools/GuiStorageScannerMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.rftools; 2 | 3 | import com.cleanroommc.bogosorter.common.sort.SortHandler; 4 | 5 | import net.minecraft.item.ItemStack; 6 | 7 | import mcjty.rftools.blocks.storagemonitor.GuiStorageScanner; 8 | import org.spongepowered.asm.mixin.Mixin; 9 | import org.spongepowered.asm.mixin.injection.At; 10 | import org.spongepowered.asm.mixin.injection.Redirect; 11 | 12 | import java.util.Comparator; 13 | import java.util.function.Function; 14 | 15 | @Mixin(value = GuiStorageScanner.class, remap = false) 16 | public class GuiStorageScannerMixin { 17 | 18 | @Redirect(method = "updateContentsList", 19 | at = @At( 20 | value = "INVOKE", 21 | target = "Ljava/util/Comparator;comparing(Ljava/util/function/Function;)Ljava/util/Comparator;", 22 | ordinal = 0 23 | )) 24 | public Comparator redirectComparator(Function no_one_likes_alphabetical_order) { 25 | return SortHandler.getClientItemComparator(); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/MixinContainerHorseInventory.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import com.cleanroommc.bogosorter.api.ISortableContainer; 4 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 5 | 6 | import net.minecraft.entity.passive.AbstractChestHorse; 7 | import net.minecraft.entity.passive.AbstractHorse; 8 | import net.minecraft.inventory.ContainerHorseInventory; 9 | 10 | import org.spongepowered.asm.mixin.Final; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Shadow; 13 | 14 | @Mixin(ContainerHorseInventory.class) 15 | public class MixinContainerHorseInventory implements ISortableContainer { 16 | 17 | @Shadow 18 | @Final 19 | private AbstractHorse horse; 20 | 21 | @Override 22 | public void buildSortingContext(ISortingContextBuilder builder) { 23 | if (horse instanceof AbstractChestHorse && ((AbstractChestHorse) horse).hasChest()) { 24 | builder.addSlotGroup(2, 3 * ((AbstractChestHorse) horse).getInventoryColumns() + 2, ((AbstractChestHorse) horse).getInventoryColumns()); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/enderio/MixinBuffer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.enderio; 2 | 3 | import com.cleanroommc.bogosorter.api.IPosSetter; 4 | import com.cleanroommc.bogosorter.api.ISortableContainer; 5 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 6 | 7 | import crazypants.enderio.machines.machine.buffer.ContainerBuffer; 8 | import crazypants.enderio.machines.machine.buffer.TileBuffer; 9 | import org.spongepowered.asm.mixin.Mixin; 10 | 11 | @Mixin(ContainerBuffer.class) 12 | public abstract class MixinBuffer implements ISortableContainer { 13 | 14 | @Override 15 | public void buildSortingContext(ISortingContextBuilder builder) { 16 | EIOContainerAccessor eioContainer = (EIOContainerAccessor) this; 17 | if (eioContainer.getTe() instanceof TileBuffer.TileBufferItem) { 18 | builder.addSlotGroup(0, 9, 3) 19 | .buttonPosSetter(IPosSetter.TOP_RIGHT_VERTICAL); 20 | } else if (eioContainer.getTe() instanceof TileBuffer.TileBufferOmni) { 21 | builder.addSlotGroup(0, 9, 3); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/ironchests/MixinIronShulkerContainer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.ironchests; 2 | 3 | import com.cleanroommc.bogosorter.api.IPosSetter; 4 | import com.cleanroommc.bogosorter.api.ISortableContainer; 5 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 6 | 7 | import cpw.mods.ironchest.common.blocks.shulker.IronShulkerBoxType; 8 | import cpw.mods.ironchest.common.gui.shulker.ContainerIronShulkerBox; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | @Mixin(value = ContainerIronShulkerBox.class, remap = false) 14 | public class MixinIronShulkerContainer implements ISortableContainer { 15 | 16 | @Shadow 17 | private IronShulkerBoxType type; 18 | 19 | @Override 20 | public void buildSortingContext(ISortingContextBuilder builder) { 21 | builder.addSlotGroup(0, type.size, type.rowLength) 22 | .buttonPosSetter(IPosSetter.TOP_RIGHT_VERTICAL); 23 | } 24 | 25 | @Override 26 | public @Nullable IPosSetter getPlayerButtonPosSetter() { 27 | return IPosSetter.TOP_RIGHT_VERTICAL; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/gtceu/MixinToolHelper.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.gtceu; 2 | 3 | import com.cleanroommc.bogosorter.common.refill.DamageHelper; 4 | 5 | import net.minecraft.entity.EntityLivingBase; 6 | import net.minecraft.entity.player.EntityPlayerMP; 7 | import net.minecraft.item.ItemStack; 8 | 9 | import gregtech.api.items.toolitem.ToolHelper; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.injection.At; 12 | import org.spongepowered.asm.mixin.injection.Inject; 13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 14 | 15 | @Mixin(ToolHelper.class) 16 | public class MixinToolHelper { 17 | 18 | @Inject(method = "damageItem(Lnet/minecraft/item/ItemStack;Lnet/minecraft/entity/EntityLivingBase;I)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/ItemStack;setItemDamage(I)V", shift = At.Shift.AFTER), cancellable = true) 19 | private static void damageItem(ItemStack stack, EntityLivingBase entity, int damage, CallbackInfo ci) { 20 | if (entity instanceof EntityPlayerMP && DamageHelper.damageItemHook((EntityPlayerMP) entity, stack)) { 21 | ci.cancel(); 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/BogoSorterTransformer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core; 2 | 3 | import com.cleanroommc.bogosorter.core.visitor.EntityPlayerVisitor; 4 | import com.cleanroommc.bogosorter.core.visitor.PIMVisitor; 5 | 6 | import net.minecraft.launchwrapper.IClassTransformer; 7 | 8 | import org.objectweb.asm.ClassReader; 9 | import org.objectweb.asm.ClassWriter; 10 | 11 | public class BogoSorterTransformer implements IClassTransformer { 12 | 13 | @Override 14 | public byte[] transform(String name, String transformedName, byte[] classBytes) { 15 | switch (transformedName) { 16 | case PIMVisitor.CLASS_NAME: { 17 | ClassWriter classWriter = new ClassWriter(0); 18 | new ClassReader(classBytes).accept(new PIMVisitor(classWriter), 0); 19 | return classWriter.toByteArray(); 20 | } 21 | case EntityPlayerVisitor.CLASS_NAME: { 22 | ClassWriter classWriter = new ClassWriter(0); 23 | new ClassReader(classBytes).accept(new EntityPlayerVisitor(classWriter), 0); 24 | return classWriter.toByteArray(); 25 | } 26 | } 27 | return classBytes; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/ironchests/MixinIronChestContainer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.ironchests; 2 | 3 | import com.cleanroommc.bogosorter.api.IPosSetter; 4 | import com.cleanroommc.bogosorter.api.ISortableContainer; 5 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 6 | 7 | import cpw.mods.ironchest.common.blocks.chest.IronChestType; 8 | import cpw.mods.ironchest.common.gui.chest.ContainerIronChest; 9 | import org.jetbrains.annotations.Nullable; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | 13 | @Mixin(value = ContainerIronChest.class, remap = false) 14 | public class MixinIronChestContainer implements ISortableContainer { 15 | 16 | @Shadow 17 | private IronChestType type; 18 | 19 | @Override 20 | public void buildSortingContext(ISortingContextBuilder builder) { 21 | if (type != IronChestType.DIRTCHEST9000) { 22 | builder.addSlotGroup(0, type.size, type.rowLength) 23 | .buttonPosSetter(IPosSetter.TOP_RIGHT_VERTICAL); 24 | } 25 | } 26 | 27 | @Override 28 | public @Nullable IPosSetter getPlayerButtonPosSetter() { 29 | return IPosSetter.TOP_RIGHT_VERTICAL; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/ISlot.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import net.minecraft.entity.player.EntityPlayer; 4 | import net.minecraft.inventory.IInventory; 5 | import net.minecraft.inventory.Slot; 6 | import net.minecraft.item.ItemStack; 7 | 8 | /** 9 | * A custom slot interface. Useful if mods have a slot that does not implement the necessary methods. 10 | * {@link Slot} implements this interface via mixin. 11 | */ 12 | public interface ISlot { 13 | 14 | Slot bogo$getRealSlot(); 15 | 16 | int bogo$getX(); 17 | 18 | int bogo$getY(); 19 | 20 | int bogo$getSlotNumber(); 21 | 22 | int bogo$getSlotIndex(); 23 | 24 | IInventory bogo$getInventory(); 25 | 26 | void bogo$putStack(ItemStack itemStack); 27 | 28 | ItemStack bogo$getStack(); 29 | 30 | int bogo$getMaxStackSize(ItemStack itemStack); 31 | 32 | int bogo$getItemStackLimit(ItemStack itemStack); 33 | 34 | boolean bogo$isEnabled(); 35 | 36 | boolean bogo$isItemValid(ItemStack stack); 37 | 38 | boolean bogo$canTakeStack(EntityPlayer player); 39 | 40 | void bogo$onSlotChanged(); 41 | 42 | void bogo$onSlotChanged(ItemStack oldItem, ItemStack newItem); 43 | 44 | ItemStack bogo$onTake(EntityPlayer player, ItemStack itemStack); 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/BogoSorterCore.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core; 2 | 3 | import net.minecraftforge.common.ForgeVersion; 4 | import net.minecraftforge.fml.relauncher.IFMLLoadingPlugin; 5 | 6 | import zone.rong.mixinbooter.IEarlyMixinLoader; 7 | 8 | import java.util.Collections; 9 | import java.util.List; 10 | import java.util.Map; 11 | import javax.annotation.Nullable; 12 | 13 | @IFMLLoadingPlugin.Name("BogoSorter-Core") 14 | @IFMLLoadingPlugin.MCVersion(ForgeVersion.mcVersion) 15 | public class BogoSorterCore implements IFMLLoadingPlugin, IEarlyMixinLoader { 16 | 17 | @Override 18 | public String[] getASMTransformerClass() { 19 | return new String[0]; 20 | } 21 | 22 | @Override 23 | public String getModContainerClass() { 24 | return null; 25 | } 26 | 27 | @Nullable 28 | @Override 29 | public String getSetupClass() { 30 | return null; 31 | } 32 | 33 | @Override 34 | public void injectData(Map data) { 35 | } 36 | 37 | @Override 38 | public String getAccessTransformerClass() { 39 | return "com.cleanroommc.bogosorter.core.BogoSorterTransformer"; 40 | } 41 | 42 | @Override 43 | public List getMixinConfigs() { 44 | return Collections.singletonList("mixin.bogosorter.json"); 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/compat/InfinitySlotWrapper.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.compat; 2 | 3 | import com.cleanroommc.bogosorter.core.mixin.avaritiaddons.InfinityMatchingAccessor; 4 | 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.item.ItemStack; 7 | 8 | import org.jetbrains.annotations.NotNull; 9 | import wanion.avaritiaddons.block.chest.infinity.InfinitySlot; 10 | 11 | public class InfinitySlotWrapper extends FixedLimitSlot { 12 | 13 | public final InfinitySlot infinitySlot; 14 | 15 | public InfinitySlotWrapper(InfinitySlot slot) { 16 | super(slot, Integer.MAX_VALUE); 17 | this.infinitySlot = slot; 18 | } 19 | 20 | @Override 21 | public void bogo$putStack(@NotNull ItemStack itemStack) { 22 | ((InfinityMatchingAccessor) (Object) this.infinitySlot.getInfinityMatching()).invokeSetStack(itemStack, itemStack.getCount()); 23 | bogo$onSlotChanged(); 24 | } 25 | 26 | @Override 27 | public @NotNull ItemStack bogo$getStack() { 28 | return this.infinitySlot.getInfinityMatching().getStack(); 29 | } 30 | 31 | @Override 32 | public boolean bogo$isItemValid(ItemStack stack) { 33 | return true; 34 | } 35 | 36 | @Override 37 | public boolean bogo$canTakeStack(EntityPlayer player) { 38 | return true; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/ISortableContainer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import org.jetbrains.annotations.ApiStatus; 4 | import org.jetbrains.annotations.Nullable; 5 | 6 | import java.util.function.BiConsumer; 7 | 8 | /** 9 | * This interface marks a {@link net.minecraft.inventory.Container} as sortable. 10 | * Implementing this interface takes priority over {@link IBogoSortAPI#addCompat(Class, BiConsumer)} and 11 | * {@link IBogoSortAPI#addPlayerSortButtonPosition(Class, IPosSetter)}, but has the same effect. 12 | */ 13 | public interface ISortableContainer { 14 | 15 | /** 16 | * Is called when the container is opened. Add slot groups this container adds here. 17 | * Do not add the player inventory here (except if Bogosorter doesn't do it automatically). 18 | * 19 | * @param builder builder to build slot groups 20 | */ 21 | @ApiStatus.OverrideOnly 22 | void buildSortingContext(ISortingContextBuilder builder); 23 | 24 | /** 25 | * Determines where the buttons of the player inventory (if exists) should be placed. 26 | * Returning null will result in no sort buttons. 27 | * 28 | * @return player inventory sort button position function 29 | */ 30 | @Nullable 31 | default IPosSetter getPlayerButtonPosSetter() { 32 | return IPosSetter.TOP_RIGHT_HORIZONTAL; 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/SortConfigChangeEvent.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common; 2 | 3 | import com.cleanroommc.bogosorter.api.SortRule; 4 | import com.cleanroommc.bogosorter.common.config.BogoSorterConfig; 5 | import com.cleanroommc.bogosorter.common.sort.NbtSortRule; 6 | import com.cleanroommc.bogosorter.common.sort.SortHandler; 7 | 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraftforge.fml.common.eventhandler.Event; 10 | import net.minecraftforge.fml.relauncher.Side; 11 | import net.minecraftforge.fml.relauncher.SideOnly; 12 | 13 | import org.jetbrains.annotations.Unmodifiable; 14 | 15 | import java.util.Collections; 16 | import java.util.Comparator; 17 | import java.util.List; 18 | 19 | public class SortConfigChangeEvent extends Event { 20 | 21 | @Unmodifiable 22 | public final List> configuredItemSortRules; 23 | @Unmodifiable 24 | public final List configuredNbtSortRules; 25 | 26 | public SortConfigChangeEvent() { 27 | this.configuredItemSortRules = Collections.unmodifiableList(BogoSorterConfig.sortRules); 28 | this.configuredNbtSortRules = Collections.unmodifiableList(BogoSorterConfig.nbtSortRules); 29 | } 30 | 31 | @SideOnly(Side.CLIENT) 32 | public Comparator getItemComparator() { 33 | return SortHandler.getClientItemComparator(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/config/ConfigReloadCommand.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.config; 2 | 3 | import com.cleanroommc.bogosorter.common.network.NetworkHandler; 4 | import com.cleanroommc.bogosorter.common.network.SReloadConfig; 5 | 6 | import net.minecraft.command.CommandBase; 7 | import net.minecraft.command.ICommandSender; 8 | import net.minecraft.entity.player.EntityPlayerMP; 9 | import net.minecraft.server.MinecraftServer; 10 | import net.minecraft.util.text.TextComponentTranslation; 11 | 12 | import org.jetbrains.annotations.NotNull; 13 | 14 | public class ConfigReloadCommand extends CommandBase { 15 | 16 | @Override 17 | public @NotNull String getName() { 18 | return "reload"; 19 | } 20 | 21 | @Override 22 | public @NotNull String getUsage(@NotNull ICommandSender sender) { 23 | return "/bogosort reload"; 24 | } 25 | 26 | @Override 27 | public void execute(@NotNull MinecraftServer server, @NotNull ICommandSender sender, String @NotNull [] args) { 28 | if (sender instanceof EntityPlayerMP) { 29 | NetworkHandler.sendToPlayer(new SReloadConfig(), (EntityPlayerMP) sender); 30 | sender.sendMessage(new TextComponentTranslation("bogosort.command.config_relaod.success")); 31 | } 32 | } 33 | 34 | @Override 35 | public int getRequiredPermissionLevel() { 36 | return 0; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/LateMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter; 2 | 3 | import net.minecraftforge.fml.common.Loader; 4 | 5 | import com.google.common.collect.ImmutableList; 6 | import gregtech.GregTechVersion; 7 | import zone.rong.mixinbooter.ILateMixinLoader; 8 | 9 | import java.util.List; 10 | import java.util.stream.Collectors; 11 | 12 | public class LateMixin implements ILateMixinLoader { 13 | 14 | public static final List modMixins = ImmutableList.of("ironchest", "thermalexpansion", "enderio", 15 | "gregtechceu", "colossalchests", "galacticraftcore", "galacticraftplanets", "charset", 16 | "simplybackpacks", "avaritiaddons", "improvedbackpacks", "quark", "rftools", "hbm"); 17 | 18 | @Override 19 | public List getMixinConfigs() { 20 | return modMixins.stream().map(mod -> "mixin.bogosorter." + mod + ".json").collect(Collectors.toList()); 21 | } 22 | 23 | @Override 24 | public boolean shouldMixinConfigQueue(String mixinConfig) { 25 | String[] parts = mixinConfig.split("\\."); 26 | return parts.length != 4 || shouldEnableModMixin(parts[2]); 27 | } 28 | 29 | @SuppressWarnings("all") 30 | public boolean shouldEnableModMixin(String mod) { 31 | if ("gregtechceu".equals(mod)) { 32 | return Loader.isModLoaded("gregtech") && GregTechVersion.MAJOR >= 2; 33 | } 34 | return Loader.isModLoaded(mod); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/IPacket.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import net.minecraft.client.network.NetHandlerPlayClient; 4 | import net.minecraft.network.NetHandlerPlayServer; 5 | import net.minecraft.network.PacketBuffer; 6 | import net.minecraftforge.fml.common.network.simpleimpl.IMessage; 7 | import net.minecraftforge.fml.relauncher.Side; 8 | import net.minecraftforge.fml.relauncher.SideOnly; 9 | 10 | import io.netty.buffer.ByteBuf; 11 | 12 | import java.io.IOException; 13 | 14 | /** 15 | * Joinked from Multiblocked 16 | */ 17 | public interface IPacket extends IMessage { 18 | 19 | void encode(PacketBuffer buf) throws IOException; 20 | 21 | void decode(PacketBuffer buf) throws IOException; 22 | 23 | @Override 24 | default void fromBytes(ByteBuf buf) { 25 | try { 26 | decode(new PacketBuffer(buf)); 27 | } catch (IOException e) { 28 | e.printStackTrace(); 29 | } 30 | } 31 | 32 | @Override 33 | default void toBytes(ByteBuf buf) { 34 | try { 35 | encode(new PacketBuffer(buf)); 36 | } catch (IOException e) { 37 | e.printStackTrace(); 38 | } 39 | } 40 | 41 | @SideOnly(Side.CLIENT) 42 | default IPacket executeClient(NetHandlerPlayClient handler) { 43 | return null; 44 | } 45 | 46 | default IPacket executeServer(NetHandlerPlayServer handler) { 47 | return null; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/IPosSetter.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | /** 4 | * A function to set the sort button pos of {@link ISlotGroup}'s. 5 | */ 6 | @FunctionalInterface 7 | public interface IPosSetter { 8 | 9 | IPosSetter TOP_RIGHT_HORIZONTAL = (slotGroup, buttonPos) -> { 10 | if (slotGroup.getSlots().size() < slotGroup.getRowSize()) { 11 | buttonPos.setPos(-1000, -1000); 12 | } else { 13 | ISlot topRight = slotGroup.getSlots().get(slotGroup.getRowSize() - 1); 14 | buttonPos.setPos(topRight.bogo$getX() + 17, topRight.bogo$getY() - 2); 15 | } 16 | }; 17 | 18 | IPosSetter TOP_RIGHT_VERTICAL = (slotGroup, buttonPos) -> { 19 | if (slotGroup.getSlots().size() < slotGroup.getRowSize()) { 20 | buttonPos.setPos(-1000, -1000); 21 | } else { 22 | ISlot topRight = slotGroup.getSlots().get(slotGroup.getRowSize() - 1); 23 | buttonPos.setVertical(); 24 | buttonPos.setTopLeft(); 25 | buttonPos.setPos(topRight.bogo$getX() + 18, topRight.bogo$getY() - 1); 26 | } 27 | }; 28 | 29 | /** 30 | * Called every frame, to make sure the buttons are always in the right position. 31 | * Call setters on {@link IButtonPos} here. 32 | * 33 | * @param slotGroup slot group of the buttons 34 | * @param buttonPos the mutable button pos 35 | */ 36 | void setButtonPos(ISlotGroup slotGroup, IButtonPos buttonPos); 37 | } 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Inventory Bogosorter 2 | 3 | This is aims to replace the popular Inventory Tweaks mod. 4 | 5 | ### Why? 6 | 7 | Inventory Tweaks API is very limited. It doesn't work well with modular gui libraries like ModularUI. It also has desync bugs, since it is client side only. 8 | 9 | ### Why rewrite and not just fork? 10 | 11 | The Inventory Tweaks code is very unpleasant to work with. I rather write my own clean mod. 12 | 13 | --- 14 | 15 | ## Features 16 | 17 | - sorting of player inventories in (almost) all moded GUI's (default key is middle mouse button) 18 | - sorting of many modded inventories 19 | - sort buttons for each sortable inventory 20 | - configuring of sort rules (open config with K by default) 21 | - automatically switching out tools wich are about to break 22 | - automatically refill broken tools or used up items 23 | - scroll through vertical slots above a hotbar slots while holding ALT 24 | - several key shortcuts to move items: 25 | - CTRL + LMB: transfers a single item 26 | - CTRL + RMB: transfers a single item into an empty slot 27 | - Space + LMB: transfer the whole inventory 28 | - ALT + LMB: transfers all items of the same type 29 | - Space + Q: throws the whole inventory into the world 30 | - ALT + Q: throws all the items of the same type into the world 31 | 32 | ## TODO's 33 | 34 | - sorting profiles 35 | - bind certain profiles to a certain block? (might be difficult) 36 | - radial menu to quickly choose profile 37 | - choose profile for ae2 and jei 38 | - configurable sort sound 39 | - animation? 40 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/CHotbarSwap.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import net.minecraft.item.ItemStack; 4 | import net.minecraft.network.NetHandlerPlayServer; 5 | import net.minecraft.network.PacketBuffer; 6 | 7 | import java.io.IOException; 8 | 9 | public class CHotbarSwap implements IPacket { 10 | 11 | private int hotbarIndex; 12 | private int swapIndex; 13 | 14 | public CHotbarSwap() { 15 | } 16 | 17 | public CHotbarSwap(int hotbarIndex, int swapIndex) { 18 | this.hotbarIndex = hotbarIndex; 19 | this.swapIndex = swapIndex; 20 | } 21 | 22 | @Override 23 | public void encode(PacketBuffer buf) throws IOException { 24 | buf.writeVarInt(hotbarIndex); 25 | buf.writeVarInt(swapIndex); 26 | } 27 | 28 | @Override 29 | public void decode(PacketBuffer buf) throws IOException { 30 | this.hotbarIndex = buf.readVarInt(); 31 | this.swapIndex = buf.readVarInt(); 32 | } 33 | 34 | @Override 35 | public IPacket executeServer(NetHandlerPlayServer handler) { 36 | ItemStack hotbarItem = handler.player.inventory.mainInventory.get(this.hotbarIndex); 37 | ItemStack toSwapItem = handler.player.inventory.mainInventory.get(this.swapIndex); 38 | if (hotbarItem.equals(toSwapItem)) return null; 39 | handler.player.inventory.mainInventory.set(this.hotbarIndex, toSwapItem); 40 | handler.player.inventory.mainInventory.set(this.swapIndex, hotbarItem); 41 | return null; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/SortRule.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import java.util.Comparator; 4 | 5 | public class SortRule implements Comparator { 6 | 7 | private static int nextId = 0; 8 | 9 | private final String key; 10 | private final Comparator comparator; 11 | private boolean inverted = false; 12 | private final int syncId; 13 | 14 | public SortRule(String key, Comparator comparator) { 15 | this.key = key; 16 | this.comparator = comparator; 17 | this.syncId = nextId++; 18 | } 19 | 20 | public String getKey() { 21 | return key; 22 | } 23 | 24 | public String getNameLangKey() { 25 | return "bogosort.sortrules.item." + key + ".name"; 26 | } 27 | 28 | public String getDescriptionLangKey() { 29 | return "bogosort.sortrules.item." + key + ".description"; 30 | } 31 | 32 | public boolean isInverted() { 33 | return inverted; 34 | } 35 | 36 | public void setInverted(boolean inverted) { 37 | this.inverted = inverted; 38 | } 39 | 40 | public int getSyncId() { 41 | return syncId; 42 | } 43 | 44 | public boolean isEmpty() { 45 | return false; 46 | } 47 | 48 | @Override 49 | public int compare(T o1, T o2) { 50 | return inverted ? comparator.compare(o2, o1) : comparator.compare(o1, o2); 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return "SortRule{" + 56 | "key='" + key + '\'' + 57 | '}'; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/gtceu/MixinToolMetaItem.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.gtceu; 2 | 3 | /*@Mixin(value = ToolMetaItem.class, remap = false) 4 | public abstract class MixinToolMetaItem { 5 | 6 | @Shadow 7 | public abstract int getItemDamage(ItemStack itemStack); 8 | 9 | @Shadow 10 | public abstract int getMaxItemDamage(ItemStack itemStack); 11 | 12 | @Inject(method = "damageItem", at = @At(value = "INVOKE", target = "Ljava/lang/Math;min(II)I")) 13 | private void damageItem(ItemStack stack, EntityLivingBase entity, int vanillaDamage, boolean allowPartial, boolean simulate, CallbackInfoReturnable cir) { 14 | if (!simulate && entity instanceof EntityPlayer) { 15 | EntityPlayer player = ((EntityPlayer) entity); 16 | PlayerConfig playerConfig = PlayerConfig.get(player); 17 | if (!playerConfig.enableAutoRefill || playerConfig.autoRefillDamageThreshold <= 0) return; 18 | 19 | if (RefillHandler.shouldHandleRefill(player, stack) && stack.hasTagCompound() && stack.getTagCompound().hasKey("GT.ToolStats")) { 20 | int durabilityLeft = getMaxItemDamage(stack) - getItemDamage(stack); 21 | if (durabilityLeft > 0 && durabilityLeft <= playerConfig.autoRefillDamageThreshold) { 22 | RefillHandler.handle(player.inventory.currentItem, stack, player, true); 23 | //new RefillHandler(player.inventory.currentItem, stack, player, true).handleRefill(); 24 | } 25 | } 26 | } 27 | } 28 | }*/ 29 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/compat/gtce/SortableSlotWidget.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.compat.gtce; 2 | 3 | import net.minecraft.inventory.IInventory; 4 | import net.minecraftforge.items.IItemHandler; 5 | import net.minecraftforge.items.IItemHandlerModifiable; 6 | 7 | import gregtech.api.gui.widgets.SlotWidget; 8 | import org.jetbrains.annotations.Nullable; 9 | 10 | public class SortableSlotWidget extends SlotWidget { 11 | 12 | @Nullable 13 | private String sortArea; 14 | 15 | public SortableSlotWidget(IInventory inventory, int slotIndex, int xPosition, int yPosition, boolean canTakeItems, boolean canPutItems) { 16 | super(inventory, slotIndex, xPosition, yPosition, canTakeItems, canPutItems); 17 | } 18 | 19 | public SortableSlotWidget(IItemHandler itemHandler, int slotIndex, int xPosition, int yPosition, boolean canTakeItems, boolean canPutItems) { 20 | super(itemHandler, slotIndex, xPosition, yPosition, canTakeItems, canPutItems); 21 | } 22 | 23 | public SortableSlotWidget(IItemHandlerModifiable itemHandler, int slotIndex, int xPosition, int yPosition) { 24 | super(itemHandler, slotIndex, xPosition, yPosition); 25 | } 26 | 27 | public SortableSlotWidget(IInventory inventory, int slotIndex, int xPosition, int yPosition) { 28 | super(inventory, slotIndex, xPosition, yPosition); 29 | } 30 | 31 | public SortableSlotWidget setSortArea(@Nullable String sortArea) { 32 | this.sortArea = sortArea; 33 | return this; 34 | } 35 | 36 | public @Nullable String getSortArea() { 37 | return sortArea; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/api/java/buildcraft/api/tools/IToolWrench.java: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2011-2015, SpaceToad and the BuildCraft Team http://www.mod-buildcraft.com 2 | * 3 | * The BuildCraft API is distributed under the terms of the MIT License. Please check the contents of the license, which 4 | * should be located as "LICENSE.API" in the BuildCraft source code distribution. */ 5 | package buildcraft.api.tools; 6 | 7 | import net.minecraft.entity.player.EntityPlayer; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.util.EnumHand; 10 | import net.minecraft.util.math.RayTraceResult; 11 | 12 | /*** Implement this interface on subclasses of Item to have that item work as a wrench for buildcraft */ 13 | public interface IToolWrench { 14 | 15 | /*** Called to ensure that the wrench can be used. 16 | * 17 | * @param player - The player doing the wrenching 18 | * @param hand - Which hand was holding the wrench 19 | * @param wrench - The item stack that holds the wrench 20 | * @param rayTrace - The object that is being wrenched 21 | * 22 | * @return true if wrenching is allowed, false if not */ 23 | boolean canWrench(EntityPlayer player, EnumHand hand, ItemStack wrench, RayTraceResult rayTrace); 24 | 25 | /*** Callback after the wrench has been used. This can be used to decrease durability or for other purposes. 26 | * 27 | * @param player - The player doing the wrenching 28 | * @param hand - Which hand was holding the wrench 29 | * @param wrench - The item stack that holds the wrench 30 | * @param rayTrace - The object that is being wrenched */ 31 | void wrenchUsed(EntityPlayer player, EnumHand hand, ItemStack wrench, RayTraceResult rayTrace); 32 | } 33 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/compat/screen/WarningScreen.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.compat.screen; 2 | 3 | import net.minecraft.client.gui.GuiButton; 4 | import net.minecraft.client.gui.GuiMainMenu; 5 | import net.minecraft.client.gui.GuiScreen; 6 | import net.minecraft.client.resources.I18n; 7 | import net.minecraftforge.fml.relauncher.Side; 8 | import net.minecraftforge.fml.relauncher.SideOnly; 9 | 10 | import java.util.List; 11 | 12 | @SideOnly(Side.CLIENT) 13 | public class WarningScreen extends GuiScreen { 14 | 15 | public static boolean wasOpened = false; 16 | 17 | public final List messages; 18 | private int textHeight; 19 | 20 | public WarningScreen(List messages) { 21 | this.messages = messages; 22 | } 23 | 24 | @Override 25 | public void drawScreen(int mouseX, int mouseY, float partialTicks) { 26 | this.drawDefaultBackground(); 27 | int i = this.height / 2 - this.textHeight / 2; 28 | if (this.messages != null) { 29 | for (String s : this.messages) { 30 | this.drawCenteredString(this.fontRenderer, s, this.width / 2, i, 16777215); 31 | i += this.fontRenderer.FONT_HEIGHT; 32 | } 33 | } 34 | super.drawScreen(mouseX, mouseY, partialTicks); 35 | } 36 | 37 | @Override 38 | public void actionPerformed(GuiButton button) { 39 | if (button.id == 0) { 40 | this.mc.displayGuiScreen(new GuiMainMenu()); 41 | } 42 | } 43 | 44 | @Override 45 | public void initGui() { 46 | this.textHeight = this.messages.size() * this.fontRenderer.FONT_HEIGHT; 47 | this.buttonList.add(new GuiButton(0, this.width / 2 - 100, Math.min(this.height / 2 + this.textHeight / 2 + this.fontRenderer.FONT_HEIGHT, this.height - 30), I18n.format("gui.toTitle"))); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/CSlotSync.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.network.NetHandlerPlayServer; 7 | import net.minecraft.network.PacketBuffer; 8 | 9 | import org.apache.commons.lang3.tuple.Pair; 10 | 11 | import java.io.IOException; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | 15 | public class CSlotSync implements IPacket { 16 | 17 | private final List> content; 18 | 19 | public CSlotSync() { 20 | content = new ArrayList<>(); 21 | } 22 | 23 | public CSlotSync(List> content) { 24 | this.content = content; 25 | } 26 | 27 | @Override 28 | public void encode(PacketBuffer buf) { 29 | buf.writeVarInt(content.size()); 30 | for (Pair pair : content) { 31 | buf.writeItemStack(pair.getKey()); 32 | buf.writeCompoundTag(pair.getKey().getTagCompound()); 33 | buf.writeVarInt(pair.getValue()); 34 | } 35 | } 36 | 37 | @Override 38 | public void decode(PacketBuffer buf) throws IOException { 39 | for (int i = 0, n = buf.readVarInt(); i < n; i++) { 40 | ItemStack stack = buf.readItemStack(); 41 | stack.setTagCompound(buf.readCompoundTag()); 42 | content.add(Pair.of(stack, buf.readVarInt())); 43 | } 44 | } 45 | 46 | @Override 47 | public IPacket executeServer(NetHandlerPlayServer handler) { 48 | for (Pair pair : content) { 49 | BogoSortAPI.getSlot(handler.player.openContainer, pair.getValue()).bogo$putStack(pair.getKey()); 50 | } 51 | handler.player.openContainer.detectAndSendChanges(); 52 | return null; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/IButtonPos.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | /** 4 | * Determines the true sort button pos for slot groups. 5 | */ 6 | public interface IButtonPos { 7 | 8 | void setEnabled(boolean enabled); 9 | 10 | /** 11 | * Sets position where the buttons will be placed. 12 | * 13 | * @param x x pos 14 | * @param y y pos 15 | */ 16 | void setPos(int x, int y); 17 | 18 | /** 19 | * Sets the alignment of the buttons. Determines where the buttons are placed relative to the pos. 20 | * For example if the alignment is bottom left, then the pos will be the bottom left corner of the buttons. 21 | * 22 | * @param alignment alignment 23 | */ 24 | void setAlignment(Alignment alignment); 25 | 26 | /** 27 | * Sets the layout of the buttons. Horizontal is next to each other and vertical is on top of each other. 28 | * 29 | * @param layout layout 30 | */ 31 | void setLayout(Layout layout); 32 | 33 | default void setTopLeft() { 34 | setAlignment(Alignment.TOP_LEFT); 35 | } 36 | 37 | default void setTopRight() { 38 | setAlignment(Alignment.TOP_RIGHT); 39 | } 40 | 41 | default void setBottomLeft() { 42 | setAlignment(Alignment.BOTTOM_LEFT); 43 | } 44 | 45 | default void setBottomRight() { 46 | setAlignment(Alignment.BOTTOM_RIGHT); 47 | } 48 | 49 | default void setHorizontal() { 50 | setLayout(Layout.HORIZONTAL); 51 | } 52 | 53 | default void setVertical() { 54 | setLayout(Layout.VERTICAL); 55 | } 56 | 57 | boolean isEnabled(); 58 | 59 | int getX(); 60 | 61 | int getY(); 62 | 63 | Alignment getAlignment(); 64 | 65 | Layout getLayout(); 66 | 67 | enum Alignment { 68 | TOP_RIGHT, TOP_LEFT, BOTTOM_RIGHT, BOTTOM_LEFT 69 | } 70 | 71 | enum Layout { 72 | HORIZONTAL, VERTICAL 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/enderio/MixinEIOStorage.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.enderio; 2 | 3 | import com.cleanroommc.bogosorter.api.IPosSetter; 4 | import com.cleanroommc.bogosorter.api.ISortableContainer; 5 | import com.cleanroommc.bogosorter.api.ISortingContextBuilder; 6 | 7 | import net.minecraft.inventory.Container; 8 | import net.minecraft.inventory.EntityEquipmentSlot; 9 | import net.minecraft.inventory.Slot; 10 | 11 | import crazypants.enderio.base.item.darksteel.upgrade.storage.StorageCap; 12 | import crazypants.enderio.base.item.darksteel.upgrade.storage.StorageContainer; 13 | import crazypants.enderio.util.EIOCombinedInvWrapper; 14 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 15 | import it.unimi.dsi.fastutil.objects.ObjectArrayList; 16 | import org.spongepowered.asm.mixin.Mixin; 17 | 18 | import java.util.List; 19 | import java.util.Map; 20 | 21 | @Mixin(StorageContainer.class) 22 | public class MixinEIOStorage implements ISortableContainer { 23 | 24 | @Override 25 | public void buildSortingContext(ISortingContextBuilder builder) { 26 | Map> slots = new Object2ObjectOpenHashMap<>(); 27 | EIOCombinedInvWrapper itemHandler = ((StorageContainer) (Object) this).getItemHandler(); 28 | for (int i = 0; i < itemHandler.getSlots(); i++) { 29 | EntityEquipmentSlot current = itemHandler.getHandlerFromSlot(i).getEquipmentSlot(); 30 | Slot slot = ((Container) (Object) this).inventorySlots.get(i); 31 | slots.computeIfAbsent(current, key -> new ObjectArrayList<>()).add(slot); 32 | } 33 | slots.forEach((slot, slotList) -> builder.addSlotGroupOf(slotList, StorageUpgradeAccessor.invokeCols(slot)) 34 | .buttonPosSetter((slotGroup, buttonPos) -> { 35 | IPosSetter.TOP_RIGHT_HORIZONTAL.setButtonPos(slotGroup, buttonPos); 36 | buttonPos.setEnabled(slotGroup.getSlots().get(0).bogo$isEnabled()); 37 | })); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/ClientSortData.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.common.sort.color.ItemColorHelper; 4 | 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.network.PacketBuffer; 7 | import net.minecraftforge.fml.relauncher.Side; 8 | import net.minecraftforge.fml.relauncher.SideOnly; 9 | 10 | import it.unimi.dsi.fastutil.ints.IntArrayList; 11 | import it.unimi.dsi.fastutil.ints.IntList; 12 | import org.apache.commons.lang3.StringUtils; 13 | 14 | public class ClientSortData { 15 | 16 | @SideOnly(Side.CLIENT) 17 | public static ClientSortData of(ItemStack itemStack, boolean getColor, boolean getName) { 18 | int color = getColor ? ItemColorHelper.getItemColorHue(itemStack) : 0; 19 | String name = getName ? itemStack.getDisplayName() : StringUtils.EMPTY; 20 | return new ClientSortData(color, name); 21 | } 22 | 23 | public static ClientSortData readFromPacket(PacketBuffer buf) { 24 | int color = buf.readVarInt(); 25 | String name = buf.readString(64); 26 | ClientSortData sortData = new ClientSortData(color, name); 27 | for (int i = 0, n = buf.readVarInt(); i < n; i++) { 28 | sortData.getSlotNumbers().add(buf.readVarInt()); 29 | } 30 | return sortData; 31 | } 32 | 33 | private final int color; 34 | private final String name; 35 | private final IntList slotNumbers = new IntArrayList(); 36 | 37 | public ClientSortData(int color, String name) { 38 | this.color = color; 39 | this.name = name; 40 | } 41 | 42 | public int getColor() { 43 | return color; 44 | } 45 | 46 | public IntList getSlotNumbers() { 47 | return slotNumbers; 48 | } 49 | 50 | public String getName() { 51 | return name; 52 | } 53 | 54 | public void writeToPacket(PacketBuffer buf) { 55 | buf.writeVarInt(color); 56 | buf.writeString(name); 57 | buf.writeVarInt(slotNumbers.size()); 58 | for (int i : slotNumbers) buf.writeVarInt(i); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/config/BogoSortCommandTree.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.config; 2 | 3 | import com.cleanroommc.bogosorter.common.OreDictHelper; 4 | 5 | import net.minecraft.command.CommandBase; 6 | import net.minecraft.command.CommandException; 7 | import net.minecraft.command.ICommandSender; 8 | import net.minecraft.entity.player.EntityPlayer; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.server.MinecraftServer; 11 | import net.minecraft.util.text.TextComponentString; 12 | import net.minecraftforge.server.command.CommandTreeBase; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | public class BogoSortCommandTree extends CommandTreeBase { 17 | 18 | public BogoSortCommandTree() { 19 | addSubcommand(new ConfigReloadCommand()); 20 | addSubcommand(new CommandBase() { 21 | @Override 22 | public String getName() { 23 | return "hand"; 24 | } 25 | 26 | @Override 27 | public String getUsage(ICommandSender sender) { 28 | return "/bogosorter hand"; 29 | } 30 | 31 | @Override 32 | public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException { 33 | if (sender instanceof EntityPlayer) { 34 | ItemStack itemStack = ((EntityPlayer) sender).getHeldItemMainhand(); 35 | if (itemStack.isEmpty()) itemStack = ((EntityPlayer) sender).getHeldItemOffhand(); 36 | if (itemStack.isEmpty()) return; 37 | String material = OreDictHelper.getMaterial(itemStack); 38 | String prefix = OreDictHelper.getOrePrefix(itemStack); 39 | sender.sendMessage(new TextComponentString("Material: " + material)); 40 | sender.sendMessage(new TextComponentString("OrePrefix: " + prefix)); 41 | } 42 | } 43 | }); 44 | } 45 | 46 | @Override 47 | public @NotNull String getName() { 48 | return "bogosorter"; 49 | } 50 | 51 | @Override 52 | public @NotNull String getUsage(@NotNull ICommandSender sender) { 53 | return "/bogosorter [reload]"; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/config/PlayerConfig.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.config; 2 | 3 | import com.cleanroommc.bogosorter.common.network.CConfigSync; 4 | import com.cleanroommc.bogosorter.common.network.NetworkHandler; 5 | import com.cleanroommc.bogosorter.common.network.NetworkUtils; 6 | 7 | import net.minecraft.entity.player.EntityPlayer; 8 | import net.minecraft.entity.player.EntityPlayerMP; 9 | import net.minecraft.network.PacketBuffer; 10 | import net.minecraftforge.fml.relauncher.Side; 11 | import net.minecraftforge.fml.relauncher.SideOnly; 12 | 13 | import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; 14 | import org.jetbrains.annotations.NotNull; 15 | 16 | import java.util.Map; 17 | 18 | public class PlayerConfig { 19 | 20 | private static final Map playerConfig = new Object2ObjectOpenHashMap<>(); 21 | private static final PlayerConfig CLIENT = new PlayerConfig(); 22 | 23 | public boolean enableAutoRefill = true; 24 | public int autoRefillDamageThreshold = 1; 25 | 26 | public static PlayerConfig get(@NotNull EntityPlayer player) { 27 | if (NetworkUtils.isDedicatedClient()) { 28 | return CLIENT; 29 | } 30 | if (player instanceof EntityPlayerMP) { 31 | return playerConfig.computeIfAbsent((EntityPlayerMP) player, key -> new PlayerConfig()); 32 | } 33 | throw new IllegalStateException("Could net get player config for " + player.getName()); 34 | } 35 | 36 | public static void checkPlayers() { 37 | playerConfig.keySet().removeIf(player -> !player.isAddedToWorld()); 38 | } 39 | 40 | @SideOnly(Side.CLIENT) 41 | public static PlayerConfig getClient() { 42 | return CLIENT; 43 | } 44 | 45 | public void writePacket(PacketBuffer buffer) { 46 | buffer.writeBoolean(enableAutoRefill); 47 | buffer.writeVarInt(autoRefillDamageThreshold); 48 | } 49 | 50 | public void readPacket(PacketBuffer buffer) { 51 | enableAutoRefill = buffer.readBoolean(); 52 | autoRefillDamageThreshold = buffer.readVarInt(); 53 | } 54 | 55 | @SideOnly(Side.CLIENT) 56 | public static void syncToServer() { 57 | NetworkHandler.sendToServer(new CConfigSync()); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/gtceu/MixinMetaTileEntityCrate.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.gtceu; 2 | 3 | import com.cleanroommc.bogosorter.compat.gtce.IModularSortable; 4 | import com.cleanroommc.bogosorter.compat.gtce.SortableSlotWidget; 5 | 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraftforge.items.ItemStackHandler; 8 | 9 | import gregtech.api.gui.GuiTextures; 10 | import gregtech.api.gui.ModularUI; 11 | import gregtech.api.gui.resources.TextureArea; 12 | import gregtech.common.metatileentities.storage.MetaTileEntityCrate; 13 | import org.spongepowered.asm.mixin.Final; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.Overwrite; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | 18 | @Mixin(value = MetaTileEntityCrate.class, remap = false) 19 | public class MixinMetaTileEntityCrate { 20 | 21 | @Shadow 22 | @Final 23 | private int inventorySize; 24 | 25 | @Shadow 26 | private ItemStackHandler inventory; 27 | 28 | /** 29 | * @author brachy84 30 | * @reason because it works 31 | */ 32 | @Overwrite 33 | public ModularUI createUI(EntityPlayer entityPlayer) { 34 | int factor = inventorySize / 9 > 8 ? 18 : 9; 35 | ModularUI.Builder builder = ModularUI.builder(GuiTextures.BACKGROUND, 176 + (factor == 18 ? 176 : 0), 8 + this.inventorySize / factor * 18 + 104).label(5, 5, bogosorter$getThis().getMetaFullName()); 36 | 37 | for (int i = 0; i < this.inventorySize; ++i) { 38 | builder.widget(new SortableSlotWidget(inventory, i, 7 * (factor == 18 ? 2 : 1) + i % factor * 18, 18 + i / factor * 18) 39 | .setSortArea("chest") 40 | .setBackgroundTexture(new TextureArea[]{GuiTextures.SLOT})); 41 | } 42 | 43 | builder.bindPlayerInventory(entityPlayer.inventory, GuiTextures.SLOT, 7 + (factor == 18 ? 88 : 0), 18 + this.inventorySize / factor * 18 + 11); 44 | ModularUI modularUI = builder.build(bogosorter$getThis().getHolder(), entityPlayer); 45 | ((IModularSortable) (Object) modularUI).addSortArea("chest", factor); 46 | return modularUI; 47 | } 48 | 49 | private MetaTileEntityCrate bogosorter$getThis() { 50 | return (MetaTileEntityCrate) (Object) (this); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/ISlotGroup.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import org.jetbrains.annotations.Nullable; 4 | import org.jetbrains.annotations.UnmodifiableView; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * A slot group is a list of slots which is organized in a rectangle. 10 | * It doesn't necessarily need to be a rectangle, but you might run into issues if the shape is more complex. 11 | */ 12 | public interface ISlotGroup { 13 | 14 | /** 15 | * An unmodifiable view of all the slots of this group. 16 | * 17 | * @return all slots 18 | */ 19 | @UnmodifiableView 20 | List getSlots(); 21 | 22 | /** 23 | * Returns how many slots are in row. This is mostly used to determine the button position with 24 | * {@link IPosSetter#TOP_RIGHT_VERTICAL} and {@link IPosSetter#TOP_RIGHT_HORIZONTAL}. If the slot group shape is 25 | * not rectangular, try to return the row size of the first row. 26 | * 27 | * @return slots per row 28 | */ 29 | int getRowSize(); 30 | 31 | /** 32 | * Returns the priority that this group takes when items are transferred via shortcuts. 33 | * 34 | * @return priority 35 | */ 36 | int getPriority(); 37 | 38 | /** 39 | * Returns if this slot groups only consists of player inventory slots. It does not need to be the full player 40 | * inventory. The player hotbar is usually not part of this. 41 | * 42 | * @return if all slots are part of the player inventory 43 | */ 44 | boolean isPlayerInventory(); 45 | 46 | /** 47 | * Sets the priority of this slot group. Can determine where items are transferred first with shortcuts. 48 | * Returns itself to be used in a builder like manner. 49 | * 50 | * @param priority priority 51 | * @return this 52 | */ 53 | ISlotGroup priority(int priority); 54 | 55 | /** 56 | * Sets a custom function to determine the position of sort buttons. Default is top right corner. 57 | * Returns itself to be used in a builder like manner. 58 | * 59 | * @param posSetter pos function or null if no buttons are desired 60 | * @return this 61 | */ 62 | ISlotGroup buttonPosSetter(@Nullable IPosSetter posSetter); 63 | 64 | default boolean canBeSorted() { 65 | return getSlots().size() > 1; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/refill/DamageHelper.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.refill; 2 | 3 | import com.cleanroommc.bogosorter.common.config.PlayerConfig; 4 | 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.inventory.EntityEquipmentSlot; 7 | import net.minecraft.item.ItemArmor; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraftforge.common.ISpecialArmor; 10 | 11 | public class DamageHelper { 12 | 13 | public static boolean damageItemHook(EntityPlayer player, ItemStack itemStack) { 14 | PlayerConfig playerConfig = PlayerConfig.get(player); 15 | if (!playerConfig.enableAutoRefill || playerConfig.autoRefillDamageThreshold <= 0) return false; 16 | 17 | if (RefillHandler.shouldHandleRefill(player, itemStack) && isNotArmor(itemStack)) { 18 | int index = player.inventory.currentItem; 19 | ItemStack handItem = player.getHeldItemMainhand(); 20 | if (handItem != itemStack) { 21 | handItem = player.getHeldItemOffhand(); 22 | if (handItem != itemStack) return false; 23 | index = RefillHandler.OFFHAND_INDEX; 24 | } 25 | 26 | int durabilityLeft = itemStack.getMaxDamage() - itemStack.getItemDamage(); 27 | if (durabilityLeft >= 0 && durabilityLeft < playerConfig.autoRefillDamageThreshold) { 28 | return RefillHandler.handle(index, itemStack, player, true); 29 | } 30 | } 31 | return false; 32 | } 33 | 34 | private static boolean isNotArmor(ItemStack itemStack) { 35 | if (itemStack.getItem() instanceof ItemArmor || itemStack.getItem() instanceof ISpecialArmor) return false; 36 | EntityEquipmentSlot slot = itemStack.getItem().getEquipmentSlot(itemStack); 37 | return slot == null || slot == EntityEquipmentSlot.MAINHAND || slot == EntityEquipmentSlot.OFFHAND; 38 | } 39 | 40 | public static int getDurability(ItemStack item) { 41 | if (item.isEmpty()) return 0; 42 | if (item.getMaxDamage() <= 0) return 0; 43 | if (isUnbreakable(item)) { 44 | return item.getMaxDamage() + 1; 45 | } 46 | return item.getMaxDamage() - item.getItemDamage() + 1; 47 | } 48 | 49 | public static boolean isUnbreakable(ItemStack item) { 50 | return !item.isEmpty() && item.hasTagCompound() && item.getTagCompound().getBoolean("Unbreakable"); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/color/ColorUtil.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort.color; 2 | 3 | import java.awt.*; 4 | 5 | public final class ColorUtil { 6 | 7 | private ColorUtil() { 8 | 9 | } 10 | 11 | /** 12 | * http://www.compuphase.com/cmetric.htm 13 | * http://stackoverflow.com/a/6334454 14 | * Returns 0 for equal colors, nonzero for colors that look different. 15 | * The return value is farther from 0 the more different the colors look. 16 | */ 17 | public static double fastPerceptualColorDistanceSquared(int[] color1, int[] color2) { 18 | final int red1 = color1[0]; 19 | final int red2 = color2[0]; 20 | final int redMean = (red1 + red2) >> 1; 21 | final int r = red1 - red2; 22 | final int g = color1[1] - color2[1]; 23 | final int b = color1[2] - color2[2]; 24 | return (((512 + redMean) * r * r) >> 8) + 4 * g * g + (((767 - redMean) * b * b) >> 8); 25 | } 26 | 27 | /** 28 | * http://www.compuphase.com/cmetric.htm 29 | * http://stackoverflow.com/a/6334454 30 | * Returns 0 for equal colors, nonzero for colors that look different. 31 | * The return value is farther from 0 the more different the colors look. 32 | *

33 | * Weighs the distance from grey more heavily, to avoid matching grey and colorful colors together. 34 | */ 35 | public static double slowPerceptualColorDistanceSquared(int[] color1, int[] color2) { 36 | final double colorDistance = fastPerceptualColorDistanceSquared(color1, color2); 37 | 38 | final double grey1 = (color1[0] + color1[1] + color1[2]) / 3; 39 | final double grey2 = (color2[0] + color2[1] + color2[2]) / 3; 40 | final double greyDistance1 = Math.abs(grey1 - color1[0]) + Math.abs(grey1 - color1[1]) + Math.abs(grey1 - color1[2]); 41 | final double greyDistance2 = Math.abs(grey2 - color2[0]) + Math.abs(grey2 - color2[1]) + Math.abs(grey2 - color2[2]); 42 | final double greyDistance = greyDistance1 - greyDistance2; 43 | 44 | return colorDistance + (greyDistance * greyDistance / 10.0); 45 | } 46 | 47 | public static double slowPerceptualColorDistanceSquared(Color color1, Color color2) { 48 | final int[] colorInts1 = {color1.getRed(), color1.getGreen(), color1.getBlue()}; 49 | final int[] colorInts2 = {color2.getRed(), color2.getGreen(), color2.getBlue()}; 50 | return slowPerceptualColorDistanceSquared(colorInts1, colorInts2); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/ItemSortContainer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | 5 | import net.minecraft.item.ItemStack; 6 | 7 | import java.util.Objects; 8 | 9 | public class ItemSortContainer { 10 | 11 | private final ItemStack itemStack; 12 | private final ClientSortData sortData; 13 | 14 | public ItemSortContainer(ItemStack itemStack, ClientSortData sortData) { 15 | this.itemStack = itemStack.copy(); 16 | this.sortData = sortData; 17 | } 18 | 19 | public ItemStack getItemStack() { 20 | return itemStack; 21 | } 22 | 23 | public ClientSortData getSortData() { 24 | return sortData; 25 | } 26 | 27 | public int getColorHue() { 28 | return sortData.getColor(); 29 | } 30 | 31 | public String getName() { 32 | return sortData.getName(); 33 | } 34 | 35 | public void shrink(int amount) { 36 | this.itemStack.shrink(amount); 37 | } 38 | 39 | public void grow(int amount) { 40 | this.itemStack.grow(amount); 41 | } 42 | 43 | public int getAmount() { 44 | return this.itemStack.getCount(); 45 | } 46 | 47 | public boolean canMakeStack() { 48 | return getAmount() > 0; 49 | } 50 | 51 | public ItemStack makeStack(int max) { 52 | return this.itemStack.splitStack(max); 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | ItemStack o = itemStack; 58 | return Objects.hash(o.getItem(), o.getMetadata(), o.getTagCompound(), BogoSortAPI.getItemAccessor(o).getCapNBT()); 59 | } 60 | 61 | @Override 62 | public boolean equals(Object b1) { 63 | ItemStack a = itemStack; 64 | if (a == b1) return true; 65 | if (a == null || b1 == null) return false; 66 | ItemStack b; 67 | if (b1 instanceof ItemStack) { 68 | b = (ItemStack) b1; 69 | } else if (b1 instanceof ItemSortContainer) { 70 | b = ((ItemSortContainer) b1).itemStack; 71 | } else { 72 | return false; 73 | } 74 | return (a.isEmpty() && b.isEmpty()) || 75 | (a.getItem() == b.getItem() && 76 | a.getMetadata() == b.getMetadata() && 77 | Objects.equals(a.getTagCompound(), b.getTagCompound()) && 78 | Objects.equals(BogoSortAPI.getItemAccessor(a).getCapNBT(), BogoSortAPI.getItemAccessor(b).getCapNBT())); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/compat/SlotDelegate.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.compat; 2 | 3 | import com.cleanroommc.bogosorter.api.ISlot; 4 | 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.inventory.IInventory; 7 | import net.minecraft.inventory.Slot; 8 | import net.minecraft.item.ItemStack; 9 | 10 | public class SlotDelegate implements ISlot { 11 | 12 | private final Slot slot; 13 | 14 | public SlotDelegate(Slot slot) { 15 | this.slot = slot; 16 | } 17 | 18 | @Override 19 | public Slot bogo$getRealSlot() { 20 | return slot; 21 | } 22 | 23 | @Override 24 | public int bogo$getX() { 25 | return slot.xPos; 26 | } 27 | 28 | @Override 29 | public int bogo$getY() { 30 | return slot.yPos; 31 | } 32 | 33 | @Override 34 | public int bogo$getSlotNumber() { 35 | return slot.slotNumber; 36 | } 37 | 38 | @Override 39 | public int bogo$getSlotIndex() { 40 | return slot.getSlotIndex(); 41 | } 42 | 43 | @Override 44 | public IInventory bogo$getInventory() { 45 | return slot.inventory; 46 | } 47 | 48 | @Override 49 | public void bogo$putStack(ItemStack itemStack) { 50 | slot.putStack(itemStack); 51 | } 52 | 53 | @Override 54 | public ItemStack bogo$getStack() { 55 | return slot.getStack(); 56 | } 57 | 58 | @Override 59 | public int bogo$getMaxStackSize(ItemStack itemStack) { 60 | return itemStack.getMaxStackSize(); 61 | } 62 | 63 | @Override 64 | public int bogo$getItemStackLimit(ItemStack itemStack) { 65 | return slot.getItemStackLimit(itemStack); 66 | } 67 | 68 | @Override 69 | public boolean bogo$isEnabled() { 70 | return slot.isEnabled(); 71 | } 72 | 73 | @Override 74 | public boolean bogo$isItemValid(ItemStack stack) { 75 | return slot.isItemValid(stack); 76 | } 77 | 78 | @Override 79 | public boolean bogo$canTakeStack(EntityPlayer player) { 80 | return slot.canTakeStack(player); 81 | } 82 | 83 | @Override 84 | public void bogo$onSlotChanged() { 85 | slot.onSlotChanged(); 86 | } 87 | 88 | @Override 89 | public void bogo$onSlotChanged(ItemStack oldItem, ItemStack newItem) { 90 | slot.onSlotChange(newItem, oldItem); 91 | } 92 | 93 | @Override 94 | public ItemStack bogo$onTake(EntityPlayer player, ItemStack itemStack) { 95 | return slot.onTake(player, itemStack); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/NbtSortRule.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.api.SortRule; 4 | 5 | import net.minecraft.nbt.NBTBase; 6 | 7 | import java.util.Comparator; 8 | import java.util.function.Function; 9 | 10 | public class NbtSortRule extends SortRule { 11 | 12 | private final String tagPath; 13 | 14 | public NbtSortRule(String key, String tagPath, Comparator comparator) { 15 | super(key, createComparator(tagPath, comparator)); 16 | this.tagPath = tagPath; 17 | } 18 | 19 | public NbtSortRule(String key, String tagPath, int expectedType) { 20 | this(key, tagPath, createComparator(expectedType, ItemCompareHelper::compareNbtBase, nbtBase -> nbtBase)); 21 | } 22 | 23 | public NbtSortRule(String key, String tagPath, int expectedType, Comparator comparator, Function converter) { 24 | this(key, tagPath, createComparator(expectedType, comparator, converter)); 25 | } 26 | 27 | private static Comparator createComparator(String path, Comparator comparator) { 28 | return (o1, o2) -> { 29 | if (o1 == null || o2 == null) return 0; 30 | NBTBase nbt1 = ItemCompareHelper.findSubTag(path, o1); 31 | NBTBase nbt2 = ItemCompareHelper.findSubTag(path, o2); 32 | return comparator.compare(nbt1, nbt2); 33 | }; 34 | } 35 | 36 | private static Comparator createComparator(int expectedType, Comparator comparator, Function converter) { 37 | return (o1, o2) -> { 38 | if (o1 == o2) return 0; 39 | if (o1 == null) return -1; 40 | if (o2 == null) return 1; 41 | if (o1.getId() != expectedType && o2.getId() != expectedType) return 0; 42 | if (o1.getId() != expectedType) return -1; 43 | if (o2.getId() != expectedType) return 1; 44 | T t1 = converter.apply(o1); 45 | T t2 = converter.apply(o2); 46 | if (t1 == t2) return 0; 47 | if (t1 == null) return -1; 48 | if (t2 == null) return 1; 49 | return comparator.compare(t1, t2); 50 | }; 51 | } 52 | 53 | @Override 54 | public String getNameLangKey() { 55 | return "bogosort.sortrules.nbt." + getKey() + ".name"; 56 | } 57 | 58 | @Override 59 | public String getDescriptionLangKey() { 60 | return "bogosort.sortrules.nbt." + getKey() + ".description"; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/SlotGroup.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.api.IPosSetter; 4 | import com.cleanroommc.bogosorter.api.ISlot; 5 | import com.cleanroommc.bogosorter.api.ISlotGroup; 6 | 7 | import org.jetbrains.annotations.Nullable; 8 | import org.jetbrains.annotations.UnmodifiableView; 9 | 10 | import java.util.Collections; 11 | import java.util.List; 12 | 13 | public class SlotGroup implements ISlotGroup { 14 | 15 | public static final SlotGroup EMPTY = new SlotGroup(Collections.emptyList(), 0); 16 | 17 | private final boolean player; 18 | private final boolean hotbar; 19 | private final List slots; 20 | private final int rowSize; 21 | private int priority; 22 | private IPosSetter posSetter; 23 | 24 | public SlotGroup(List slots, int rowSize) { 25 | this(false, false, slots, rowSize); 26 | } 27 | 28 | public SlotGroup(boolean player, boolean hotbar, List slots, int rowSize) { 29 | this.player = player; 30 | this.hotbar = player && hotbar; 31 | this.slots = Collections.unmodifiableList(slots); 32 | this.rowSize = rowSize; 33 | this.priority = 0; 34 | this.posSetter = IPosSetter.TOP_RIGHT_HORIZONTAL; 35 | } 36 | 37 | @Override 38 | public @UnmodifiableView List getSlots() { 39 | return this.slots; 40 | } 41 | 42 | @Override 43 | public int getRowSize() { 44 | return this.rowSize; 45 | } 46 | 47 | @Override 48 | public int getPriority() { 49 | return this.priority; 50 | } 51 | 52 | @Override 53 | public boolean isPlayerInventory() { 54 | return this.player; 55 | } 56 | 57 | public boolean isHotbar() { 58 | return this.hotbar; 59 | } 60 | 61 | @Nullable 62 | public IPosSetter getPosSetter() { 63 | return posSetter; 64 | } 65 | 66 | @Override 67 | public ISlotGroup priority(int priority) { 68 | this.priority = priority; 69 | return this; 70 | } 71 | 72 | @Override 73 | public ISlotGroup buttonPosSetter(@Nullable IPosSetter posSetter) { 74 | this.posSetter = posSetter; 75 | return this; 76 | } 77 | 78 | public boolean hasSlot(int slotNumber) { 79 | for (ISlot slot : getSlots()) { 80 | if (slot.bogo$getSlotNumber() == slotNumber) return true; 81 | } 82 | return false; 83 | } 84 | 85 | public boolean isEmpty() { 86 | return getSlots().isEmpty(); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/MixinEntityLivingBase.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | import com.cleanroommc.bogosorter.common.config.PlayerConfig; 5 | import com.cleanroommc.bogosorter.common.refill.RefillHandler; 6 | 7 | import net.minecraft.entity.EntityLivingBase; 8 | import net.minecraft.entity.player.EntityPlayer; 9 | import net.minecraft.item.ItemStack; 10 | 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture; 16 | 17 | @Mixin(EntityLivingBase.class) 18 | public abstract class MixinEntityLivingBase { 19 | 20 | /** 21 | * activeItemStackCopy = what was used 22 | * itemstack = the item's onItemUseFinish return item (usually empty, but can return a bowl, bottle, etc) 23 | */ 24 | @Inject(method = "onItemUseFinish", 25 | at = @At( 26 | value = "INVOKE", 27 | target = "Lnet/minecraft/entity/EntityLivingBase;setHeldItem(Lnet/minecraft/util/EnumHand;Lnet/minecraft/item/ItemStack;)V", 28 | shift = At.Shift.AFTER 29 | ), 30 | locals = LocalCapture.CAPTURE_FAILHARD 31 | ) 32 | private void onItemUseFinish(CallbackInfo ci, ItemStack activeItemStackCopy, ItemStack itemstack) { 33 | if (!(bogosorter$getThis() instanceof EntityPlayer player)) return; 34 | if (!PlayerConfig.get(player).enableAutoRefill) return; 35 | // used in cases where a modded item returns itself with a different durability (AA coffee, Botania Vials, etc) 36 | if (ItemStack.areItemsEqualIgnoreDurability(activeItemStackCopy, itemstack)) { 37 | return; 38 | } 39 | 40 | if (RefillHandler.shouldHandleRefill(player, activeItemStackCopy, true)) { 41 | boolean didSwap = RefillHandler.handle(player.inventory.currentItem, activeItemStackCopy, player, false);//new RefillHandler(player.inventory.currentItem, activeItemStackCopy, player).handleRefill(); 42 | if (didSwap && !itemstack.isEmpty()) { 43 | if (!player.inventory.addItemStackToInventory(itemstack)) { 44 | BogoSorter.LOGGER.info("Dropping item that does not fit"); 45 | player.dropItem(itemstack, true, false); 46 | } 47 | } 48 | } 49 | } 50 | 51 | private EntityLivingBase bogosorter$getThis() { 52 | return (EntityLivingBase) (Object) this; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/ISortingContextBuilder.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import net.minecraft.inventory.Container; 4 | import net.minecraft.inventory.Slot; 5 | 6 | import org.jetbrains.annotations.ApiStatus; 7 | 8 | import java.util.List; 9 | 10 | /** 11 | * A helper interface to create {@link ISlotGroup} instances. 12 | * Meant to be used in {@link ISortableContainer#buildSortingContext(ISortingContextBuilder)} 13 | */ 14 | @ApiStatus.NonExtendable 15 | public interface ISortingContextBuilder { 16 | 17 | /** 18 | * Creates and registers a slot group with a list of slots. 19 | * 20 | * @param slots slot list 21 | * @param rowSize This is mostly used to determine the button position with {@link IPosSetter#TOP_RIGHT_VERTICAL} 22 | * and {@link IPosSetter#TOP_RIGHT_HORIZONTAL}. If the slot group shape is not rectangular, 23 | * try to use the row size of the first row. 24 | * @return the created slot group 25 | */ 26 | ISlotGroup addSlotGroupOf(List slots, int rowSize); 27 | 28 | /** 29 | * Creates and registers a slot group with a list of slots. 30 | * 31 | * @param slots slot list 32 | * @param rowSize This is mostly used to determine the button position with {@link IPosSetter#TOP_RIGHT_VERTICAL} 33 | * and {@link IPosSetter#TOP_RIGHT_HORIZONTAL}. If the slot group shape is not rectangular, 34 | * try to use the row size of the first row. 35 | * @return the created slot group 36 | */ 37 | ISlotGroup addSlotGroup(List slots, int rowSize); 38 | 39 | /** 40 | * Creates and registers a slot group based on a start and end index. 41 | * 42 | * @param startIndex index of the first slot (including) 43 | * @param endIndex index of the end slot (excluding) 44 | * @param rowSize This is mostly used to determine the button position with {@link IPosSetter#TOP_RIGHT_VERTICAL} 45 | * and {@link IPosSetter#TOP_RIGHT_HORIZONTAL}. If the slot group shape is not rectangular, 46 | * try to use the row size of the first row. 47 | * @return the created slot group 48 | */ 49 | ISlotGroup addSlotGroup(int startIndex, int endIndex, int rowSize); 50 | 51 | /** 52 | * Creates and registers a generic slot group. It assumes that all non player slots belong to the same group and 53 | * that the slot group has a rectangular shape. 54 | * 55 | * @return the created slot group or a dummy if not enough slots where found. 56 | */ 57 | ISlotGroup addGenericSlotGroup(); 58 | 59 | Container getContainer(); 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/CShortcut.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | import com.cleanroommc.bogosorter.ShortcutHandler; 5 | import com.cleanroommc.bogosorter.api.ISlot; 6 | 7 | import net.minecraft.inventory.Container; 8 | import net.minecraft.network.NetHandlerPlayServer; 9 | import net.minecraft.network.PacketBuffer; 10 | 11 | import java.io.IOException; 12 | 13 | public class CShortcut implements IPacket { 14 | 15 | private Type type; 16 | private int slotNumber; 17 | 18 | public CShortcut(Type type, int slotNumber) { 19 | this.type = type; 20 | this.slotNumber = slotNumber; 21 | } 22 | 23 | public CShortcut() { 24 | } 25 | 26 | @Override 27 | public void encode(PacketBuffer buf) throws IOException { 28 | buf.writeEnumValue(type); 29 | buf.writeVarInt(slotNumber); 30 | } 31 | 32 | @Override 33 | public void decode(PacketBuffer buf) throws IOException { 34 | type = buf.readEnumValue(Type.class); 35 | slotNumber = buf.readVarInt(); 36 | } 37 | 38 | @Override 39 | public IPacket executeServer(NetHandlerPlayServer handler) { 40 | Container container = handler.player.openContainer; 41 | if (container == null) throw new IllegalStateException("Expected open container on server"); 42 | ISlot slot = BogoSortAPI.getSlot(container, slotNumber);//container.getSlot(slotNumber); 43 | if (!slot.bogo$canTakeStack(handler.player)) { 44 | return null; 45 | } 46 | switch (type) { 47 | case MOVE_ALL: 48 | ShortcutHandler.moveAllItems(handler.player, container, slot, false); 49 | break; 50 | case MOVE_ALL_SAME: 51 | ShortcutHandler.moveAllItems(handler.player, container, slot, true); 52 | break; 53 | case MOVE_SINGLE: 54 | ShortcutHandler.moveSingleItem(handler.player, container, slot, false); 55 | break; 56 | case MOVE_SINGLE_EMPTY: 57 | ShortcutHandler.moveSingleItem(handler.player, container, slot, true); 58 | break; 59 | case DROP_ALL: 60 | ShortcutHandler.dropItems(handler.player, container, slot, false); 61 | break; 62 | case DROP_ALL_SAME: 63 | ShortcutHandler.dropItems(handler.player, container, slot, true); 64 | break; 65 | } 66 | container.detectAndSendChanges(); 67 | return null; 68 | } 69 | 70 | public enum Type { 71 | MOVE_ALL, MOVE_ALL_SAME, MOVE_SINGLE, MOVE_SINGLE_EMPTY, DROP_ALL, DROP_ALL_SAME 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/SlotMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin; 2 | 3 | import com.cleanroommc.bogosorter.api.ISlot; 4 | 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.inventory.IInventory; 7 | import net.minecraft.inventory.Slot; 8 | import net.minecraft.item.ItemStack; 9 | 10 | import org.spongepowered.asm.mixin.Final; 11 | import org.spongepowered.asm.mixin.Mixin; 12 | import org.spongepowered.asm.mixin.Shadow; 13 | 14 | @Mixin(Slot.class) 15 | public class SlotMixin implements ISlot { 16 | 17 | @Shadow 18 | public int xPos; 19 | 20 | @Shadow 21 | public int yPos; 22 | 23 | @Shadow 24 | public int slotNumber; 25 | 26 | @Shadow 27 | @Final 28 | public IInventory inventory; 29 | 30 | @Override 31 | public Slot bogo$getRealSlot() { 32 | return (Slot) (Object) this; 33 | } 34 | 35 | @Override 36 | public int bogo$getX() { 37 | return xPos; 38 | } 39 | 40 | @Override 41 | public int bogo$getY() { 42 | return yPos; 43 | } 44 | 45 | @Override 46 | public int bogo$getSlotNumber() { 47 | return slotNumber; 48 | } 49 | 50 | @Override 51 | public int bogo$getSlotIndex() { 52 | return bogo$this().getSlotIndex(); 53 | } 54 | 55 | @Override 56 | public IInventory bogo$getInventory() { 57 | return inventory; 58 | } 59 | 60 | @Override 61 | public void bogo$putStack(ItemStack itemStack) { 62 | bogo$this().putStack(itemStack); 63 | } 64 | 65 | @Override 66 | public ItemStack bogo$getStack() { 67 | return bogo$this().getStack(); 68 | } 69 | 70 | @Override 71 | public int bogo$getMaxStackSize(ItemStack itemStack) { 72 | return itemStack.getMaxStackSize(); 73 | } 74 | 75 | @Override 76 | public int bogo$getItemStackLimit(ItemStack itemStack) { 77 | return bogo$this().getItemStackLimit(itemStack); 78 | } 79 | 80 | @Override 81 | public boolean bogo$isEnabled() { 82 | return bogo$this().isEnabled(); 83 | } 84 | 85 | @Override 86 | public boolean bogo$isItemValid(ItemStack stack) { 87 | return bogo$this().isItemValid(stack); 88 | } 89 | 90 | @Override 91 | public boolean bogo$canTakeStack(EntityPlayer player) { 92 | return bogo$this().canTakeStack(player); 93 | } 94 | 95 | @Override 96 | public void bogo$onSlotChanged() { 97 | bogo$this().onSlotChanged(); 98 | } 99 | 100 | @Override 101 | public void bogo$onSlotChanged(ItemStack oldItem, ItemStack newItem) { 102 | bogo$this().onSlotChange(newItem, oldItem); 103 | } 104 | 105 | @Override 106 | public ItemStack bogo$onTake(EntityPlayer player, ItemStack itemStack) { 107 | return bogo$this().onTake(player, itemStack); 108 | } 109 | 110 | public Slot bogo$this() { 111 | return (Slot) (Object) this; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/NetworkUtils.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | 5 | import net.minecraft.client.entity.EntityPlayerSP; 6 | import net.minecraft.entity.player.EntityPlayer; 7 | import net.minecraft.nbt.NBTTagCompound; 8 | import net.minecraft.network.PacketBuffer; 9 | import net.minecraftforge.fluids.FluidStack; 10 | import net.minecraftforge.fml.common.FMLCommonHandler; 11 | 12 | import io.netty.buffer.ByteBuf; 13 | import io.netty.buffer.Unpooled; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | import java.io.IOException; 17 | import java.nio.charset.StandardCharsets; 18 | import java.util.function.Consumer; 19 | 20 | public class NetworkUtils { 21 | 22 | public static final Consumer EMPTY_PACKET = buffer -> { 23 | }; 24 | 25 | public static boolean isDedicatedClient() { 26 | return FMLCommonHandler.instance().getSide().isClient(); 27 | } 28 | 29 | public static boolean isClient(EntityPlayer player) { 30 | if (player == null) throw new NullPointerException("Can't get side of null player!"); 31 | return player.world == null ? player instanceof EntityPlayerSP : player.world.isRemote; 32 | } 33 | 34 | public static void writePacketBuffer(PacketBuffer writeTo, PacketBuffer writeFrom) { 35 | writeTo.writeVarInt(writeFrom.readableBytes()); 36 | writeTo.writeBytes(writeFrom); 37 | } 38 | 39 | public static PacketBuffer readPacketBuffer(PacketBuffer buf) { 40 | ByteBuf directSliceBuffer = buf.readBytes(buf.readVarInt()); 41 | ByteBuf copiedDataBuffer = Unpooled.copiedBuffer(directSliceBuffer); 42 | directSliceBuffer.release(); 43 | return new PacketBuffer(copiedDataBuffer); 44 | } 45 | 46 | public static void writeFluidStack(PacketBuffer buffer, @Nullable FluidStack fluidStack) { 47 | if (fluidStack == null) { 48 | buffer.writeBoolean(true); 49 | } else { 50 | buffer.writeBoolean(false); 51 | NBTTagCompound fluidStackTag = fluidStack.writeToNBT(new NBTTagCompound()); 52 | buffer.writeCompoundTag(fluidStackTag); 53 | } 54 | } 55 | 56 | @Nullable 57 | public static FluidStack readFluidStack(PacketBuffer buffer) throws IOException { 58 | if (buffer.readBoolean()) { 59 | return null; 60 | } 61 | return FluidStack.loadFluidStackFromNBT(buffer.readCompoundTag()); 62 | } 63 | 64 | public static void writeStringSafe(PacketBuffer buffer, String string) { 65 | byte[] bytesTest = string.getBytes(StandardCharsets.UTF_8); 66 | byte[] bytes; 67 | 68 | if (bytesTest.length > 32767) { 69 | bytes = new byte[32767]; 70 | System.arraycopy(bytesTest, 0, bytes, 0, 32767); 71 | BogoSorter.LOGGER.warn("Warning! Synced string exceeds max length!"); 72 | } else { 73 | bytes = bytesTest; 74 | } 75 | buffer.writeVarInt(bytes.length); 76 | buffer.writeBytes(bytes); 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/NetworkHandler.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | 5 | import net.minecraft.client.network.NetHandlerPlayClient; 6 | import net.minecraft.entity.player.EntityPlayerMP; 7 | import net.minecraft.network.NetHandlerPlayServer; 8 | import net.minecraft.util.IThreadListener; 9 | import net.minecraft.world.World; 10 | import net.minecraftforge.fml.common.FMLCommonHandler; 11 | import net.minecraftforge.fml.common.network.NetworkRegistry; 12 | import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; 13 | import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; 14 | import net.minecraftforge.fml.relauncher.Side; 15 | 16 | /** 17 | * Joinked from Multiblocked 18 | */ 19 | public class NetworkHandler { 20 | 21 | public static final SimpleNetworkWrapper network = NetworkRegistry.INSTANCE.newSimpleChannel(BogoSorter.ID); 22 | private static int packetId = 0; 23 | 24 | public static void init() { 25 | registerC2S(CSlotSync.class); 26 | registerC2S(CShortcut.class); 27 | registerC2S(CConfigSync.class); 28 | registerC2S(CSort.class); 29 | registerC2S(CHotbarSwap.class); 30 | registerS2C(SReloadConfig.class); 31 | registerS2C(SRefillSound.class); 32 | } 33 | 34 | private static void registerC2S(Class clazz) { 35 | network.registerMessage(C2SHandler, clazz, packetId++, Side.SERVER); 36 | } 37 | 38 | private static void registerS2C(Class clazz) { 39 | network.registerMessage(S2CHandler, clazz, packetId++, Side.CLIENT); 40 | } 41 | 42 | public static void sendToServer(IPacket packet) { 43 | network.sendToServer(packet); 44 | } 45 | 46 | public static void sendToWorld(IPacket packet, World world) { 47 | network.sendToDimension(packet, world.provider.getDimension()); 48 | } 49 | 50 | public static void sendToPlayer(IPacket packet, EntityPlayerMP player) { 51 | network.sendTo(packet, player); 52 | } 53 | 54 | final static IMessageHandler S2CHandler = (message, ctx) -> { 55 | NetHandlerPlayClient handler = ctx.getClientHandler(); 56 | IThreadListener threadListener = FMLCommonHandler.instance().getWorldThread(handler); 57 | if (threadListener.isCallingFromMinecraftThread()) { 58 | return message.executeClient(handler); 59 | } else { 60 | threadListener.addScheduledTask(() -> message.executeClient(handler)); 61 | } 62 | return null; 63 | }; 64 | final static IMessageHandler C2SHandler = (message, ctx) -> { 65 | NetHandlerPlayServer handler = ctx.getServerHandler(); 66 | IThreadListener threadListener = FMLCommonHandler.instance().getWorldThread(handler); 67 | if (threadListener.isCallingFromMinecraftThread()) { 68 | return message.executeServer(handler); 69 | } else { 70 | threadListener.addScheduledTask(() -> message.executeServer(handler)); 71 | } 72 | return null; 73 | }; 74 | } 75 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/ButtonPos.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.api.IButtonPos; 4 | 5 | import java.util.Objects; 6 | 7 | public class ButtonPos implements IButtonPos { 8 | 9 | private boolean enabled = true; 10 | private int x = 0, y = 0; 11 | private Alignment alignment = Alignment.BOTTOM_RIGHT; 12 | private Layout layout = Layout.HORIZONTAL; 13 | 14 | public void reset() { 15 | this.enabled = true; 16 | this.x = 0; 17 | this.y = 0; 18 | this.alignment = Alignment.BOTTOM_RIGHT; 19 | this.layout = Layout.HORIZONTAL; 20 | } 21 | 22 | @Override 23 | public void setEnabled(boolean enabled) { 24 | this.enabled = enabled; 25 | } 26 | 27 | @Override 28 | public void setPos(int x, int y) { 29 | this.x = x; 30 | this.y = y; 31 | } 32 | 33 | @Override 34 | public void setAlignment(Alignment alignment) { 35 | this.alignment = Objects.requireNonNull(alignment); 36 | } 37 | 38 | @Override 39 | public void setLayout(Layout layout) { 40 | this.layout = Objects.requireNonNull(layout); 41 | } 42 | 43 | @Override 44 | public boolean isEnabled() { 45 | return this.enabled; 46 | } 47 | 48 | @Override 49 | public int getX() { 50 | return this.x; 51 | } 52 | 53 | @Override 54 | public int getY() { 55 | return this.y; 56 | } 57 | 58 | @Override 59 | public Alignment getAlignment() { 60 | return this.alignment; 61 | } 62 | 63 | @Override 64 | public Layout getLayout() { 65 | return this.layout; 66 | } 67 | 68 | public void applyPos(int guiLeft, int guiTop, ButtonHandler.SortButton sortButton, ButtonHandler.SortButton settingsButton) { 69 | int s = ButtonHandler.BUTTON_SIZE; 70 | boolean h = this.layout == Layout.HORIZONTAL; 71 | switch (this.alignment) { 72 | case TOP_LEFT: { 73 | sortButton.x = this.x; 74 | sortButton.y = this.y; 75 | break; 76 | } 77 | case TOP_RIGHT: { 78 | sortButton.x = h ? this.x - s - s : this.x - s; 79 | sortButton.y = this.y; 80 | break; 81 | } 82 | case BOTTOM_LEFT: { 83 | sortButton.x = this.x; 84 | sortButton.y = h ? this.y - s : this.y - s - s; 85 | break; 86 | } 87 | case BOTTOM_RIGHT: { 88 | sortButton.x = h ? this.x - s - s : this.x - s; 89 | sortButton.y = h ? this.y - s : this.y - s - s; 90 | break; 91 | } 92 | } 93 | sortButton.x += guiLeft; 94 | sortButton.y += guiTop; 95 | if (h) { 96 | settingsButton.x = sortButton.x + s; 97 | settingsButton.y = sortButton.y; 98 | } else { 99 | settingsButton.x = sortButton.x; 100 | settingsButton.y = sortButton.y + s; 101 | } 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/sort/DefaultRules.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.sort; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | import com.cleanroommc.bogosorter.BogoSorter; 5 | 6 | import net.minecraft.nbt.NBTBase; 7 | import net.minecraft.nbt.NBTTagList; 8 | import net.minecraft.nbt.NBTTagString; 9 | import net.minecraftforge.common.util.Constants; 10 | import net.minecraftforge.fml.common.Loader; 11 | 12 | public class DefaultRules { 13 | 14 | public static void init(BogoSortAPI api) { 15 | api.registerItemSortingRule("mod", ItemCompareHelper::compareMod); 16 | api.registerItemSortingRule("id", ItemCompareHelper::compareId); 17 | api.registerItemSortingRule("meta", ItemCompareHelper::compareMeta); 18 | api.registerItemSortingRule("registry_order", ItemCompareHelper::compareRegistryOrder); 19 | api.registerClientItemSortingRule("display_name", ItemCompareHelper::compareDisplayName, ItemCompareHelper::compareDisplayName); 20 | api.registerItemSortingRule("nbt_size", ItemCompareHelper::compareNbtSize); 21 | api.registerItemSortingRule("nbt_has", ItemCompareHelper::compareHasNbt); 22 | api.registerItemSortingRule("nbt_rules", ItemCompareHelper::compareNbtValues); 23 | api.registerItemSortingRule("nbt_all_values", ItemCompareHelper::compareNbtAllValues); 24 | api.registerItemSortingRule("count", ItemCompareHelper::compareCount); 25 | api.registerItemSortingRule("ore_dict", ItemCompareHelper::compareOreDict); 26 | api.registerItemSortingRule("material", ItemCompareHelper::compareMaterial); 27 | api.registerItemSortingRule("ore_prefix", ItemCompareHelper::compareOrePrefix); 28 | api.registerItemSortingRule("burn_time", ItemCompareHelper::compareBurnTime); 29 | api.registerItemSortingRule("block_type", ItemCompareHelper::compareBlockType); 30 | api.registerItemSortingRule("hunger", ItemCompareHelper::compareHunger); 31 | api.registerItemSortingRule("saturation", ItemCompareHelper::compareSaturation); 32 | api.registerClientItemSortingRule("color", ItemCompareHelper::compareColor, ItemCompareHelper::compareColor); 33 | 34 | if (Loader.isModLoaded("projecte")) { 35 | api.registerItemSortingRule("emc", ItemCompareHelper::compareEMC); 36 | } 37 | 38 | api.registerNbtSortingRule("potion", "Potion", Constants.NBT.TAG_STRING, ItemCompareHelper::comparePotionId, DefaultRules::getPotionId); 39 | api.registerNbtSortingRule("enchantment", "ench", Constants.NBT.TAG_LIST, ItemCompareHelper::compareEnchantments, nbtBase -> (NBTTagList) nbtBase); 40 | api.registerNbtSortingRule("enchantment_book", "StoredEnchantments", Constants.NBT.TAG_LIST, ItemCompareHelper::compareEnchantments, nbtBase -> (NBTTagList) nbtBase); 41 | if (BogoSorter.isAnyGtLoaded()) { 42 | api.registerNbtSortingRule("gt_circ_config", "Configuration", Constants.NBT.TAG_INT); 43 | api.registerNbtSortingRule("gt_item_damage", "GT.ToolStats/Dmg", Constants.NBT.TAG_INT); 44 | } 45 | } 46 | 47 | private static String getPotionId(NBTBase nbt) { 48 | String[] potion = ((NBTTagString) nbt).getString().split(":"); 49 | return potion[potion.length - 1]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/avaritiaddons/ContainerInfinityChestMixin.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.avaritiaddons; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | import com.cleanroommc.bogosorter.api.ISlot; 5 | import com.cleanroommc.bogosorter.common.sort.GuiSortingContext; 6 | import com.cleanroommc.bogosorter.common.sort.SlotGroup; 7 | import com.cleanroommc.bogosorter.compat.InfinitySlotWrapper; 8 | 9 | import net.minecraft.entity.player.EntityPlayer; 10 | import net.minecraft.inventory.ClickType; 11 | import net.minecraft.inventory.Container; 12 | import net.minecraft.item.ItemStack; 13 | 14 | import org.jetbrains.annotations.NotNull; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.Shadow; 17 | import org.spongepowered.asm.mixin.injection.At; 18 | import org.spongepowered.asm.mixin.injection.Inject; 19 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 20 | import wanion.avaritiaddons.block.chest.infinity.ContainerInfinityChest; 21 | 22 | import javax.annotation.Nonnull; 23 | 24 | @Mixin(ContainerInfinityChest.class) 25 | public abstract class ContainerInfinityChestMixin { 26 | 27 | @Shadow 28 | @Nonnull 29 | public abstract ItemStack transferStackInSlot(@NotNull EntityPlayer entityPlayer, int slot); 30 | 31 | @Inject(method = "slotClick", at = @At("HEAD"), cancellable = true) 32 | public void onSlotClick(int slotId, int dragType, ClickType clickTypeIn, EntityPlayer player, CallbackInfoReturnable cir) { 33 | if (slotId < 0) return; 34 | Container container = (Container) (Object) this; 35 | ISlot slot = BogoSortAPI.getSlot(container, slotId); 36 | if (slot instanceof InfinitySlotWrapper && clickTypeIn == ClickType.QUICK_MOVE) { 37 | transferStackInSlot(player, slotId); 38 | cir.setReturnValue(ItemStack.EMPTY); 39 | } 40 | } 41 | 42 | @Inject(method = "transferStackInSlot", at = @At("HEAD"), cancellable = true) 43 | public void transferItem(EntityPlayer entityPlayer, int slotNumber, CallbackInfoReturnable cir) { 44 | Container container = (Container) (Object) this; 45 | ISlot slot = BogoSortAPI.getSlot(container, slotNumber); 46 | 47 | if (slot.bogo$getStack().isEmpty()) { 48 | cir.setReturnValue(ItemStack.EMPTY); 49 | return; 50 | } 51 | ItemStack stack = slot.bogo$getStack(); 52 | ItemStack toInsert = stack.copy(); 53 | int amount = Math.min(stack.getCount(), stack.getMaxStackSize()); 54 | toInsert.setCount(amount); 55 | GuiSortingContext sortingContext = GuiSortingContext.getOrCreate(container); 56 | 57 | SlotGroup slots = sortingContext.getSlotGroup(slot.bogo$getSlotNumber()); 58 | SlotGroup otherSlots = BogoSortAPI.isPlayerSlot(slot) ? sortingContext.getNonPlayerSlotGroup() : sortingContext.getPlayerSlotGroup(); 59 | if (otherSlots == null || slots == otherSlots) { 60 | cir.setReturnValue(ItemStack.EMPTY); 61 | return; 62 | } 63 | 64 | toInsert = BogoSortAPI.insert(container, otherSlots.getSlots(), toInsert); 65 | stack.shrink(amount - toInsert.getCount()); 66 | slot.bogo$putStack(stack.isEmpty() ? ItemStack.EMPTY : stack); 67 | 68 | cir.setReturnValue(toInsert); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/McUtils.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common; 2 | 3 | import net.minecraft.entity.item.EntityItem; 4 | import net.minecraft.entity.player.EntityPlayer; 5 | import net.minecraft.item.ItemStack; 6 | import net.minecraft.world.World; 7 | import net.minecraftforge.items.IItemHandler; 8 | import net.minecraftforge.items.ItemHandlerHelper; 9 | import net.minecraftforge.items.wrapper.PlayerMainInvWrapper; 10 | 11 | import org.jetbrains.annotations.Nullable; 12 | 13 | import java.util.List; 14 | import javax.annotation.Nonnull; 15 | 16 | public class McUtils { 17 | 18 | public static void dropItem(ItemStack stack, World world, double x, double y, double z) { 19 | dropItem(stack, world, x, y, z, null, false, 10); 20 | } 21 | 22 | public static void dropItem(ItemStack stack, World world, double x, double y, double z, @Nullable String thrower, boolean noDespawn, int pickUpDelay) { 23 | if (!world.isRemote && !stack.isEmpty() && !world.restoringBlockSnapshots) { 24 | double d0 = (double) (world.rand.nextFloat() * 0.5F) + 0.25D; 25 | double d1 = (double) (world.rand.nextFloat() * 0.5F) + 0.25D; 26 | double d2 = (double) (world.rand.nextFloat() * 0.5F) + 0.25D; 27 | EntityItem entityitem = new EntityItem(world, x + d0, y + d1, z + d2, stack); 28 | entityitem.setPickupDelay(pickUpDelay); 29 | entityitem.setThrower(thrower); 30 | if (noDespawn) { 31 | entityitem.setNoDespawn(); 32 | } 33 | world.spawnEntity(entityitem); 34 | } 35 | } 36 | 37 | public static void giveItemsToPlayer(EntityPlayer player, List items) { 38 | if (player == null || items.isEmpty()) return; 39 | if (player.world.isRemote) throw new IllegalStateException("Should only be called from server side!"); 40 | PlayerMainInvWrapper itemHandler = new PlayerMainInvWrapper(player.inventory); 41 | items.removeIf(item -> { 42 | ItemStack remainder = insertToPlayer(itemHandler, item, false); 43 | return remainder.isEmpty(); 44 | }); 45 | for (ItemStack item : items) { 46 | player.dropItem(item, false, false); 47 | } 48 | } 49 | 50 | public static ItemStack insertToPlayer(PlayerMainInvWrapper itemHandler, ItemStack stack, boolean simulate) { 51 | if (itemHandler == null || stack.isEmpty()) 52 | return stack; 53 | 54 | // not stackable -> just insert into a new slot 55 | if (!stack.isStackable()) { 56 | return insertItem(itemHandler, stack, simulate, 9); 57 | } 58 | 59 | int sizeInventory = itemHandler.getSlots(); 60 | 61 | // go through the inventory and try to fill up already existing items 62 | for (int i = 9; i < sizeInventory; i++) { 63 | ItemStack slot = itemHandler.getStackInSlot(i); 64 | if (ItemHandlerHelper.canItemStacksStackRelaxed(slot, stack)) { 65 | stack = itemHandler.insertItem(i, stack, simulate); 66 | 67 | if (stack.isEmpty()) { 68 | break; 69 | } 70 | } 71 | } 72 | 73 | return insertItem(itemHandler, stack, simulate, 9); 74 | } 75 | 76 | public static ItemStack insertItem(IItemHandler dest, @Nonnull ItemStack stack, boolean simulate, int startSlot) { 77 | if (dest == null || stack.isEmpty()) 78 | return stack; 79 | 80 | for (int i = startSlot; i < dest.getSlots(); i++) { 81 | stack = dest.insertItem(i, stack, simulate); 82 | if (stack.isEmpty()) { 83 | return ItemStack.EMPTY; 84 | } 85 | } 86 | 87 | return stack; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/network/CSort.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.network; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | import com.cleanroommc.bogosorter.api.SortRule; 5 | import com.cleanroommc.bogosorter.common.sort.ClientSortData; 6 | import com.cleanroommc.bogosorter.common.sort.NbtSortRule; 7 | import com.cleanroommc.bogosorter.common.sort.SortHandler; 8 | 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.network.NetHandlerPlayServer; 11 | import net.minecraft.network.PacketBuffer; 12 | 13 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; 14 | 15 | import java.io.IOException; 16 | import java.util.ArrayList; 17 | import java.util.Collection; 18 | import java.util.List; 19 | 20 | public class CSort implements IPacket { 21 | 22 | private Collection clientSortDataList; 23 | private List> sortRules; 24 | private List nbtSortRules; 25 | private int hover; 26 | private boolean player; 27 | 28 | public CSort(Collection clientSortDataList, List> sortRules, List nbtSortRules, int hover, boolean player) { 29 | this.clientSortDataList = clientSortDataList; 30 | this.sortRules = sortRules; 31 | this.nbtSortRules = nbtSortRules; 32 | this.hover = hover; 33 | this.player = player; 34 | } 35 | 36 | public CSort() { 37 | } 38 | 39 | @Override 40 | public void encode(PacketBuffer buf) throws IOException { 41 | buf.writeVarInt(hover); 42 | buf.writeBoolean(player); 43 | buf.writeVarInt(clientSortDataList.size()); 44 | for (ClientSortData sortData : clientSortDataList) { 45 | sortData.writeToPacket(buf); 46 | } 47 | buf.writeVarInt(sortRules.size()); 48 | for (SortRule sortRule : sortRules) { 49 | buf.writeVarInt(sortRule.getSyncId()); 50 | buf.writeBoolean(sortRule.isInverted()); 51 | } 52 | buf.writeVarInt(nbtSortRules.size()); 53 | for (NbtSortRule sortRule : nbtSortRules) { 54 | buf.writeVarInt(sortRule.getSyncId()); 55 | buf.writeBoolean(sortRule.isInverted()); 56 | } 57 | } 58 | 59 | @Override 60 | public void decode(PacketBuffer buf) { 61 | hover = buf.readVarInt(); 62 | player = buf.readBoolean(); 63 | clientSortDataList = new ArrayList<>(); 64 | for (int i = 0, n = buf.readVarInt(); i < n; i++) { 65 | clientSortDataList.add(ClientSortData.readFromPacket(buf)); 66 | } 67 | sortRules = new ArrayList<>(); 68 | for (int i = 0, n = buf.readVarInt(); i < n; i++) { 69 | SortRule sortRule = BogoSortAPI.INSTANCE.getItemSortRule(buf.readVarInt()); 70 | sortRule.setInverted(buf.readBoolean()); 71 | sortRules.add(sortRule); 72 | } 73 | nbtSortRules = new ArrayList<>(); 74 | for (int i = 0, n = buf.readVarInt(); i < n; i++) { 75 | NbtSortRule sortRule = BogoSortAPI.INSTANCE.getNbtSortRule(buf.readVarInt()); 76 | sortRule.setInverted(buf.readBoolean()); 77 | nbtSortRules.add(sortRule); 78 | } 79 | } 80 | 81 | @Override 82 | public IPacket executeServer(NetHandlerPlayServer handler) { 83 | SortHandler.cacheItemSortRules.put(handler.player, sortRules); 84 | SortHandler.cacheNbtSortRules.put(handler.player, nbtSortRules); 85 | Int2ObjectOpenHashMap map = new Int2ObjectOpenHashMap<>(); 86 | for (ClientSortData sortData : clientSortDataList) { 87 | for (int i : sortData.getSlotNumbers()) { 88 | map.put(i, sortData); 89 | } 90 | } 91 | SortHandler sortHandler = new SortHandler(handler.player, handler.player.openContainer, map); 92 | sortHandler.sort(hover); 93 | return null; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/lang/zh_cn.lang: -------------------------------------------------------------------------------- 1 | bogosort.key.categories=物品栏Bogo排序整理 2 | bogosort.key.sort_config=打开排序配置 3 | bogosort.key.sort=排序物品栏 4 | 5 | bogosort.key.move_all=移动所有 6 | bogosort.key.move_all_same=移动所有相似项 7 | bogosort.key.move_single=移动单个 8 | bogosort.key.move_single_empty=移动单个至空槽位 9 | bogosort.key.throw_all_same=丢出所有相似项 10 | bogosort.key.throw_all=丢出所有 11 | 12 | bogosort.gui.title=排序配置 13 | bogosort.gui.tab.general.name=常规 14 | bogosort.gui.tab.profiles.name=配置文件 15 | bogosort.gui.tab.item_sort_rules.name=物品排序规则 16 | bogosort.gui.tab.nbt_sort_rules.name=NBT排序规则 17 | bogosort.gui.available_sort_rules=可用的排序规则 18 | bogosort.gui.configured_sort_rules=已配置的排序规则 19 | bogosort.gui.enable_refill=启用快捷栏自动替换 20 | bogosort.gui.refill_comment=检测到夸克。若禁用该选项,夸克的自动替换仍可能在起效。可在夸克的“Management” -> “Automatic Tool Restock”配置中更改。 21 | bogosort.gui.refill_threshold=自动替换耐久阈值 22 | bogosort.gui.ascending=升序 23 | bogosort.gui.descending=降序 24 | bogosort.gui.hotbar_scrolling=启用快捷栏纵列滚动 25 | bogosort.gui.hotbar_scrolling.tooltip=按住ALT键滚动选取物品栏对应列 26 | bogosort.gui.enabled=启用 27 | bogosort.gui.button.enabled=在GUI中启用排序和设置按钮 28 | bogosort.gui.button.color=排序按钮的背景颜色 29 | 30 | bogosort.command.config_relaod.success=重新加载排序配置 31 | 32 | bogosort.sortrules.item.mod.name=模组名称 33 | bogosort.sortrules.item.id.name=注册名称 34 | bogosort.sortrules.item.meta.name=元数据 35 | bogosort.sortrules.item.registry_order.name=注册顺序 36 | bogosort.sortrules.item.display_name.name=显示名称 37 | bogosort.sortrules.item.nbt_size.name=NBT标签大小 38 | bogosort.sortrules.item.nbt_has.name=是否具有NBT标签 39 | bogosort.sortrules.item.nbt_rules.name=NBT规则 40 | bogosort.sortrules.item.nbt_all_values.name=所有NBT值 41 | bogosort.sortrules.item.count.name=堆叠大小 42 | bogosort.sortrules.item.ore_dict.name=矿物词典 43 | bogosort.sortrules.item.material.name=材料 44 | bogosort.sortrules.item.ore_prefix.name=矿词前缀 45 | bogosort.sortrules.item.burn_time.name=燃烧时间 46 | bogosort.sortrules.item.block_type.name=方块类型 47 | bogosort.sortrules.item.hunger.name=饥饿值 48 | bogosort.sortrules.item.saturation.name=饱和度 49 | bogosort.sortrules.item.emc.name=EMC值 50 | bogosort.sortrules.item.color.name=颜色 51 | 52 | bogosort.sortrules.item.mod.description=根据模组名称的字母顺序对物品排序 53 | bogosort.sortrules.item.id.description=根据注册名称的字母顺序对项目排序(不含模组) 54 | bogosort.sortrules.item.meta.description=根据元数据对物品排序 55 | bogosort.sortrules.item.registry_order.description=根据注册顺序对物品排序 56 | bogosort.sortrules.item.display_name.description=根据物品显示名称的字母顺序对物品排序 57 | bogosort.sortrules.item.nbt_size.description=根据元数据NBT标签大小对物品排序 58 | bogosort.sortrules.item.nbt_has.description=根据是否具有NBT标签对物品排序 59 | bogosort.sortrules.item.nbt_rules.description=根据已配置的NBT排序规则对物品排序 60 | bogosort.sortrules.item.nbt_all_values.description=尝试通过比较所有NBT标签和子标签对物品排序 61 | bogosort.sortrules.item.count.description=根据堆叠大小对物品排序 62 | bogosort.sortrules.item.ore_dict.description=根据矿物词典的数量和字母顺序对物品排序 63 | bogosort.sortrules.item.material.description=根据材料名称的字母顺序对物品排序(例如铁、金、铜等) 64 | bogosort.sortrules.item.ore_prefix.description=根据矿词前缀(例如锭,块,板,齿轮等)对物品排序 65 | bogosort.sortrules.item.burn_time.description=根据燃烧时间对物品排序 66 | bogosort.sortrules.item.block_type.description=根据方块类型对物品排序(例如完整方块、台阶、楼梯等) 67 | bogosort.sortrules.item.hunger.description=根据回复的饥饿值对物品排序 68 | bogosort.sortrules.item.saturation.description=根据回复的饱和度对物品排序 69 | bogosort.sortrules.item.emc.description=根据EMC值对物品排序 70 | bogosort.sortrules.item.color.description=根据颜色亮度值对物品排序 71 | 72 | bogosort.sortrules.nbt.potion.name=药水 73 | bogosort.sortrules.nbt.enchantment.name=魔咒 74 | bogosort.sortrules.nbt.enchantment_book.name=附魔书 75 | bogosort.sortrules.nbt.gt_circ_config.name=格雷科技可编程电路 76 | bogosort.sortrules.nbt.gt_item_damage.name=格雷科技工具耐久 77 | 78 | bogosort.sortrules.nbt.potion.description=根据效果和等级对药水排序 79 | bogosort.sortrules.nbt.enchantment.description=根据效果和等级对附魔物品排序 80 | bogosort.sortrules.nbt.enchantment_book.description=根据效果和等级对附魔书排序 81 | bogosort.sortrules.nbt.gt_circ_config.description=根据配置对格雷科技的编程电路排序 82 | bogosort.sortrules.nbt.gt_item_damage.description=根据耐久对格雷科技的工具排序 83 | 84 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/lang/ja_jp.lang: -------------------------------------------------------------------------------- 1 | bogosort.key.categories=Inventory Bogo Sorter 2 | bogosort.key.sort_config=ソート設定を開く 3 | bogosort.key.sort=インベントリをソート 4 | 5 | bogosort.key.move_all=すべて移動 6 | bogosort.key.move_all_same=同じアイテムをすべて移動 7 | bogosort.key.move_single=単体を移動 8 | bogosort.key.move_single_empty=空スロットに単体を移動 9 | bogosort.key.throw_all_same=同じアイテムをすべて捨てる 10 | bogosort.key.throw_all=すべて捨てる 11 | 12 | bogosort.gui.title=ソート設定 13 | bogosort.gui.tab.general.name=一般 14 | bogosort.gui.tab.profiles.name=プロファイル 15 | bogosort.gui.tab.item_sort_rules.name=アイテムソートルール 16 | bogosort.gui.tab.nbt_sort_rules.name=NBTソートルール 17 | bogosort.gui.available_sort_rules=利用可能なソートルール 18 | bogosort.gui.configured_sort_rules=設定済みソートルール 19 | bogosort.gui.enable_refill=ホットバー自動補充を有効化 20 | bogosort.gui.refill_comment=Quarkが導入されています。このオプションを無効にしても、Quark側の機能は有効な場合があります。「管理」→「自動ツール補充」で設定を確認してください。 21 | bogosort.gui.refill_threshold=自動補充の耐久値しきい値 22 | bogosort.gui.ascending=昇順 23 | bogosort.gui.descending=降順 24 | bogosort.gui.hotbar_scrolling=ホットバー列スクロールを有効化 25 | bogosort.gui.hotbar_scrolling.tooltip=ALTを押しながらインベントリ列をスクロール 26 | bogosort.gui.enabled=有効 27 | bogosort.gui.button.enabled=GUIでソート/設定ボタンを有効化 28 | bogosort.gui.button.color=ソートボタンの背景色 29 | 30 | bogosort.command.config_relaod.success=ソート設定を再読み込みしました 31 | 32 | bogosort.sortrules.item.mod.name=Mod名 33 | bogosort.sortrules.item.id.name=レジストリ名 34 | bogosort.sortrules.item.meta.name=メタ値 35 | bogosort.sortrules.item.registry_order.name=レジストリ順 36 | bogosort.sortrules.item.display_name.name=表示名 37 | bogosort.sortrules.item.nbt_size.name=NBTタグサイズ 38 | bogosort.sortrules.item.nbt_has.name=NBTタグの有無 39 | bogosort.sortrules.item.nbt_rules.name=NBTルール 40 | bogosort.sortrules.item.nbt_all_values.name=すべてのNBT値 41 | bogosort.sortrules.item.count.name=スタック数 42 | bogosort.sortrules.item.ore_dict.name=鉱石辞書 43 | bogosort.sortrules.item.material.name=素材 44 | bogosort.sortrules.item.ore_prefix.name=鉱石接頭辞 45 | bogosort.sortrules.item.burn_time.name=燃焼時間 46 | bogosort.sortrules.item.block_type.name=ブロックタイプ 47 | bogosort.sortrules.item.hunger.name=空腹回復量 48 | bogosort.sortrules.item.saturation.name=満腹度回復量 49 | bogosort.sortrules.item.emc.name=EMC値 50 | bogosort.sortrules.item.color.name=色相値 51 | 52 | bogosort.sortrules.item.mod.description=Mod名のアルファベット順でソート 53 | bogosort.sortrules.item.id.description=レジストリ名(Mod名を除く)のアルファベット順でソート 54 | bogosort.sortrules.item.meta.description=メタ値の数値順でソート 55 | bogosort.sortrules.item.registry_order.description=レジストリ登録順でソート 56 | bogosort.sortrules.item.display_name.description=表示名のアルファベット順でソート 57 | bogosort.sortrules.item.nbt_size.description=NBTタグサイズの数値順でソート 58 | bogosort.sortrules.item.nbt_has.description=NBTタグの有無でソート 59 | bogosort.sortrules.item.nbt_rules.description=設定されたNBTソートルールに基づいてソート 60 | bogosort.sortrules.item.nbt_all_values.description=全てのNBTタグとサブタグを比較してソート 61 | bogosort.sortrules.item.count.description=スタック数の数値順でソート 62 | bogosort.sortrules.item.ore_dict.description=鉱石辞書名の数値またはアルファベット順でソート 63 | bogosort.sortrules.item.material.description=素材名(例:Iron, Gold, Copperなど)のアルファベット順でソート 64 | bogosort.sortrules.item.ore_prefix.description=鉱石接頭辞(例:ingot, nugget, plate, gearなど)でソート 65 | bogosort.sortrules.item.burn_time.description=燃焼時間の数値順でソート 66 | bogosort.sortrules.item.block_type.description=ブロックの種類(例:フルブロック、ハーフブロック、階段など)でソート 67 | bogosort.sortrules.item.hunger.description=空腹回復量の数値順でソート 68 | bogosort.sortrules.item.saturation.description=満腹度回復量の数値順でソート 69 | bogosort.sortrules.item.emc.description=EMC値の数値順でソート 70 | bogosort.sortrules.item.color.description=色相値の数値順でソート 71 | 72 | bogosort.sortrules.nbt.potion.name=ポーション 73 | bogosort.sortrules.nbt.enchantment.name=エンチャント 74 | bogosort.sortrules.nbt.enchantment_book.name=エンチャント本 75 | bogosort.sortrules.nbt.gt_circ_config.name=GTプログラム回路 76 | bogosort.sortrules.nbt.gt_item_damage.name=GTツールの損傷度 77 | 78 | bogosort.sortrules.nbt.potion.description=効果とレベルでポーションをソート 79 | bogosort.sortrules.nbt.enchantment.description=効果とレベルでエンチャントアイテムをソート 80 | bogosort.sortrules.nbt.enchantment_book.description=効果とレベルでエンチャント本をソート 81 | bogosort.sortrules.nbt.gt_circ_config.description=GregTechのプログラマブル回路を設定値でソート 82 | bogosort.sortrules.nbt.gt_item_damage.description=GregTechツールを損傷度でソート 83 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/lang/ko_kr.lang: -------------------------------------------------------------------------------- 1 | bogosort.key.categories=인벤토리 보고소트 2 | bogosort.key.sort_config=정리 설정 열기 3 | bogosort.key.sort=인벤토리 정리 4 | 5 | bogosort.key.move_all=Move all 6 | bogosort.key.move_all_same=Move all similar 7 | bogosort.key.move_single=Move single 8 | bogosort.key.move_single_empty=Move Single to empty 9 | bogosort.key.throw_all_same=Throw all similar 10 | bogosort.key.throw_all=Throw all 11 | 12 | bogosort.gui.title=정리 설정 13 | bogosort.gui.tab.general.name=일반 14 | bogosort.gui.tab.profiles.name=프로필 15 | bogosort.gui.tab.item_sort_rules.name=아이템 정리 규칙 16 | bogosort.gui.tab.nbt_sort_rules.name=NBT 정리 규칙 17 | bogosort.gui.available_sort_rules=사용 가능한 정리 규칙 18 | bogosort.gui.configured_sort_rules=구성된 정리 규칙 19 | bogosort.gui.enable_refill=자동 핫바 채우기 활성화 20 | bogosort.gui.refill_comment=Quark 모드가 설치되어 있습니다. 이 옵션을 비활성화해도 Quark의 기능은 활성화되어 있을 수 있습니다. '관리' -> '자동 도구 재공급'에서 해당 설정을 찾을 수 있습니다. 21 | bogosort.gui.refill_threshold=자동 채우기 내구도 임계값 22 | bogosort.gui.ascending=오름차순 23 | bogosort.gui.descending=내림차순 24 | bogosort.gui.hotbar_scrolling=핫바 열 스크롤 활성화 25 | bogosort.gui.hotbar_scrolling.tooltip=ALT 키를 누른 채로 인벤토리 열을 스크롤하세요 26 | bogosort.gui.enabled=활성화 27 | bogosort.gui.button.enabled=GUI에 정리 및 설정 버튼 활성화 28 | bogosort.gui.button.color=정리 버튼 배경색 29 | 30 | bogosort.command.config_relaod.success=정리 설정을 다시 불러왔습니다 31 | 32 | bogosort.sortrules.item.mod.name=모드 이름 33 | bogosort.sortrules.item.id.name=레지스트리 이름 34 | bogosort.sortrules.item.meta.name=메타 값 35 | bogosort.sortrules.item.registry_order.name=레지스트리 순서 36 | bogosort.sortrules.item.display_name.name=표시 이름 37 | bogosort.sortrules.item.nbt_size.name=NBT 태그 크기 38 | bogosort.sortrules.item.nbt_has.name=NBT 태그 보유 여부 39 | bogosort.sortrules.item.nbt_rules.name=NBT 규칙 40 | bogosort.sortrules.item.nbt_all_values.name=모든 NBT 값 41 | bogosort.sortrules.item.count.name=스택 크기 42 | bogosort.sortrules.item.ore_dict.name=광물 사전 43 | bogosort.sortrules.item.material.name=재료 44 | bogosort.sortrules.item.ore_prefix.name=광물 접두사 45 | bogosort.sortrules.item.burn_time.name=연소 시간 46 | bogosort.sortrules.item.block_type.name=블록 유형 47 | bogosort.sortrules.item.hunger.name=허기 48 | bogosort.sortrules.item.saturation.name=포만감 49 | bogosort.sortrules.item.emc.name=EMC 값 50 | bogosort.sortrules.item.color.name=색상 51 | 52 | bogosort.sortrules.item.mod.description=모드 이름의 알파벳순으로 아이템을 정리합니다 53 | bogosort.sortrules.item.id.description=레지스트리 이름(모드 제외)의 알파벳순으로 아이템을 정리합니다 54 | bogosort.sortrules.item.meta.description=메타 값의 숫자 순서로 아이템을 정리합니다 55 | bogosort.sortrules.item.registry_order.description=레지스트리 순서의 숫자 순서로 아이템을 정리합니다 56 | bogosort.sortrules.item.display_name.description=표시 이름의 알파벳순으로 아이템을 정리합니다 57 | bogosort.sortrules.item.nbt_size.description=NBT 태그 크기의 숫자 순서로 아이템을 정리합니다 58 | bogosort.sortrules.item.nbt_has.description=NBT 태그 유무에 따라 아이템을 정리합니다 59 | bogosort.sortrules.item.nbt_rules.description=구성된 NBT 정리 규칙에 따라 아이템을 정리합니다 60 | bogosort.sortrules.item.nbt_all_values.description=모든 nbt 태그와 하위 태그를 비교하여 아이템을 정리합니다 61 | bogosort.sortrules.item.count.description=스택 크기의 숫자 순서로 아이템을 정리합니다 62 | bogosort.sortrules.item.ore_dict.description=광물 사전의 숫자 및/또는 알파벳순으로 아이템을 정리합니다 63 | bogosort.sortrules.item.material.description=재료 이름(예: 철, 금, 구리...)의 알파벳순으로 아이템을 정리합니다 64 | bogosort.sortrules.item.ore_prefix.description=광물 접두사(예: 주괴, 조각, 판, 톱니바퀴...)에 따라 아이템을 정리합니다 65 | bogosort.sortrules.item.burn_time.description=연료 연소 시간의 숫자 순서로 아이템을 정리합니다 66 | bogosort.sortrules.item.block_type.description=아이템의 블록 유형(예: 전체 블록, 반 블록, 계단...)에 따라 아이템을 정리합니다 67 | bogosort.sortrules.item.hunger.description=허기 회복량의 숫자 순서로 아이템을 정리합니다 68 | bogosort.sortrules.item.saturation.description=포만감 회복량의 숫자 순서로 아이템을 정리합니다 69 | bogosort.sortrules.item.emc.description=EMC 값의 숫자 순서로 아이템을 정리합니다 70 | bogosort.sortrules.item.color.description=색상 색조 값의 숫자 순서로 아이템을 정리합니다 71 | 72 | bogosort.sortrules.nbt.potion.name=물약 73 | bogosort.sortrules.nbt.enchantment.name=마법 부여 74 | bogosort.sortrules.nbt.enchantment_book.name=마법이 부여된 책 75 | bogosort.sortrules.nbt.gt_circ_config.name=GT 프로그래밍 가능한 회로 76 | bogosort.sortrules.nbt.gt_item_damage.name=GT 도구 손상도 77 | 78 | bogosort.sortrules.nbt.potion.description=효과와 레벨에 따라 물약을 정리합니다 79 | bogosort.sortrules.nbt.enchantment.description=효과와 레벨에 따라 마법이 부여된 아이템을 정리합니다 80 | bogosort.sortrules.nbt.enchantment_book.description=효과와 레벨에 따라 마법이 부여된 책을 정리합니다 81 | bogosort.sortrules.nbt.gt_circ_config.description=구성(configuration)에 따라 그레그테크 프로그래밍 회로를 정리합니다 82 | bogosort.sortrules.nbt.gt_item_damage.description=손상도에 따라 그레그테크 도구를 정리합니다 83 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/visitor/EntityPlayerVisitor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.visitor; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | import com.cleanroommc.bogosorter.core.CatServerHelper; 5 | 6 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 7 | 8 | import org.objectweb.asm.ClassVisitor; 9 | import org.objectweb.asm.MethodVisitor; 10 | import org.objectweb.asm.Opcodes; 11 | 12 | public class EntityPlayerVisitor extends ClassVisitor implements Opcodes { 13 | 14 | public static final String CLASS_NAME = "net.minecraft.entity.player.EntityPlayer"; 15 | public static final boolean DEOBF = FMLLaunchHandler.isDeobfuscatedEnvironment(); 16 | private static final String METHOD_NAME = DEOBF ? "damageShield" : "func_184590_k"; 17 | private static final String INTERACT_ON_FUNC = DEOBF ? "interactOn" : "func_190775_a"; 18 | private static final String ATTACK_ENTITY_FUNC = DEOBF ? "attackTargetEntityWithCurrentItem" : "func_71059_n"; 19 | private static final String FEF_CLASS = "net/minecraftforge/event/ForgeEventFactory"; 20 | private static final String ON_DESTROY_ITEM_FUNC = "onPlayerDestroyItem"; 21 | 22 | public EntityPlayerVisitor(ClassVisitor cv) { 23 | super(ASM5, cv); 24 | } 25 | 26 | @Override 27 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 28 | MethodVisitor mv = super.visitMethod(access, name, desc, signature, exceptions); 29 | if (access == ACC_PROTECTED && METHOD_NAME.equals(name) && "(F)V".equals(desc)) { 30 | return new TargetMethodVisitor(mv); 31 | } 32 | if (access == ACC_PUBLIC && INTERACT_ON_FUNC.equals(name)) { 33 | return new InteractOnVisitor(mv); 34 | } 35 | if (access == ACC_PUBLIC && ATTACK_ENTITY_FUNC.equals(name)) { 36 | return new AttackTargetEntityWithCurrentItemVisitor(mv); 37 | } 38 | return mv; 39 | } 40 | 41 | private static class TargetMethodVisitor extends MethodVisitor { 42 | 43 | public TargetMethodVisitor(MethodVisitor mv) { 44 | super(ASM5, mv); 45 | } 46 | 47 | @Override 48 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 49 | super.visitFieldInsn(opcode, owner, name, desc); 50 | if (opcode == PUTFIELD && "activeItemStack".equals(name)) { 51 | visitVarInsn(ALOAD, 0); 52 | visitVarInsn(ALOAD, 2); 53 | visitVarInsn(ALOAD, 4); 54 | PIMVisitor.visitOnDestroy(this); 55 | BogoSorter.LOGGER.info("Applied EntityPlayer damageShield ASM"); 56 | } 57 | } 58 | } 59 | 60 | public static class InteractOnVisitor extends MethodVisitor { 61 | 62 | public InteractOnVisitor(MethodVisitor mv) { 63 | super(ASM5, mv); 64 | } 65 | 66 | @Override 67 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 68 | super.visitMethodInsn(opcode, owner, name, desc, itf); 69 | if ((opcode == INVOKEVIRTUAL && PIMVisitor.PLAYER_CLASS.equals(owner) && PIMVisitor.SET_HELD_ITEM_FUNC.equals(name)) || 70 | (opcode == INVOKESTATIC && FEF_CLASS.equals(owner) && ON_DESTROY_ITEM_FUNC.equals(name))) { 71 | visitVarInsn(ALOAD, 0); 72 | visitVarInsn(ALOAD, 5); 73 | visitVarInsn(ALOAD, 2); 74 | PIMVisitor.visitOnDestroy(this); 75 | BogoSorter.LOGGER.info("Applied EntityPlayer interactOn ASM"); 76 | } 77 | } 78 | } 79 | 80 | public static class AttackTargetEntityWithCurrentItemVisitor extends MethodVisitor { 81 | 82 | public AttackTargetEntityWithCurrentItemVisitor(MethodVisitor mv) { 83 | super(ASM5, mv); 84 | } 85 | 86 | @Override 87 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 88 | super.visitMethodInsn(opcode, owner, name, desc, itf); 89 | if (opcode == INVOKEVIRTUAL && PIMVisitor.PLAYER_CLASS.equals(owner) && PIMVisitor.SET_HELD_ITEM_FUNC.equals(name)) { 90 | visitVarInsn(ALOAD, 0); 91 | visitVarInsn(ALOAD, CatServerHelper.isCatServerLoaded() ? 26 : 25); 92 | visitFieldInsn(GETSTATIC, PIMVisitor.HAND_CLASS, "MAIN_HAND", "L" + PIMVisitor.HAND_CLASS + ";"); 93 | PIMVisitor.visitOnDestroy(this); 94 | BogoSorter.LOGGER.info("Applied EntityPlayer attackTargetEntityWithCurrentItem ASM"); 95 | } 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/config/Serializer.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common.config; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | import com.cleanroommc.bogosorter.common.network.NetworkUtils; 5 | import com.cleanroommc.bogosorter.common.sort.SortHandler; 6 | 7 | import net.minecraft.client.Minecraft; 8 | import net.minecraftforge.fml.common.Loader; 9 | import net.minecraftforge.fml.relauncher.Side; 10 | import net.minecraftforge.fml.relauncher.SideOnly; 11 | 12 | import com.google.gson.Gson; 13 | import com.google.gson.GsonBuilder; 14 | import com.google.gson.JsonElement; 15 | import com.google.gson.JsonObject; 16 | import com.google.gson.JsonParser; 17 | import com.google.gson.stream.JsonReader; 18 | import org.apache.commons.lang3.StringUtils; 19 | 20 | import java.io.File; 21 | import java.io.FileInputStream; 22 | import java.io.FileOutputStream; 23 | import java.io.InputStreamReader; 24 | import java.io.OutputStreamWriter; 25 | import java.io.Reader; 26 | import java.io.Writer; 27 | import java.nio.charset.StandardCharsets; 28 | import java.nio.file.Files; 29 | 30 | public class Serializer { 31 | 32 | public static final JsonParser jsonParser = new JsonParser(); 33 | public static final Gson gson = new GsonBuilder().setPrettyPrinting().create(); 34 | public static final String cfgPath = Loader.instance().getConfigDir().toString(); 35 | public static final File configJsonPath = new File(cfgPath + path("", "bogosorter", "config.json")); 36 | public static final File orePrefixJsonPath = new File(cfgPath + path("", "bogosorter", "orePrefix.json")); 37 | 38 | private static String path(String... path) { 39 | return StringUtils.join(path, File.separatorChar); 40 | } 41 | 42 | private Serializer() { 43 | } 44 | 45 | @SideOnly(Side.CLIENT) 46 | public static void saveConfig() { 47 | JsonObject json = new JsonObject(); 48 | BogoSorterConfig.save(json); 49 | saveJson(configJsonPath, json); 50 | } 51 | 52 | public static void loadConfig() { 53 | if (NetworkUtils.isDedicatedClient()) { 54 | if (!Files.exists(configJsonPath.toPath())) { 55 | BogoSorterConfig.loadDefaultRules(); 56 | saveConfig(); 57 | } 58 | JsonElement jsonElement = loadJson(configJsonPath); 59 | if (jsonElement == null || !jsonElement.isJsonObject()) { 60 | BogoSorter.LOGGER.error("Error loading config!"); 61 | } else { 62 | BogoSorterConfig.load(jsonElement.getAsJsonObject()); 63 | SortHandler.cacheItemSortRules.put(Minecraft.getMinecraft().player, BogoSorterConfig.sortRules); 64 | SortHandler.cacheNbtSortRules.put(Minecraft.getMinecraft().player, BogoSorterConfig.nbtSortRules); 65 | } 66 | } 67 | 68 | if (!Files.exists(orePrefixJsonPath.toPath())) { 69 | saveOrePrefixes(); 70 | return; 71 | } 72 | JsonElement jsonElement = loadJson(orePrefixJsonPath); 73 | if (jsonElement == null || !jsonElement.isJsonObject()) { 74 | BogoSorter.LOGGER.error("Error loading ore prefix config!"); 75 | return; 76 | } 77 | BogoSorterConfig.loadOrePrefixes(jsonElement.getAsJsonObject()); 78 | } 79 | 80 | public static void saveOrePrefixes() { 81 | JsonObject json = new JsonObject(); 82 | BogoSorterConfig.saveOrePrefixes(json); 83 | saveJson(orePrefixJsonPath, json); 84 | } 85 | 86 | public static JsonElement loadJson(File file) { 87 | try { 88 | if (!file.isFile()) return null; 89 | Reader reader = new InputStreamReader(new FileInputStream(file), StandardCharsets.UTF_8); 90 | JsonElement json = jsonParser.parse(new JsonReader(reader)); 91 | reader.close(); 92 | return json; 93 | } catch (Exception e) { 94 | BogoSorter.LOGGER.error("Failed to read file on path {}", file, e); 95 | } 96 | return null; 97 | } 98 | 99 | public static boolean saveJson(File file, JsonElement element) { 100 | try { 101 | if (!file.getParentFile().isDirectory()) { 102 | if (!file.getParentFile().mkdirs()) { 103 | BogoSorter.LOGGER.error("Failed to create file dirs on path {}", file); 104 | } 105 | } 106 | Writer writer = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8); 107 | writer.write(gson.toJson(element)); 108 | writer.close(); 109 | return true; 110 | } catch (Exception e) { 111 | BogoSorter.LOGGER.error("Failed to save file on path {}", file, e); 112 | } 113 | return false; 114 | } 115 | 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/mixin/galacticraft/planets/MixinEntitySlimeling.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.mixin.galacticraft.planets; 2 | 3 | import net.minecraft.entity.EntityLivingBase; 4 | import net.minecraft.entity.passive.EntityTameable; 5 | import net.minecraft.entity.player.EntityPlayer; 6 | import net.minecraft.entity.player.EntityPlayerMP; 7 | import net.minecraft.init.Items; 8 | import net.minecraft.item.Item; 9 | import net.minecraft.item.ItemStack; 10 | import net.minecraft.util.EnumHand; 11 | import net.minecraft.util.text.TextComponentString; 12 | import net.minecraft.world.World; 13 | 14 | import micdoodle8.mods.galacticraft.api.entity.IEntityBreathable; 15 | import micdoodle8.mods.galacticraft.core.entities.player.GCPlayerStats; 16 | import micdoodle8.mods.galacticraft.core.util.GCCoreUtil; 17 | import micdoodle8.mods.galacticraft.planets.mars.MarsModuleClient; 18 | import micdoodle8.mods.galacticraft.planets.mars.entities.EntitySlimeling; 19 | import org.spongepowered.asm.mixin.Mixin; 20 | import org.spongepowered.asm.mixin.Shadow; 21 | 22 | @Mixin(EntitySlimeling.class) 23 | public abstract class MixinEntitySlimeling extends EntityTameable implements IEntityBreathable { 24 | 25 | @Shadow(remap = false) 26 | public abstract void setSittingAI(boolean sitting); 27 | 28 | @Shadow(remap = false) 29 | public abstract void setOwnerUsername(String username); 30 | 31 | @Shadow(remap = false) 32 | protected abstract void setRandomFavFood(); 33 | 34 | @Shadow(remap = false) 35 | public abstract Item getFavoriteFood(); 36 | 37 | public MixinEntitySlimeling(World worldIn) { 38 | super(worldIn); 39 | } 40 | 41 | @Override 42 | public boolean processInteract(EntityPlayer player, EnumHand hand) { 43 | ItemStack itemstack = player.inventory.getCurrentItem(); 44 | EntitySlimeling entity = (EntitySlimeling) (Object) this; 45 | 46 | if (this.isTamed()) { 47 | if (!itemstack.isEmpty()) { 48 | if (itemstack.getItem() == this.getFavoriteFood()) { 49 | if (this.isOwner(player)) { 50 | if (!this.world.isRemote) { 51 | itemstack.shrink(1); 52 | if (itemstack.isEmpty()) { 53 | player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); 54 | } 55 | } 56 | 57 | if (this.world.isRemote) { 58 | MarsModuleClient.openSlimelingGui(entity, 1); 59 | } 60 | 61 | if (this.rand.nextInt(3) == 0) { 62 | this.setRandomFavFood(); 63 | } 64 | } else if (player instanceof EntityPlayerMP) { 65 | GCPlayerStats stats = GCPlayerStats.get(player); 66 | if (stats.getChatCooldown() == 0) { 67 | player.sendMessage(new TextComponentString(GCCoreUtil.translate("gui.slimeling.chat.wrong_player"))); 68 | stats.setChatCooldown(100); 69 | } 70 | } 71 | } else if (this.world.isRemote) { 72 | MarsModuleClient.openSlimelingGui(entity, 0); 73 | } 74 | } else if (this.world.isRemote) { 75 | MarsModuleClient.openSlimelingGui(entity, 0); 76 | } 77 | 78 | return true; 79 | } else if (!itemstack.isEmpty() && itemstack.getItem() == Items.SLIME_BALL) { 80 | if (!player.capabilities.isCreativeMode) { 81 | itemstack.shrink(1); 82 | } 83 | 84 | if (itemstack.isEmpty()) { 85 | player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); 86 | } 87 | 88 | if (!this.world.isRemote) { 89 | if (this.rand.nextInt(3) == 0) { 90 | this.setTamed(true); 91 | this.getNavigator().clearPath(); 92 | this.setAttackTarget(null); 93 | this.setSittingAI(true); 94 | this.setHealth(20.0F); 95 | this.setOwnerId(player.getUniqueID()); 96 | this.setOwnerUsername(player.getName()); 97 | this.playTameEffect(true); 98 | this.world.setEntityState(this, (byte) 7); 99 | } else { 100 | this.playTameEffect(false); 101 | this.world.setEntityState(this, (byte) 6); 102 | } 103 | } 104 | 105 | return true; 106 | } else { 107 | return super.processInteract(player, hand); 108 | } 109 | } 110 | 111 | } 112 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/core/visitor/PIMVisitor.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.core.visitor; 2 | 3 | import com.cleanroommc.bogosorter.BogoSorter; 4 | 5 | import net.minecraftforge.fml.relauncher.FMLLaunchHandler; 6 | 7 | import org.objectweb.asm.ClassVisitor; 8 | import org.objectweb.asm.MethodVisitor; 9 | import org.objectweb.asm.Opcodes; 10 | 11 | public class PIMVisitor extends ClassVisitor implements Opcodes { 12 | 13 | public static final String CLASS_NAME = "net.minecraft.server.management.PlayerInteractionManager"; 14 | public static final boolean DEOBF = FMLLaunchHandler.isDeobfuscatedEnvironment(); 15 | public static final String METHOD_NAME = DEOBF ? "processRightClick" : "func_187250_a"; 16 | public static final String TRY_HARVEST_BLOCK_FUNC = DEOBF ? "tryHarvestBlock" : "func_180237_b"; 17 | public static final String PLAYER_CLASS = "net/minecraft/entity/player/EntityPlayer"; 18 | public static final String PLAYER_MP_CLASS = "net/minecraft/entity/player/EntityPlayerMP"; 19 | public static final String SET_HELD_ITEM_FUNC = DEOBF ? "setHeldItem" : "func_184611_a"; 20 | public static final String ITEM_STACK_CLASS = "net/minecraft/item/ItemStack"; 21 | public static final String EMPTY = DEOBF ? "EMPTY" : "field_190927_a"; 22 | public static final String REFILL_HANDLER_CLASS = "com/cleanroommc/bogosorter/common/refill/RefillHandler"; 23 | public static final String ON_DESTROY_FUNC = "onDestroyItem"; 24 | public static final String ON_DESTROY_FUNC_DESC = "(Lnet/minecraft/entity/player/EntityPlayer;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/EnumHand;)V"; 25 | public static final String FEF_CLASS = "net/minecraftforge/event/ForgeEventFactory"; 26 | public static final String ON_DESTROY_ITEM_FUNC = "onPlayerDestroyItem"; 27 | public static final String PIM_CLASS = "net/minecraft/server/management/PlayerInteractionManager"; 28 | public static final String HAND_CLASS = "net/minecraft/util/EnumHand"; 29 | 30 | public PIMVisitor(ClassVisitor cv) { 31 | super(ASM5, cv); 32 | } 33 | 34 | public static void visitOnDestroy(MethodVisitor mv) { 35 | mv.visitMethodInsn(INVOKESTATIC, REFILL_HANDLER_CLASS, ON_DESTROY_FUNC, ON_DESTROY_FUNC_DESC, false); 36 | } 37 | 38 | @Override 39 | public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { 40 | MethodVisitor visitor = super.visitMethod(access, name, desc, signature, exceptions); 41 | if (METHOD_NAME.equals(name)) { 42 | return new TargetMethodVisitor(visitor); 43 | } 44 | if (access == ACC_PUBLIC && TRY_HARVEST_BLOCK_FUNC.equals(name)) { 45 | return new TryHarvestBlockVisitor(visitor); 46 | } 47 | return visitor; 48 | } 49 | 50 | public static class TargetMethodVisitor extends MethodVisitor { 51 | 52 | private boolean inject = false; 53 | 54 | public TargetMethodVisitor(MethodVisitor mv) { 55 | super(ASM5, mv); 56 | } 57 | 58 | @Override 59 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 60 | super.visitMethodInsn(opcode, owner, name, desc, itf); 61 | if (inject && opcode == INVOKEVIRTUAL && PLAYER_CLASS.equals(owner) && SET_HELD_ITEM_FUNC.equals(name)) { 62 | visitVarInsn(ALOAD, 1); 63 | visitVarInsn(ALOAD, 8); 64 | visitVarInsn(ALOAD, 4); 65 | visitOnDestroy(this); 66 | inject = false; 67 | BogoSorter.LOGGER.info("Applied PIM processRightClick ASM"); 68 | } 69 | } 70 | 71 | @Override 72 | public void visitFieldInsn(int opcode, String owner, String name, String desc) { 73 | super.visitFieldInsn(opcode, owner, name, desc); 74 | if (opcode == GETSTATIC && ITEM_STACK_CLASS.equals(owner) && EMPTY.equals(name)) { 75 | inject = true; 76 | } 77 | } 78 | } 79 | 80 | public static class TryHarvestBlockVisitor extends MethodVisitor { 81 | 82 | public TryHarvestBlockVisitor(MethodVisitor mv) { 83 | super(ASM5, mv); 84 | } 85 | 86 | @Override 87 | public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { 88 | super.visitMethodInsn(opcode, owner, name, desc, itf); 89 | if (opcode == INVOKESTATIC && FEF_CLASS.equals(owner) && ON_DESTROY_ITEM_FUNC.equals(name)) { 90 | visitVarInsn(ALOAD, 0); 91 | visitFieldInsn(GETFIELD, PIM_CLASS, DEOBF ? "player" : "field_73090_b", "L" + PLAYER_MP_CLASS + ";"); 92 | visitVarInsn(ALOAD, 9); 93 | visitFieldInsn(GETSTATIC, HAND_CLASS, "MAIN_HAND", "L" + HAND_CLASS + ";"); 94 | visitOnDestroy(this); 95 | BogoSorter.LOGGER.info("Applied PIM tryHarvestBlock ASM"); 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | # This workflow must be manually triggered. It accepts a version and a release type. 2 | # First it sets the version in gradle.properties to the new version and pushes it. 3 | # Then it generates a log, based on commits. 4 | # After that builds a jar and uploads it to curseforge/modrinth/GitHub releases 5 | 6 | name: Publish mod version 7 | 8 | on: 9 | workflow_dispatch: 10 | inputs: 11 | version: 12 | description: 'Mod version' 13 | required: true 14 | release_type: 15 | description: 'Release type' 16 | type: choice 17 | default: 'beta' 18 | options: 19 | - 'release' 20 | - 'beta' 21 | - 'alpha' 22 | 23 | jobs: 24 | build: 25 | runs-on: ubuntu-latest 26 | steps: 27 | - name: Checkout Repository 28 | uses: actions/checkout@v3 29 | with: 30 | token: ${{ secrets.PAT }} 31 | 32 | - name: Check if tag already exists 33 | run: | 34 | if git rev-parse --verify --quiet "v${{ github.event.inputs.version }}"; then 35 | echo "Version ${{ github.event.inputs.version }} already exists, aborting workflow." 36 | exit 1 37 | fi 38 | 39 | - name: Set version 40 | run: sed -i "s/mod_version.*=.*/mod_version = ${{ github.event.inputs.version }}/g" gradle.properties 41 | 42 | - name: Commit and push gradle.properties 43 | uses: stefanzweifel/git-auto-commit-action@v4 44 | with: 45 | commit_message: "Bump version to ${{ github.event.inputs.version }}" 46 | commit_options: "--no-verify" 47 | file_pattern: gradle.properties 48 | tagging_message: "v${{ github.event.inputs.version }}" 49 | 50 | - name: Setup Java 51 | uses: actions/setup-java@v3 52 | with: 53 | distribution: 'temurin' 54 | java-version: '8' 55 | 56 | - name: Grant execute permission for gradlew 57 | run: chmod +x gradlew 58 | - name: Build with Gradle 59 | run: ./gradlew build 60 | 61 | - name: Publish Minecraft Mods 62 | uses: Kir-Antipov/mc-publish@v3.2 63 | with: 64 | curseforge-id: 632327 65 | curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} 66 | 67 | modrinth-id: CuLATCrJ 68 | modrinth-featured: true 69 | modrinth-token: ${{ secrets.MODRINTH_TOKEN }} 70 | 71 | github-tag: "v${{ github.event.inputs.version }}" 72 | github-generate-changelog: true 73 | github-draft: false 74 | github-prerelease: false 75 | github-token: ${{ secrets.PAT }} 76 | 77 | files-primary: build/libs/!(*-@(dev|sources|javadoc)).jar 78 | files-secondary: build/libs/*-@(dev|sources|javadoc).jar 79 | name: InventoryBogoSorter-${{ github.event.inputs.version }} 80 | version: ${{ github.event.inputs.version }} 81 | version-type: ${{ github.event.inputs.release_type }} 82 | changelog: "[Click here](https://github.com/CleanroomMC/InventoryBogoSorter/releases/tag/v${{ github.event.inputs.version }})" 83 | loaders: | 84 | forge 85 | game-versions: | 86 | 1.12.2 87 | dependencies: | 88 | mixin-booter | depends | 8.3 89 | modularui | depends | 2.1.0 90 | railcraft | recommends | * 91 | ender-io | recommends | * 92 | thermal-expansion | recommends | * 93 | draconic-evolution | recommends | * 94 | projecte | recommends | * 95 | bibliocraft | recommends | * 96 | actually-additions | recommends | * 97 | iron-chests | recommends | * 98 | project-red-exploration | recommends | * 99 | immersive-engineering | recommends | * 100 | colossal-chests | recommends | * 101 | cyclic | recommends | * 102 | industrial-craft | recommends | * 103 | ic2-classic | recommends | * 104 | angry-pixel-the-betweenlands-mod | recommends | * 105 | ender-storage-1-8 | recommends | * 106 | rustic | recommends | * 107 | metalchests | recommends | * 108 | charset-storage-chests | recommends | * 109 | quark-oddities | recommends | * 110 | terrafirmacraft | recommends | * 111 | future-mc | recommends | * 112 | travelers-backpack | recommends | * 113 | energy-control | recommends | * 114 | gregtech-ce-unofficial | recommends | * 115 | galacticraft-legacy | recommends | * 116 | ae2-extended-life | recommends | * 117 | simply-backpacks | recommends | 1.4.9 118 | improvedbackpacks | recommends | * 119 | expandable-inventory | recommends | * 120 | charm | recommends | * 121 | cooking-for-blockheads | recommends | * 122 | mekanism | recommends | * 123 | constructs-armory | recommends | * 124 | java: | 125 | 8 126 | retry-attempts: 2 127 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/lang/en_us.lang: -------------------------------------------------------------------------------- 1 | bogosort.key.categories=Inventory Bogo Sorter 2 | bogosort.key.sort_config=Open Sort Config 3 | bogosort.key.sort=Sort Inventory 4 | 5 | bogosort.key.move_all=Move all 6 | bogosort.key.move_all_same=Move all similar 7 | bogosort.key.move_single=Move single 8 | bogosort.key.move_single_empty=Move Single to empty 9 | bogosort.key.throw_all_same=Throw all similar 10 | bogosort.key.throw_all=Throw all 11 | 12 | bogosort.gui.title=Sort Config 13 | bogosort.gui.tab.general.name=General 14 | bogosort.gui.tab.profiles.name=Profiles 15 | bogosort.gui.tab.item_sort_rules.name=Item sort rules 16 | bogosort.gui.tab.nbt_sort_rules.name=NBT sort rules 17 | bogosort.gui.available_sort_rules=Available Sort-Rules 18 | bogosort.gui.configured_sort_rules=Configured Sort-Rules 19 | bogosort.gui.enable_refill=Enable auto hotbar refill 20 | bogosort.gui.refill_comment=Quark is installed. If this option is disabled, theirs might still be enabled. You can find the config at 'Management' -> 'Automatic Tool Restock'. 21 | bogosort.gui.refill_threshold=Auto refill damage threshold 22 | bogosort.gui.ascending=Ascending 23 | bogosort.gui.descending=Descending 24 | bogosort.gui.hotbar_scrolling=Enable hotbar column scrolling 25 | bogosort.gui.hotbar_scrolling.tooltip=Scroll though inventory column by holding ALT 26 | bogosort.gui.enabled=Enabled 27 | bogosort.gui.button.enabled=Enable sort and config buttons in GUI's 28 | bogosort.gui.button.color=Background color of sort buttons 29 | 30 | bogosort.command.config_relaod.success=Reloaded sorting config 31 | 32 | bogosort.sortrules.item.mod.name=Mod name 33 | bogosort.sortrules.item.id.name=Registry name 34 | bogosort.sortrules.item.meta.name=Meta value 35 | bogosort.sortrules.item.registry_order.name=Registry Order 36 | bogosort.sortrules.item.display_name.name=Display Name 37 | bogosort.sortrules.item.nbt_size.name=NBT tag size 38 | bogosort.sortrules.item.nbt_has.name=Has NBT tag 39 | bogosort.sortrules.item.nbt_rules.name=NBT rules 40 | bogosort.sortrules.item.nbt_all_values.name=All NBT values 41 | bogosort.sortrules.item.count.name=Stack size 42 | bogosort.sortrules.item.ore_dict.name=Ore dict 43 | bogosort.sortrules.item.material.name=Material 44 | bogosort.sortrules.item.ore_prefix.name=Ore prefix 45 | bogosort.sortrules.item.burn_time.name=Burn Time 46 | bogosort.sortrules.item.block_type.name=Block Type 47 | bogosort.sortrules.item.hunger.name=Hunger 48 | bogosort.sortrules.item.saturation.name=Saturation 49 | bogosort.sortrules.item.emc.name=EMC Value 50 | bogosort.sortrules.item.color.name=Color 51 | 52 | bogosort.sortrules.item.mod.description=Sorts items alphabetically by its mod name 53 | bogosort.sortrules.item.id.description=Sorts items alphabetically by its registry name (without mod) 54 | bogosort.sortrules.item.meta.description=Sorts items numerically by its meta value 55 | bogosort.sortrules.item.registry_order.description=Sorts items numerically by its registry order 56 | bogosort.sortrules.item.display_name.description=Sorts items alphabetically by its displayed name 57 | bogosort.sortrules.item.nbt_size.description=Sorts items numerically by its meta value NBT tag size 58 | bogosort.sortrules.item.nbt_has.description=Sorts items based on if or if not that have a NBT tag 59 | bogosort.sortrules.item.nbt_rules.description=Sorts items based on configured NBT sort rules 60 | bogosort.sortrules.item.nbt_all_values.description=Tries to sort items by comparing all nbt tags and subtags 61 | bogosort.sortrules.item.count.description=Sorts items numerically by its stack size 62 | bogosort.sortrules.item.ore_dict.description=Sorts items numerically and/or alphabetically by its ore dicts 63 | bogosort.sortrules.item.material.description=Sorts items alphabetically by its material name (f.e. Iron, Gold, Copper...) 64 | bogosort.sortrules.item.ore_prefix.description=Sorts items by their ore prefix (f.e. ingot, nugget, plate, gear...) 65 | bogosort.sortrules.item.burn_time.description=Sorts items numerically by its fuel burn time 66 | bogosort.sortrules.item.block_type.description=Sorts items based on what type of block the item is (f.e. full block, slab, stairs ...) 67 | bogosort.sortrules.item.hunger.description=Sorts items numerically by its hunger refill value 68 | bogosort.sortrules.item.saturation.description=Sorts items numerically by its saturation refill value 69 | bogosort.sortrules.item.emc.description=Sorts items numerically by its EMC value 70 | bogosort.sortrules.item.color.description=Sorts items numerically by its color hue value 71 | 72 | bogosort.sortrules.nbt.potion.name=Potions 73 | bogosort.sortrules.nbt.enchantment.name=Enchantments 74 | bogosort.sortrules.nbt.enchantment_book.name=Ench. books 75 | bogosort.sortrules.nbt.gt_circ_config.name=GT prog. circuit 76 | bogosort.sortrules.nbt.gt_item_damage.name=GT tool damage 77 | 78 | bogosort.sortrules.nbt.potion.description=Sorts potions by effect and level 79 | bogosort.sortrules.nbt.enchantment.description=Sorts enchanted items by effect and level 80 | bogosort.sortrules.nbt.enchantment_book.description=Sorts enchanted books by effect and level 81 | bogosort.sortrules.nbt.gt_circ_config.description=Sorts GregTech programmable circuits by their configuration 82 | bogosort.sortrules.nbt.gt_item_damage.description=Sorts GregTech tools by their damage 83 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/lang/ru_ru.lang: -------------------------------------------------------------------------------- 1 | bogosort.key.categories=Инвентарь Bogo Sorter 2 | bogosort.key.sort_config=Открыть конфигурацию сортировки 3 | bogosort.key.sort=Сортировать инвентарь 4 | 5 | bogosort.key.move_all=Move all 6 | bogosort.key.move_all_same=Move all similar 7 | bogosort.key.move_single=Move single 8 | bogosort.key.move_single_empty=Move Single to empty 9 | bogosort.key.throw_all_same=Throw all similar 10 | bogosort.key.throw_all=Throw all 11 | 12 | bogosort.gui.title=Конфигурация сортировки 13 | bogosort.gui.tab.general.name=Общие 14 | bogosort.gui.tab.profiles.name=Профили 15 | bogosort.gui.tab.item_sort_rules.name=Правила сортировки предметов 16 | bogosort.gui.tab.nbt_sort_rules.name=Правила сортировки NBT 17 | bogosort.gui.available_sort_rules=Доступные правила сортировки 18 | bogosort.gui.configured_sort_rules=Настроенные правила сортировки 19 | bogosort.gui.enable_refill=Включить автопополнение панели быстрого доступа 20 | bogosort.gui.refill_comment=Quark is installed. If this option is disabled, theirs might still be enabled. You can find the config at 'Management' -> 'Automatic Tool Restock'. 21 | bogosort.gui.refill_threshold=Порог урона автопополнения 22 | bogosort.gui.ascending=По возрастанию 23 | bogosort.gui.descending=По убыванию 24 | bogosort.gui.hotbar_scrolling=Включить прокрутку стобцов на панели быстрого доступа 25 | bogosort.gui.hotbar_scrolling.tooltip=Прокручивание стобцов инвентаря при зажатой клавише ALT 26 | bogosort.gui.enabled=Включено 27 | bogosort.gui.button.enabled=Enable sort and config buttons in GUI's 28 | bogosort.gui.button.color=Background color of sort buttons 29 | 30 | bogosort.command.config_relaod.success=Перезагружен конфиг сортировки 31 | 32 | bogosort.sortrules.item.mod.name=Имя мода 33 | bogosort.sortrules.item.id.name=Имя реестра 34 | bogosort.sortrules.item.meta.name=Мета-значение 35 | bogosort.sortrules.item.registry_order.name=Порядок реестра 36 | bogosort.sortrules.item.display_name.name=Отображаемое имя 37 | bogosort.sortrules.item.nbt_size.name=Размер тега NBT 38 | bogosort.sortrules.item.nbt_has.name=Имеет тег NBT 39 | bogosort.sortrules.item.nbt_rules.name=Правила NBT 40 | bogosort.sortrules.item.nbt_all_values.name=Все значения NBT 41 | bogosort.sortrules.item.count.name=Размер стека 42 | bogosort.sortrules.item.ore_dict.name=Рудный словарь 43 | bogosort.sortrules.item.material.name=Материал 44 | bogosort.sortrules.item.ore_prefix.name=Префикс руды 45 | bogosort.sortrules.item.burn_time.name=Время записи 46 | bogosort.sortrules.item.block_type.name=Тип блока 47 | bogosort.sortrules.item.hunger.name=Голод 48 | bogosort.sortrules.item.saturation.name=Насыщенность 49 | bogosort.sortrules.item.emc.name=Значение EMC 50 | bogosort.sortrules.item.color.name=Цвет 51 | 52 | bogosort.sortrules.item.mod.description=Сортирует предметы в алфавитном порядке по имени мода 53 | bogosort.sortrules.item.id.description=Сортирует элементы в алфавитном порядке по имени в реестре (без мода) 54 | bogosort.sortrules.item.meta.description=Сортирует элементы численно по их мета-значению 55 | bogosort.sortrules.item.registry_order.description=Сортирует элементы по порядку в реестре 56 | bogosort.sortrules.item.display_name.description=Сортирует элементы в алфавитном порядке по отображаемому имени 57 | bogosort.sortrules.item.nbt_size.description=Сортирует элементы численно по размеру мета-значения NBT-тега 58 | bogosort.sortrules.item.nbt_has.description=Сортирует предметы по признаку наличия или отсутствия тега NBT 59 | bogosort.sortrules.item.nbt_rules.description=Сортирует элементы на основе настроенных правил сортировки NBT 60 | bogosort.sortrules.item.nbt_all_values.description=Пытается отсортировать элементы, сравнивая все теги и подтеги nbt 61 | bogosort.sortrules.item.count.description=Сортирует предметы по размеру стопки 62 | bogosort.sortrules.item.ore_dict.description=Сортирует предметы в числовом и/или алфавитном порядке по их рудным словарям 63 | bogosort.sortrules.item.material.description=Сортирует предметы в алфавитном порядке по названию материала (например, железо, золото, медь...) 64 | bogosort.sortrules.item.ore_prefix.description=Сортирует предметы по их префиксу руды (например, слиток, самородок, пластина, снаряжение...) 65 | bogosort.sortrules.item.burn_time.description=Сортирует предметы по времени сжигания топлива 66 | bogosort.sortrules.item.block_type.description=Сортирует предметы на основе типа блока, к которому они относятся (например, полноценный блок, плита, ступеньки и т.д.) 67 | bogosort.sortrules.item.hunger.description=Сортирует предметы в числовом порядке по значению восполнения голода 68 | bogosort.sortrules.item.saturation.description=Сортирует предметы в числовом порядке по значению насыщения 69 | bogosort.sortrules.item.emc.description==Сортировка элементов по их значению EMC 70 | bogosort.sortrules.item.color.description==Сортирует элементы в числовом порядке по значению оттенка цвета 71 | 72 | bogosort.sortrules.nbt.potion.name=Зелья 73 | bogosort.sortrules.nbt.enchantment.name=Чары 74 | bogosort.sortrules.nbt.enchantment_book.name=Зачаровать. книги 75 | bogosort.sortrules.nbt.gt_circ_config.name=Программируемая схема GT 76 | bogosort.sortrules.nbt.gt_item_damage.name=Урон инструмента GT 77 | 78 | bogosort.sortrules.nbt.potion.description=Сортирует зелья по эффекту и уровню 79 | bogosort.sortrules.nbt.enchantment.description=Сортирует зачарованные предметы по эффекту и уровню 80 | bogosort.sortrules.nbt.enchantment_book.description=Сортирует зачарованные книги по эффекту и уровню 81 | bogosort.sortrules.nbt.gt_circ_config.description=Сортирует программируемые схемы GregTech по их конфигурации 82 | bogosort.sortrules.nbt.gt_item_damage.description=Сортирует инструменты GregTech по их повреждению 83 | -------------------------------------------------------------------------------- /src/main/resources/assets/bogosorter/lang/pt_br.lang: -------------------------------------------------------------------------------- 1 | bogosort.key.categories=Classificador Bogo de Inventário 2 | bogosort.key.sort_config=Abrir configuração de classificação 3 | bogosort.key.sort=Classificação do Inventário 4 | 5 | bogosort.key.move_all=Move all 6 | bogosort.key.move_all_same=Move all similar 7 | bogosort.key.move_single=Move single 8 | bogosort.key.move_single_empty=Move Single to empty 9 | bogosort.key.throw_all_same=Throw all similar 10 | bogosort.key.throw_all=Throw all 11 | 12 | bogosort.gui.title=Configuração da Classificação 13 | bogosort.gui.tab.general.name=Geral 14 | bogosort.gui.tab.profiles.name=Profiles 15 | bogosort.gui.tab.item_sort_rules.name=Regras de classificação de itens 16 | bogosort.gui.tab.nbt_sort_rules.name=regras de classificação NBT 17 | bogosort.gui.available_sort_rules=Regras de classificação disponíveis 18 | bogosort.gui.configured_sort_rules=Regras de classificação configuradas 19 | bogosort.gui.enable_refill=Ativar recarga automática da hotbar 20 | bogosort.gui.refill_comment=Quark is installed. If this option is disabled, theirs might still be enabled. You can find the config at 'Management' -> 'Automatic Tool Restock'. 21 | bogosort.gui.refill_threshold=Limiar de dano de recarga automática 22 | bogosort.gui.ascending=Ascendente 23 | bogosort.gui.descending=descendente 24 | bogosort.gui.hotbar_scrolling=Rolagem da coluna Hotbar 25 | bogosort.gui.hotbar_scrolling.tooltip=Percorra a coluna de inventário segurando ALT 26 | bogosort.gui.enabled=Habilitado 27 | bogosort.gui.button.enabled=Enable sort and config buttons in GUI's 28 | bogosort.gui.button.color=Background color of sort buttons 29 | 30 | bogosort.command.config_relaod.success=Configuração de classificação recarregada 31 | 32 | bogosort.sortrules.item.mod.name=Nome do Mod 33 | bogosort.sortrules.item.id.name=Nome do registro 34 | bogosort.sortrules.item.meta.name=Metavalor 35 | bogosort.sortrules.item.registry_order.name=Pedido de registro 36 | bogosort.sortrules.item.display_name.name=Nome em Exibição 37 | bogosort.sortrules.item.nbt_size.name=Tamanho da etiqueta NBT 38 | bogosort.sortrules.item.nbt_has.name=Tem etiqueta NBT 39 | bogosort.sortrules.item.nbt_rules.name=regras NBT 40 | bogosort.sortrules.item.nbt_all_values.name=Todos os valores NBT 41 | bogosort.sortrules.item.count.name=Tamanho da pilha 42 | bogosort.sortrules.item.ore_dict.name=Ditado de Minério 43 | bogosort.sortrules.item.material.name=Material 44 | bogosort.sortrules.item.ore_prefix.name=Prefixo de minério 45 | bogosort.sortrules.item.burn_time.name=Tempo de queima 46 | bogosort.sortrules.item.block_type.name=Block Type 47 | bogosort.sortrules.item.hunger.name=Fome 48 | bogosort.sortrules.item.saturation.name=Saturação 49 | bogosort.sortrules.item.emc.name=Valor EMC 50 | bogosort.sortrules.item.color.name=Cor 51 | 52 | bogosort.sortrules.item.mod.description=Classifica os itens em ordem alfabética pelo nome do mod 53 | bogosort.sortrules.item.id.description=Classifica os itens em ordem alfabética por seu nome de registro (sem mod) 54 | bogosort.sortrules.item.meta.description=Classifica os itens numericamente por seu valor meta 55 | bogosort.sortrules.item.registry_order.description=Classifica os itens numericamente por sua ordem de registro 56 | bogosort.sortrules.item.display_name.description=Classifica os itens em ordem alfabética pelo nome exibido 57 | bogosort.sortrules.item.nbt_size.description=Classifica os itens numericamente por seu tamanho de tag NBT de meta valor 58 | bogosort.sortrules.item.nbt_has.description=Classifica os itens com base no fato de terem ou não uma tag NBT 59 | bogosort.sortrules.item.nbt_rules.description=Classifica itens com base em regras de classificação NBT configuradas 60 | bogosort.sortrules.item.nbt_all_values.description=Tenta classificar itens comparando todas as tags e subtags nbt 61 | bogosort.sortrules.item.count.description=Classifica os itens numericamente pelo tamanho da pilha 62 | bogosort.sortrules.item.ore_dict.description=Classifica os itens numericamente e/ou alfabeticamente por seus ditados de minério 63 | bogosort.sortrules.item.material.description=Classifica os itens em ordem alfabética pelo nome do material (por exemplo, Ferro, Ouro, Cobre...) 64 | bogosort.sortrules.item.ore_prefix.description=Classifica os itens por seu prefixo de minério (por exemplo, lingote, pepita, placa, engrenagem...) 65 | bogosort.sortrules.item.burn_time.description=Classifica os itens numericamente por seu tempo de queima de combustível 66 | bogosort.sortrules.item.block_type.description=Sorts items based on what type of block the item is (f.e. full block, slab, stairs ...)bogosort.key.move_all=Move allbogosort.key.move_all=Move allbogosort.key.move_all=Move all 67 | bogosort.sortrules.item.hunger.description=Classifica os itens numericamente por seu valor de reabastecimento de fome 68 | bogosort.sortrules.item.saturation.description=Classifica os itens numericamente por seu valor de recarga de saturação 69 | bogosort.sortrules.item.emc.description==Classifica os itens numericamente por seu valor EMC 70 | bogosort.sortrules.item.color.description==Classifica os itens numericamente por seu valor de matiz de cor 71 | 72 | bogosort.sortrules.nbt.potion.name=Poções 73 | bogosort.sortrules.nbt.enchantment.name=Encantamentos 74 | bogosort.sortrules.nbt.enchantment_book.name=Livros de encantamento 75 | bogosort.sortrules.nbt.gt_circ_config.name=Circuito programável GT 76 | bogosort.sortrules.nbt.gt_item_damage.name=Dano da ferramenta GT 77 | 78 | bogosort.sortrules.nbt.potion.description=Classifica poções por efeito e nível 79 | bogosort.sortrules.nbt.enchantment.description=Classifica itens encantados por efeito e nível 80 | bogosort.sortrules.nbt.enchantment_book.description=Classifica livros encantados por efeito e nível 81 | bogosort.sortrules.nbt.gt_circ_config.description=Classifica os circuitos programáveis GregTech por sua configuração 82 | bogosort.sortrules.nbt.gt_item_damage.description=Classifica as ferramentas GregTech por seu danobogosort.key.move_all=Move all 83 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/common/HotbarSwap.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.common; 2 | 3 | import com.cleanroommc.bogosorter.common.network.CHotbarSwap; 4 | import com.cleanroommc.bogosorter.common.network.NetworkHandler; 5 | 6 | import net.minecraft.client.Minecraft; 7 | import net.minecraft.client.gui.GuiIngame; 8 | import net.minecraft.client.gui.GuiScreen; 9 | import net.minecraft.client.renderer.GlStateManager; 10 | import net.minecraft.client.renderer.RenderHelper; 11 | import net.minecraft.client.renderer.RenderItem; 12 | import net.minecraft.entity.player.EntityPlayer; 13 | import net.minecraft.item.ItemStack; 14 | import net.minecraft.util.ResourceLocation; 15 | import net.minecraft.util.math.MathHelper; 16 | import net.minecraftforge.client.event.RenderGameOverlayEvent; 17 | import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; 18 | import net.minecraftforge.fml.common.gameevent.InputEvent; 19 | 20 | import org.lwjgl.input.Mouse; 21 | 22 | public class HotbarSwap { 23 | 24 | private static final ResourceLocation WIDGETS_TEX_PATH = new ResourceLocation("textures/gui/widgets.png"); 25 | 26 | private static boolean enabled = true; 27 | private static boolean show; 28 | private static int verticalIndex = 0; 29 | 30 | public static boolean doCancelHotbarSwap() { 31 | return show; 32 | } 33 | 34 | public static void setEnabled(boolean enabled) { 35 | HotbarSwap.enabled = enabled; 36 | } 37 | 38 | public static boolean isEnabled() { 39 | return enabled; 40 | } 41 | 42 | @SubscribeEvent 43 | public static void render(RenderGameOverlayEvent.Post event) { 44 | if (enabled && event.getType() == RenderGameOverlayEvent.ElementType.ALL && show) { 45 | GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); 46 | 47 | EntityPlayer player = Minecraft.getMinecraft().player; 48 | GuiIngame gui = Minecraft.getMinecraft().ingameGUI; 49 | int m = event.getResolution().getScaledWidth() / 2; 50 | if (verticalIndex != 0) { 51 | Minecraft.getMinecraft().getTextureManager().bindTexture(WIDGETS_TEX_PATH); 52 | gui.drawTexturedModalRect(m - 91 - 1 + player.inventory.currentItem * 20, event.getResolution().getScaledHeight() - 22 - 17 - 18 * verticalIndex, 0, 22, 24, 22); 53 | } 54 | 55 | GlStateManager.enableRescaleNormal(); 56 | GlStateManager.enableBlend(); 57 | GlStateManager.tryBlendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ZERO); 58 | RenderHelper.enableGUIStandardItemLighting(); 59 | 60 | int x = m - 90 + player.inventory.currentItem * 20 + 2; 61 | int y = event.getResolution().getScaledHeight() - 16 - 3 - 70; 62 | for (int i = 1; i < 4; i++) { 63 | renderHotbarItem(x, y, event.getPartialTicks(), player, player.inventory.getStackInSlot(player.inventory.currentItem + i * 9)); 64 | y += 18; 65 | } 66 | 67 | RenderHelper.disableStandardItemLighting(); 68 | GlStateManager.disableRescaleNormal(); 69 | GlStateManager.disableBlend(); 70 | } 71 | } 72 | 73 | @SubscribeEvent 74 | public static void onKeyInput(InputEvent.KeyInputEvent event) { 75 | if (!enabled || Minecraft.getMinecraft().world == null || Minecraft.getMinecraft().player == null) { 76 | return; 77 | } 78 | if (show) { 79 | if (!GuiScreen.isAltKeyDown()) { 80 | // swap items on server 81 | if (verticalIndex != 0) { 82 | int index = 4 - verticalIndex; 83 | int current = Minecraft.getMinecraft().player.inventory.currentItem; 84 | NetworkHandler.sendToServer(new CHotbarSwap(current, current + index * 9)); 85 | } 86 | 87 | show = false; 88 | verticalIndex = 0; 89 | } 90 | } else { 91 | if (GuiScreen.isAltKeyDown()) { 92 | show = true; 93 | verticalIndex = 0; 94 | } 95 | } 96 | } 97 | 98 | @SubscribeEvent 99 | public static void onMouseInput(InputEvent.MouseInputEvent event) { 100 | if (!enabled) return; 101 | if (show) { 102 | int scroll = Mouse.getEventDWheel(); 103 | if (scroll != 0) { 104 | scroll = MathHelper.clamp(scroll, -1, 1); 105 | verticalIndex += scroll; 106 | if (verticalIndex > 3) { 107 | verticalIndex = 0; 108 | } else if (verticalIndex < 0) { 109 | verticalIndex = 3; 110 | } 111 | } 112 | } 113 | } 114 | 115 | private static void renderHotbarItem(int x, int y, float partialTicks, EntityPlayer player, ItemStack stack) { 116 | if (!stack.isEmpty()) { 117 | RenderItem renderer = Minecraft.getMinecraft().getRenderItem(); 118 | float f = (float) stack.getAnimationsToGo() - partialTicks; 119 | 120 | if (f > 0.0F) { 121 | GlStateManager.pushMatrix(); 122 | float f1 = 1.0F + f / 5.0F; 123 | GlStateManager.translate((float) (x + 8), (float) (y + 12), 0.0F); 124 | GlStateManager.scale(1.0F / f1, (f1 + 1.0F) / 2.0F, 1.0F); 125 | GlStateManager.translate((float) (-(x + 8)), (float) (-(y + 12)), 0.0F); 126 | } 127 | 128 | renderer.renderItemAndEffectIntoGUI(player, stack, x, y); 129 | 130 | if (f > 0.0F) { 131 | GlStateManager.popMatrix(); 132 | } 133 | 134 | renderer.renderItemOverlays(Minecraft.getMinecraft().fontRenderer, stack, x, y); 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/com/cleanroommc/bogosorter/api/IBogoSortAPI.java: -------------------------------------------------------------------------------- 1 | package com.cleanroommc.bogosorter.api; 2 | 3 | import com.cleanroommc.bogosorter.BogoSortAPI; 4 | 5 | import net.minecraft.client.gui.GuiScreen; 6 | import net.minecraft.inventory.Container; 7 | import net.minecraft.inventory.Slot; 8 | import net.minecraft.item.ItemStack; 9 | import net.minecraft.nbt.NBTBase; 10 | import net.minecraftforge.fml.relauncher.Side; 11 | import net.minecraftforge.fml.relauncher.SideOnly; 12 | 13 | import org.jetbrains.annotations.ApiStatus; 14 | import org.jetbrains.annotations.NotNull; 15 | import org.jetbrains.annotations.Nullable; 16 | 17 | import java.util.Comparator; 18 | import java.util.List; 19 | import java.util.function.BiConsumer; 20 | import java.util.function.Function; 21 | 22 | @ApiStatus.NonExtendable 23 | public interface IBogoSortAPI { 24 | 25 | static IBogoSortAPI getInstance() { 26 | return BogoSortAPI.INSTANCE; 27 | } 28 | 29 | /** 30 | * Register a function that converts a {@link Slot} to a {@link ISlot}. Useful if modders messed up. 31 | * 32 | * @param clazz slot class 33 | * @param function converter function 34 | * @param slot type 35 | */ 36 | void addSlotGetter(Class clazz, Function function); 37 | 38 | /** 39 | * Registers a function which handles slot insertions in a custom way. 40 | * 41 | * @param clazz container class 42 | * @param insertable custom insertion function 43 | */ 44 | void addCustomInsertable(Class clazz, ICustomInsertable insertable); 45 | 46 | /** 47 | * Adds sorting compat for a container class 48 | * 49 | * @param clazz container class 50 | * @param builder sorting compat builder 51 | * @param container type 52 | */ 53 | void addCompat(Class clazz, BiConsumer builder); 54 | 55 | /** 56 | * Adds generic sorting compat for a container class. Meaning the slots must layed out in a rectangular shape. 57 | * 58 | * @param clazz container class 59 | * @param container type 60 | */ 61 | default void addGenericCompat(Class clazz) { 62 | addCompat(clazz, (container, builder) -> builder.addGenericSlotGroup()); 63 | } 64 | 65 | /** 66 | * Adds sorting compat for a container class. 67 | * Is useful when you don't have access to the super class of {@link T} 68 | * 69 | * @param clazz container class 70 | * @param builder sorting compat builder 71 | * @param container type 72 | */ 73 | @ApiStatus.Internal 74 | void addCompatSimple(Class clazz, BiConsumer builder); 75 | 76 | /** 77 | * Registers a function to figure out where to place player inventory sort buttons. 78 | * 79 | * @param clazz class of the container 80 | * @param buttonPos pos function or null if no buttons are desired 81 | * @throws IllegalArgumentException if the class is not of a container 82 | */ 83 | void addPlayerSortButtonPosition(Class clazz, @Nullable IPosSetter buttonPos); 84 | 85 | /** 86 | * Removes sorting compat for a container class 87 | * 88 | * @param clazz container class 89 | * @param container type 90 | */ 91 | void removeCompat(Class clazz); 92 | 93 | /** 94 | * Registers a sorting rule for items 95 | * 96 | * @param itemComparator comparator 97 | */ 98 | void registerItemSortingRule(String key, Comparator itemComparator); 99 | 100 | /** 101 | * Registers a sorting rule for NBT tags 102 | * 103 | * @param tagPath path of the nbt tag. Separate sub tags with '/' 104 | * @param comparator comparator sorting the tags based on tagPath 105 | */ 106 | void registerNbtSortingRule(String key, String tagPath, Comparator comparator); 107 | 108 | /** 109 | * Registers a sorting rule for NBT tags 110 | * 111 | * @param tagPath path of the nbt tag. Separate sub tags with '/' 112 | * @param expectedType the expected NBT tag id. Will be automatically compared 113 | * @see net.minecraftforge.common.util.Constants.NBT for expectedType 114 | */ 115 | void registerNbtSortingRule(String key, String tagPath, int expectedType); 116 | 117 | /** 118 | * Registers a sorting rule for NBT tags 119 | * 120 | * @param tagPath path of the nbt tag. Separate sub tags with '/' 121 | * @param expectedType the expected NBT tag id 122 | * @param comparator comparator of the type converted by converter 123 | * @param converter converts the tag found at the tagPath for the comparator 124 | * @see net.minecraftforge.common.util.Constants.NBT for expectedType 125 | */ 126 | void registerNbtSortingRule(String key, String tagPath, int expectedType, Comparator comparator, Function converter); 127 | 128 | /** 129 | * Opens the bogosort config gui 130 | */ 131 | @SideOnly(Side.CLIENT) 132 | default void openConfigGui() { 133 | openConfigGui(null); 134 | } 135 | 136 | @SideOnly(Side.CLIENT) 137 | void openConfigGui(GuiScreen old); 138 | 139 | /** 140 | * Tries to sort a slot group with the given slot. 141 | * 142 | * @param slot slot of slot group to sort 143 | * @return if the slot group will be sorted (on server side) 144 | */ 145 | @SideOnly(Side.CLIENT) 146 | boolean sortSlotGroup(Slot slot); 147 | 148 | /** 149 | * Turns a slot into a generic interface slot 150 | * 151 | * @param slot slot 152 | * @return generic slot 153 | */ 154 | ISlot getSlot(Slot slot); 155 | 156 | /** 157 | * Transforms a list of slots using {@link #getSlot(Slot)} 158 | * 159 | * @param slots list of slots 160 | * @return list of generic slots 161 | */ 162 | List getSlots(@NotNull List slots); 163 | } 164 | --------------------------------------------------------------------------------