From 1c465412239da1806df56a9c1341b0eda0952192 Mon Sep 17 00:00:00 2001 From: Jason Mitchell Date: Thu, 6 Jan 2022 01:24:28 -0800 Subject: [PATCH] CraftingStation side chest now work with any IInventory with a configurable blacklist. (#35) * CraftingStation side chest now work with any IInventory with a configurable blacklist. * Check ISidedInventory and accessible slots. Still needs some work for shift clicking. * Backport shift click behavior and some helper functions * Fix NEI overlap, and tinker's tool station integration * Fix NEI shift clicking by redoing math --- build.gradle | 171 ++++-- gradle.properties | 2 +- .../nei/CraftingStationOverlayHandler.java | 7 +- .../nei/CraftingStationStackPositioner.java | 27 +- .../java/tconstruct/tools/gui/ChestSlot.java | 32 ++ .../tools/gui/CraftingStationGui.java | 406 ++++++++++---- .../tconstruct/tools/gui/GuiBorderWidget.java | 91 ++++ .../tconstruct/tools/gui/GuiElementDuex.java | 91 ++++ .../tools/gui/GuiElementScalable.java | 92 ++++ .../tconstruct/tools/gui/GuiSliderWidget.java | 281 ++++++++++ .../inventory/CraftingStationContainer.java | 508 +++++++++++------- .../tools/logic/CraftingStationLogic.java | 217 ++++---- .../tconstruct/util/config/PHConstruct.java | 29 +- .../assets/tinker/textures/gui/generic.png | Bin 0 -> 585 bytes 14 files changed, 1455 insertions(+), 499 deletions(-) create mode 100644 src/main/java/tconstruct/tools/gui/ChestSlot.java create mode 100644 src/main/java/tconstruct/tools/gui/GuiBorderWidget.java create mode 100644 src/main/java/tconstruct/tools/gui/GuiElementDuex.java create mode 100644 src/main/java/tconstruct/tools/gui/GuiElementScalable.java create mode 100644 src/main/java/tconstruct/tools/gui/GuiSliderWidget.java create mode 100644 src/main/resources/assets/tinker/textures/gui/generic.png diff --git a/build.gradle b/build.gradle index a380f6c7..00472c8e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,4 @@ -//version: ffe7b130f98fdfa1ac7c6ba4bd34722a55ab28d4 +//version: 8fa7883b6196c1765266f4e6ddf3118d5043aafb /* DO NOT CHANGE THIS FILE! @@ -32,7 +32,7 @@ buildscript { } } dependencies { - classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.4' + classpath 'com.github.GTNewHorizons:ForgeGradle:1.2.5' } } @@ -42,6 +42,7 @@ plugins { id("org.ajoberstar.grgit") version("3.1.1") id("com.github.johnrengelman.shadow") version("4.0.4") id("com.palantir.git-version") version("0.12.3") + id("maven-publish") } apply plugin: 'forge' @@ -87,33 +88,27 @@ checkPropertyExists("containsMixinsAndOrCoreModOnly") checkPropertyExists("usesShadowedDependencies") checkPropertyExists("developmentEnvironmentUserName") -def checkPropertyExists(String propertyName) { - if (project.hasProperty(propertyName) == false) { - throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") - } -} - String javaSourceDir = "src/main/java/" String scalaSourceDir = "src/main/scala/" String targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") String targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") -if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { +if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"modGroup\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } if(apiPackage) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") - if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"apiPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } } if(accessTransformersFile) { String targetFile = "src/main/resources/META-INF/" + accessTransformersFile - if(new File(targetFile).exists() == false) { + if(getFile(targetFile).exists() == false) { throw new GradleException("Could not resolve \"accessTransformersFile\"! Could not find " + targetFile) } } @@ -125,14 +120,14 @@ if(usesMixins.toBoolean()) { targetPackageJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") targetPackageScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinsPackage.toString().replaceAll("\\.", "/") - if((new File(targetPackageJava).exists() || new File(targetPackageScala).exists()) == false) { + if((getFile(targetPackageJava).exists() || getFile(targetPackageScala).exists()) == false) { throw new GradleException("Could not resolve \"mixinsPackage\"! Could not find " + targetPackageJava + " or " + targetPackageScala) } String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + mixinPlugin.toString().replaceAll("\\.", "/") + ".java" - if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { throw new GradleException("Could not resolve \"mixinPlugin\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) } } @@ -141,7 +136,7 @@ if(coreModClass) { String targetFileJava = javaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" String targetFileScala = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".scala" String targetFileScalaJava = scalaSourceDir + modGroup.toString().replaceAll("\\.", "/") + "/" + coreModClass.toString().replaceAll("\\.", "/") + ".java" - if((new File(targetFileJava).exists() || new File(targetFileScala).exists() || new File(targetFileScalaJava).exists()) == false) { + if((getFile(targetFileJava).exists() || getFile(targetFileScala).exists() || getFile(targetFileScalaJava).exists()) == false) { throw new GradleException("Could not resolve \"coreModClass\"! Could not find " + targetFileJava + " or " + targetFileScala + " or " + targetFileScalaJava) } } @@ -163,8 +158,14 @@ try { catch (Exception e) { throw new IllegalStateException("This mod must be version controlled by Git AND the repository must provide at least one tag!"); } + group = modGroup -archivesBaseName = modId +if(project.hasProperty("customArchiveBaseName") && customArchiveBaseName) { + archivesBaseName = customArchiveBaseName +} +else { + archivesBaseName = modId +} minecraft { version = minecraftVersion + "-" + forgeVersion + "-" + minecraftVersion @@ -194,7 +195,9 @@ if(file("addon.gradle").exists()) { apply from: 'repositories.gradle' configurations { - implementation.extendsFrom(shadowImplementation) + implementation.extendsFrom(shadowImplementation) // TODO: remove after all uses are refactored + implementation.extendsFrom(shadowCompile) + implementation.extendsFrom(shadeCompile) } repositories { @@ -240,7 +243,7 @@ def mixinSrg = "${tasks.reobf.temporaryDir}" + File.separator + "mixins.srg" task generateAssets { if(usesMixins.toBoolean()) { - new File(projectDir.toString() + "/src/main/resources/", "mixins." + modId + ".json").text = """{ + getFile("/src/main/resources/mixins." + modId + ".json").text = """{ "required": true, "minVersion": "0.7.11", "package": "${modGroup}.${mixinsPackage}", @@ -260,16 +263,28 @@ task relocateShadowJar(type: ConfigureShadowRelocation) { } shadowJar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + manifest { attributes(getManifestAttributes()) } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation] + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] dependsOn(relocateShadowJar) } jar { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + manifest { attributes(getManifestAttributes()) } @@ -343,31 +358,31 @@ tasks.withType(JavaExec).configureEach { } processResources - { - // this will ensure that this task is redone when the versions change. - inputs.property "version", project.version - inputs.property "mcversion", project.minecraft.version +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version - // replace stuff in mcmod.info, nothing else - from(sourceSets.main.resources.srcDirs) { - include 'mcmod.info' + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' - // replace version and mcversion - expand "minecraftVersion": project.minecraft.version, - "modVersion": versionDetails().lastTag, - "modId": modId, - "modName": modName - } + // replace version and mcversion + expand "minecraftVersion": project.minecraft.version, + "modVersion": versionDetails().lastTag, + "modId": modId, + "modName": modName + } - if(usesMixins.toBoolean()) { - from refMap - } + if(usesMixins.toBoolean()) { + from refMap + } - // copy everything else, thats not the mcmod.info - from(sourceSets.main.resources.srcDirs) { - exclude 'mcmod.info' - } - } + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} def getManifestAttributes() { def manifestAttributes = [:] @@ -400,6 +415,12 @@ task sourcesJar(type: Jar) { } task shadowDevJar(type: ShadowJar) { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + from sourceSets.main.output getArchiveClassifier().set("dev") @@ -408,7 +429,7 @@ task shadowDevJar(type: ShadowJar) { } minimize() // This will only allow shading for actually used classes - configurations = [project.configurations.shadowImplementation] + configurations = [project.configurations.shadowImplementation, project.configurations.shadowCompile] } task relocateShadowDevJar(type: ConfigureShadowRelocation) { @@ -423,6 +444,12 @@ task circularResolverJar(type: Jar) { } task devJar(type: Jar) { + project.configurations.shadeCompile.each { dep -> + from(project.zipTree(dep)) { + exclude 'META-INF', 'META-INF/**' + } + } + from sourceSets.main.output getArchiveClassifier().set("dev") @@ -438,11 +465,11 @@ task devJar(type: Jar) { task apiJar(type: Jar) { from (sourceSets.main.allJava) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } from (sourceSets.main.output) { - include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString() + '/**' + include modGroup.toString().replaceAll("\\.", "/") + "/" + apiPackage.toString().replaceAll("\\.", "/") + '/**' } from (sourceSets.main.resources.srcDirs) { @@ -460,18 +487,50 @@ artifacts { } } +// publishing +publishing { + publications { + maven(MavenPublication) { + artifact source: jar + artifact source: sourcesJar, classifier: "src" + artifact source: devJar, classifier: "dev" + if (apiPackage) { + artifact source: apiJar, classifier: "api" + } + + groupId = System.getenv("ARTIFACT_GROUP_ID") ?: group + artifactId = System.getenv("ARTIFACT_ID") ?: project.name + version = System.getenv("ARTIFACT_VERSION") ?: project.version + } + } + + repositories { + maven { + String owner = System.getenv("REPOSITORY_OWNER") ?: "Unknown" + String repositoryName = System.getenv("REPOSITORY_NAME") ?: "Unknown" + String githubRepositoryUrl = "https://maven.pkg.github.com/$owner/$repositoryName" + name = "GitHubPackages" + url = githubRepositoryUrl + credentials { + username = System.getenv("GITHUB_ACTOR") ?: "NONE" + password = System.getenv("GITHUB_TOKEN") ?: "NONE" + } + } + } +} + // Updating task updateBuildScript { doLast { - if (updateBuildScript()) return + if (performBuildScriptUpdate(projectDir.toString())) return print("Build script already up-to-date!") } } -if (isNewBuildScriptVersionAvailable()) { +if (isNewBuildScriptVersionAvailable(projectDir.toString())) { if (autoUpdateBuildScript.toBoolean()) { - updateBuildScript() + performBuildScriptUpdate(projectDir.toString()) } else { println("Build script update available! Run 'gradle updateBuildScript'") } @@ -481,9 +540,9 @@ static URL availableBuildScriptUrl() { new URL("https://raw.githubusercontent.com/SinTh0r4s/ExampleMod1.7.10/main/build.gradle") } -static boolean updateBuildScript() { - if (isNewBuildScriptVersionAvailable()) { - def buildscriptFile = new File("build.gradle") +boolean performBuildScriptUpdate(String projectDir) { + if (isNewBuildScriptVersionAvailable(projectDir)) { + def buildscriptFile = getFile("build.gradle") availableBuildScriptUrl().withInputStream { i -> buildscriptFile.withOutputStream { it << i } } print("Build script updated. Please REIMPORT the project or RESTART your IDE!") return true @@ -491,10 +550,10 @@ static boolean updateBuildScript() { return false } -static boolean isNewBuildScriptVersionAvailable() { +boolean isNewBuildScriptVersionAvailable(String projectDir) { Map parameters = ["connectTimeout": 2000, "readTimeout": 2000] - String currentBuildScript = new File("build.gradle").getText() + String currentBuildScript = getFile("build.gradle").getText() String currentBuildScriptHash = getVersionHash(currentBuildScript) String availableBuildScript = availableBuildScriptUrl().newInputStream(parameters).getText() String availableBuildScriptHash = getVersionHash(availableBuildScript) @@ -515,3 +574,15 @@ configure(updateBuildScript) { group = 'forgegradle' description = 'Updates the build script to the latest version' } + +// Helper methods + +def checkPropertyExists(String propertyName) { + if (project.hasProperty(propertyName) == false) { + throw new GradleException("This project requires a property \"" + propertyName + "\"! Please add it your \"gradle.properties\". You can find all properties and their description here: https://github.com/SinTh0r4s/ExampleMod1.7.10/blob/main/gradle.properties") + } +} + +def getFile(String relativePath) { + return new File(projectDir, relativePath) +} diff --git a/gradle.properties b/gradle.properties index a9ca3f7c..c091b7ce 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ forgeVersion = 10.13.4.1614 # restart Minecraft in development. Choose this dependent on your mod: # Do you need consistent player progressing (for example Thaumcraft)? -> Select a name # Do you need to test how your custom blocks interacts with a player that is not the owner? -> leave name empty -developmentEnvironmentUserName = "Developer" +developmentEnvironmentUserName = Developer # Define a source file of your project with: # public static final String VERSION = "GRADLETOKEN_VERSION"; diff --git a/src/main/java/tconstruct/plugins/nei/CraftingStationOverlayHandler.java b/src/main/java/tconstruct/plugins/nei/CraftingStationOverlayHandler.java index 7063f75f..4ae7d45a 100644 --- a/src/main/java/tconstruct/plugins/nei/CraftingStationOverlayHandler.java +++ b/src/main/java/tconstruct/plugins/nei/CraftingStationOverlayHandler.java @@ -5,9 +5,7 @@ import codechicken.nei.recipe.IRecipeHandler; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.inventory.Slot; import tconstruct.tools.gui.CraftingStationGui; -import tconstruct.tools.gui.ToolStationGui; import tconstruct.tools.inventory.CraftingStationContainer; -import tconstruct.tools.inventory.ToolStationContainer; import tconstruct.tools.logic.CraftingStationLogic; /** @@ -18,8 +16,9 @@ public class CraftingStationOverlayHandler extends DefaultOverlayHandler @Override public void overlayRecipe(GuiContainer gui, IRecipeHandler recipe, int recipeIndex, boolean shift) { if(gui.inventorySlots instanceof CraftingStationContainer) { - if(((CraftingStationContainer) gui.inventorySlots).logic.chest != null) { - offsetx = 5 + CraftingStationGui.CHEST_WIDTH; + final CraftingStationContainer station = (CraftingStationContainer)gui.inventorySlots; + if(station.logic.chest != null && gui instanceof CraftingStationGui) { + offsetx = 5 + ((CraftingStationGui)gui).getChestWidth(); } else { offsetx = 5; diff --git a/src/main/java/tconstruct/plugins/nei/CraftingStationStackPositioner.java b/src/main/java/tconstruct/plugins/nei/CraftingStationStackPositioner.java index d0d31ddc..fcc8b10d 100644 --- a/src/main/java/tconstruct/plugins/nei/CraftingStationStackPositioner.java +++ b/src/main/java/tconstruct/plugins/nei/CraftingStationStackPositioner.java @@ -1,38 +1,33 @@ package tconstruct.plugins.nei; -import java.util.ArrayList; - -import tconstruct.TConstruct; -import tconstruct.tools.gui.CraftingStationGui; -import net.minecraft.client.Minecraft; import codechicken.nei.PositionedStack; import codechicken.nei.api.IStackPositioner; import codechicken.nei.recipe.GuiRecipe; +import net.minecraft.client.Minecraft; +import tconstruct.TConstruct; +import tconstruct.tools.gui.CraftingStationGui; -public class CraftingStationStackPositioner implements IStackPositioner -{ +import java.util.ArrayList; + +public class CraftingStationStackPositioner implements IStackPositioner { @Override - public ArrayList positionStacks (ArrayList stacks) - { + public ArrayList positionStacks (ArrayList stacks) { - if (Minecraft.getMinecraft().currentScreen instanceof GuiRecipe) - { + if (Minecraft.getMinecraft().currentScreen instanceof GuiRecipe) { GuiRecipe recipeGui = (GuiRecipe) Minecraft.getMinecraft().currentScreen; - if (!(recipeGui.firstGui instanceof CraftingStationGui)) - { + if (!(recipeGui.firstGui instanceof CraftingStationGui)) { TConstruct.logger.warn("No CraftingStationGui found!"); return stacks; } CraftingStationGui gui = (CraftingStationGui) recipeGui.firstGui; - int offsetX = gui.hasChest() ? 5 + CraftingStationGui.CHEST_WIDTH : 5; + int offsetX = gui.hasChest() ? 5 + gui.getChestWidth() : 5; int offsetY = 11; - for (PositionedStack stack : stacks) - { + for (PositionedStack stack : stacks) { stack.relx += offsetX; stack.rely += offsetY; } diff --git a/src/main/java/tconstruct/tools/gui/ChestSlot.java b/src/main/java/tconstruct/tools/gui/ChestSlot.java new file mode 100644 index 00000000..4212bbcc --- /dev/null +++ b/src/main/java/tconstruct/tools/gui/ChestSlot.java @@ -0,0 +1,32 @@ +package tconstruct.tools.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; + +public class ChestSlot extends Slot { + /* + * A Slot, used for adjacent Chest Inventories, that can be disabled. + */ + public boolean enabled = true; + + public ChestSlot(IInventory inventory, int index, int xPosition, int yPosition) { + super(inventory, index, xPosition, yPosition); + } + + @SideOnly(Side.CLIENT) + @Override + public boolean func_111238_b/*isEnabled*/() { + return enabled; + } + + public void disable() { + enabled = false; + } + + public void enable() { + enabled = true; + } + +} diff --git a/src/main/java/tconstruct/tools/gui/CraftingStationGui.java b/src/main/java/tconstruct/tools/gui/CraftingStationGui.java index cb6ba85c..be5e7bfe 100644 --- a/src/main/java/tconstruct/tools/gui/CraftingStationGui.java +++ b/src/main/java/tconstruct/tools/gui/CraftingStationGui.java @@ -7,6 +7,8 @@ import cpw.mods.fml.common.Optional; import net.minecraft.client.gui.GuiTextField; import net.minecraft.client.gui.inventory.GuiContainer; import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; import net.minecraft.util.ResourceLocation; @@ -20,48 +22,72 @@ import tconstruct.library.tools.ToolMaterial; import tconstruct.library.util.HarvestLevels; import tconstruct.tools.logic.CraftingStationLogic; +import java.awt.Rectangle; import java.util.Collections; import java.util.List; @Optional.Interface(iface = "codechicken.nei.api.INEIGuiHandler", modid = "NotEnoughItems") -public class CraftingStationGui extends GuiContainer implements INEIGuiHandler -{ +public class CraftingStationGui extends GuiContainer implements INEIGuiHandler { + /* + * Slider/slots related. Taken & adapted from Tinkers Construct 1.12 under the MIT License + */ + private static final ResourceLocation gui_inventory = new ResourceLocation("tinker", "textures/gui/generic.png"); + + public static final GuiElementScalable slotElement = new GuiElementScalable(7, 7, 18, 18, 64, 64); + public static final GuiElementScalable slotEmptyElement = new GuiElementScalable(7 + 18, 7, 18, 18, 64, 64); + + private static final GuiElementDuex sliderNormal = new GuiElementDuex(7, 25, 10, 15, 64, 64); + private static final GuiElementDuex sliderLow = new GuiElementDuex(17, 25, 10, 15, 64, 64); + private static final GuiElementDuex sliderHigh = new GuiElementDuex(27, 25, 10, 15, 64, 64); + private static final GuiElementDuex sliderTop = new GuiElementDuex(43, 7, 12, 1, 64, 64); + private static final GuiElementDuex sliderBottom = new GuiElementDuex(43, 38, 12, 1, 64, 64); + private static final GuiElementScalable sliderBackground = new GuiElementScalable(43, 8, 12, 30, 64, 64); + private static final GuiElementScalable textBackground = new GuiElementScalable(7 + 18, 7, 18, 10, 64, 64); + + private final GuiSliderWidget slider = new GuiSliderWidget(sliderNormal, sliderHigh, sliderLow, sliderTop, sliderBottom, sliderBackground); + private final GuiBorderWidget border = new GuiBorderWidget(); + + private int firstSlotId; + private int lastSlotId; + private int chestSlotCount; + + /* end slider/slots */ + + private static final ResourceLocation background = new ResourceLocation("tinker", "textures/gui/tinkertable.png"); + private static final ResourceLocation description = new ResourceLocation("tinker", "textures/gui/description.png"); + private static final ResourceLocation icons = new ResourceLocation("tinker", "textures/gui/icons.png"); + public boolean active; + + // Panel positions public String toolName; public GuiTextField text; public String title, body = ""; CraftingStationLogic logic; - public static final int CHEST_WIDTH = 116; - - // Panel positions - private int craftingLeft = 0; private int craftingTop = 0; private int craftingTextLeft = 0; - private int descLeft = 0; private int descTop = 0; private int descTextLeft = 0; - + private int chestLeft = 0; private int chestTop = 0; - - public CraftingStationGui(InventoryPlayer inventory, CraftingStationLogic logic, World world, int x, int y, int z) - { + private int chestWidth = 0; + private int chestHeight = 0; + + public CraftingStationGui(InventoryPlayer inventory, CraftingStationLogic logic, World world, int x, int y, int z) { super(logic.getGuiContainer(inventory, world, x, y, z)); this.logic = logic; - // text = new GuiTextField(this.fontRendererObj, this.xSize / 2 - 5, 8, - // 30, 12); - // this.text.setText(""); + title = "\u00A7n" + StatCollector.translateToLocal("gui.toolforge1"); body = StatCollector.translateToLocal("gui.toolforge2"); toolName = ""; } @Override - public void initGui () - { + public void initGui() { super.initGui(); this.xSize = 176; @@ -73,20 +99,15 @@ public class CraftingStationGui extends GuiContainer implements INEIGuiHandler this.craftingLeft = this.guiLeft; this.craftingTop = this.guiTop; - if (logic.tinkerTable) - { + if (logic.tinkerTable) { this.descLeft = this.guiLeft + 176; this.descTop = this.craftingTop; } - if (logic.chest != null) - { - this.xSize += CHEST_WIDTH; - this.guiLeft -= CHEST_WIDTH; - this.chestLeft = this.guiLeft; - this.chestTop = this.craftingTop; - if (logic.doubleChest != null) - this.ySize = 187; + if (logic.chest != null) { + updateChest(); + } else { + slider.hide(); } this.craftingTextLeft = this.craftingLeft - this.guiLeft; @@ -94,14 +115,11 @@ public class CraftingStationGui extends GuiContainer implements INEIGuiHandler } @Override - protected void drawGuiContainerForegroundLayer (int par1, int par2) - { - if (logic.chest != null) - { - if(logic.chest.get() instanceof TileEntity) { - TileEntity te = (TileEntity)logic.chest.get(); - if(te.getWorldObj().getTileEntity(te.xCoord, te.yCoord, te.zCoord) == null && te.getWorldObj().isRemote) - { + protected void drawGuiContainerForegroundLayer(int par1, int par2) { + if (logic.chest != null) { + if (logic.chest.get() instanceof TileEntity) { + TileEntity te = (TileEntity) logic.chest.get(); + if (te == null || te.getWorldObj().getTileEntity(te.xCoord, te.yCoord, te.zCoord) == null && te.getWorldObj().isRemote) { mc.thePlayer.closeScreen(); return; } @@ -112,46 +130,43 @@ public class CraftingStationGui extends GuiContainer implements INEIGuiHandler this.fontRendererObj.drawString(StatCollector.translateToLocal(logic.tinkerTable ? "crafters.TinkerTable" : logic.getInvName()), craftingTextLeft + 8, 6, 0x202020); this.fontRendererObj.drawString(StatCollector.translateToLocal("container.inventory"), craftingTextLeft + 8, 72, 0x202020); - // this.fontRendererObj.drawString(toolName + "_", this.xSize / 2 - 18, - // 8, 0xffffff); - - if (logic.tinkerTable) - { + if (logic.tinkerTable) { if (logic.isStackInSlot(0)) // output slot = modified item drawToolStats(logic.getStackInSlot(0)); - else if (logic.isStackInSlot(5)) // center slot if no output item - { + else if (logic.isStackInSlot(5)) { // center slot if no output item // other slots empty? - if(!logic.isStackInSlot(1) && !logic.isStackInSlot(2) && !logic.isStackInSlot(3) && !logic.isStackInSlot(4) - && !logic.isStackInSlot(6) && !logic.isStackInSlot(7) && !logic.isStackInSlot(8) && !logic.isStackInSlot(9)) + if (!logic.isStackInSlot(1) && !logic.isStackInSlot(2) && !logic.isStackInSlot(3) && !logic.isStackInSlot(4) + && !logic.isStackInSlot(6) && !logic.isStackInSlot(7) && !logic.isStackInSlot(8) && !logic.isStackInSlot(9)) drawToolStats(logic.getStackInSlot(5)); else drawToolInformation(); - } - else + } else drawToolInformation(); } } - void drawToolStats (ItemStack stack) - { - if(stack.getItem() instanceof IModifyable) + void drawToolStats(ItemStack stack) { + if (stack.getItem() instanceof IModifyable) ToolStationGuiHelper.drawToolStats(stack, descTextLeft + 10, 0); - int matID = PatternBuilder.instance.getPartID(stack); - if (matID != Short.MAX_VALUE && matID > 0) - { + if (matID != Short.MAX_VALUE && matID > 0) { ToolMaterial material = TConstructRegistry.getMaterial(matID); - if(material != null) + if (material != null) drawMaterialStats(material); } } - - protected void drawMaterialStats(ToolMaterial materialEnum) - { + + void drawToolInformation() { + int offsetX = descTextLeft + 63; + + this.drawCenteredString(fontRendererObj, title, offsetX, 8, 0xffffff); + fontRendererObj.drawSplitString(body, offsetX - 56, 24, 115, 0xffffff); + } + + protected void drawMaterialStats(ToolMaterial materialEnum) { final int baseX = descTextLeft + 8; final int baseY = 8; @@ -172,56 +187,58 @@ public class CraftingStationGui extends GuiContainer implements INEIGuiHandler this.fontRendererObj.drawString(StatCollector.translateToLocal("gui.partcrafter10") + attack / 2f + heart, baseX, baseY + 60, 0xffffff); } - void drawToolInformation () - { - int offsetX = descTextLeft + 63; - - this.drawCenteredString(fontRendererObj, title, offsetX, 8, 0xffffff); - fontRendererObj.drawSplitString(body, offsetX - 56, 24, 115, 0xffffff); - } - - private static final ResourceLocation background = new ResourceLocation("tinker", "textures/gui/tinkertable.png"); - private static final ResourceLocation description = new ResourceLocation("tinker", "textures/gui/description.png"); - private static final ResourceLocation icons = new ResourceLocation("tinker", "textures/gui/icons.png"); - private static final ResourceLocation chest = new ResourceLocation("tinker", "textures/gui/chestside.png"); - @Override - protected void drawGuiContainerBackgroundLayer (float par1, int par2, int par3) - { + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + // Draw the background GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(background); this.drawTexturedModalRect(this.craftingLeft, this.craftingTop, 0, 0, 176, 166); - if (active) - { + if (active) { this.drawTexturedModalRect(this.craftingLeft + 62, this.craftingTop, 0, 166, 112, 22); } this.mc.getTextureManager().bindTexture(icons); - // Draw the slots + // Draw the slots if (logic.tinkerTable && !logic.isStackInSlot(5)) this.drawTexturedModalRect(this.craftingLeft + 47, this.craftingTop + 33, 0, 233, 18, 18); GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - this.mc.getTextureManager().bindTexture(icons); - // Draw chest side - if (logic.chest != null) - { - GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); - this.mc.getTextureManager().bindTexture(chest); + + this.mc.getTextureManager().bindTexture(gui_inventory); + if(hasChest()) { + chestLeft += border.w; + chestTop += border.h; - if (logic.doubleChest == null) - this.drawTexturedModalRect(this.chestLeft, this.chestTop, 0, 0, 122, 114); - else - this.drawTexturedModalRect(this.chestLeft, this.chestTop, 125, 0, 122, 187); + border.draw(); + + int x = chestLeft; + int y = chestTop; + final int midW = chestWidth - border.w * 2; + + if (shouldDrawName()) { + textBackground.drawScaledX(chestLeft, chestTop, midW); + y += textBackground.h; + } + + drawChestSlots(x, y); + + // slider + if (slider.isEnabled()) { + slider.update(mouseX, mouseY, !isMouseOverFullSlot(mouseX, mouseY) && isMouseInChest(mouseX, mouseY)); + slider.draw(); + + updateChestSlots(); + } + + chestLeft -= border.w; + chestTop -= border.h; } - // Draw description - if (logic.tinkerTable) - { + if (logic.tinkerTable) { GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); this.mc.getTextureManager().bindTexture(description); this.drawTexturedModalRect(this.descLeft, this.descTop, 0, 0, 126, 172); @@ -230,19 +247,10 @@ public class CraftingStationGui extends GuiContainer implements INEIGuiHandler } @Override - public VisiblityData modifyVisiblity (GuiContainer gui, VisiblityData currentVisibility) - { - if (width - xSize < 107) - { - currentVisibility.showWidgets = false; - } - else - { - currentVisibility.showWidgets = true; - } + public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) { + currentVisibility.showWidgets = width - xSize >= 107; - if (guiLeft < 58) - { + if (guiLeft < 58) { currentVisibility.showStateButtons = false; } @@ -250,37 +258,209 @@ public class CraftingStationGui extends GuiContainer implements INEIGuiHandler } @Override - public Iterable getItemSpawnSlots (GuiContainer gui, ItemStack item) - { + public Iterable getItemSpawnSlots(GuiContainer gui, ItemStack item) { return null; } @Override - public List getInventoryAreas (GuiContainer gui) - { + public List getInventoryAreas(GuiContainer gui) { return Collections.emptyList(); } @Override - public boolean handleDragNDrop (GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) - { + public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) { return false; } @Override - public boolean hideItemPanelSlot (GuiContainer gui, int x, int y, int w, int h) { + public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h) { + final int cw = (logic.chest != null ? chestWidth : 0); + if(logic.chest != null) { + final Rectangle blah = new Rectangle(x, y, w, h); + final Rectangle chestRectangle = new Rectangle( + chestLeft, chestTop, chestWidth, chestHeight + (shouldDrawName() ? textBackground.y : 0) + (border.h * 2) + ); + + if(chestRectangle.intersects(blah)) + return true; + } + if (y + h - 4 < guiTop || y + 4 > guiTop + ySize) return false; - - if (x - w - 4 < guiLeft - (logic.chest != null ? 40 : 0) || x + 4 > guiLeft + xSize + (logic.tinkerTable ? 126 : 0)) - return false; - - return true; + + return x - w - 4 >= guiLeft + cw && x + 4 <= guiLeft + xSize + cw + (logic.tinkerTable ? 126 : 0); } - - public boolean hasChest() - { + + public boolean hasChest() { return logic.chest != null; } + public boolean isMouseInChest(int mouseX, int mouseY) { + final int xMod = (slider.isEnabled() ? slider.width : 0) + border.w; + final int yMod = (shouldDrawName() ? textBackground.y : 0) + (border.h * 2); + + return mouseX >= (this.chestLeft - xMod) && mouseX < (chestLeft + chestWidth + xMod) && + mouseY >= (this.chestTop - yMod) && mouseY < (chestTop + chestHeight + yMod); + } + + public boolean isMouseOverFullSlot(int mouseX, int mouseY) { + for(final Object slot : inventorySlots.inventorySlots) { + if(isMouseOverSlot((Slot)slot, mouseX, mouseY) && ((Slot)slot).getHasStack()) { + return true; + } + } + return false; + } + + protected boolean shouldDrawName() { + return this.logic.chest != null && this.logic.chest.get().getInventoryName() != null && !this.logic.chest.get().getInventoryName().isEmpty(); + } + + @Override + public void func_146977_a/*drawSlot*/(Slot slot) { + if(!slot.func_111238_b/*isEnabled*/()) return; + + super.func_146977_a(slot); + } + + public boolean shouldDrawSlot(Slot slot) { + if(!(slot instanceof ChestSlot)) return true; + + if(slot.getSlotIndex() >= chestSlotCount) return false; + + // all visible + if(!slider.isEnabled()) return true; + + return firstSlotId <= slot.getSlotIndex() && lastSlotId > slot.getSlotIndex(); + } + + @Override + public boolean isMouseOverSlot(Slot slotIn, int mouseX, int mouseY) { + return super.isMouseOverSlot(slotIn, mouseX, mouseY) && shouldDrawSlot(slotIn); + } + + private int getDisplayedRows() { + return chestHeight / slotElement.h; + } + + private int calcCappedYSize(int max) { + int h = slotElement.h * logic.invRows; + + // not higher than the max + while(h > max) { + h -= slotElement.h; + } + return h; + } + + public int getChestWidth() { + return chestWidth; + } + + // updatePosition + public void updateChest() { + chestHeight = calcCappedYSize(CraftingStationGui.slotElement.h * 10); + chestSlotCount = logic.slotCount; + + // slider needed? + if(getDisplayedRows() < logic.invRows) { + slider.enable(); + } + else { + slider.disable(); + } + + chestWidth = logic.invColumns * CraftingStationGui.slotElement.w + 2 * border.w + (slider.isEnabled() ? slider.width : 0); + + chestLeft = guiLeft - chestWidth; + chestTop = guiTop; + + // Leaving out the xsize increase by chestSize and adjusting where it's used, because otherwise it shifts both the bookmarks and item panel + // way too far out. + //xSize += guiLeft - chestLeft; + guiLeft = chestLeft; + + if (logic.doubleChest != null) + this.ySize = 187; + + border.setPosition(chestLeft, chestTop); + border.setSize(chestWidth, chestHeight + (shouldDrawName() ? textBackground.h : 0) + 2 * border.h); + + slider.show(); + slider.setPosition(chestLeft + logic.invColumns * slotElement.w + border.w, chestTop + (shouldDrawName() ? textBackground.h : 0) + border.h); + slider.setSize(chestHeight); + slider.setSliderParameters(0, logic.invRows - getDisplayedRows(), 1); + + updateChestSlots(); + } + + // updates slot visibility + protected void updateChestSlots() { + if(!hasChest()) return; + + final IInventory secondInventory = logic.getSecondInventory(); + + int xOffset = border.w; + int yOffset = border.h; + + if(shouldDrawName()) { + yOffset += textBackground.h; + } + + firstSlotId = slider.getValue() * logic.invColumns; + lastSlotId = Math.min(chestSlotCount, firstSlotId + getDisplayedRows() * logic.invColumns); + + for(Object o : inventorySlots.inventorySlots) { + if(!(o instanceof ChestSlot)) continue; + + final ChestSlot slot = (ChestSlot)o; + + if(shouldDrawSlot(slot)) { + slot.enable(); + // calc position of the slot + final int offset = slot.getSlotIndex() + (slot.inventory == secondInventory ? 27 : 0) - firstSlotId; + final int x = (offset % logic.invColumns) * CraftingStationGui.slotElement.w; + final int y = (offset / logic.invColumns) * CraftingStationGui.slotElement.h; + + slot.xDisplayPosition = x + xOffset + 1 /*- this.chestWidth*/; + slot.yDisplayPosition = y + yOffset + 1; + } + else { + slot.disable(); + slot.xDisplayPosition = 0; + slot.yDisplayPosition = 0; + } + } + } + + + // drawSlots + protected void drawChestSlots(int xPos, int yPos) { + if(!hasChest()) return; + + int width = logic.invColumns * slotElement.w; + int height = chestHeight - border.h * 2; + + int fullRows = (lastSlotId - firstSlotId) / logic.invColumns; + int slotsLeft = (lastSlotId - firstSlotId) % logic.invColumns; + + int y; // We use it after the loop + for(y = 0; y < fullRows * slotElement.h && y < height; y += slotElement.h) { + slotElement.drawScaledX(xPos, yPos + y, width); + } + + // draw partial row and unused slots + if(slotsLeft > 0) { + slotElement.drawScaledX(xPos, yPos + y, slotsLeft * slotElement.w); + // empty slots that don't exist + slotEmptyElement.drawScaledX(xPos + slotsLeft * slotElement.w, yPos + y, width - slotsLeft * slotElement.w); + } + } + + + /* + * Hide the deprecated stuff at the bottom + */ + @Deprecated + public static final int CHEST_WIDTH = 116; } diff --git a/src/main/java/tconstruct/tools/gui/GuiBorderWidget.java b/src/main/java/tconstruct/tools/gui/GuiBorderWidget.java new file mode 100644 index 00000000..19d212c0 --- /dev/null +++ b/src/main/java/tconstruct/tools/gui/GuiBorderWidget.java @@ -0,0 +1,91 @@ +package tconstruct.tools.gui; + +/* + * Taken from Tinker's Construct 1.12 under the MIT License + * + * The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +public class GuiBorderWidget { + // all elements based on generic gui + public GuiElementDuex cornerTopLeft = new GuiElementDuex(0, 0, 7, 7, 64, 64); + public GuiElementDuex cornerTopRight = new GuiElementDuex(64 - 7, 0, 7, 7, 64, 64); + public GuiElementDuex cornerBottomLeft = new GuiElementDuex(0, 64 - 7, 7, 7, 64, 64); + public GuiElementDuex cornerBottomRight = new GuiElementDuex(64 - 7, 64 - 7, 7, 7, 64, 64); + + public GuiElementScalable borderTop = new GuiElementScalable(7, 0, 64 - 7 - 7, 7, 64, 64); + public GuiElementScalable borderBottom = new GuiElementScalable(7, 64 - 7, 64 - 7 - 7, 7, 64, 64); + public GuiElementScalable borderLeft = new GuiElementScalable(0, 7, 7, 64 - 7 - 7, 64, 64); + public GuiElementScalable borderRight = new GuiElementScalable(64 - 7, 7, 7, 64 - 7 - 7, 64, 64); + + public int xPos; + public int yPos; + public int height; + public int width; + public int w = borderLeft.w; + public int h = borderTop.h; + + public void setPosition(int x, int y) { + this.xPos = x; + this.yPos = y; + } + + public void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + /** Sets the size so that the given point is the upper left corner of the inside */ + public void setPosInner(int x, int y) { + setPosition(x - cornerTopLeft.w, y - cornerTopLeft.h); + } + + /** Sets the size so that it surrounds the given area */ + public void sedSizeInner(int width, int height) { + setSize(width + borderLeft.w + borderRight.w, height + borderTop.h + borderBottom.h); + } + + public int getWidthWithBorder(int width) { + return width + borderRight.w + borderLeft.w; + } + + public int getHeightWithBorder(int height) { + return height + borderTop.h + borderBottom.h; + } + + public void draw() { + int x = xPos; + int y = yPos; + int midW = width - borderLeft.w - borderRight.w; + int midH = height - borderTop.h - borderBottom.h; + + // top row + x += cornerTopLeft.draw(x, y); + x += borderTop.drawScaledX(x, y, midW); + cornerTopRight.draw(x, y); + + // center row + x = xPos; + y += borderTop.h; + x += borderLeft.drawScaledY(x, y, midH); + x += midW; + borderRight.drawScaledY(x, y, midH); + + // bottom row + x = xPos; + y += midH; + x += cornerBottomLeft.draw(x, y); + x += borderBottom.drawScaledX(x, y, midW); + cornerBottomRight.draw(x, y); + } +} diff --git a/src/main/java/tconstruct/tools/gui/GuiElementDuex.java b/src/main/java/tconstruct/tools/gui/GuiElementDuex.java new file mode 100644 index 00000000..09021e37 --- /dev/null +++ b/src/main/java/tconstruct/tools/gui/GuiElementDuex.java @@ -0,0 +1,91 @@ +package tconstruct.tools.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.gui.GuiScreen; + +/* + * Taken from Mantle 1.12-1.3.3.49 under the MIT License + * + * The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +@SideOnly(Side.CLIENT) +public class GuiElementDuex { + + // this is totally completely ugly but it's a simple solution that doesn't clutter everything too much >_> + public static int defaultTexW = 256; + public static int defaultTexH = 256; + + public final int x; + public final int y; + public final int w; + public final int h; + + public int texW; + public int texH; + + public GuiElementDuex(int x, int y, int w, int h, int texW, int texH) { + this(x, y, w, h); + setTextureSize(texW, texH); + + defaultTexW = texW; + defaultTexH = texH; + } + + public GuiElementDuex(int x, int y, int w, int h) { + this.x = x; + this.y = y; + this.w = w; + this.h = h; + setTextureSize(defaultTexW, defaultTexH); + } + + public GuiElementDuex setTextureSize(int w, int h) { + texW = w; + texH = h; + + return this; + } + + public GuiElementDuex shift(int xd, int yd) { + return new GuiElementDuex(this.x + xd, this.y + yd, this.w, this.h, this.texW, this.texH); + } + + /** + * Draws the element at the given x/y coordinates + * + * @param xPos X-Coordinate on the screen + * @param yPos Y-Coordinate on the screen + */ + public int draw(int xPos, int yPos) { + // drawModalRectWithCustomSizedTexture + GuiScreen.func_146110_a(xPos, yPos, x, y, w, h, texW, texH); + return w; + } + + public static class Builder { + + public int w; + public int h; + + public Builder(int w, int h) { + this.w = w; + this.h = h; + } + + public GuiElementDuex get(int x, int y, int w, int h) { + return new GuiElementDuex(x, y, w, h, this.w, this.h); + } + } +} \ No newline at end of file diff --git a/src/main/java/tconstruct/tools/gui/GuiElementScalable.java b/src/main/java/tconstruct/tools/gui/GuiElementScalable.java new file mode 100644 index 00000000..94e68058 --- /dev/null +++ b/src/main/java/tconstruct/tools/gui/GuiElementScalable.java @@ -0,0 +1,92 @@ +package tconstruct.tools.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import net.minecraft.client.gui.GuiScreen; + +/* + * Taken from Mantle 1.12-1.3.3.49 under the MIT License + * + * The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +@SideOnly(Side.CLIENT) +public class GuiElementScalable extends GuiElementDuex { + + public GuiElementScalable(int x, int y, int w, int h, int texW, int texH) { + super(x, y, w, h, texW, texH); + } + + public GuiElementScalable(int x, int y, int w, int h) { + super(x, y, w, h); + } + + public int drawScaledX(int xPos, int yPos, int width) { + for(int i = 0; i < width / w; i++) { + draw(xPos + i * w, yPos); + } + // remainder that doesn't fit total width + int remainder = width % w; + if(remainder > 0) { + GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, h, texW, texH); + } + + return width; + } + + public int drawScaledY(int xPos, int yPos, int height) { + for(int i = 0; i < height / h; i++) { + draw(xPos, yPos + i * h); + } + // remainder that doesn't fit total width + int remainder = height % h; + if(remainder > 0) { + // drawModalRectWithCustomSizedTexture + GuiScreen.func_146110_a(xPos, yPos + height - remainder, x, y, w, remainder, texW, texH); + } + + return w; + } + + public int drawScaled(int xPos, int yPos, int width, int height) { + // we draw full height row-wise + int full = height / this.h; + for(int i = 0; i < full; i++) { + drawScaledX(xPos, yPos + i * this.h, width); + } + + yPos += full * this.h; + + // and the remainder is drawn manually + int yRest = height % this.h; + // the same as drawScaledX but with the remaining height + for(int i = 0; i < width / w; i++) { + drawScaledY(xPos + i * w, yPos, yRest); + } + // remainder that doesn't fit total width + int remainder = width % w; + if(remainder > 0) { + // drawModalRectWithCustomSizedTexture + GuiScreen.func_146110_a(xPos + width - remainder, yPos, x, y, remainder, yRest, texW, texH); + } + + return width; + } + + @Override + public GuiElementScalable shift(int xd, int yd) { + GuiElementScalable element = new GuiElementScalable(this.x + xd, this.y + yd, this.w, this.h); + element.setTextureSize(texW, texH); + return element; + } +} \ No newline at end of file diff --git a/src/main/java/tconstruct/tools/gui/GuiSliderWidget.java b/src/main/java/tconstruct/tools/gui/GuiSliderWidget.java new file mode 100644 index 00000000..54d12b4f --- /dev/null +++ b/src/main/java/tconstruct/tools/gui/GuiSliderWidget.java @@ -0,0 +1,281 @@ +package tconstruct.tools.gui; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import org.lwjgl.input.Mouse; + +/* + * Taken from Mantle 1.12-1.3.3.49 under the MIT License + * + * The MIT License (MIT) Copyright (c) 2013-2014 Slime Knights (mDiyo, fuj1n, Sunstrike, progwml6, pillbox, alexbegt) + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + */ + +// a vertical slider! +@SideOnly(Side.CLIENT) +public class GuiSliderWidget { + // gui info + public final GuiElementDuex slider; + public final GuiElementDuex sliderHighlighted; + public final GuiElementDuex sliderDisabled; + public final GuiElementDuex slideBarTop; + public final GuiElementDuex slideBarBottom; + public final GuiElementScalable slideBar; + public int xPos; + public int yPos; + public int height; + public int width; + public int sliderOffset; // x-offset of the slider to the left edge of the slideBar + // slider info + protected int minValue; + protected int maxValue; + protected int increment; + // positioning info + protected int currentValue; + protected boolean enabled; + protected boolean hidden; + + protected boolean isScrolling; + protected boolean isHighlighted; + // where the slider was clicked on the slider itself (not on the bar, on the thing that slides) + private int clickX; + private int clickY; + private boolean clickedBar; // if the bar has already been clicked and not released + + public GuiSliderWidget(GuiElementDuex slider, GuiElementDuex sliderHighlighted, GuiElementDuex sliderDisabled, GuiElementDuex slideBarTop, GuiElementDuex slideBarBottom, GuiElementScalable slideBar) { + this.slider = slider; + this.sliderHighlighted = sliderHighlighted; + this.sliderDisabled = sliderDisabled; + this.slideBar = slideBar; + this.slideBarTop = slideBarTop; + this.slideBarBottom = slideBarBottom; + + height = slideBar.h; + width = slideBar.w; + currentValue = minValue = 0; + maxValue = slideBar.h; + increment = 1; + + sliderOffset = Math.abs(slideBar.w - slider.w) / 2; + + isScrolling = false; + isHighlighted = false; + + enabled = true; + hidden = false; + } + + /** + * Where the part will be drawn. Upper left corner. + */ + public void setPosition(int x, int y) { + this.xPos = x; + this.yPos = y; + } + + public void setSize(int width, int height) { + this.width = width; + this.height = height; + } + + /** + * Sets the height of the whole slider and slidebar + */ + public void setSize(int height) { + this.height = height; + } + + /** + * specifies the values that the slider represents + */ + public void setSliderParameters(int min, int max, int stepsize) { + this.minValue = min; + this.maxValue = max; + this.increment = stepsize; + + // just in case + setSliderValue(currentValue); + } + + public int setSliderValue(int val) { + if (val > maxValue) { + val = maxValue; + } else if (val < minValue) { + val = minValue; + } + + currentValue = val; + return currentValue; + } + + public int getValue() { + if (isHidden()) { + return 0; + } + return Math.min(maxValue, Math.max(minValue, currentValue)); + } + + public boolean isHidden() { + return this.hidden; + } + + public void setHidden(boolean hidden) { + this.hidden = hidden; + } + + public void enable() { + this.enabled = true; + } + + public void disable() { + this.enabled = false; + } + + public boolean isEnabled() { + return this.enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public void hide() { + this.hidden = true; + } + + public void show() { + this.hidden = false; + } + + public void draw() { + if (hidden) { + return; + } + + // slidebar background + slideBarTop.draw(xPos, yPos); + slideBar.drawScaledY(xPos, yPos + slideBarTop.h, getUsableSlidebarHeight()); + slideBarBottom.draw(xPos, yPos + height - slideBarBottom.h); + + int x = xPos + sliderOffset; + int y = yPos + getSliderTop(); + + // the slider depending on state + if (enabled) { + if (isScrolling) { + sliderDisabled.draw(x, y); + } else if (isHighlighted) { + sliderHighlighted.draw(x, y); + } else { + slider.draw(x, y); + } + } else { + sliderDisabled.draw(x, y); + } + } + + private int getUsableSlidebarHeight() { + return height - slideBarTop.h - slideBarBottom.h; + } + + private int getSliderTop() { + float d = maxValue - minValue; + d = (float) (currentValue - minValue) / d; + d *= getUsableSlidebarHeight() - slider.h; + + return (int) d + slideBarTop.h; + } + + public void update(int mouseX, int mouseY, boolean useMouseWheel) { + if (!enabled || hidden) { + return; + } + + boolean mouseDown = Mouse.isButtonDown(0); // left mouse button + int wheel = Mouse.getDWheel(); + + if (useMouseWheel) { + if (wheel > 0) { + decrement(); + return; + } else if (wheel < 0) { + increment(); + return; + } + } + + // relative position inside the widget + int x = mouseX - xPos; + int y = mouseY - yPos; + + // reset click data + if (!mouseDown && clickedBar) { + clickedBar = false; + } + + // button not pressed and scrolling -> stop scrolling + if (!mouseDown && isScrolling) { + isScrolling = false; + } + // button pressed and scrolling -> update position of slider + else if (isScrolling) { + float d = maxValue - minValue; + float val = (float) (y - clickY) / (float) (getUsableSlidebarHeight() - slider.h); + val *= d; + + if (val < (float) increment / 2f) { + // < 1/2 increment + setSliderValue(minValue); + } else if (val > maxValue - ((float) increment / 2f)) { + // > max-1/2 increment + setSliderValue(maxValue); + } else { + // in between + setSliderValue((int) (minValue + (float) increment * Math.round(val))); + } + } + // not scrolling yet but possibly inside the slider + else if (x >= 0 && y >= getSliderTop() && + x - sliderOffset <= slider.w && y <= getSliderTop() + slider.h) { + isHighlighted = true; + if (mouseDown) { + isScrolling = true; + clickX = x - sliderOffset; + clickY = y - getSliderTop(); + } + } + // not on the slider but clicked on the bar + else if (mouseDown && !clickedBar && + x >= 0 && y >= 0 && + x <= slideBar.w && y <= height) { + if (y < getSliderTop()) { + decrement(); + } else { + increment(); + } + + clickedBar = true; + } else { + isHighlighted = false; + } + } + + public int decrement() { + setSliderValue(currentValue - increment); + return currentValue; + } + + public int increment() { + setSliderValue(currentValue + increment); + return currentValue; + } +} \ No newline at end of file diff --git a/src/main/java/tconstruct/tools/inventory/CraftingStationContainer.java b/src/main/java/tconstruct/tools/inventory/CraftingStationContainer.java index 5f72eafe..ed8d60cd 100644 --- a/src/main/java/tconstruct/tools/inventory/CraftingStationContainer.java +++ b/src/main/java/tconstruct/tools/inventory/CraftingStationContainer.java @@ -1,12 +1,12 @@ package tconstruct.tools.inventory; -import java.lang.ref.WeakReference; - +import com.google.common.primitives.Ints; import net.minecraft.block.Block; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.inventory.Container; import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.ISidedInventory; import net.minecraft.inventory.InventoryCrafting; import net.minecraft.inventory.Slot; import net.minecraft.item.Item; @@ -16,25 +16,34 @@ import net.minecraft.world.World; import tconstruct.library.crafting.ModifyBuilder; import tconstruct.library.modifier.IModifyable; import tconstruct.tools.TinkerTools; +import tconstruct.tools.gui.ChestSlot; import tconstruct.tools.logic.CraftingStationLogic; -public class CraftingStationContainer extends Container -{ - /** The crafting matrix inventory (3x3). */ - public InventoryCrafting craftMatrix;// = new InventoryCrafting(this, 3, 3); - public IInventory craftResult;// = new InventoryCraftResult(); - public CraftingStationLogic logic; - private World worldObj; - EntityPlayer player; - private int posX; - private int posY; - private int posZ; - private WeakReference[] inventories; +import javax.annotation.Nonnull; +import java.lang.ref.WeakReference; +import java.util.HashSet; +import java.util.Set; - public CraftingStationContainer(InventoryPlayer inventorplayer, CraftingStationLogic logic, int x, int y, int z) - { +public class CraftingStationContainer extends Container { + private final World worldObj; + private final int posX; + private final int posY; + private final int posZ; + + @SuppressWarnings("rawtypes") + private final WeakReference [] inventories; + + /** + * The crafting matrix inventory (3x3). + */ + public InventoryCrafting craftMatrix; + public IInventory craftResult; + public CraftingStationLogic logic; + EntityPlayer player; + + public CraftingStationContainer(InventoryPlayer inventoryplayer, CraftingStationLogic logic, int x, int y, int z) { this.worldObj = logic.getWorldObj(); - this.player = inventorplayer.player; + this.player = inventoryplayer.player; this.posX = x; this.posY = y; this.posZ = z; @@ -43,75 +52,194 @@ public class CraftingStationContainer extends Container craftResult = new InventoryCraftingStationResult(logic); this.inventories = logic.getInventories(); - int row; - int column; + int row, col; - int craftingOffsetX = 30; - int inventoryOffsetX = 8; + int bothOffset = 0; + + if (logic.chest != null) { + if(logic.slotCount > 54) + bothOffset += 12; // SlideBar.width - if (logic.chest != null) - { - craftingOffsetX += 116; - inventoryOffsetX += 116; + bothOffset += 122; } + final int craftingOffsetX = 30 + bothOffset; + final int inventoryOffsetX = 8 + bothOffset; + + + // 0 - crafting slot + this.addSlotToContainer(new SlotCraftingStation(inventoryplayer.player, this.craftMatrix, this.craftResult, 0, craftingOffsetX + 94, 35)); - this.addSlotToContainer(new SlotCraftingStation(inventorplayer.player, this.craftMatrix, this.craftResult, 0, craftingOffsetX + 94, 35)); - - for (row = 0; row < 3; ++row) - { - for (column = 0; column < 3; ++column) - { - this.addSlotToContainer(new Slot(this.craftMatrix, column + row * 3, craftingOffsetX + column * 18, 17 + row * 18)); + // 1 - 9 - Crafting Matrix + for (row = 0; row < 3; ++row) { + for (col = 0; col < 3; ++col) { + this.addSlotToContainer(new Slot(this.craftMatrix, col + row * 3, craftingOffsetX + col * 18, 17 + row * 18)); } } - //Player Inventory - for (row = 0; row < 3; ++row) - { - for (column = 0; column < 9; ++column) - { - this.addSlotToContainer(new Slot(inventorplayer, column + row * 9 + 9, inventoryOffsetX + column * 18, 84 + row * 18)); + // Player Inventory 10 - 36 + for (row = 0; row < 3; ++row) { + for (col = 0; col < 9; ++col) { + this.addSlotToContainer(new Slot(inventoryplayer, col + row * 9 + 9, inventoryOffsetX + col * 18, 84 + row * 18)); } } - - for (column = 0; column < 9; ++column) - { - this.addSlotToContainer(new Slot(inventorplayer, column, inventoryOffsetX + column * 18, 142)); + // Player Hotbar - 37 - 45 + for (col = 0; col < 9; ++col) { + this.addSlotToContainer(new Slot(inventoryplayer, col, inventoryOffsetX + col * 18, 142)); } - //Side inventory - if (logic.chest != null) - { - IInventory firstChest = logic.chest.get(); - IInventory secondChest = logic.doubleChest == null ? null : logic.doubleChest.get(); + // Side inventory - 46+ + if (logic.chest != null) { + IInventory inv = logic.getFirstInventory(); + IInventory secondInv = logic.getSecondInventory(); - if (logic.doubleFirst && logic.doubleChest != null) - { - secondChest = logic.chest.get(); - firstChest = logic.doubleChest.get(); - } - - int count = 0; - for (column = 0; column < 9; column++) - { - for (row = 0; row < 6; row++) - { - int value = count < 27 ? count : count - 27; - this.addSlotToContainer(new Slot(count < 27 ? firstChest : secondChest, value, 8 + row * 18, 19 + column * 18)); - count++; - if (count >= 27 && secondChest == null) - break; + final Set accessibleSlots = inv instanceof ISidedInventory ? new HashSet<>(Ints.asList(((ISidedInventory) inv).getAccessibleSlotsFromSide(logic.chestDirection.getOpposite().ordinal()))) : null; + + int index = 0, curIndex = 0; + IInventory curInv; + final int invSize = inv.getSizeInventory() * (secondInv != null ? 2 : 1); + for (row = 0; row < logic.invRows; row++) { + for (col = 0; col < logic.invColumns; col++) { + if(index >= invSize) break; + // Adjust the inventory to account for double chests + curInv = secondInv != null && index >= 27 ? secondInv : inv; + // Adjust the index for the inventory + curIndex = secondInv != null && index >= 27 ? index - 27 : index; + + if(accessibleSlots == null || accessibleSlots.contains(curIndex)) { + this.addSlotToContainer(new ChestSlot(curInv, curIndex, 8 + col * 18, 19 + row * 18)); + } + index++; } - if (count >= 27 && secondChest == null) - break; } } this.onCraftMatrixChanged(this.craftMatrix); } - public void onCraftMatrixChanged (IInventory par1IInventory) - { + public ItemStack modifyItem() { + ItemStack input = craftMatrix.getStackInSlot(4); + if (input != null) { + Item item = input.getItem(); + if (item instanceof IModifyable) { + ItemStack[] slots = new ItemStack[8]; + for (int i = 0; i < 4; i++) { + slots[i] = craftMatrix.getStackInSlot(i); + slots[i + 4] = craftMatrix.getStackInSlot(i + 5); + } + return ModifyBuilder.instance.modifyItem(input, slots); + } + } + return null; + } + + public ItemStack transferStackInSlot(EntityPlayer entityPlayer, int index) { + Slot slot = (Slot) this.inventorySlots.get(index); + + if(slot == null || !slot.getHasStack()) { + return null; + } + + ItemStack ret = slot.getStack().copy(); + ItemStack itemstack = slot.getStack().copy(); + + boolean nothingDone = true; + + if (index == 0) { + // Crafting Result + if (ret.getItem() instanceof IModifyable) { + nothingDone &= this.mergeCraftedStack(itemstack, logic.getSizeInventory(), this.inventorySlots.size(), true, entityPlayer); + } else { + // First refill the attached chests + nothingDone &= this.refillChest(itemstack); + + // Then try moving to player inventory + nothingDone &= moveToPlayerInventory(itemstack); + } + + slot.onSlotChange(itemstack, ret); + } else if(index >= 1 && index < 10) { // From Crafting Grid + // First refill the attached chests + nothingDone &= this.refillChest(itemstack); + + // Then try moving to player inventory + nothingDone &= moveToPlayerInventory(itemstack); + } + else if (index >= 10 && index < 46) { // From Player Inv or Hotbar + // First to the crafting Matrix + nothingDone &= moveToCraftingGrid(itemstack); + + // Then to any attached chest + nothingDone &= this.moveToChest(itemstack); + } else { // From the Attached Chests + // First to the crafting Matrix + nothingDone &= moveToCraftingGrid(itemstack); + + // Then To Player Inv or Hotbar + nothingDone &= moveToPlayerInventory(itemstack); + } + + if(nothingDone) { + return null; + } + + if (itemstack.stackSize == 0) { + slot.putStack(null); + } else { + slot.onSlotChanged(); + } + + if (itemstack.stackSize == ret.stackSize) { + return null; + } + + slot.onPickupFromSlot(entityPlayer, itemstack); + + return ret; + } + protected boolean refillChest(ItemStack itemstack) { + if(itemstack == null || itemstack.stackSize <= 0 || logic.slotCount == 0) return false; + + return !this.mergeItemStackRefill(itemstack, 46, 46 + logic.slotCount, false); + } + + protected boolean moveToChest(ItemStack itemstack) { + if(itemstack == null || itemstack.stackSize <= 0 || logic.slotCount == 0) return false; + + return !this.mergeItemStack(itemstack, 46, 46 + logic.slotCount, false); + } + + protected boolean moveToPlayerInventory(ItemStack itemstack) { + if(itemstack == null || itemstack.stackSize <= 0) return false; + + return !this.mergeItemStack(itemstack, 10, 46, false); + } + + protected boolean moveToCraftingGrid(ItemStack itemstack) { + if(itemstack == null || itemstack.stackSize <= 0) return false; + + return !this.mergeItemStack(itemstack, 1, 10, true); + } + + public boolean func_94530_a/*canMergeSlot*/(ItemStack par1ItemStack, Slot par2Slot) { + return par2Slot.inventory != this.craftResult && super.func_94530_a(par1ItemStack, par2Slot); + } + + @Override + public void onContainerClosed(EntityPlayer par1EntityPlayer) { + super.onContainerClosed(par1EntityPlayer); + + if (!this.worldObj.isRemote) { + for (int i = 0; i < 9; ++i) { + ItemStack itemstack = this.craftMatrix.getStackInSlotOnClosing(i); + + if (itemstack != null) { + par1EntityPlayer.dropPlayerItemWithRandomChoice(itemstack, false); + } + } + } + } + + public void onCraftMatrixChanged(IInventory par1IInventory) { ItemStack tool = modifyItem(); if (tool != null) this.craftResult.setInventorySlotContents(0, tool); @@ -119,51 +247,8 @@ public class CraftingStationContainer extends Container this.craftResult.setInventorySlotContents(0, CraftingManager.getInstance().findMatchingRecipe(this.craftMatrix, this.worldObj)); } - public ItemStack modifyItem () - { - ItemStack input = craftMatrix.getStackInSlot(4); - if (input != null) - { - Item item = input.getItem(); - if (item instanceof IModifyable) - { - ItemStack[] slots = new ItemStack[8]; - for (int i = 0; i < 4; i++) - { - slots[i] = craftMatrix.getStackInSlot(i); - slots[i + 4] = craftMatrix.getStackInSlot(i + 5); - } - ItemStack output = ModifyBuilder.instance.modifyItem(input, slots); - if (output != null) - return output; - } - } - return null; - } - @Override - public void onContainerClosed (EntityPlayer par1EntityPlayer) - { - super.onContainerClosed(par1EntityPlayer); - - if (!this.worldObj.isRemote) - { - for (int i = 0; i < 9; ++i) - { - ItemStack itemstack = this.craftMatrix.getStackInSlotOnClosing(i); - - if (itemstack != null) - { - par1EntityPlayer.dropPlayerItemWithRandomChoice(itemstack, false); - } - } - } - } - - @Override - public boolean canInteractWith (EntityPlayer player) - { - + public boolean canInteractWith(EntityPlayer player) { Block block = worldObj.getBlock(this.posX, this.posY, this.posZ); if (block != TinkerTools.craftingStationWood && block != TinkerTools.craftingSlabWood) return false; @@ -174,105 +259,23 @@ public class CraftingStationContainer extends Container return player.getDistanceSq((double) this.posX + 0.5D, (double) this.posY + 0.5D, (double) this.posZ + 0.5D) <= 64.0D; } - public ItemStack transferStackInSlot (EntityPlayer par1EntityPlayer, int par2) - { - ItemStack itemstack = null; - Slot slot = (Slot) this.inventorySlots.get(par2); - - if (slot != null && slot.getHasStack()) - { - ItemStack itemstack1 = slot.getStack(); - itemstack = itemstack1.copy(); - - if (par2 == 0) - { - if (itemstack.getItem() instanceof IModifyable) - { - if (!this.mergeCraftedStack(itemstack1, logic.getSizeInventory(), this.inventorySlots.size(), true, par1EntityPlayer)) - { - return null; - } - } - else - { - if (!this.mergeItemStack(itemstack1, 10, 46, true)) - { - return null; - } - } - - slot.onSlotChange(itemstack1, itemstack); - } - else if (par2 >= 10 && par2 < 37) - { - if (!this.mergeItemStack(itemstack1, 37, 46, false)) - { - return null; - } - } - else if (par2 >= 37 && par2 < 46) - { - if (!this.mergeItemStack(itemstack1, 10, 37, false)) - { - return null; - } - } - else if (!this.mergeItemStack(itemstack1, 10, 46, false)) - { - return null; - } - - if (itemstack1.stackSize == 0) - { - slot.putStack((ItemStack) null); - } - else - { - slot.onSlotChanged(); - } - - if (itemstack1.stackSize == itemstack.stackSize) - { - return null; - } - - slot.onPickupFromSlot(par1EntityPlayer, itemstack1); - } - - return itemstack; - } - - protected boolean mergeCraftedStack (ItemStack stack, int slotsStart, int slotsTotal, boolean playerInventory, EntityPlayer player) - { + protected boolean mergeCraftedStack(ItemStack stack, int slotsStart, int slotsTotal, boolean playerInventory, EntityPlayer player) { boolean failedToMerge = false; int slotIndex = slotsStart; - if (playerInventory) - { + if (playerInventory) { slotIndex = slotsTotal - 1; } Slot otherInventorySlot; - ItemStack copyStack = null; + ItemStack copyStack; - if (stack.stackSize > 0) - { - if (playerInventory) - { - slotIndex = slotsTotal - 1; - } - else - { - slotIndex = slotsStart; - } - - while (!playerInventory && slotIndex < slotsTotal || playerInventory && slotIndex >= slotsStart) - { + if (stack.stackSize > 0) { + while (!playerInventory && slotIndex < slotsTotal || playerInventory && slotIndex >= slotsStart) { otherInventorySlot = (Slot) this.inventorySlots.get(slotIndex); copyStack = otherInventorySlot.getStack(); - if (copyStack == null) - { + if (copyStack == null) { otherInventorySlot.putStack(stack.copy()); otherInventorySlot.onSlotChanged(); stack.stackSize = 0; @@ -280,12 +283,9 @@ public class CraftingStationContainer extends Container break; } - if (playerInventory) - { + if (playerInventory) { --slotIndex; - } - else - { + } else { ++slotIndex; } } @@ -294,8 +294,102 @@ public class CraftingStationContainer extends Container return failedToMerge; } - public boolean func_94530_a (ItemStack par1ItemStack, Slot par2Slot) - { - return par2Slot.inventory != this.craftResult && super.func_94530_a(par1ItemStack, par2Slot); + @Override + protected boolean mergeItemStack(@Nonnull ItemStack stack, int startIndex, int endIndex, boolean useEndIndex) { + boolean ret = mergeItemStackRefill(stack, startIndex, endIndex, useEndIndex); + if(stack.stackSize > 0) { + ret |= mergeItemStackMove(stack, startIndex, endIndex, useEndIndex); + } + return ret; } + + // only refills items that are already present + protected boolean mergeItemStackRefill(@Nonnull ItemStack stack, int startIndex, int endIndex, boolean useEndIndex) { + if(stack.stackSize <= 0) { + return false; + } + + boolean didSomething = false; + int k = useEndIndex ? endIndex - 1 : startIndex; + + + Slot slot; + ItemStack itemstack1; + + if(stack.isStackable()) { + while(stack.stackSize > 0 && (!useEndIndex && k < endIndex || useEndIndex && k >= startIndex)) { + slot = (Slot)this.inventorySlots.get(k); + itemstack1 = slot.getStack(); + + if(itemstack1 != null + && itemstack1.getItem() == stack.getItem() + && (!stack.getHasSubtypes() || stack.getItemDamage() == itemstack1.getItemDamage()) + && ItemStack.areItemStackTagsEqual(stack, itemstack1) + && this.func_94530_a/*canMergeSlot*/(stack, slot)) { + int l = itemstack1.stackSize + stack.stackSize; + int limit = Math.min(stack.getMaxStackSize(), slot.getSlotStackLimit()); + + if(l <= limit) { + stack.stackSize = 0; + itemstack1.stackSize = l; + slot.onSlotChanged(); + didSomething = true; + } + else if(itemstack1.stackSize < limit) { + stack.stackSize -= (limit - itemstack1.stackSize); + itemstack1.stackSize = limit; + slot.onSlotChanged(); + didSomething = true; + } + } + + if(useEndIndex) --k; + else ++k; + } + } + + return didSomething; + } + + // only moves items into empty slots + protected boolean mergeItemStackMove(@Nonnull ItemStack stack, int startIndex, int endIndex, boolean useEndIndex) { + if(stack.stackSize <= 0) { + return false; + } + + boolean didSomething = false; + int k = useEndIndex ? endIndex - 1 : startIndex; + + while(!useEndIndex && k < endIndex || useEndIndex && k >= startIndex) { + final Slot slot = (Slot)this.inventorySlots.get(k); + ItemStack itemstack1 = slot.getStack(); + + if((itemstack1 == null || itemstack1.stackSize == 0) && slot.isItemValid(stack) && this.func_94530_a/*canMergeSlot*/(stack, slot)) { + // Forge: Make sure to respect isItemValid in the slot. + int limit = slot.getSlotStackLimit(); + ItemStack stack2 = stack.copy(); + if(stack2.stackSize > limit) { + stack2.stackSize = limit; + stack.stackSize -= limit; + } + else { + stack.stackSize = 0; + } + slot.putStack(stack2); + slot.onSlotChanged(); + didSomething = true; + + if(stack.stackSize <= 0) { + break; + } + } + + if(useEndIndex) --k; + else ++k; + } + + return didSomething; + } + } + diff --git a/src/main/java/tconstruct/tools/logic/CraftingStationLogic.java b/src/main/java/tconstruct/tools/logic/CraftingStationLogic.java index f4469507..6d8a0d56 100644 --- a/src/main/java/tconstruct/tools/logic/CraftingStationLogic.java +++ b/src/main/java/tconstruct/tools/logic/CraftingStationLogic.java @@ -1,7 +1,5 @@ package tconstruct.tools.logic; -import java.lang.ref.WeakReference; - import mantle.blocks.abstracts.InventoryLogic; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; @@ -13,11 +11,16 @@ import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityChest; import net.minecraft.tileentity.TileEntityFurnace; import net.minecraft.world.World; +import net.minecraftforge.common.util.ForgeDirection; import tconstruct.tools.inventory.CraftingStationContainer; +import tconstruct.util.config.PHConstruct; -public class CraftingStationLogic extends InventoryLogic implements ISidedInventory -{ - public WeakReference chest; // TODO: These are prototypes +import java.lang.ref.WeakReference; + +public class CraftingStationLogic extends InventoryLogic implements ISidedInventory { + public ForgeDirection chestDirection = ForgeDirection.UNKNOWN; + public int chestSize; + public WeakReference chest; public WeakReference doubleChest; public WeakReference patternChest; public WeakReference furnace; @@ -25,91 +28,131 @@ public class CraftingStationLogic extends InventoryLogic implements ISidedInvent public boolean stencilTable; public boolean doubleFirst; - public CraftingStationLogic() - { - super(10); // 9 for crafting, 1 for output, 6 for extensions, 1 for - // plans + public int invRows, invColumns, slotCount; + + public CraftingStationLogic() { + super(10); // 9 for crafting, 1 for output } @Override - public Container getGuiContainer (InventoryPlayer inventoryplayer, World world, int x, int y, int z) - { + public boolean canDropInventorySlot(int slot) { + return slot != 0; + } + + @Override + public ItemStack decrStackSize(int slot, int quantity) { + if (slot == 0) { + for (int i = 1; i < getSizeInventory(); i++) + decrStackSize(i, 1); + } + return super.decrStackSize(slot, quantity); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer player) { + return isUseableByPlayer(player, this.getInventories()) && super.isUseableByPlayer(player); + } + + @Override + public Container getGuiContainer(InventoryPlayer inventoryplayer, World world, int x, int y, int z) { chest = null; + chestSize = 0; + slotCount = 0; + chestDirection = ForgeDirection.UNKNOWN; doubleChest = null; patternChest = null; furnace = null; tinkerTable = false; - int[] ys = { y, y - 1, y + 1 }; - for (byte iy = 0; iy < 3; iy++) - { - int yPos = ys[iy]; - for (int xPos = x - 1; xPos <= x + 1; xPos++) - { - for (int zPos = z - 1; zPos <= z + 1; zPos++) - { - TileEntity tile = world.getTileEntity(xPos, yPos, zPos); - if (chest == null && tile instanceof TileEntityChest) - { - chest = new WeakReference(tile); - checkForChest(world, xPos, yPos, zPos, 1, 0); - checkForChest(world, xPos, yPos, zPos, -1, 0); - checkForChest(world, xPos, yPos, zPos, 0, 1); - checkForChest(world, xPos, yPos, zPos, 0, -1); - } - else if (patternChest == null && tile instanceof PatternChestLogic) - patternChest = new WeakReference(tile); - else if (furnace == null && (tile instanceof TileEntityFurnace || tile instanceof FurnaceLogic)) - furnace = new WeakReference(tile); - else if (tinkerTable == false && tile instanceof ToolStationLogic) - tinkerTable = true; - } + + for (final ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { + final int xPos = x + dir.offsetX, yPos = y + dir.offsetY, zPos = z + dir.offsetZ; + final TileEntity tile = world.getTileEntity(xPos, yPos, zPos); + if (!(tile instanceof IInventory) || (tile instanceof CraftingStationLogic) || isBlacklisted(tile.getClass())) continue; + + final IInventory inv = (IInventory) tile; + + if (patternChest == null && tile instanceof PatternChestLogic) { + patternChest = new WeakReference<>(inv); + continue; + } else if (furnace == null && (tile instanceof TileEntityFurnace || tile instanceof FurnaceLogic)) { + furnace = new WeakReference<>(inv); + continue; + } else if (!tinkerTable && tile instanceof ToolStationLogic) { + tinkerTable = true; + continue; } + + if(tile instanceof ISidedInventory && ((ISidedInventory)tile).getAccessibleSlotsFromSide(dir.getOpposite().ordinal()).length == 0) continue; + + if (chest == null && inv.isUseableByPlayer(inventoryplayer.player)) { + chest = new WeakReference<>(inv); + chestDirection = dir; + invColumns = 6; + chestSize = tile instanceof ISidedInventory ? ((ISidedInventory)tile).getAccessibleSlotsFromSide(dir.getOpposite().ordinal()).length : inv.getSizeInventory(); + + if (tile instanceof TileEntityChest) { + checkForChest(world, xPos, yPos, zPos, 1, 0); + checkForChest(world, xPos, yPos, zPos, -1, 0); + checkForChest(world, xPos, yPos, zPos, 0, 1); + checkForChest(world, xPos, yPos, zPos, 0, -1); + } + slotCount = chestSize * (doubleChest != null ? 2 : 1); + invRows = (int) Math.ceil((double) slotCount / invColumns); + } + } return new CraftingStationContainer(inventoryplayer, this, x, y, z); } - void checkForChest (World world, int x, int y, int z, int dx, int dz) - { + private boolean isBlacklisted(Class clazz) { + return PHConstruct.craftingStationBlacklist.contains(clazz.getName()); + } + + void checkForChest(World world, int x, int y, int z, int dx, int dz) { TileEntity tile = world.getTileEntity(x + dx, y, z + dz); - if (tile instanceof TileEntityChest) - { - doubleChest = new WeakReference(tile); + if (tile instanceof TileEntityChest) { + doubleChest = new WeakReference<>((IInventory) tile); doubleFirst = dx + dz < 0; } } + + public boolean isDoubleChest() { + return this.doubleChest != null; + } + + public IInventory getFirstInventory() { + if (doubleFirst && doubleChest != null) { + return doubleChest.get(); + } else { + return chest.get(); + } + } + + public IInventory getSecondInventory() { + if(!isDoubleChest()) return null; + + if (doubleFirst) { + return chest.get(); + } else { + return doubleChest == null ? null : doubleChest.get(); + } + } @Override - protected String getDefaultName () - { + protected String getDefaultName() { return "crafters.CraftingStation"; } @Override - public boolean canDropInventorySlot (int slot) - { - if (slot == 0) - return false; + public boolean hasCustomInventoryName() { return true; } - @Override - public int[] getAccessibleSlotsFromSide (int var1) - { - return new int[] {}; - } - - @Override - public boolean isUseableByPlayer(EntityPlayer player) - { - return isUseableByPlayer(player, this.getInventories()) && super.isUseableByPlayer(player); - } - + @SuppressWarnings({"unchecked", "rawtypes"}) public static boolean isUseableByPlayer(EntityPlayer player, WeakReference[] inventories) { - for (WeakReference ref : inventories) - { - if (ref != null) - { + for (WeakReference ref : inventories) { + if (ref != null) { IInventory inv = ref.get(); if (inv != null && !inv.isUseableByPlayer(player)) return false; @@ -119,63 +162,45 @@ public class CraftingStationLogic extends InventoryLogic implements ISidedInvent return true; } + @SuppressWarnings("rawtypes") + public WeakReference[] getInventories() { + return new WeakReference[]{this.chest, this.doubleChest, this.patternChest, this.furnace}; + } + @Override - public boolean canInsertItem (int i, ItemStack itemstack, int j) - { + public int[] getAccessibleSlotsFromSide(int var1) { + return new int[]{}; + } + + @Override + public boolean canInsertItem(int i, ItemStack itemstack, int j) { return false; } @Override - public ItemStack decrStackSize (int slot, int quantity) - { - if (slot == 0) - { - for (int i = 1; i < getSizeInventory(); i++) - decrStackSize(i, 1); - } - return super.decrStackSize(slot, quantity); - } - - @Override - public boolean canExtractItem (int i, ItemStack itemstack, int j) - { + public boolean canExtractItem(int i, ItemStack itemstack, int j) { return false; } @Override - public String getInventoryName () - { + public String getInventoryName() { return getDefaultName(); } @Override - public boolean hasCustomInventoryName () - { - return true; - } - - @Override - public void closeInventory () - { + public void openInventory() { // TODO Auto-generated method stub } @Override - public void openInventory () - { + public void closeInventory() { // TODO Auto-generated method stub } - public WeakReference[] getInventories() - { - return new WeakReference[] { this.chest, this.doubleChest, this.patternChest, this.furnace }; - } - @Override - public boolean canUpdate () - { + public boolean canUpdate() { return false; } } diff --git a/src/main/java/tconstruct/util/config/PHConstruct.java b/src/main/java/tconstruct/util/config/PHConstruct.java index 40bd7f46..54bc6a82 100644 --- a/src/main/java/tconstruct/util/config/PHConstruct.java +++ b/src/main/java/tconstruct/util/config/PHConstruct.java @@ -1,10 +1,15 @@ package tconstruct.util.config; -import java.io.File; -import net.minecraftforge.common.config.*; +import com.google.common.collect.Sets; +import net.minecraftforge.common.config.ConfigCategory; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.common.config.Property; import tconstruct.TConstruct; import tconstruct.library.tools.AbilityHelper; +import java.io.File; +import java.util.Set; + public class PHConstruct { @@ -83,22 +88,17 @@ public class PHConstruct boolean ic2 = true; boolean xycraft = true; - try - { + try { Class c = Class.forName("ic2.core.IC2"); ic2 = false; } - catch (Exception e) - { - } - try - { + catch (Exception ignored) {} + + try { Class c = Class.forName("soaryn.xycraft.core.XyCraft"); xycraft = false; } - catch (Exception e) - { - } + catch (Exception ignored) {} generateCopper = config.get("Worldgen Disabler", "Generate Copper", ic2).getBoolean(ic2); generateTin = config.get("Worldgen Disabler", "Generate Tin", ic2).getBoolean(ic2); @@ -214,6 +214,10 @@ public class PHConstruct extraBlockUpdates = config.get("Experimental", "Send additional block updates when using AOE tools", true,"This fixes very fast tools sometimes resulting in ghost blocks, but causes a bit more network traffic. Should be fine in theory.").getBoolean(true); heartDropBlacklist = config.get("Experimental", "YellowHeartDropBlacklist", new String[] {"entitynpc", "entitycustomnpc"}, "Entity classes listed here will not drop yellow hearts. The values are the actual class names in lowercase.").getStringList(); + craftingStationBlacklist = Sets.newHashSet(config.get("CraftingStationBlacklist", "tileEntities", new String[] { + "wanion.avaritiaddons.block.chest.infinity.TileEntityInfinityChest" + }).getStringList()); + /* Save the configuration file only if it has changed */ if (config.hasChanged()) config.save(); @@ -396,4 +400,5 @@ public class PHConstruct public static boolean minimalTextures; public static boolean extraBlockUpdates; public static String[] heartDropBlacklist; + public static Set craftingStationBlacklist; } diff --git a/src/main/resources/assets/tinker/textures/gui/generic.png b/src/main/resources/assets/tinker/textures/gui/generic.png new file mode 100644 index 0000000000000000000000000000000000000000..d2d5df2aae710af423246912c3ad3a58db008289 GIT binary patch literal 585 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=Y)RhkE)2&((0E!z5>SM*z$3Dl zfr0N32s4Umcr^e8*-JcqUD@w*un1eIUJ6|s$-uyP&C|s(q~g}wS&r+P3`AVtE5A9o zQ2BAkO2<2G(uR-pJYqOrFHliAGiM{y;_4N``{T6(0_yE9RSOFRYrVCOne}}ZSKZQw zeMkN*+*+nyC%E(IyPaY-3>r)G`ox7D<~?7`zTy6RMuyB;hj#CO==5QkjfLKG#vi%n z=CjYQ!9NKUYdHF#Pr_3>4vLVpx88<<|J?3r=l1Qeq{` z$G~u6)0%B}?-X0h^>6*FHu>b`=yjKK%%rcWUl7Tde8yq+7x~6Zj3o@R4(u1;lmkD5 z=cEN1U4B#JrY9|5r8On>=cknai)`vGR8qt00!2K})|Z?$mRmAK>dVH>$DD)AG?#9< zCiOjh-t+j{W9MEA|0&v8lf{3y;6whOr=|yZ*5npHiB>EKp8@rk%(S%