diff --git a/.github/resources/BigInv_compat.png b/.github/resources/BigInv_compat.png new file mode 100644 index 0000000..059b3d9 Binary files /dev/null and b/.github/resources/BigInv_compat.png differ diff --git a/.github/resources/InventoryTabs.png b/.github/resources/InventoryTabs.png new file mode 100644 index 0000000..e3112f6 Binary files /dev/null and b/.github/resources/InventoryTabs.png differ diff --git a/.github/resources/Tabs_showcase.gif b/.github/resources/Tabs_showcase.gif new file mode 100644 index 0000000..35cdf81 Binary files /dev/null and b/.github/resources/Tabs_showcase.gif differ diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..f7478a9 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,39 @@ +# Automatically build the project and run any configured tests for every push +# and submitted pull request. This can help catch issues that only occur on +# certain platforms or Java versions, and provides a first line of defence +# against bad commits. + +name: build +on: [pull_request, push] + +jobs: + build: + strategy: + matrix: + # Use these Java versions + java: [ + 17 # Minimum supported by Minecraft + ] + # and run on both Linux and Windows + os: [ubuntu-20.04, windows-latest] + runs-on: ${{ matrix.os }} + steps: + - name: checkout repository + uses: actions/checkout@v2 + - name: validate gradle wrapper + uses: gradle/wrapper-validation-action@v1 + - name: setup jdk ${{ matrix.java }} + uses: actions/setup-java@v1 + with: + java-version: ${{ matrix.java }} + - name: make gradle wrapper executable + if: ${{ runner.os != 'Windows' }} + run: chmod +x ./gradlew + - name: build + run: ./gradlew build + - name: capture build artifacts + if: ${{ runner.os == 'Linux' && matrix.java == '17' }} # Only upload artifacts built from latest java on one OS + uses: actions/upload-artifact@v2 + with: + name: Artifacts + path: build/libs/ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..f623def --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,34 @@ +name: Publish Artifacts + +on: + release: + types: [published] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 17 + uses: actions/setup-java@v2 + with: + distribution: 'adopt-hotspot' + java-version: 17 + cache: 'gradle' + - name: make gradle wrapper executable + run: chmod +x ./gradlew + - name: build + run: ./gradlew build + - uses: Kir-Antipov/mc-publish@v3.0 + with: + curseforge-id: 585506 + modrinth-id: F1AqcMCK + modrinth-featured: true + modrinth-unfeature-mode: intersection + modrinth-token: ${{ secrets.MODRINTH_TOKEN }} + curseforge-token: ${{ secrets.CURSEFORGE_TOKEN }} + version-type: beta + version-resolver: all + loaders: | + fabric + quilt \ No newline at end of file diff --git a/README.md b/README.md index b853262..b612534 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,48 @@ # InventoryTabs -Adds tabs to access nearby blocks. +Adds tabs to access nearby blocks without leaving your inventory. Completely client-side. Requires Cloth Config API. + +
+ +![Inventory Tabs showcase](https://raw.githubusercontent.com/Andrew6rant/inventorytabs/1.18.x/.github/resources/InventoryTabs.png) + + + +![Showcase GIF](https://raw.githubusercontent.com/Andrew6rant/inventorytabs/1.18.x/.github/resources/Tabs_showcase.gif) + +
+ +Also has [BigInv](https://github.com/SollyW/BigInv) and [PlayerEx](https://www.curseforge.com/minecraft/mc-mods/playerex) support! + +
+ +![BigInv support](https://raw.githubusercontent.com/Andrew6rant/inventorytabs/1.18.x/.github/resources/BigInv_compat.png) + + + +![PlayerEx support](https://user-images.githubusercontent.com/57331134/175751311-6edb68b4-82f4-4104-ba45-38139303536c.png) + +
+ +New in 0.8.1: Chest icons and hover text can be changed by nearby item frames! + +![InventoryTabs-nearby-item-frames](https://user-images.githubusercontent.com/57331134/180107483-11429056-8e99-4529-ad7d-7091032fb9aa.gif) + +New in 0.9.0: Entity support! + +
+ +![Chest Minecart showcase](https://user-images.githubusercontent.com/57331134/180368210-2510a9a3-0efb-49c9-9a1b-66b137739bf9.gif) + + + +![Villager inventory showcase](https://user-images.githubusercontent.com/57331134/180335139-9db9e488-9e1d-467f-9877-13db22173453.png) + +
+ ## Devs ### Importing -To add **Inventory Tabs** to your project, you need to add ``https://jitpack.io`` as a repo and ``com.github.cakewhip:inventorytabs:mcA.B.C-vX.Y.Z`` as a dependency. For example: +To add **Inventory Tabs** to your project, you need to add ``https://jitpack.io`` as a repo and ``com.github.Andrew6rant:InventoryTabs:inventorytabs-(mod version)-(Minecraft version)`` as a dependency. For example: ``` repositories { maven { @@ -12,9 +51,10 @@ repositories { } dependencies { - modImplementation "com.github.cakewhip:inventorytabs:mcA.B.C-vX.Y.Z" + modImplementation "com.github.Andrew6rant:InventoryTabs:inventorytabs-0.6.1-1.19.x" } ``` + See the releases page for available versions. ### Adding Custom Tabs @@ -36,3 +76,6 @@ Your handled screen needs to update the ``TabManager``, which you can grab a ref Finally, there are some methods to call for rendering and managing the tabs. In the ``render`` method before anything is drawn, call ``TabRenderer#renderBackground``. In the ``drawBackground``, call ``TabRenderer#renderForeground`` and ``TabRenderer#renderHoverTooltips``. In the ``mouseClicked`` method, call ``TabManager#mouseClicked``. If your screen's GUI dynamically changes (in the case of a recipe book opening), you can implement the ``TabRenderingHints`` interface and offset the top and bottom rows however you like. + +## Credits +This 1.18 and 1.19 port is based on LiamMCW's fork of the original mod by cakewhip. Full credits can be found at https://github.com/Andrew6rant/inventorytabs/graphs/contributors. diff --git a/build.gradle b/build.gradle index 4ea4e6d..14bfd2d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,19 +1,23 @@ plugins { - id 'fabric-loom' version '0.8-SNAPSHOT' + id 'fabric-loom' version '0.12-SNAPSHOT' id 'maven-publish' } -sourceCompatibility = JavaVersion.VERSION_16 -targetCompatibility = JavaVersion.VERSION_16 +sourceCompatibility = JavaVersion.VERSION_1_8 +targetCompatibility = JavaVersion.VERSION_1_8 archivesBaseName = project.archives_base_name -version = "${project.mod_version}-${project.minecraft_version}" +version = project.mod_version group = project.maven_group repositories { maven { url "https://maven.shedaniel.me/" } + maven { + name = 'terraformers maven' + url "https://maven.terraformersmc.com/releases" + } } dependencies { @@ -28,6 +32,11 @@ dependencies { modApi("me.shedaniel.cloth:cloth-config-fabric:${project.clothconfig_version}") { exclude(group: "net.fabricmc.fabric-api") } + + + modCompileOnly("com.terraformersmc:modmenu:${project.modmenu_version}") { + transitive = false + } // PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs. // You may need to force-disable transitiveness on them. } @@ -47,8 +56,8 @@ tasks.withType(JavaCompile).configureEach { // If Javadoc is generated, this must be specified in that task too. it.options.encoding = "UTF-8" - // Minecraft 1.17 (21w19a) upwards uses Java 16. - it.options.release = 16 + // Minecraft 1.18 (1.18-pre2) upwards uses Java 17. + it.options.release = 8 } java { @@ -58,6 +67,10 @@ java { withSourcesJar() } +loom { + setupRemappedVariants = true +} + jar { from("LICENSE") { rename { "${it}_${project.archivesBaseName}"} @@ -68,13 +81,7 @@ jar { publishing { publications { mavenJava(MavenPublication) { - // add all the jars that should be included when publishing to maven - artifact(remapJar) { - builtBy remapJar - } - artifact(sourcesJar) { - builtBy remapSourcesJar - } + from components.java } } diff --git a/gradle.properties b/gradle.properties index 621d107..e7a026d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -5,13 +5,14 @@ org.gradle.jvmargs=-Xmx1G # check these on https://fabricmc.net/versions.html minecraft_version=1.16.5 yarn_mappings=1.16.5+build.10 - loader_version=0.11.6 + loader_version=0.14.9 # Mod Properties - mod_version = 0.3.0 + mod_version = 0.9.beta-1.16.5 maven_group = com.kqp archives_base_name = inventorytabs # Dependencies - fabric_version=0.36.0+1.16 - clothconfig_version=4.11.26 + fabric_version=0.42.0+1.16 + clothconfig_version=4.14.54 + modmenu_version=1.14.14 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 05679dc..e750102 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/jitpack.yml b/jitpack.yml new file mode 100644 index 0000000..4a7f508 --- /dev/null +++ b/jitpack.yml @@ -0,0 +1,5 @@ +jdk: + - openjdk17 +before_install: + - sdk install java 17.0.1-open + - sdk use java 17.0.1-open diff --git a/settings.gradle b/settings.gradle index 5b60df3..b02216b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,10 +1,10 @@ pluginManagement { repositories { - jcenter() maven { name = 'Fabric' url = 'https://maven.fabricmc.net/' } + mavenCentral() gradlePluginPortal() } } diff --git a/src/main/java/com/kqp/inventorytabs/api/TabProviderRegistry.java b/src/main/java/com/kqp/inventorytabs/api/TabProviderRegistry.java index 596cefc..a9915ab 100644 --- a/src/main/java/com/kqp/inventorytabs/api/TabProviderRegistry.java +++ b/src/main/java/com/kqp/inventorytabs/api/TabProviderRegistry.java @@ -1,32 +1,32 @@ package com.kqp.inventorytabs.api; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import com.kqp.inventorytabs.init.InventoryTabs; -import com.kqp.inventorytabs.tabs.provider.ChestTabProvider; -import com.kqp.inventorytabs.tabs.provider.EnderChestTabProvider; -import com.kqp.inventorytabs.tabs.provider.PlayerInventoryTabProvider; -import com.kqp.inventorytabs.tabs.provider.ShulkerBoxTabProvider; -import com.kqp.inventorytabs.tabs.provider.SimpleBlockTabProvider; -import com.kqp.inventorytabs.tabs.provider.TabProvider; - -import net.minecraft.block.AnvilBlock; -import net.minecraft.block.Block; -import net.minecraft.block.Blocks; +import com.kqp.inventorytabs.interf.TabManagerContainer; +import com.kqp.inventorytabs.tabs.provider.*; + +import net.minecraft.block.*; +import net.minecraft.client.MinecraftClient; +import net.minecraft.tag.BlockTags; +import net.minecraft.tag.Tag; import net.minecraft.util.Identifier; import net.minecraft.util.registry.Registry; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + /** * Registry for tab providers. */ public class TabProviderRegistry { + private static final Logger LOGGER = LogManager.getLogger("InventoryTabs"); private static final Map TAB_PROVIDERS = new HashMap<>(); public static final PlayerInventoryTabProvider PLAYER_INVENTORY_TAB_PROVIDER = (PlayerInventoryTabProvider) register( InventoryTabs.id("player_inventory_tab_provider"), new PlayerInventoryTabProvider()); + public static final SimpleEntityTabProvider ENTITY_TAB_PROVIDER = (SimpleEntityTabProvider) register( + InventoryTabs.id("entity_tab_provider"), new SimpleEntityTabProvider()); public static final SimpleBlockTabProvider SIMPLE_BLOCK_TAB_PROVIDER = (SimpleBlockTabProvider) register( InventoryTabs.id("simple_block_tab_provider"), new SimpleBlockTabProvider()); public static final ChestTabProvider CHEST_TAB_PROVIDER = (ChestTabProvider) register( @@ -35,108 +35,104 @@ public class TabProviderRegistry { InventoryTabs.id("ender_chest_tab_provider"), new EnderChestTabProvider()); public static final ShulkerBoxTabProvider SHULKER_BOX_TAB_PROVIDER = (ShulkerBoxTabProvider) register( InventoryTabs.id("shulker_box_tab_provider"), new ShulkerBoxTabProvider()); - - public static void init() { - addVanillaSimpleBlockTabProviders(); - addVanillaChestTabProviders(); - addModSimpleBlockTabProviders(); - } - - private static void addVanillaSimpleBlockTabProviders() { - registerSimpleBlock(Blocks.FURNACE); - registerSimpleBlock(Blocks.CARTOGRAPHY_TABLE); - registerSimpleBlock(Blocks.CRAFTING_TABLE); - registerSimpleBlock(Blocks.ENCHANTING_TABLE); - registerSimpleBlock(Blocks.GRINDSTONE); - registerSimpleBlock(Blocks.LOOM); - registerSimpleBlock(Blocks.SMITHING_TABLE); - registerSimpleBlock(Blocks.STONECUTTER); - registerSimpleBlock(Blocks.BARREL); - registerSimpleBlock(Blocks.BLAST_FURNACE); - registerSimpleBlock(Blocks.SMOKER); - registerSimpleBlock(Blocks.BREWING_STAND); - registerSimpleBlock(Blocks.DISPENSER); - registerSimpleBlock(Blocks.DROPPER); - registerSimpleBlock(Blocks.HOPPER); - + public static final UniqueTabProvider UNIQUE_TAB_PROVIDER = (UniqueTabProvider) register( + InventoryTabs.id("crafting_table_tab_provider"), new UniqueTabProvider()); + public static final LecternTabProvider LECTERN_TAB_PROVIDER = (LecternTabProvider) register( + InventoryTabs.id("lectern_tab_provider"), new LecternTabProvider()); + public static final InventoryTabProvider INVENTORY_TAB_PROVIDER = (InventoryTabProvider) register( + InventoryTabs.id("inventory_tab_provider"), new InventoryTabProvider()); + + public static void init(String configMsg) { + LOGGER.info("InventoryTabs: Attempting to "+configMsg+" config..."); + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.warn("InventoryTabs: DEBUG ENABLED"); + } + Set invalidSet = new HashSet<>(); + Set tagSet = new HashSet<>(); + Set blockSet = new HashSet<>(); + for (String overrideEntry : InventoryTabs.getConfig().excludeTab) { + if (overrideEntry.startsWith("#")) { + tagSet.add(overrideEntry.trim().substring(1)); + } else { + blockSet.add(overrideEntry); + } + } Registry.BLOCK.forEach(block -> { - if (block instanceof AnvilBlock) { - registerSimpleBlock(block); + if (block instanceof BlockEntityProvider) { + if (block instanceof AbstractChestBlock) { + registerChest(block); + } else if (!(block instanceof AbstractBannerBlock) && !(block instanceof AbstractSignBlock) && !(block instanceof AbstractSkullBlock) && !(block instanceof BeehiveBlock) && !(block instanceof BedBlock) && !(block instanceof BellBlock) && !(block instanceof CampfireBlock) && !(block instanceof ComparatorBlock) && !(block instanceof ConduitBlock) && !(block instanceof DaylightDetectorBlock) && !(block instanceof EndGatewayBlock) && !(block instanceof EndPortalBlock) && !(block instanceof JukeboxBlock) && !(block instanceof PistonExtensionBlock) && !(block instanceof SpawnerBlock)) { + registerSimpleBlock(block); + } + } else if (block instanceof CraftingTableBlock && !(block instanceof FletchingTableBlock) || block instanceof AnvilBlock || block instanceof CartographyTableBlock || block instanceof GrindstoneBlock || block instanceof LoomBlock || block instanceof StonecutterBlock) { + registerUniqueBlock(block); } + configRemove(block, tagSet, invalidSet); }); + configRemove(blockSet); + configAdd(); + registerEntity(new Identifier("minecraft:entity.minecraft.chest_minecart")); + + MinecraftClient client = MinecraftClient.getInstance(); + TabManagerContainer tabManagerContainer = (TabManagerContainer) client; + tabManagerContainer.getTabManager().removeTabs(); + LOGGER.info(configMsg.equals("save") ? "InventoryTabs: Config saved!": "InventoryTabs: Config "+configMsg+"ed!"); + } + + private static void modCompatAdd() { + registerInventoryTab(new Identifier("onastick", "crafting_table_on_a_stick")); + registerInventoryTab(new Identifier("onastick", "smithing_table_on_a_stick")); + registerInventoryTab(new Identifier("onastick", "cartography_table_on_a_stick")); + registerInventoryTab(new Identifier("onastick", "anvil_on_a_stick")); + registerInventoryTab(new Identifier("onastick", "loom_on_a_stick")); + registerInventoryTab(new Identifier("onastick", "grindstone_on_a_stick")); + registerInventoryTab(new Identifier("onastick", "stonecutter_on_a_stick")); + registerInventoryTab(new Identifier("craftingpad", "craftingpad")); + } + + public static boolean isValid(String overrideEntry, String[] splitEntry, Set invalidSet) { + if (splitEntry.length != 2) { + invalidSet.add(overrideEntry); + return false; + } + return true; + } + + private static void configRemove(Set blockSet) { + for (String overrideEntry : blockSet) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Excluding: " + overrideEntry); + } + removeSimpleBlock(new Identifier(overrideEntry)); + } + } + + private static void configRemove(Block block, Set tagSet, Set invalidSet) { + for (String overrideEntry : tagSet) { + String[] splitEntry = overrideEntry.split(":"); // split into two parts: tag id, item name + if (isValid(overrideEntry, splitEntry, invalidSet)) { + Tag blockTag = BlockTags.getTagGroup().getTag(new Identifier(splitEntry[0], splitEntry[1])); + if (blockTag != null && block.isIn(blockTag)) { + removeSimpleBlock(block); + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Excluding: " + block); + } + } + } + } + } + + private static void configAdd() { + for (String included_tab : InventoryTabs.getConfig().includeTab) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Including: " + included_tab); + } + registerSimpleBlock(new Identifier(included_tab)); + } } - private static void addVanillaChestTabProviders() { - registerChest(Blocks.CHEST); - registerChest(Blocks.TRAPPED_CHEST); - } - - private static void addModSimpleBlockTabProviders() { - registerSimpleBlock(new Identifier("morecraftingtables", "warped_crafting_table")); - registerSimpleBlock(new Identifier("morecraftingtables", "spruce_crafting_table")); - registerSimpleBlock(new Identifier("morecraftingtables", "jungle_crafting_table")); - registerSimpleBlock(new Identifier("morecraftingtables", "dark_oak_crafting_table")); - registerSimpleBlock(new Identifier("morecraftingtables", "crimson_crafting_table")); - registerSimpleBlock(new Identifier("morecraftingtables", "birch_crafting_table")); - registerSimpleBlock(new Identifier("morecraftingtables", "acacia_crafting_table")); - - registerSimpleBlock(new Identifier("linkedstorage", "storageblock")); - - registerSimpleBlock(new Identifier("fabric-furnaces", "obsidian_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "nether_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "iron_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "gold_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "fabric_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "ethereal_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "end_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "emerald_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "diamond_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_obsidian_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_nether_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_iron_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_gold_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_fabric_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_ethereal_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_end_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_emerald_furnace")); - registerSimpleBlock(new Identifier("fabric-furnaces", "crystal_diamond_furnace")); - - registerSimpleBlock(new Identifier("automated_crafting", "auto_crafter")); - - registerSimpleBlock(new Identifier("byg", "zelkova_crafting_table")); - registerSimpleBlock(new Identifier("byg", "witch_hazel_crafting_table")); - registerSimpleBlock(new Identifier("byg", "willow_crafting_table")); - registerSimpleBlock(new Identifier("byg", "skyris_crafting_table")); - registerSimpleBlock(new Identifier("byg", "redwood_crafting_table")); - registerSimpleBlock(new Identifier("byg", "rainbow_eucalyptus_crafting_table")); - registerSimpleBlock(new Identifier("byg", "pine_crafting_table")); - registerSimpleBlock(new Identifier("byg", "aspen_crafting_table")); - registerSimpleBlock(new Identifier("byg", "baobab_crafting_table")); - registerSimpleBlock(new Identifier("byg", "blue_enchanted_crafting_table")); - registerSimpleBlock(new Identifier("byg", "cherry_crafting_table")); - registerSimpleBlock(new Identifier("byg", "cika_crafting_table")); - registerSimpleBlock(new Identifier("byg", "cypress_crafting_table")); - registerSimpleBlock(new Identifier("byg", "ebony_crafting_table")); - registerSimpleBlock(new Identifier("byg", "fir_crafting_table")); - registerSimpleBlock(new Identifier("byg", "green_enchanted_crafting_table")); - registerSimpleBlock(new Identifier("byg", "holly_crafting_table")); - registerSimpleBlock(new Identifier("byg", "jacaranda_crafting_table")); - registerSimpleBlock(new Identifier("byg", "mahogany_crafting_table")); - registerSimpleBlock(new Identifier("byg", "mangrove_crafting_table")); - registerSimpleBlock(new Identifier("byg", "maple_crafting_table")); - - registerSimpleBlock(new Identifier("better-nether", "crafting_table_crimson")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_mushroom")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_mushroom_fir")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_reed")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_rubeus")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_stalagnate")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_warped")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_wart")); - registerSimpleBlock(new Identifier("better-nether", "crafting_table_willow")); - registerSimpleBlock(new Identifier("better-nether", "basalt_furnace")); - registerSimpleBlock(new Identifier("better-nether", "blackstone_furnace")); - registerSimpleBlock(new Identifier("better-nether", "netherrack_furnace")); + public static void registerInventoryTab(Identifier itemId) { + INVENTORY_TAB_PROVIDER.addItem(itemId); } /** @@ -145,6 +141,9 @@ private static void addModSimpleBlockTabProviders() { * @param block */ public static void registerSimpleBlock(Block block) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Registering: " + block); + } SIMPLE_BLOCK_TAB_PROVIDER.addBlock(block); } @@ -154,18 +153,47 @@ public static void registerSimpleBlock(Block block) { * @param blockId */ public static void registerSimpleBlock(Identifier blockId) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Registering: " + blockId); + } SIMPLE_BLOCK_TAB_PROVIDER.addBlock(blockId); } + + public static void removeSimpleBlock(Block block) { + SIMPLE_BLOCK_TAB_PROVIDER.removeBlock(block); + } + + public static void removeSimpleBlock(Identifier blockId) { + SIMPLE_BLOCK_TAB_PROVIDER.removeBlock(blockId); + } + /** * Used to register a chest with the chest tab provider. * * @param block */ public static void registerChest(Block block) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Registering: " + block); + } CHEST_TAB_PROVIDER.addChestBlock(block); } + public static void registerUniqueBlock(Block block) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Registering: " + block); + } + UNIQUE_TAB_PROVIDER.addUniqueBlock(block); + } + + public static void registerEntity(Identifier entityId) { + if (InventoryTabs.getConfig().debugEnabled) { + LOGGER.info("Registering: " + entityId); + } + ENTITY_TAB_PROVIDER.addEntity(entityId); + } + /** * Used to register a chest with the chest tab provider. * @@ -177,7 +205,6 @@ public static void registerChest(Identifier blockId) { public static TabProvider register(Identifier id, TabProvider tabProvider) { TAB_PROVIDERS.put(id, tabProvider); - return tabProvider; } diff --git a/src/main/java/com/kqp/inventorytabs/init/InventoryTabs.java b/src/main/java/com/kqp/inventorytabs/init/InventoryTabs.java index 1cfcc50..db40d74 100644 --- a/src/main/java/com/kqp/inventorytabs/init/InventoryTabs.java +++ b/src/main/java/com/kqp/inventorytabs/init/InventoryTabs.java @@ -1,12 +1,23 @@ package com.kqp.inventorytabs.init; +import com.kqp.inventorytabs.api.TabProviderRegistry; import me.shedaniel.autoconfig.AutoConfig; -import me.shedaniel.autoconfig.serializer.JanksonConfigSerializer; +import me.shedaniel.autoconfig.ConfigHolder; +import me.shedaniel.autoconfig.serializer.GsonConfigSerializer; import net.fabricmc.api.ModInitializer; +import net.fabricmc.fabric.api.client.networking.v1.ClientLoginConnectionEvents; +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.util.ActionResult; import net.minecraft.util.Identifier; public class InventoryTabs implements ModInitializer { public static final String ID = "inventorytabs"; + static ConfigHolder inventoryTabsConfig; + + public static boolean isBigInvLoaded; + public static boolean isPlayerExLoaded; + public static boolean isLevelzLoaded; public static Identifier id(String path) { return new Identifier(ID, path); @@ -14,7 +25,17 @@ public static Identifier id(String path) { @Override public void onInitialize() { - AutoConfig.register(InventoryTabsConfig.class, JanksonConfigSerializer::new); + inventoryTabsConfig = AutoConfig.register(InventoryTabsConfig.class, GsonConfigSerializer::new); + inventoryTabsConfig.registerSaveListener((configHolder, config) -> { + TabProviderRegistry.init("save"); + return ActionResult.success(true); + }); + ClientLoginConnectionEvents.INIT.register((handler, client) -> TabProviderRegistry.init("load")); + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register((server, resourceManager, success) -> TabProviderRegistry.init("reload")); + + isBigInvLoaded = FabricLoader.getInstance().isModLoaded("biginv"); + isPlayerExLoaded = FabricLoader.getInstance().isModLoaded("playerex"); + isLevelzLoaded = FabricLoader.getInstance().isModLoaded("levelz"); } public static InventoryTabsConfig getConfig() { diff --git a/src/main/java/com/kqp/inventorytabs/init/InventoryTabsClient.java b/src/main/java/com/kqp/inventorytabs/init/InventoryTabsClient.java index 16029bc..33b82d3 100644 --- a/src/main/java/com/kqp/inventorytabs/init/InventoryTabsClient.java +++ b/src/main/java/com/kqp/inventorytabs/init/InventoryTabsClient.java @@ -1,6 +1,5 @@ package com.kqp.inventorytabs.init; -import com.kqp.inventorytabs.api.TabProviderRegistry; import com.kqp.inventorytabs.interf.TabManagerContainer; import org.lwjgl.glfw.GLFW; @@ -9,6 +8,9 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; import net.fabricmc.fabric.api.client.keybinding.v1.KeyBindingHelper; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.CreativeInventoryScreen; +import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.option.KeyBinding; import net.minecraft.client.util.InputUtil; @@ -20,8 +22,6 @@ public class InventoryTabsClient implements ClientModInitializer { @Override public void onInitializeClient() { - TabProviderRegistry.init(); - // Handle state of tab managerInventoryTabsClient ClientTickEvents.START_WORLD_TICK.register(world -> { MinecraftClient client = MinecraftClient.getInstance(); @@ -33,4 +33,8 @@ public void onInitializeClient() { } }); } + + public static boolean screenSupported(Screen screen) { + return (screen instanceof HandledScreen) && !(screen instanceof CreativeInventoryScreen); + } } diff --git a/src/main/java/com/kqp/inventorytabs/init/InventoryTabsConfig.java b/src/main/java/com/kqp/inventorytabs/init/InventoryTabsConfig.java index e4fdff7..8708756 100644 --- a/src/main/java/com/kqp/inventorytabs/init/InventoryTabsConfig.java +++ b/src/main/java/com/kqp/inventorytabs/init/InventoryTabsConfig.java @@ -2,10 +2,27 @@ import me.shedaniel.autoconfig.ConfigData; import me.shedaniel.autoconfig.annotation.Config; +import me.shedaniel.autoconfig.annotation.ConfigEntry; + +import java.util.Arrays; +import java.util.List; @Config(name = "inventory_tabs") public class InventoryTabsConfig implements ConfigData { - public boolean doSightChecksFlag = false; + @ConfigEntry.Gui.Tooltip + public boolean doSightChecksFlag = true; + @ConfigEntry.Gui.Tooltip public boolean rotatePlayer = false; - public boolean targetAllScreenHandledBlocks = false; + + @ConfigEntry.Gui.Tooltip + public List excludeTab = Arrays.asList( + "tiered:reforging_station", + "#techreborn:block_entities_without_inventories", + "#inventorytabs:mod_compat_blacklist" + ); + + @ConfigEntry.Gui.Tooltip + public List includeTab = Arrays.asList(); + + public boolean debugEnabled = false; } diff --git a/src/main/java/com/kqp/inventorytabs/init/InventoryTabsModMenu.java b/src/main/java/com/kqp/inventorytabs/init/InventoryTabsModMenu.java new file mode 100644 index 0000000..976cf68 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/init/InventoryTabsModMenu.java @@ -0,0 +1,15 @@ +package com.kqp.inventorytabs.init; + +import io.github.prospector.modmenu.api.ConfigScreenFactory; +import io.github.prospector.modmenu.api.ModMenuApi; +import me.shedaniel.autoconfig.AutoConfig; +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; + +@Environment(EnvType.CLIENT) +public class InventoryTabsModMenu implements ModMenuApi { + @Override + public ConfigScreenFactory getModConfigScreenFactory() { + return parent -> AutoConfig.getConfigScreen(InventoryTabsConfig.class, parent).get(); + } +} diff --git a/src/main/java/com/kqp/inventorytabs/mixin/ControlsListWidget$KeyBindingEntryMixin_SoftConflict.java b/src/main/java/com/kqp/inventorytabs/mixin/ControlsListWidget$KeyBindingEntryMixin_SoftConflict.java new file mode 100644 index 0000000..af502a3 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/mixin/ControlsListWidget$KeyBindingEntryMixin_SoftConflict.java @@ -0,0 +1,36 @@ +package com.kqp.inventorytabs.mixin; + +import java.util.Objects; + +import com.kqp.inventorytabs.init.InventoryTabsClient; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyArg; + +import net.minecraft.client.gui.screen.option.ControlsListWidget; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.text.Text; +import net.minecraft.text.TextColor; +import net.minecraft.util.Formatting; + +/** + * The 'Tab' keybinding conflicts with the multiplayer player list keybind, but since you can only see the player list when outside the inventory + * anyways, the conflict can be soft and not hard. + */ +@Mixin(ControlsListWidget.KeyBindingEntry.class) +public class ControlsListWidget$KeyBindingEntryMixin_SoftConflict { + @Shadow @Final private KeyBinding binding; + + @ModifyArg(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/ButtonWidget;setMessage(Lnet/minecraft/text/Text;)V")) + public Text setMessage(Text text) { + TextColor c = text.getStyle().getColor(); + if(c != null && c.getRgb() == Objects.requireNonNull(Formatting.RED.getColorValue())) { + if(this.binding == InventoryTabsClient.NEXT_TAB_KEY_BIND) { + text = text.copy().formatted(Formatting.GOLD); + } + } + return text; + } +} diff --git a/src/main/java/com/kqp/inventorytabs/mixin/KeyBindingMixin_SoftConflict.java b/src/main/java/com/kqp/inventorytabs/mixin/KeyBindingMixin_SoftConflict.java new file mode 100644 index 0000000..0709020 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/mixin/KeyBindingMixin_SoftConflict.java @@ -0,0 +1,64 @@ +package com.kqp.inventorytabs.mixin; + +import java.util.Map; +import java.util.Objects; + +import com.kqp.inventorytabs.init.InventoryTabsClient; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.option.KeyBinding; +import net.minecraft.client.util.InputUtil; + +@Mixin(KeyBinding.class) +public abstract class KeyBindingMixin_SoftConflict { + @Shadow @Final private static Map keysById; + + @Shadow private InputUtil.Key boundKey; + + @Shadow private int timesPressed; + + @Shadow public abstract void setPressed(boolean pressed); + + @Shadow private boolean pressed; + + @Inject(method = "onKeyPressed", at = @At(value = "FIELD", target = "Lnet/minecraft/client/option/KeyBinding;timesPressed:I"), + locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true) + private static void onKeyPressed(InputUtil.Key key, CallbackInfo ci, KeyBinding binding) { + KeyBindingMixin_SoftConflict alternative = (KeyBindingMixin_SoftConflict) (Object) findAlternative(key, binding, InventoryTabsClient.NEXT_TAB_KEY_BIND); + if(alternative != null) { + alternative.timesPressed++; + ci.cancel(); + } + } + + @Inject(method = "setKeyPressed", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/option/KeyBinding;setPressed(Z)V"), cancellable = true, locals = LocalCapture.CAPTURE_FAILHARD) + private static void keyPressed(InputUtil.Key key, boolean pressed, CallbackInfo ci, KeyBinding keyBinding) { + KeyBinding alternative = findAlternative(key, keyBinding, InventoryTabsClient.NEXT_TAB_KEY_BIND); + if(alternative != null) { + alternative.setPressed(pressed); + ci.cancel(); + } + } + + private static KeyBinding findAlternative(InputUtil.Key key, KeyBinding binding, KeyBinding alternativeTo) { + Screen screen = MinecraftClient.getInstance().currentScreen; + if(binding == alternativeTo && !InventoryTabsClient.screenSupported(screen)) { + for(KeyBinding value : keysById.values()) { + KeyBindingMixin_SoftConflict self = (KeyBindingMixin_SoftConflict) (Object) value; + InputUtil.Key bound = self.boundKey; + if(Objects.equals(bound, key) && value != alternativeTo) { + return value; + } + } + } + return null; + } +} diff --git a/src/main/java/com/kqp/inventorytabs/mixin/VanillaScreenTabAdder.java b/src/main/java/com/kqp/inventorytabs/mixin/VanillaScreenTabAdder.java index 407f5a2..b5b7994 100644 --- a/src/main/java/com/kqp/inventorytabs/mixin/VanillaScreenTabAdder.java +++ b/src/main/java/com/kqp/inventorytabs/mixin/VanillaScreenTabAdder.java @@ -3,6 +3,7 @@ import java.util.HashSet; import java.util.Set; +import com.kqp.inventorytabs.init.InventoryTabsClient; import com.kqp.inventorytabs.interf.TabManagerContainer; import com.kqp.inventorytabs.tabs.TabManager; import com.kqp.inventorytabs.tabs.render.TabRenderingHints; @@ -10,6 +11,10 @@ import com.kqp.inventorytabs.tabs.tab.Tab; import com.kqp.inventorytabs.util.ChestUtil; +import net.fabricmc.loader.api.FabricLoader; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.screen.ingame.*; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -20,33 +25,24 @@ import net.fabricmc.api.Environment; import net.minecraft.block.ChestBlock; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.gui.screen.ingame.AbstractFurnaceScreen; -import net.minecraft.client.gui.screen.ingame.AnvilScreen; -import net.minecraft.client.gui.screen.ingame.BrewingStandScreen; -import net.minecraft.client.gui.screen.ingame.CartographyTableScreen; -import net.minecraft.client.gui.screen.ingame.CraftingScreen; -import net.minecraft.client.gui.screen.ingame.EnchantmentScreen; -import net.minecraft.client.gui.screen.ingame.Generic3x3ContainerScreen; -import net.minecraft.client.gui.screen.ingame.GenericContainerScreen; -import net.minecraft.client.gui.screen.ingame.GrindstoneScreen; -import net.minecraft.client.gui.screen.ingame.HandledScreen; -import net.minecraft.client.gui.screen.ingame.HopperScreen; -import net.minecraft.client.gui.screen.ingame.InventoryScreen; -import net.minecraft.client.gui.screen.ingame.LoomScreen; -import net.minecraft.client.gui.screen.ingame.ShulkerBoxScreen; -import net.minecraft.client.gui.screen.ingame.SmithingScreen; -import net.minecraft.client.gui.screen.ingame.StonecutterScreen; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @Environment(EnvType.CLIENT) @Mixin(HandledScreen.class) -public class VanillaScreenTabAdder implements TabRenderingHints { +public abstract class VanillaScreenTabAdder extends Screen implements TabRenderingHints { + private static final boolean isBRBLoaded = FabricLoader.getInstance().isModLoaded("brb"); // Better Recipe Book compat + + protected VanillaScreenTabAdder(Text title) { + super(title); + } + @Inject(method = "init", at = @At("RETURN")) private void initTabRenderer(CallbackInfo callbackInfo) { - if (screenSupported()) { + if (InventoryTabsClient.screenSupported(this)) { MinecraftClient client = MinecraftClient.getInstance(); TabManager tabManager = ((TabManagerContainer) client).getTabManager(); @@ -97,7 +93,7 @@ private void initTabRenderer(CallbackInfo callbackInfo) { @Inject(method = "render", at = @At("HEAD")) protected void drawBackgroundTabs(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo callbackInfo) { - if (screenSupported()) { + if (InventoryTabsClient.screenSupported(this)) { if (!screenDoesDumbBlock()) { MinecraftClient client = MinecraftClient.getInstance(); TabManager tabManager = ((TabManagerContainer) client).getTabManager(); @@ -110,7 +106,7 @@ protected void drawBackgroundTabs(MatrixStack matrices, int mouseX, int mouseY, @Inject(method = "render", at = @At("TAIL")) protected void drawForegroundTabs(MatrixStack matrices, int mouseX, int mouseY, float delta, CallbackInfo callbackInfo) { - if (screenSupported()) { + if (InventoryTabsClient.screenSupported(this)) { MinecraftClient client = MinecraftClient.getInstance(); TabManager tabManager = ((TabManagerContainer) client).getTabManager(); @@ -121,7 +117,7 @@ protected void drawForegroundTabs(MatrixStack matrices, int mouseX, int mouseY, @Inject(method = "mouseClicked", at = @At("HEAD"), cancellable = true) public void mouseClicked(double mouseX, double mouseY, int button, CallbackInfoReturnable callbackInfo) { - if (screenSupported()) { + if (InventoryTabsClient.screenSupported(this)) { TabManager tabManager = ((TabManagerContainer) MinecraftClient.getInstance()).getTabManager(); if (tabManager.mouseClicked(mouseX, mouseY, button)) { @@ -132,7 +128,7 @@ public void mouseClicked(double mouseX, double mouseY, int button, CallbackInfoR @Inject(method = "keyPressed", at = @At("HEAD"), cancellable = true) public void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoReturnable callbackInfo) { - if (screenSupported()) { + if (InventoryTabsClient.screenSupported(this)) { TabManager tabManager = ((TabManagerContainer) MinecraftClient.getInstance()).getTabManager(); if (tabManager.keyPressed(keyCode, scanCode, modifiers)) { @@ -143,21 +139,22 @@ public void keyPressed(int keyCode, int scanCode, int modifiers, CallbackInfoRet @Override public int getTopRowXOffset() { - HandledScreen screen = (HandledScreen) (Object) this; - if (screen instanceof InventoryScreen) { - if (((InventoryScreen) screen).getRecipeBookWidget().isOpen()) { - return 77; - } - } else if (screen instanceof AbstractFurnaceScreen) { - if (((AbstractFurnaceScreen) screen).recipeBook.isOpen()) { - return 77; - } - } else if (screen instanceof CraftingScreen) { - if (((CraftingScreen) screen).getRecipeBookWidget().isOpen()) { - return 77; + if (!isBRBLoaded) { + HandledScreen screen = (HandledScreen) (Object) this; + if (screen instanceof InventoryScreen) { + if (((InventoryScreen) screen).getRecipeBookWidget().isOpen()) { + return 77; + } + } else if (screen instanceof AbstractFurnaceScreen) { + if (((AbstractFurnaceScreen) screen).recipeBook.isOpen()) { + return 77; + } + } else if (screen instanceof CraftingScreen) { + if (((CraftingScreen) screen).getRecipeBookWidget().isOpen()) { + return 77; + } } } - return 0; } @@ -170,20 +167,7 @@ public int getBottomRowXOffset() { public int getBottomRowYOffset() { return screenNeedsOffset() ? -1 : 0; } - - private boolean screenSupported() { - HandledScreen screen = (HandledScreen) (Object) this; - - return screen instanceof GenericContainerScreen || screen instanceof InventoryScreen - || screen instanceof AbstractFurnaceScreen || screen instanceof AnvilScreen - || screen instanceof CraftingScreen || screen instanceof ShulkerBoxScreen - || screen instanceof EnchantmentScreen || screen instanceof BrewingStandScreen - || screen instanceof SmithingScreen || screen instanceof CartographyTableScreen - || screen instanceof LoomScreen || screen instanceof StonecutterScreen - || screen instanceof GrindstoneScreen || screen instanceof HopperScreen - || screen instanceof Generic3x3ContainerScreen; - } - + private boolean screenDoesDumbBlock() { HandledScreen screen = (HandledScreen) (Object) this; diff --git a/src/main/java/com/kqp/inventorytabs/tabs/TabManager.java b/src/main/java/com/kqp/inventorytabs/tabs/TabManager.java index 995be96..e60cf5e 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/TabManager.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/TabManager.java @@ -11,20 +11,22 @@ import com.kqp.inventorytabs.mixin.accessor.HandledScreenAccessor; import com.kqp.inventorytabs.tabs.render.TabRenderInfo; import com.kqp.inventorytabs.tabs.render.TabRenderer; +import com.kqp.inventorytabs.tabs.render.TabRenderingHints; +import com.kqp.inventorytabs.tabs.tab.PlayerInventoryTab; import com.kqp.inventorytabs.tabs.tab.Tab; import com.kqp.inventorytabs.util.MouseUtil; -import org.lwjgl.glfw.GLFW; - import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.sound.PositionedSoundInstance; -import net.minecraft.client.util.InputUtil; import net.minecraft.network.packet.c2s.play.CloseHandledScreenC2SPacket; import net.minecraft.sound.SoundEvents; +import static com.kqp.inventorytabs.init.InventoryTabs.*; + /** * Manages everything related to tabs. */ @@ -53,6 +55,12 @@ public void update() { public void setCurrentTab(Tab tab) { this.currentTab = tab; } + public void removeTabs() { + for (int i = 0; i < tabs.size(); i++) { + tabs.remove(i); + i--; + } + } private void refreshAvailableTabs() { // Remove old ones @@ -68,6 +76,17 @@ private void refreshAvailableTabs() { tabProvider.addAvailableTabs(MinecraftClient.getInstance().player, tabs); }); + if (currentTab != null) { + for (int i = 0; i < tabs.size(); i++) { + Tab tab = tabs.get(i); + if (currentTab != tab && currentTab.equals(tab)) { + // We've come across a tab we already have open + tabs.set(i, currentTab); + break; + } + } + } + // Sort tabs.sort( Comparator.comparing(Tab::getPriority).reversed().thenComparing(tab -> tab.getHoverText().getString())); @@ -85,7 +104,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } // Check back button - if (new Rectangle(x - TabRenderer.BUTTON_WIDTH - 4, y - 16, TabRenderer.BUTTON_WIDTH, + if (new Rectangle(x - TabRenderer.BUTTON_WIDTH - 4 + ((TabRenderingHints) currentScreen).getTopRowXOffset(), y - 16, TabRenderer.BUTTON_WIDTH, TabRenderer.BUTTON_HEIGHT).contains(mouseX, mouseY)) { if (canGoBackAPage()) { setCurrentPage(currentPage - 1); @@ -96,7 +115,7 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { } // Check forward button - if (new Rectangle(x + guiWidth + 4, y - 16, TabRenderer.BUTTON_WIDTH, TabRenderer.BUTTON_HEIGHT) + if (new Rectangle(x + guiWidth + 4 + ((TabRenderingHints) currentScreen).getTopRowXOffset(), y - 16, TabRenderer.BUTTON_WIDTH, TabRenderer.BUTTON_HEIGHT) .contains(mouseX, mouseY)) { if (canGoForwardAPage()) { setCurrentPage(currentPage + 1); @@ -132,16 +151,18 @@ public boolean mouseClicked(double mouseX, double mouseY, int button) { public boolean keyPressed(int keyCode, int scanCode, int modifiers) { if (InventoryTabsClient.NEXT_TAB_KEY_BIND.matchesKey(keyCode, scanCode)) { int currentTabIndex = tabs.indexOf(currentTab); - - if (InputUtil.isKeyPressed(MinecraftClient.getInstance().getWindow().getHandle(), - GLFW.GLFW_KEY_LEFT_SHIFT)) { + if (Screen.hasShiftDown()) { if (currentTabIndex > 0) { onTabClick(tabs.get(currentTabIndex - 1)); + } else { + onTabClick(tabs.get(tabs.size() - 1)); } return true; } else { if (currentTabIndex < tabs.size() - 1) { onTabClick(tabs.get(currentTabIndex + 1)); + } else { + onTabClick(tabs.get(0)); } return true; @@ -164,7 +185,9 @@ public void onTabClick(Tab tab) { MouseUtil.push(); // Set tab open flag - tabOpenedRecently = true; + if (!(tab instanceof PlayerInventoryTab)) { + tabOpenedRecently = true; + } // Close any handled screens // This fixes the inventory desync issue @@ -190,8 +213,13 @@ public void onOpenTab(Tab tab) { public int pageOf(Tab tab) { int index = tabs.indexOf(tab); - - return index / (getMaxRowLength() * 2); + if(isBigInvLoaded) { + return index / (getMaxRowLength() * 2 + 5); + } else if(isPlayerExLoaded || isLevelzLoaded) { + return index / (getMaxRowLength() * 2 - 2); + } else { + return index / (getMaxRowLength() * 2); + } } public int getMaxRowLength() { @@ -210,7 +238,13 @@ public HandledScreen getCurrentScreen() { } public void setCurrentPage(int page) { - if (page > 0 && tabs.size() < getMaxRowLength() * 2) { + int maxRowLength = getMaxRowLength() * 2; + if (isPlayerExLoaded) { + maxRowLength =- 3; + } else if (isLevelzLoaded) { + maxRowLength =- 2; + } + if (page > 0 && tabs.size() < maxRowLength) { System.err.println("Not enough tabs to paginate, ignoring"); return; @@ -234,7 +268,15 @@ public boolean screenOpenedViaTab() { } public int getMaxPages() { - return tabs.size() / (getMaxRowLength() * 2 + 1); + if(isBigInvLoaded) { + return tabs.size() / (getMaxRowLength() * 2 + 6); + } else if(isPlayerExLoaded) { + return tabs.size() / (getMaxRowLength() * 2 - 2); + } else if(isLevelzLoaded) { + return tabs.size() / (getMaxRowLength() * 2 - 1); + } else { + return tabs.size() / (getMaxRowLength() * 2 + 1); + } } public boolean canGoBackAPage() { diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/ChestTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/ChestTabProvider.java index c93350f..70f7eab 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/provider/ChestTabProvider.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/ChestTabProvider.java @@ -38,9 +38,7 @@ public void addAvailableTabs(ClientPlayerEntity player, List tabs) { // Add any chests that are blocked chestTabs.stream().filter(tab -> ChestBlock.isChestBlocked(world, tab.blockPos)).forEach(tabsToRemove::add); - for (int i = 0; i < chestTabs.size(); i++) { - ChestTab tab = chestTabs.get(i); - + for (ChestTab tab : chestTabs) { if (!tabsToRemove.contains(tab)) { if (ChestUtil.isDouble(world, tab.blockPos)) { tabsToRemove.add(new ChestTab(tab.blockId, ChestUtil.getOtherChestBlockPos(world, tab.blockPos))); diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/EntityTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/EntityTabProvider.java new file mode 100644 index 0000000..fac2ced --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/EntityTabProvider.java @@ -0,0 +1,62 @@ +package com.kqp.inventorytabs.tabs.provider; + +import com.kqp.inventorytabs.tabs.tab.Tab; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.Inventory; +import net.minecraft.inventory.InventoryChangedListener; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; + +import java.util.List; + +public abstract class EntityTabProvider implements TabProvider { + public static final int SEARCH_DISTANCE = 5; + @Override + public void addAvailableTabs(ClientPlayerEntity player, List tabs) { + World world = player.world; + List entityList = world.getNonSpectatingEntities(Entity.class, new Box(player.getBlockPos().getX()-SEARCH_DISTANCE, player.getBlockPos().getY()-SEARCH_DISTANCE, player.getBlockPos().getZ()-SEARCH_DISTANCE, player.getBlockPos().getX()+SEARCH_DISTANCE, player.getBlockPos().getY()+SEARCH_DISTANCE, player.getBlockPos().getZ()+SEARCH_DISTANCE)); + + for (Entity entity : entityList) { + if (!(entity instanceof PlayerEntity) && ((entity instanceof Inventory) || (entity instanceof InventoryChangedListener))) { + if (matches(entity)) { + boolean add = false; + + Vec3d playerHead = player.getPos().add(0D, player.getEyeHeight(player.getPose()), 0D); + Vec3d blockVec = new Vec3d(entity.getX() + 0.5D, entity.getY() + 0.5D, + entity.getZ() + 0.5D); + + if (blockVec.subtract(playerHead).lengthSquared() <= SEARCH_DISTANCE * SEARCH_DISTANCE) { + add = true; + } + + + if (add) { + Tab tab = createTab(entity); + + if (!tabs.contains(tab)) { + tabs.add(tab); + } + } + } + } + } + } + /** + * Checks to see if block at passsed block position matches criteria. + * + * @param entity + * @return + */ + public abstract boolean matches(Entity entity); + + /** + * Method to create tabs. + * + * @param entity + * @return + */ + public abstract Tab createTab(Entity entity); +} \ No newline at end of file diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/InventoryTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/InventoryTabProvider.java new file mode 100644 index 0000000..46d2a51 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/InventoryTabProvider.java @@ -0,0 +1,44 @@ +package com.kqp.inventorytabs.tabs.provider; + +import com.kqp.inventorytabs.tabs.tab.InventoryTab; +import com.kqp.inventorytabs.tabs.tab.Tab; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Identifier; +import net.minecraft.util.registry.Registry; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +public class InventoryTabProvider implements TabProvider { + private static final Set inventoryItems = new HashSet<>(); + + @Override + public void addAvailableTabs(ClientPlayerEntity player, List tabs) { + Set itemSet = inventoryItems.stream().map(Registry.ITEM::get).collect(Collectors.toSet()); + for (Item item : itemSet) { + if (player.inventory.contains(new ItemStack(item))) { + Tab tab = new InventoryTab(item); + if (tabs.stream().filter(c -> c instanceof InventoryTab).noneMatch(c -> ((InventoryTab) c).itemId == item)) { + tabs.add(tab); + } + } + } + } + + public void addItem(Identifier blockId) { + inventoryItems.add(blockId); + } + + public Set getItemIds() { + return inventoryItems; + } + + public static Set getItems() { + return inventoryItems.stream().map(Registry.ITEM::get).collect(Collectors.toSet()); + } + +} diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/LecternTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/LecternTabProvider.java new file mode 100644 index 0000000..e5f0aa3 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/LecternTabProvider.java @@ -0,0 +1,52 @@ +package com.kqp.inventorytabs.tabs.provider; + +import com.kqp.inventorytabs.tabs.tab.SimpleBlockTab; +import com.kqp.inventorytabs.tabs.tab.Tab; +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.LecternBlockEntity; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static net.minecraft.block.LecternBlock.HAS_BOOK; +//import static net.minecraft.state.property.Properties.HAS_BOOK; + +public class LecternTabProvider extends BlockTabProvider { + @Override + public void addAvailableTabs(ClientPlayerEntity player, List tabs) { + super.addAvailableTabs(player, tabs); + Set tabsToRemove = new HashSet<>(); + List lecternTabs = tabs.stream().filter(tab -> tab instanceof SimpleBlockTab).map(tab -> (SimpleBlockTab) tab) + .filter(tab -> tab.blockId == Registry.BLOCK.getId(Blocks.LECTERN)).collect(Collectors.toList()); + lecternTabs.stream().filter(tab -> { + BlockEntity blockEntity = player.world.getBlockEntity(tab.blockPos); + + if (blockEntity instanceof LecternBlockEntity) { + BlockState blockState = player.world.getBlockState(tab.blockPos); + + return !blockState.get(HAS_BOOK); + } + + return false; + }).forEach(tabsToRemove::add); + + tabs.removeAll(tabsToRemove); + } + @Override + public boolean matches(World world, BlockPos pos) { + return false; + } + + @Override + public Tab createTab(World world, BlockPos pos) { + return null; + } +} diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/PlayerInventoryTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/PlayerInventoryTabProvider.java index a14de88..099c300 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/provider/PlayerInventoryTabProvider.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/PlayerInventoryTabProvider.java @@ -10,12 +10,11 @@ public class PlayerInventoryTabProvider implements TabProvider { @Override public void addAvailableTabs(ClientPlayerEntity player, List tabs) { - for (int i = 0; i < tabs.size(); i++) { - if (tabs.get(i) instanceof PlayerInventoryTab) { + for (Tab tab : tabs) { + if (tab instanceof PlayerInventoryTab) { return; } } - tabs.add(new PlayerInventoryTab()); } } diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/ShulkerBoxTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/ShulkerBoxTabProvider.java index c40c459..b5af14d 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/provider/ShulkerBoxTabProvider.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/ShulkerBoxTabProvider.java @@ -5,6 +5,7 @@ import java.util.Set; import java.util.stream.Collectors; +import com.kqp.inventorytabs.util.ShulkerBoxBlockInvoker; import com.kqp.inventorytabs.tabs.tab.SimpleBlockTab; import com.kqp.inventorytabs.tabs.tab.Tab; @@ -13,9 +14,7 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.ShulkerBoxBlockEntity; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.mob.ShulkerLidCollisions; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; import net.minecraft.util.registry.Registry; import net.minecraft.world.World; @@ -39,12 +38,9 @@ public void addAvailableTabs(ClientPlayerEntity player, List tabs) { if (blockEntity instanceof ShulkerBoxBlockEntity) { BlockState blockState = player.world.getBlockState(tab.blockPos); - Direction direction = blockState.get(ShulkerBoxBlock.FACING); - if (((ShulkerBoxBlockEntity) blockEntity) - .getAnimationStage() == ShulkerBoxBlockEntity.AnimationStage.CLOSED) { - return !player.world.isSpaceEmpty(ShulkerLidCollisions.getLidCollisionBox(tab.blockPos, direction)); - } + return !ShulkerBoxBlockInvoker.invokeCanOpen(blockState, player.world, tab.blockPos, + (ShulkerBoxBlockEntity) blockEntity); } return false; diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleBlockTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleBlockTabProvider.java index b0ad0fe..db405e3 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleBlockTabProvider.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleBlockTabProvider.java @@ -31,6 +31,14 @@ public void addBlock(Identifier identifier) { blockIds.add(identifier); } + public void removeBlock(Block block) { + blockIds.remove(Registry.BLOCK.getId(block)); + } + + public void removeBlock(Identifier identifier) { + blockIds.remove(identifier); + } + public Set getBlockIds() { return this.blockIds; } diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleEntityTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleEntityTabProvider.java new file mode 100644 index 0000000..a4c5f69 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/SimpleEntityTabProvider.java @@ -0,0 +1,41 @@ +package com.kqp.inventorytabs.tabs.provider; + +import com.kqp.inventorytabs.tabs.tab.SimpleEntityTab; +import com.kqp.inventorytabs.tabs.tab.Tab; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.entity.Entity; +import net.minecraft.util.Identifier; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class SimpleEntityTabProvider extends EntityTabProvider { + private final Set entities = new HashSet<>(); + + public SimpleEntityTabProvider() { + } + + @Override + public void addAvailableTabs(ClientPlayerEntity player, List tabs) { + super.addAvailableTabs(player, tabs); + // Set tabsToRemove = new HashSet<>(); + // List entityTabs = tabs.stream().filter(tab -> tab instanceof SimpleEntityTab).map(tab -> (SimpleEntityTab) tab) + // .filter(tab -> entities.contains(tab.entityId)).toList(); + // World world = player.world; + } + + @Override + public boolean matches(Entity entity) { + return entities.contains(new Identifier("minecraft:entity.minecraft.chest_minecart")); + } + + public void addEntity(Identifier entityId) { + entities.add(entityId); + } + + @Override + public Tab createTab(Entity entity) { + return new SimpleEntityTab(entity); + } +} \ No newline at end of file diff --git a/src/main/java/com/kqp/inventorytabs/tabs/provider/UniqueTabProvider.java b/src/main/java/com/kqp/inventorytabs/tabs/provider/UniqueTabProvider.java new file mode 100644 index 0000000..2a9fd4f --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/provider/UniqueTabProvider.java @@ -0,0 +1,55 @@ +package com.kqp.inventorytabs.tabs.provider; + +import com.kqp.inventorytabs.tabs.tab.SimpleBlockTab; +import com.kqp.inventorytabs.tabs.tab.Tab; +import net.minecraft.block.Block; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Provides tabs for blocks that should only have one tab at a time (e.g. Crafting Tables). + **/ +public class UniqueTabProvider extends BlockTabProvider { + private final Set uniqueBlocks = new HashSet<>(); + + @Override + public void addAvailableTabs(ClientPlayerEntity player, List tabs) { + super.addAvailableTabs(player, tabs); + Set tabsToRemove = new HashSet<>(); + List craftingTableTabs = tabs.stream().filter(tab -> tab instanceof SimpleBlockTab).map(tab -> (SimpleBlockTab) tab) + .filter(tab -> uniqueBlocks.contains(tab.blockId)).collect(Collectors.toList()); + + for (SimpleBlockTab tab : craftingTableTabs) { + if (!tabsToRemove.add(tab.blockId)) { + tabs.remove(tab); + } + } + } + + public void addUniqueBlock(Block block) { + uniqueBlocks.add(Registry.BLOCK.getId(block)); + } + + public void addUniqueBlock(Identifier blockId) { + uniqueBlocks.add(blockId); + } + + public void removeUniqueBlockId(Identifier blockId) { + uniqueBlocks.remove(blockId); + } + @Override + public boolean matches(World world, BlockPos pos) { + return uniqueBlocks.contains(Registry.BLOCK.getId(world.getBlockState(pos).getBlock())); + } + + @Override + public Tab createTab(World world, BlockPos pos) { + return new SimpleBlockTab(Registry.BLOCK.getId(world.getBlockState(pos).getBlock()), pos); + } +} diff --git a/src/main/java/com/kqp/inventorytabs/tabs/render/TabRenderer.java b/src/main/java/com/kqp/inventorytabs/tabs/render/TabRenderer.java index 640c618..fad6721 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/render/TabRenderer.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/render/TabRenderer.java @@ -1,6 +1,8 @@ package com.kqp.inventorytabs.tabs.render; import java.awt.Rectangle; +import java.util.ArrayList; +import java.util.List; import com.kqp.inventorytabs.init.InventoryTabs; import com.kqp.inventorytabs.mixin.accessor.HandledScreenAccessor; @@ -14,8 +16,11 @@ import net.minecraft.client.font.TextRenderer; import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; +import static com.kqp.inventorytabs.init.InventoryTabs.*; + /** * Handles the rendering of tabs. */ @@ -86,7 +91,9 @@ private void drawButtons(MatrixStack matrices, double mouseX, double mouseY) { // Drawing back button int x = oX - BUTTON_WIDTH - 4; + x += ((TabRenderingHints) currentScreen).getTopRowXOffset(); int y = oY - 16; + y += ((TabRenderingHints) currentScreen).getTopRowYOffset(); boolean hovered = new Rectangle(x, y, BUTTON_WIDTH, BUTTON_HEIGHT).contains(mouseX, mouseY); int u = 0; u += tabManager.canGoBackAPage() && hovered ? BUTTON_WIDTH * 2 : 0; @@ -95,7 +102,9 @@ private void drawButtons(MatrixStack matrices, double mouseX, double mouseY) { // Drawing forward button x = oX + width + 4; + x += ((TabRenderingHints) currentScreen).getTopRowXOffset(); y = oY - 16; + y += ((TabRenderingHints) currentScreen).getTopRowYOffset(); hovered = new Rectangle(x, y, BUTTON_WIDTH, BUTTON_HEIGHT).contains(mouseX, mouseY); u = 15; u += tabManager.canGoForwardAPage() && hovered ? BUTTON_WIDTH * 2 : 0; @@ -105,14 +114,15 @@ private void drawButtons(MatrixStack matrices, double mouseX, double mouseY) { private void drawPageText(MatrixStack matrices) { if (tabManager.getMaxPages() > 1 && pageTextRefreshTime > 0) { - RenderSystem.pushMatrix(); + // RenderSystem.pushMatrix(); + // TODO: Figure out rendering int color = 0xFFFFFFFF; if (pageTextRefreshTime <= 20) { RenderSystem.disableTexture(); RenderSystem.enableBlend(); - RenderSystem.disableAlphaTest(); + // RenderSystem.disableAlphaTest(); RenderSystem.defaultBlendFunc(); RenderSystem.colorMask(true, true, true, true); float transparency = pageTextRefreshTime / 20F; @@ -134,7 +144,7 @@ private void drawPageText(MatrixStack matrices) { MinecraftClient.getInstance().textRenderer.draw(matrices, text, x, y, color); - RenderSystem.popMatrix(); + // RenderSystem.popMatrix(); } } @@ -167,7 +177,16 @@ public TabRenderInfo[] getTabRenderInfos() { HandledScreen currentScreen = tabManager.getCurrentScreen(); int maxRowLength = tabManager.getMaxRowLength(); - int numVisibleTabs = maxRowLength * 2; + int numVisibleTabs; + if(isBigInvLoaded) { + numVisibleTabs = (maxRowLength * 2) + 5; + } else if (isPlayerExLoaded) { + numVisibleTabs = (maxRowLength * 2) - 3; + } else if (isLevelzLoaded) { + numVisibleTabs = (maxRowLength * 2) - 2; + }else { + numVisibleTabs = maxRowLength * 2; + } int startingIndex = tabManager.currentPage * numVisibleTabs; TabRenderInfo[] tabRenderInfo = new TabRenderInfo[numVisibleTabs]; @@ -180,6 +199,11 @@ public TabRenderInfo[] getTabRenderInfos() { // Setup basic info Tab tab = tabManager.tabs.get(startingIndex + i); boolean topRow = i < maxRowLength; + if(isPlayerExLoaded) { + topRow = i < maxRowLength - 3; + } else if(isLevelzLoaded) { + topRow = i < maxRowLength - 2; + } boolean selected = tab == tabManager.currentTab; // Create tab info object @@ -195,13 +219,13 @@ public TabRenderInfo[] getTabRenderInfos() { // Calc y value if (topRow) { - tabInfo.y = y - 26; - - if (selected) { - tabInfo.y = y - 28; - } + tabInfo.y = y - 28; } else { - tabInfo.y = y + ((HandledScreenAccessor) currentScreen).getBackgroundHeight() - 4; + if(isBigInvLoaded) { + tabInfo.y = y + ((HandledScreenAccessor) currentScreen).getBackgroundHeight() + 32; + } else { + tabInfo.y = y + ((HandledScreenAccessor) currentScreen).getBackgroundHeight() - 4; + } } // Calc texture dimensions @@ -242,14 +266,33 @@ public TabRenderInfo[] getTabRenderInfos() { // Apply rendering hints if (currentScreen instanceof TabRenderingHints) { if (topRow) { - tabInfo.x += ((TabRenderingHints) currentScreen).getTopRowXOffset(); + if(isPlayerExLoaded) { + tabInfo.x += ((TabRenderingHints) currentScreen).getTopRowXOffset() + 87; + tabInfo.itemX += ((TabRenderingHints) currentScreen).getTopRowXOffset() + 87; + } else if(isLevelzLoaded) { + tabInfo.x += ((TabRenderingHints) currentScreen).getTopRowXOffset() + 54; + tabInfo.itemX += ((TabRenderingHints) currentScreen).getTopRowXOffset() + 54; + }else { + tabInfo.x += ((TabRenderingHints) currentScreen).getTopRowXOffset(); + tabInfo.itemX += ((TabRenderingHints) currentScreen).getTopRowXOffset(); + } tabInfo.y += ((TabRenderingHints) currentScreen).getTopRowYOffset(); - tabInfo.itemX += ((TabRenderingHints) currentScreen).getTopRowXOffset(); tabInfo.itemY += ((TabRenderingHints) currentScreen).getTopRowYOffset(); } else { - tabInfo.x += ((TabRenderingHints) currentScreen).getBottomRowXOffset(); + if(isBigInvLoaded) { + tabInfo.x += ((TabRenderingHints) currentScreen).getBottomRowXOffset() - 145; + tabInfo.itemX += ((TabRenderingHints) currentScreen).getBottomRowXOffset() - 145; + } else if(isPlayerExLoaded) { + tabInfo.x += ((TabRenderingHints) currentScreen).getBottomRowXOffset() + 86; + tabInfo.itemX += ((TabRenderingHints) currentScreen).getBottomRowXOffset() + 86; + } else if(isLevelzLoaded) { + tabInfo.x += ((TabRenderingHints) currentScreen).getBottomRowXOffset() + 60; + tabInfo.itemX += ((TabRenderingHints) currentScreen).getBottomRowXOffset() + 60; + }else { + tabInfo.x += ((TabRenderingHints) currentScreen).getBottomRowXOffset(); + tabInfo.itemX += ((TabRenderingHints) currentScreen).getBottomRowXOffset(); + } tabInfo.y += ((TabRenderingHints) currentScreen).getBottomRowYOffset(); - tabInfo.itemX += ((TabRenderingHints) currentScreen).getBottomRowXOffset(); tabInfo.itemY += ((TabRenderingHints) currentScreen).getBottomRowYOffset(); } } diff --git a/src/main/java/com/kqp/inventorytabs/tabs/tab/ChestTab.java b/src/main/java/com/kqp/inventorytabs/tabs/tab/ChestTab.java index 786f33a..5a2d5a6 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/tab/ChestTab.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/tab/ChestTab.java @@ -1,17 +1,38 @@ package com.kqp.inventorytabs.tabs.tab; +import com.kqp.inventorytabs.mixin.accessor.ScreenAccessor; +import com.kqp.inventorytabs.tabs.render.TabRenderInfo; +import com.kqp.inventorytabs.util.ChestUtil; import net.minecraft.block.ChestBlock; import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.screen.ingame.HandledScreen; import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.decoration.ItemFrameEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.registry.Registry; +import net.minecraft.world.World; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import static com.kqp.inventorytabs.util.ChestUtil.getOtherChestBlockPos; /** * Tab for chests */ public class ChestTab extends SimpleBlockTab { + ItemStack itemStack; public ChestTab(Identifier blockId, BlockPos blockPos) { super(blockId, blockPos); + this.itemStack = new ItemStack(Registry.BLOCK.get(blockId)); } @Override @@ -24,4 +45,45 @@ public boolean shouldBeRemoved() { return super.shouldBeRemoved(); } + + @Override + public Text getHoverText() { + if (itemStack.hasCustomName()) { + return itemStack.getName(); + } + return super.getHoverText(); + } + + @Override + public void renderTabIcon(MatrixStack matrices, TabRenderInfo tabRenderInfo, HandledScreen currentScreen) { + ItemStack itemStack = getItemFrame(); + ItemRenderer itemRenderer = ((ScreenAccessor) currentScreen).getItemRenderer(); + TextRenderer textRenderer = ((ScreenAccessor) currentScreen).getTextRenderer(); + itemRenderer.zOffset = 100.0F; + itemRenderer.renderInGuiWithOverrides(itemStack, tabRenderInfo.itemX, tabRenderInfo.itemY); + itemRenderer.renderGuiItemOverlay(textRenderer, itemStack, tabRenderInfo.itemX, tabRenderInfo.itemY); + itemRenderer.zOffset = 0.0F; + } + + public ItemStack getItemFrame() { + World world = MinecraftClient.getInstance().player.world; + itemStack = new ItemStack(world.getBlockState(blockPos).getBlock()); + BlockPos doubleChestPos = ChestUtil.isDouble(world, blockPos) ? getOtherChestBlockPos(world, blockPos) : blockPos; + Box box = new Box(blockPos, doubleChestPos); + double x = box.minX; double y = box.minY; double z = box.minZ; + double x1 = box.maxX; double y1 = box.maxY; double z1 = box.maxZ; + List list1 = world.getNonSpectatingEntities(ItemFrameEntity.class, new Box(x-0.8, y, z, x1+1.8, y1+0.8, z1+0.8)); + List list2 = world.getNonSpectatingEntities(ItemFrameEntity.class, new Box(x, y, z-0.8, x1+0.8, y1+0.8, z1+1.8)); + List list3 = world.getNonSpectatingEntities(ItemFrameEntity.class, new Box(x, y-0.8, z, x1+0.8, y1+1.8, z1+0.8)); + List list = new ArrayList<>(); + Stream.of(list1, list2, list3).forEach(list::addAll); + for(ItemFrameEntity itemFrame : list){ + ItemStack item = itemFrame.getHeldItemStack(); + if(item != null && !item.isEmpty()){ + itemStack = item; + break; + } + } + return itemStack; + } } diff --git a/src/main/java/com/kqp/inventorytabs/tabs/tab/InventoryTab.java b/src/main/java/com/kqp/inventorytabs/tabs/tab/InventoryTab.java new file mode 100644 index 0000000..3d7bb6a --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/tab/InventoryTab.java @@ -0,0 +1,43 @@ +package com.kqp.inventorytabs.tabs.tab; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.text.LiteralText; +import net.minecraft.text.Text; +import net.minecraft.world.World; + +public class InventoryTab extends Tab { + public final Item itemId; + public InventoryTab(Item itemId) { + super(new ItemStack(itemId)); + this.itemId = itemId; + } + + @Override + public void open() { + System.out.println("TESTING: Opening inventory tab"); + ClientPlayerEntity player = MinecraftClient.getInstance().player; + World world = MinecraftClient.getInstance().world; + System.out.println("Player: "+player); + System.out.println("World: "+world); + System.out.println("Item: "+itemId); + System.out.println("ItemStack: "+new ItemStack(itemId)); + System.out.println("Active hand: "+player.getActiveHand()); + Item item = new ItemStack(itemId).getItem(); + item.use(world, player, player.getActiveHand()); + //itemId.use(world, player, player.getActiveHand()); + } + + @Override + public boolean shouldBeRemoved() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + return (player == null || !player.inventory.contains(new ItemStack(itemId))); + } + + @Override + public Text getHoverText() { + return new LiteralText(itemId.getName().getString()); + } +} diff --git a/src/main/java/com/kqp/inventorytabs/tabs/tab/ShulkerBoxTab.java b/src/main/java/com/kqp/inventorytabs/tabs/tab/ShulkerBoxTab.java index f83ae28..39be5c0 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/tab/ShulkerBoxTab.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/tab/ShulkerBoxTab.java @@ -1,15 +1,14 @@ package com.kqp.inventorytabs.tabs.tab; +import com.kqp.inventorytabs.util.ShulkerBoxBlockInvoker; + import net.minecraft.block.BlockState; -import net.minecraft.block.ShulkerBoxBlock; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.ShulkerBoxBlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.entity.mob.ShulkerLidCollisions; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Direction; /** * Tab for shulker boxes. @@ -27,14 +26,9 @@ public boolean shouldBeRemoved() { if (blockEntity instanceof ShulkerBoxBlockEntity) { BlockState blockState = player.world.getBlockState(blockPos); - Direction direction = blockState.get(ShulkerBoxBlock.FACING); - - if (((ShulkerBoxBlockEntity) blockEntity) - .getAnimationStage() == ShulkerBoxBlockEntity.AnimationStage.CLOSED) { - if (!player.world.isSpaceEmpty(ShulkerLidCollisions.getLidCollisionBox(blockPos, direction))) { - return true; - } - } + + return !ShulkerBoxBlockInvoker.invokeCanOpen(blockState, player.world, blockPos, + (ShulkerBoxBlockEntity) blockEntity); } return super.shouldBeRemoved(); diff --git a/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleBlockTab.java b/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleBlockTab.java index 008ddb9..4e0434c 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleBlockTab.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleBlockTab.java @@ -9,7 +9,7 @@ import net.minecraft.block.entity.BlockEntity; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.ClientPlayerEntity; -import net.minecraft.command.argument.EntityAnchorArgumentType; +import net.minecraft.command.argument.EntityAnchorArgumentType.EntityAnchor; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NbtCompound; import net.minecraft.text.Text; @@ -44,13 +44,13 @@ public void open() { if (InventoryTabs.getConfig().doSightChecksFlag) { hitResult = BlockUtil.getLineOfSight(blockPos, client.player, 5D); } else { - hitResult = new BlockHitResult(client.player.getPos(), Direction.EAST, blockPos, false); + hitResult = new BlockHitResult(Vec3d.ofCenter(blockPos), Direction.EAST, blockPos, false); } if (hitResult != null) { if (InventoryTabs.getConfig().rotatePlayer) { - MinecraftClient.getInstance().player.lookAt(EntityAnchorArgumentType.EntityAnchor.EYES, - getBlockVec3d()); + MinecraftClient.getInstance().player.lookAt(EntityAnchor.EYES, + Vec3d.ofCenter(blockPos)); } MinecraftClient.getInstance().interactionManager.interactBlock(client.player, client.player.clientWorld, @@ -69,13 +69,15 @@ public boolean shouldBeRemoved() { if (InventoryTabs.getConfig().doSightChecksFlag) { if (BlockUtil.getLineOfSight(blockPos, player, 5D) == null) { return true; + } else { + return !BlockUtil.inRange(blockPos, player, 5D); } } - Vec3d playerHead = player.getPos().add(0D, player.getEyeHeight(player.getPose()), 0D); - return getBlockVec3d().subtract(playerHead).lengthSquared() > BlockTabProvider.SEARCH_DISTANCE + return Vec3d.ofCenter(blockPos).subtract(playerHead).lengthSquared() > BlockTabProvider.SEARCH_DISTANCE * BlockTabProvider.SEARCH_DISTANCE; + } @Override @@ -96,10 +98,6 @@ public Text getHoverText() { return new TranslatableText(world.getBlockState(blockPos).getBlock().getTranslationKey()); } - private Vec3d getBlockVec3d() { - return new Vec3d(blockPos.getX() + 0.5D, blockPos.getY() + 0.5D, blockPos.getZ() + 0.5D); - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleEntityTab.java b/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleEntityTab.java new file mode 100644 index 0000000..2ab0f52 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/tabs/tab/SimpleEntityTab.java @@ -0,0 +1,92 @@ +package com.kqp.inventorytabs.tabs.tab; + +import com.kqp.inventorytabs.mixin.accessor.ScreenAccessor; +import com.kqp.inventorytabs.tabs.render.TabRenderInfo; +import com.kqp.inventorytabs.util.EntityUtil; +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.font.TextRenderer; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.client.network.ClientPlayerEntity; +import net.minecraft.client.render.item.ItemRenderer; +import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityType; +import net.minecraft.item.ItemStack; +import net.minecraft.item.SpawnEggItem; +import net.minecraft.text.Text; +import net.minecraft.util.Hand; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.registry.Registry; +import java.util.Objects; + +public class SimpleEntityTab extends Tab { + public final Vec3d entityPos; + public final Identifier entityId; + public final Entity entity; + + public SimpleEntityTab(Entity entity) { + super(new ItemStack(Registry.ITEM.get(new Identifier("minecraft", "barrier")))); + this.entity = entity; + this.entityPos = entity.getPos(); + this.entityId = EntityType.getId(entity.getType()); + } + + @Override + public void open() { + ClientPlayerEntity player = MinecraftClient.getInstance().player; + if(player != null) { + Hand hand = player.getActiveHand(); + if(hand == null){ + hand = Hand.MAIN_HAND; + } + MinecraftClient.getInstance().interactionManager.interactEntity(player, entity, hand); + } + } + + @Override + public boolean shouldBeRemoved() { + if (entity.removed) { + return true; + } + return entityPos.distanceTo(MinecraftClient.getInstance().player.getPos()) > 5; + } + + @Override + public Text getHoverText() { + return entity.getName(); + } + + @Override + public void renderTabIcon(MatrixStack matrices, TabRenderInfo tabRenderInfo, HandledScreen currentScreen) { + ItemStack itemStack = getItemStack(); + ItemRenderer itemRenderer = ((ScreenAccessor) currentScreen).getItemRenderer(); + TextRenderer textRenderer = ((ScreenAccessor) currentScreen).getTextRenderer(); + itemRenderer.zOffset = 100.0F; + itemRenderer.renderInGuiWithOverrides(itemStack, tabRenderInfo.itemX, tabRenderInfo.itemY); + itemRenderer.renderGuiItemOverlay(textRenderer, itemStack, tabRenderInfo.itemX, tabRenderInfo.itemY); + itemRenderer.zOffset = 0.0F; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + SimpleEntityTab tab = (SimpleEntityTab) o; + return Objects.equals(entityId, tab.entityId); + } + + @Override + public int hashCode() { + return Objects.hash(entityId); + } + + public ItemStack getItemStack() { + ItemStack pickBlockResult = EntityUtil.getEntityPickResult(entity); + return pickBlockResult != null && !pickBlockResult.isEmpty() ? pickBlockResult : new ItemStack(Registry.ITEM.get(new Identifier("minecraft", "barrier"))); + } +} diff --git a/src/main/java/com/kqp/inventorytabs/tabs/tab/Tab.java b/src/main/java/com/kqp/inventorytabs/tabs/tab/Tab.java index 2aa73a9..c7f6079 100644 --- a/src/main/java/com/kqp/inventorytabs/tabs/tab/Tab.java +++ b/src/main/java/com/kqp/inventorytabs/tabs/tab/Tab.java @@ -2,7 +2,6 @@ import com.kqp.inventorytabs.mixin.accessor.ScreenAccessor; import com.kqp.inventorytabs.tabs.render.TabRenderInfo; -import com.mojang.blaze3d.systems.RenderSystem; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; @@ -72,7 +71,7 @@ public void renderTabIcon(MatrixStack matrices, TabRenderInfo tabRenderInfo, Han ItemRenderer itemRenderer = ((ScreenAccessor) currentScreen).getItemRenderer(); TextRenderer textRenderer = ((ScreenAccessor) currentScreen).getTextRenderer(); itemRenderer.zOffset = 100.0F; - RenderSystem.enableRescaleNormal(); + // RenderSystem.enableRescaleNormal(); itemRenderer.renderInGuiWithOverrides(renderItemStack, tabRenderInfo.itemX, tabRenderInfo.itemY); itemRenderer.renderGuiItemOverlay(textRenderer, renderItemStack, tabRenderInfo.itemX, tabRenderInfo.itemY); itemRenderer.zOffset = 0.0F; diff --git a/src/main/java/com/kqp/inventorytabs/util/BlockUtil.java b/src/main/java/com/kqp/inventorytabs/util/BlockUtil.java index 85bb1e2..01ef340 100644 --- a/src/main/java/com/kqp/inventorytabs/util/BlockUtil.java +++ b/src/main/java/com/kqp/inventorytabs/util/BlockUtil.java @@ -11,6 +11,20 @@ import net.minecraft.world.World; public class BlockUtil { + public static boolean inRange(BlockPos pos, PlayerEntity player, double distance) { + double distanceSquared = distance * distance; + + Vec3d playerHead = player.getPos().add(0D, player.getEyeHeight(player.getPose()), 0D); + Vec3d blockVec = new Vec3d(pos.getX(), pos.getY(), pos.getZ()); + + for (Vec3d sightOffset : SIGHT_OFFSETS) { + if (blockVec.add(sightOffset).squaredDistanceTo(playerHead) <= distanceSquared) { + return true; + } + } + + return false; + } public static BlockHitResult getLineOfSight(BlockPos pos, PlayerEntity player, double distance) { World world = player.world; BlockState blockState = world.getBlockState(pos); @@ -19,8 +33,8 @@ public static BlockHitResult getLineOfSight(BlockPos pos, PlayerEntity player, d Vec3d playerHead = player.getPos().add(0D, player.getEyeHeight(player.getPose()), 0D); Vec3d blockVec = new Vec3d(pos.getX(), pos.getY(), pos.getZ()); - for (int i = 0; i < SIGHT_OFFSETS.length; i++) { - Vec3d blockPosCheck = blockVec.add(SIGHT_OFFSETS[i]); + for (Vec3d sightOffset : SIGHT_OFFSETS) { + Vec3d blockPosCheck = blockVec.add(sightOffset); BlockHitResult result = getBlockHitResult(playerHead, blockPosCheck, distanceSquared, world, pos, blockState); diff --git a/src/main/java/com/kqp/inventorytabs/util/ChestUtil.java b/src/main/java/com/kqp/inventorytabs/util/ChestUtil.java index 5197d01..9b3796a 100644 --- a/src/main/java/com/kqp/inventorytabs/util/ChestUtil.java +++ b/src/main/java/com/kqp/inventorytabs/util/ChestUtil.java @@ -3,6 +3,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.ChestBlock; import net.minecraft.block.enums.ChestType; +import net.minecraft.state.property.Properties; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.world.World; @@ -10,9 +11,11 @@ public class ChestUtil { public static boolean isDouble(World world, BlockPos blockPos) { BlockState blockState = world.getBlockState(blockPos); - ChestType type = blockState.get(ChestBlock.CHEST_TYPE); - - return type == ChestType.LEFT || type == ChestType.RIGHT; + if (blockState.contains(Properties.CHEST_TYPE)) { + ChestType type = blockState.get(ChestBlock.CHEST_TYPE); + return type == ChestType.LEFT || type == ChestType.RIGHT; + } + return false; } public static BlockPos getOtherChestBlockPos(World world, BlockPos blockPos) { diff --git a/src/main/java/com/kqp/inventorytabs/util/EntityUtil.java b/src/main/java/com/kqp/inventorytabs/util/EntityUtil.java new file mode 100644 index 0000000..fb4bbb9 --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/util/EntityUtil.java @@ -0,0 +1,70 @@ +package com.kqp.inventorytabs.util; + +import net.minecraft.entity.Entity; +import net.minecraft.entity.decoration.ArmorStandEntity; +import net.minecraft.entity.decoration.EndCrystalEntity; +import net.minecraft.entity.decoration.ItemFrameEntity; +import net.minecraft.entity.decoration.LeashKnotEntity; +import net.minecraft.entity.decoration.painting.PaintingEntity; +import net.minecraft.entity.vehicle.AbstractMinecartEntity; +import net.minecraft.entity.vehicle.BoatEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; +import net.minecraft.item.SpawnEggItem; + +public class EntityUtil { + /** Currently hard-coded, see {@link net.minecraft.client.MinecraftClient} */ + public static ItemStack getEntityPickResult(Entity entity){ + if (entity instanceof PaintingEntity) { + return new ItemStack(Items.PAINTING); + } else if (entity instanceof LeashKnotEntity) { + return new ItemStack(Items.LEAD); + } else if (entity instanceof ItemFrameEntity) { + ItemFrameEntity itemFrameEntity = (ItemFrameEntity)entity; + ItemStack itemStack2 = itemFrameEntity.getHeldItemStack(); + return itemStack2.isEmpty() ? new ItemStack(Items.ITEM_FRAME) : itemStack2.copy(); + } else if (entity instanceof AbstractMinecartEntity) { + Item item; + AbstractMinecartEntity abstractMinecartEntity = (AbstractMinecartEntity)entity; + switch (abstractMinecartEntity.getMinecartType()) { + case FURNACE: { + item = Items.FURNACE_MINECART; + break; + } + case CHEST: { + item = Items.CHEST_MINECART; + break; + } + case TNT: { + item = Items.TNT_MINECART; + break; + } + case HOPPER: { + item = Items.HOPPER_MINECART; + break; + } + case COMMAND_BLOCK: { + item = Items.COMMAND_BLOCK_MINECART; + break; + } + default: { + item = Items.MINECART; + } + } + return new ItemStack(item); + } else if (entity instanceof BoatEntity) { + return new ItemStack(((BoatEntity)entity).asItem()); + } else if (entity instanceof ArmorStandEntity) { + return new ItemStack(Items.ARMOR_STAND); + } else if (entity instanceof EndCrystalEntity) { + return new ItemStack(Items.END_CRYSTAL); + } else { + SpawnEggItem spawnEggItem = SpawnEggItem.forEntity(entity.getType()); + if (spawnEggItem == null) { + return ItemStack.EMPTY; + } + return new ItemStack(spawnEggItem); + } + } +} diff --git a/src/main/java/com/kqp/inventorytabs/util/ShulkerBoxBlockInvoker.java b/src/main/java/com/kqp/inventorytabs/util/ShulkerBoxBlockInvoker.java new file mode 100644 index 0000000..9a0bcad --- /dev/null +++ b/src/main/java/com/kqp/inventorytabs/util/ShulkerBoxBlockInvoker.java @@ -0,0 +1,26 @@ +package com.kqp.inventorytabs.util; + +import net.minecraft.entity.mob.ShulkerLidCollisions; +import net.minecraft.util.math.Direction; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.block.BlockState; +import net.minecraft.block.ShulkerBoxBlock; +import net.minecraft.block.entity.ShulkerBoxBlockEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import static net.minecraft.block.ShulkerBoxBlock.FACING; + +//@Mixin(ShulkerBoxBlock.class) +public interface ShulkerBoxBlockInvoker { + public static boolean invokeCanOpen(BlockState state, World world, BlockPos pos, ShulkerBoxBlockEntity entity) { + if (entity.getAnimationStage() == ShulkerBoxBlockEntity.AnimationStage.CLOSED) { + Direction direction = state.get(FACING); + return world.isSpaceEmpty(ShulkerLidCollisions.getLidCollisionBox(pos, direction)); + } else { + return true; + } + }; +} diff --git a/src/main/resources/assets/inventorytabs/icon.png b/src/main/resources/assets/inventorytabs/icon.png index 7a7704f..1e9bc6e 100644 Binary files a/src/main/resources/assets/inventorytabs/icon.png and b/src/main/resources/assets/inventorytabs/icon.png differ diff --git a/src/main/resources/assets/inventorytabs/lang/en_us.json b/src/main/resources/assets/inventorytabs/lang/en_us.json new file mode 100644 index 0000000..e121d86 --- /dev/null +++ b/src/main/resources/assets/inventorytabs/lang/en_us.json @@ -0,0 +1,13 @@ +{ + "text.autoconfig.inventory_tabs.title": "Inventory Tabs Config", + "text.autoconfig.inventory_tabs.option.doSightChecksFlag": "Check if block is in line of sight", + "text.autoconfig.inventory_tabs.option.doSightChecksFlag.@Tooltip": "If §cNo§r, you are able to click on inventories through walls", + "text.autoconfig.inventory_tabs.option.rotatePlayer": "Rotate the player to face the tab's block", + "text.autoconfig.inventory_tabs.option.rotatePlayer.@Tooltip": "If §aYes§r, the player will snap to position", + "text.autoconfig.inventory_tabs.option.excludeTab": "§nDo not show§r tabs for these blocks:", + "text.autoconfig.inventory_tabs.option.excludeTab.@Tooltip": "Format: §emod_name:block_id§r, or §emod_name:tag_id§r", + "text.autoconfig.inventory_tabs.option.includeTab": "§nForce show§r tabs for these blocks:", + "text.autoconfig.inventory_tabs.option.includeTab.@Tooltip": "Format: §emod_name:block_id§r", + "text.autoconfig.inventory_tabs.option.debugEnabled": "Print debugging information (tab IDs added/removed) in the log", + "inventorytabs.key.next_tab": "Cycle Inventory Tab" +} \ No newline at end of file diff --git a/src/main/resources/data/inventorytabs/tags/blocks/mod_compat_blacklist.json b/src/main/resources/data/inventorytabs/tags/blocks/mod_compat_blacklist.json new file mode 100644 index 0000000..0cb96e3 --- /dev/null +++ b/src/main/resources/data/inventorytabs/tags/blocks/mod_compat_blacklist.json @@ -0,0 +1,6 @@ +{ + "replace": false, + "values": [ + {"id": "autopath:path", "required": false} + ] +} \ No newline at end of file diff --git a/src/main/resources/data/techreborn/tags/blocks/block_entities_without_inventories.json b/src/main/resources/data/techreborn/tags/blocks/block_entities_without_inventories.json new file mode 100644 index 0000000..e4cfd2c --- /dev/null +++ b/src/main/resources/data/techreborn/tags/blocks/block_entities_without_inventories.json @@ -0,0 +1,33 @@ +{ + "replace": false, + "values": [ + {"id": "techreborn:basic_machine_casing", "required": false}, + {"id": "techreborn:advanced_machine_casing", "required": false}, + {"id": "techreborn:industrial_machine_casing", "required": false}, + {"id": "techreborn:creative_solar_panel", "required": false}, + {"id": "techreborn:copper_cable", "required": false}, + {"id": "techreborn:tin_cable", "required": false}, + {"id": "techreborn:gold_cable", "required": false}, + {"id": "techreborn:hv_cable", "required": false}, + {"id": "techreborn:glassfiber_cable", "required": false}, + {"id": "techreborn:insulated_copper_cable", "required": false}, + {"id": "techreborn:insulated_gold_cable", "required": false}, + {"id": "techreborn:insulated_hv_cable", "required": false}, + {"id": "techreborn:superconductor_cable", "required": false}, + {"id": "techreborn:resin_basin", "required": false}, + {"id": "techreborn:dragon_egg_syphon", "required": false}, + {"id": "techreborn:lightning_rod", "required": false}, + {"id": "techreborn:water_mill", "required": false}, + {"id": "techreborn:wind_mill", "required": false}, + {"id": "techreborn:drain", "required": false}, + {"id": "techreborn:lsu_storage", "required": false}, + {"id": "techreborn:lv_transformer", "required": false}, + {"id": "techreborn:mv_transformer", "required": false}, + {"id": "techreborn:hv_transformer", "required": false}, + {"id": "techreborn:ev_transformer", "required": false}, + {"id": "techreborn:alarm", "required": false}, + {"id": "techreborn:lamp_incandescent", "required": false}, + {"id": "techreborn:lamp_led", "required": false}, + {"id": "techreborn:computer_cube", "required": false} + ] +} \ No newline at end of file diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index ed148d5..da8880c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -5,12 +5,15 @@ "name": "Inventory Tabs", "description": "Adds tabs to your inventory that lead to nearby blocks.", "authors": [ - "KQP" + "KQP", + "LiamMCW", + "Andrew6rant (Andrew Grant)", + "WNTIV> (1.16.5 backport)" ], "contact": { - "homepage": "https://github.com/LiamMCW/inventorytabs", - "sources": "https://github.com/LiamMCW/inventorytabs", - "issues": "https://github.com/LiamMCW/inventorytabs/issues" + "homepage": "https://github.com/Andrew6rant/inventorytabs", + "sources": "https://github.com/Andrew6rant/inventorytabs", + "issues": "https://github.com/Andrew6rant/inventorytabs/issues" }, "license": "MIT", "icon": "assets/inventorytabs/icon.png", @@ -21,14 +24,28 @@ ], "client": [ "com.kqp.inventorytabs.init.InventoryTabsClient" + ], + "modmenu": [ + "com.kqp.inventorytabs.init.InventoryTabsModMenu" ] }, "mixins": [ "inventorytabs.mixins.json" ], "depends": { - "fabricloader": ">=0.11.6", - "fabric": ">=0.36.0", - "minecraft": "1.16.5" + "fabricloader": ">=0.14.9", + "fabric": ">=0.42.0", + "minecraft": "1.16.5", + "cloth-config2": "*" + }, + "custom": { + "modmenu": [ + "com.kqp.inventorytabs.init.InventoryTabsConfig" + ] + }, + "suggests": { + "biginv": "*", + "playerex": "*", + "modmenu": "*" } -} +} \ No newline at end of file diff --git a/src/main/resources/inventorytabs.mixins.json b/src/main/resources/inventorytabs.mixins.json index 03abdb4..f9820d6 100644 --- a/src/main/resources/inventorytabs.mixins.json +++ b/src/main/resources/inventorytabs.mixins.json @@ -2,17 +2,21 @@ "required": true, "minVersion": "0.8", "package": "com.kqp.inventorytabs.mixin", - "compatibilityLevel": "JAVA_16", + "compatibilityLevel": "JAVA_8", "mixins": [ - "accessor.HandledScreenAccessor", - "accessor.ScreenAccessor", "CartographyTableScreenTabAdder", "LoomScreenTabAdder", "StonecutterScreenTabAdder", "TabManagerContainerImplementer", - "VanillaScreenTabAdder" + "VanillaScreenTabAdder", + "accessor.HandledScreenAccessor", + "accessor.ScreenAccessor" ], "injectors": { "defaultRequire": 1 - } + }, + "client": [ + "ControlsListWidget$KeyBindingEntryMixin_SoftConflict", + "KeyBindingMixin_SoftConflict" + ] }