commit bd9d0a4eff2efe740130acc404241e4784006996 Author: Chicken-Bomes Date: Tue Apr 29 10:54:20 2014 +1000 Initial Commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..ccc5e8ba --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/build/build +/build/.gradle diff --git a/build/build.gradle b/build/build.gradle new file mode 100644 index 00000000..65864a6e --- /dev/null +++ b/build/build.gradle @@ -0,0 +1,115 @@ +buildscript { + repositories { + mavenCentral() + mavenLocal() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + maven { + name = "sonatype" + url = "https://oss.sonatype.org/content/repositories/snapshots/" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:1.2-SNAPSHOT' + } +} + +apply plugin: 'forge' + +group = "codechicken" // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = "NotEnoughItems" + +// Define properties file +ext.configFile = file "build.properties" + +configFile.withReader { + // Load config. It shall from now be referenced as simply config or project.config + def prop = new Properties() + prop.load(it) + project.ext.config = new ConfigSlurper().parse prop +} +dependencies { + compile "codechicken:CodeChickenLib:${config.mc_version}-${config.ccl_version}:dev" + //compile "codechicken:CodeChickenCore:${config.mc_version}-${config.ccc_version}:dev" +} + +version = "${project.config.mod_version}." + System.getenv("BUILD_NUMBER") ?: "1" + +println config.mc_version + "-" + config.forge_version +// Setup the forge minecraft plugin data. Specify the preferred forge/minecraft version here +minecraft { + version = config.mc_version + "-" + config.forge_version +} + +sourceSets { + main { + def root = project.projectDir.parentFile + java { + srcDir new File(root, "src") + } + resources { + srcDir new File(root, "resources") + } + } +} + +processResources { + //redo task if any of these properties change + inputs.property "version", project.version + inputs.property "mc_version", config.mc_version + + // Replace properties in info files + from(sourceSets.main.resources.srcDirs) { + include '*.info' + expand 'version':project.version,'mc_version':config.mc_version + } + // Copy everything else + from(sourceSets.main.resources.srcDirs) { + include 'assets/**/*.*' + } +} + +task sourceJar(type: Jar) { + from sourceSets.main.allSource + classifier = 'src' + version = "${project.minecraft.version}-${project.version}" +} + +def commonManifest = { + attributes 'FMLCorePlugin': 'codechicken.nei.asm.NEICorePlugin' + attributes 'AccessTransformer': 'nei_at.cfg' +} + +jar { + classifier = 'universal' + version = "${project.minecraft.version}-${project.version}" + manifest commonManifest +} + +task devJar(type: Jar) { + from sourceSets.main.output + classifier = 'dev' + version = "${project.minecraft.version}-${project.version}" + manifest commonManifest +} + +// Tell the artifact system about our extra jars +artifacts { + archives sourceJar, devJar +} + +// Configure an upload task. +uploadArchives { + dependsOn 'reobf' + if (project.hasProperty("local_maven")) { + repositories { + logger.info('Publishing to local maven repo') + + mavenDeployer { + repository(url: "file://${local_maven}") + } + } + } +} \ No newline at end of file diff --git a/build/build.properties b/build/build.properties new file mode 100644 index 00000000..a9ad40b1 --- /dev/null +++ b/build/build.properties @@ -0,0 +1,5 @@ +mc_version=1.7.2 +forge_version=10.12.0.1054 +ccl_version=1.1.0.74 +ccc_version=1.0.0 +mod_version=1.0 diff --git a/build/gradle/wrapper/gradle-wrapper.jar b/build/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..3c7abdf1 Binary files /dev/null and b/build/gradle/wrapper/gradle-wrapper.jar differ diff --git a/build/gradle/wrapper/gradle-wrapper.properties b/build/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..244a668f --- /dev/null +++ b/build/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Wed Mar 26 13:33:58 CDT 2014 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=http\://services.gradle.org/distributions/gradle-1.11-bin.zip diff --git a/build/gradlew b/build/gradlew new file mode 100644 index 00000000..91a7e269 --- /dev/null +++ b/build/gradlew @@ -0,0 +1,164 @@ +#!/usr/bin/env bash + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn ( ) { + echo "$*" +} + +die ( ) { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; +esac + +# For Cygwin, ensure paths are in UNIX format before anything is touched. +if $cygwin ; then + [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` +fi + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >&- +APP_HOME="`pwd -P`" +cd "$SAVED" >&- + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin, switch paths to Windows format before running java +if $cygwin ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=$((i+1)) + done + case $i in + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules +function splitJvmOpts() { + JVM_OPTS=("$@") +} +eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS +JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" + +exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" diff --git a/build/gradlew.bat b/build/gradlew.bat new file mode 100644 index 00000000..8a0b282a --- /dev/null +++ b/build/gradlew.bat @@ -0,0 +1,90 @@ +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windowz variants + +if not "%OS%" == "Windows_NT" goto win9xME_args +if "%@eval[2+2]" == "4" goto 4NT_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* +goto execute + +:4NT_args +@rem Get arguments from the 4NT Shell from JP Software +set CMD_LINE_ARGS=%$ + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/build/settings.gradle b/build/settings.gradle new file mode 100644 index 00000000..398e21f6 --- /dev/null +++ b/build/settings.gradle @@ -0,0 +1,19 @@ +/* + * This settings file was auto generated by the Gradle buildInit task + * by 'sunstrike' at '21/11/13 14:14' with Gradle 1.9 + * + * The settings file is used to specify which projects to include in your build. + * In a single project build this file can be empty or even removed. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user guide at http://gradle.org/docs/1.9/userguide/multi_project_builds.html + */ + +/* +// To declare projects as part of a multi-project build use the 'include' method +include 'shared' +include 'api' +include 'services:webservice' +*/ + +rootProject.name = 'CodeChickenLib' diff --git a/dev/GuiContainer.java b/dev/GuiContainer.java new file mode 100644 index 00000000..d61a57fe --- /dev/null +++ b/dev/GuiContainer.java @@ -0,0 +1,803 @@ +package net.minecraft.client.gui.inventory; + +import codechicken.nei.guihook.GuiContainerManager; +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.texture.TextureMap; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IIcon; +import net.minecraft.util.MathHelper; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +@SideOnly(Side.CLIENT) +public abstract class GuiContainer extends GuiScreen +{ + protected static final ResourceLocation field_147001_a = new ResourceLocation("textures/gui/container/inventory.png"); + /** The X size of the inventory window in pixels. */ + public int xSize = 176; + /** The Y size of the inventory window in pixels. */ + public int ySize = 166; + /** A list of the players inventory slots */ + public Container inventorySlots; + /** + * Starting X position for the Gui. Inconsistent use for Gui backgrounds. + */ + public int guiLeft; + /** + * Starting Y position for the Gui. Inconsistent use for Gui backgrounds. + */ + public int guiTop; + private Slot theSlot; + /** Used when touchscreen is enabled. */ + private Slot clickedSlot; + /** Used when touchscreen is enabled. */ + private boolean isRightMouseClick; + /** Used when touchscreen is enabled */ + private ItemStack draggedStack; + private int field_147011_y; + private int field_147010_z; + private Slot returningStackDestSlot; + private long returningStackTime; + /** Used when touchscreen is enabled */ + private ItemStack returningStack; + private Slot field_146985_D; + private long field_146986_E; + protected final Set field_147008_s = new HashSet(); + protected boolean field_147007_t; + private int field_146987_F; + private int field_146988_G; + private boolean field_146995_H; + private int field_146996_I; + private long field_146997_J; + private Slot field_146998_K; + private int field_146992_L; + private boolean field_146993_M; + private ItemStack field_146994_N; + private static final String __OBFID = "CL_00000737"; + + public GuiContainerManager manager; + + public GuiContainer(Container par1Container) + { + this.inventorySlots = par1Container; + this.field_146995_H = true; + } + + /** + * Adds the buttons (and other controls) to the screen in question. + */ + public void initGui() + { + super.initGui(); + this.mc.thePlayer.openContainer = this.inventorySlots; + this.guiLeft = (this.width - this.xSize) / 2; + this.guiTop = (this.height - this.ySize) / 2; + } + + /** + * Draws the screen and all the components in it. + */ + public void drawScreen(int par1, int par2, float par3) + { + manager.preDraw(); + + this.drawDefaultBackground(); + int k = this.guiLeft; + int l = this.guiTop; + this.drawGuiContainerBackgroundLayer(par3, par1, par2); + GL11.glDisable(GL12.GL_RESCALE_NORMAL); + RenderHelper.disableStandardItemLighting(); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + super.drawScreen(par1, par2, par3); + RenderHelper.enableGUIStandardItemLighting(); + GL11.glPushMatrix(); + GL11.glTranslatef((float)k, (float)l, 0.0F); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + this.theSlot = null; + short short1 = 240; + short short2 = 240; + OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float)short1 / 1.0F, (float)short2 / 1.0F); + GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F); + int k1; + + for (int i1 = 0; i1 < this.inventorySlots.inventorySlots.size(); ++i1) + { + Slot slot = (Slot)this.inventorySlots.inventorySlots.get(i1); + this.func_146977_a(slot); + + if (this.isMouseOverSlot(slot, par1, par2) && slot.func_111238_b() && !manager.objectUnderMouse(par1, par2)) + { + this.theSlot = slot; + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + int j1 = slot.xDisplayPosition; + k1 = slot.yDisplayPosition; + GL11.glColorMask(true, true, true, false); + this.drawGradientRect(j1, k1, j1 + 16, k1 + 16, -2130706433, -2130706433); + GL11.glColorMask(true, true, true, true); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_DEPTH_TEST); + } + } + + //Forge: Force lighting to be disabled as there are some issue where lighting would + //incorrectly be applied based on items that are in the inventory. + GL11.glDisable(GL11.GL_LIGHTING); + this.drawGuiContainerForegroundLayer(par1, par2); + GL11.glEnable(GL11.GL_LIGHTING); + + manager.renderObjects(par1, par2); + + InventoryPlayer inventoryplayer = this.mc.thePlayer.inventory; + ItemStack itemstack = this.draggedStack == null ? inventoryplayer.getItemStack() : this.draggedStack; + + if (itemstack != null) + { + byte b0 = 8; + k1 = this.draggedStack == null ? 8 : 16; + String s = null; + + if (this.draggedStack != null && this.isRightMouseClick) + { + itemstack = itemstack.copy(); + itemstack.stackSize = MathHelper.ceiling_float_int((float)itemstack.stackSize / 2.0F); + } + else if (this.field_147007_t && this.field_147008_s.size() > 1) + { + itemstack = itemstack.copy(); + itemstack.stackSize = this.field_146996_I; + + if (itemstack.stackSize == 0) + { + s = "" + EnumChatFormatting.YELLOW + "0"; + } + } + + this.drawItemStack(itemstack, par1 - k - b0, par2 - l - k1, s); + } + + if (this.returningStack != null) + { + float f1 = (float)(Minecraft.getSystemTime() - this.returningStackTime) / 100.0F; + + if (f1 >= 1.0F) + { + f1 = 1.0F; + this.returningStack = null; + } + + k1 = this.returningStackDestSlot.xDisplayPosition - this.field_147011_y; + int j2 = this.returningStackDestSlot.yDisplayPosition - this.field_147010_z; + int l1 = this.field_147011_y + (int)((float)k1 * f1); + int i2 = this.field_147010_z + (int)((float)j2 * f1); + this.drawItemStack(this.returningStack, l1, i2, (String)null); + } + + GL11.glPopMatrix(); + /* + if (inventoryplayer.getItemStack() == null && this.theSlot != null && this.theSlot.getHasStack()) + { + ItemStack itemstack1 = this.theSlot.getStack(); + this.renderToolTip(itemstack1, par1, par2); + } + */ + manager.renderToolTips(par1, par2); + + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_DEPTH_TEST); + RenderHelper.enableStandardItemLighting(); + } + + private void drawItemStack(ItemStack p_146982_1_, int p_146982_2_, int p_146982_3_, String p_146982_4_) + { + GL11.glTranslatef(0.0F, 0.0F, 32.0F); + this.zLevel = 500.0F; + itemRender.zLevel = 500.0F; + FontRenderer font = null; + if (p_146982_1_ != null) font = p_146982_1_.getItem().getFontRenderer(p_146982_1_); + if (font == null) font = fontRendererObj; + itemRender.renderItemAndEffectIntoGUI(font, this.mc.getTextureManager(), p_146982_1_, p_146982_2_, p_146982_3_); + itemRender.renderItemOverlayIntoGUI(font, this.mc.getTextureManager(), p_146982_1_, p_146982_2_, p_146982_3_ - (this.draggedStack == null ? 0 : 8), p_146982_4_); + this.zLevel = 0.0F; + itemRender.zLevel = 0.0F; + } + + /** + * Draw the foreground layer for the GuiContainer (everything in front of the items) + */ + protected void drawGuiContainerForegroundLayer(int p_146979_1_, int p_146979_2_) {} + + protected abstract void drawGuiContainerBackgroundLayer(float var1, int var2, int var3); + + private void func_146977_a(Slot p_146977_1_) + { + int i = p_146977_1_.xDisplayPosition; + int j = p_146977_1_.yDisplayPosition; + ItemStack itemstack = p_146977_1_.getStack(); + boolean flag = false; + boolean flag1 = p_146977_1_ == this.clickedSlot && this.draggedStack != null && !this.isRightMouseClick; + ItemStack itemstack1 = this.mc.thePlayer.inventory.getItemStack(); + String s = null; + + if (p_146977_1_ == this.clickedSlot && this.draggedStack != null && this.isRightMouseClick && itemstack != null) + { + itemstack = itemstack.copy(); + itemstack.stackSize /= 2; + } + else if (this.field_147007_t && this.field_147008_s.contains(p_146977_1_) && itemstack1 != null) + { + if (this.field_147008_s.size() == 1) + { + return; + } + + if (Container.func_94527_a(p_146977_1_, itemstack1, true) && this.inventorySlots.canDragIntoSlot(p_146977_1_)) + { + itemstack = itemstack1.copy(); + flag = true; + Container.func_94525_a(this.field_147008_s, this.field_146987_F, itemstack, p_146977_1_.getStack() == null ? 0 : p_146977_1_.getStack().stackSize); + + if (itemstack.stackSize > itemstack.getMaxStackSize()) + { + s = EnumChatFormatting.YELLOW + "" + itemstack.getMaxStackSize(); + itemstack.stackSize = itemstack.getMaxStackSize(); + } + + if (itemstack.stackSize > p_146977_1_.getSlotStackLimit()) + { + s = EnumChatFormatting.YELLOW + "" + p_146977_1_.getSlotStackLimit(); + itemstack.stackSize = p_146977_1_.getSlotStackLimit(); + } + } + else + { + this.field_147008_s.remove(p_146977_1_); + this.func_146980_g(); + } + } + + this.zLevel = 100.0F; + itemRender.zLevel = 100.0F; + + if (itemstack == null) + { + IIcon iicon = p_146977_1_.getBackgroundIconIndex(); + + if (iicon != null) + { + GL11.glDisable(GL11.GL_LIGHTING); + this.mc.getTextureManager().bindTexture(TextureMap.locationItemsTexture); + this.drawTexturedModelRectFromIcon(i, j, iicon, 16, 16); + GL11.glEnable(GL11.GL_LIGHTING); + flag1 = true; + } + } + + if (!flag1) + { + if (flag) + { + drawRect(i, j, i + 16, j + 16, -2130706433); + } + + GL11.glEnable(GL11.GL_DEPTH_TEST); + manager.renderSlotUnderlay(p_146977_1_); + manager.drawSlotItem(p_146977_1_, itemstack, i, j, s); + manager.renderSlotOverlay(p_146977_1_); + } + + itemRender.zLevel = 0.0F; + this.zLevel = 0.0F; + } + + private void func_146980_g() + { + ItemStack itemstack = this.mc.thePlayer.inventory.getItemStack(); + + if (itemstack != null && this.field_147007_t) + { + this.field_146996_I = itemstack.stackSize; + ItemStack itemstack1; + int i; + + for (Iterator iterator = this.field_147008_s.iterator(); iterator.hasNext(); this.field_146996_I -= itemstack1.stackSize - i) + { + Slot slot = (Slot)iterator.next(); + itemstack1 = itemstack.copy(); + i = slot.getStack() == null ? 0 : slot.getStack().stackSize; + Container.func_94525_a(this.field_147008_s, this.field_146987_F, itemstack1, i); + + if (itemstack1.stackSize > itemstack1.getMaxStackSize()) + { + itemstack1.stackSize = itemstack1.getMaxStackSize(); + } + + if (itemstack1.stackSize > slot.getSlotStackLimit()) + { + itemstack1.stackSize = slot.getSlotStackLimit(); + } + } + } + } + + /** + * Returns the slot at the given coordinates or null if there is none. + */ + public Slot getSlotAtPosition(int p_146975_1_, int p_146975_2_) + { + for (int k = 0; k < this.inventorySlots.inventorySlots.size(); ++k) + { + Slot slot = (Slot)this.inventorySlots.inventorySlots.get(k); + + if (this.isMouseOverSlot(slot, p_146975_1_, p_146975_2_)) + { + return slot; + } + } + + return null; + } + + /** + * Called when the mouse is clicked. + */ + protected void mouseClicked(int par1, int par2, int par3) + { + super.mouseClicked(par1, par2, par3); + + if (manager.mouseClicked(par1, par2, par3)) + return; + + boolean flag = par3 == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100; + Slot slot = this.getSlotAtPosition(par1, par2); + long l = Minecraft.getSystemTime(); + this.field_146993_M = this.field_146998_K == slot && l - this.field_146997_J < 250L && this.field_146992_L == par3; + this.field_146995_H = false; + + if (par3 == 0 || par3 == 1 || flag) + { + int i1 = this.guiLeft; + int j1 = this.guiTop; + boolean flag1 = par1 < i1 || par2 < j1 || par1 >= i1 + this.xSize || par2 >= j1 + this.ySize; + int k1 = -1; + + if (slot != null) + { + k1 = slot.slotNumber; + } + + if (flag1) + { + k1 = -999; + } + + if (this.mc.gameSettings.touchscreen && flag1 && this.mc.thePlayer.inventory.getItemStack() == null) + { + this.mc.displayGuiScreen((GuiScreen)null); + return; + } + + if (k1 != -1) + { + if (this.mc.gameSettings.touchscreen) + { + if (slot != null && slot.getHasStack()) + { + this.clickedSlot = slot; + this.draggedStack = null; + this.isRightMouseClick = par3 == 1; + } + else + { + this.clickedSlot = null; + } + } + else if (!this.field_147007_t) + { + if (this.mc.thePlayer.inventory.getItemStack() == null) + { + if (par3 == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100) + { + this.handleMouseClick(slot, k1, par3, 3); + } + else + { + boolean flag2 = k1 != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54)); + byte b0 = 0; + + if (flag2) + { + this.field_146994_N = slot != null && slot.getHasStack() ? slot.getStack() : null; + b0 = 1; + } + else if (k1 == -999) + { + b0 = 4; + } + + manager.handleMouseClick(slot, k1, par3, b0); + } + + this.field_146995_H = true; + } + else + { + this.field_147007_t = true; + this.field_146988_G = par3; + this.field_147008_s.clear(); + + if (par3 == 0) + { + this.field_146987_F = 0; + } + else if (par3 == 1) + { + this.field_146987_F = 1; + } + } + } + } + } + + this.field_146998_K = slot; + this.field_146997_J = l; + this.field_146992_L = par3; + } + + /** + * Called when a mouse button is pressed and the mouse is moved around. Parameters are : mouseX, mouseY, + * lastButtonClicked & timeSinceMouseClick. + */ + protected void mouseClickMove(int p_146273_1_, int p_146273_2_, int p_146273_3_, long p_146273_4_) + { + Slot slot = this.getSlotAtPosition(p_146273_1_, p_146273_2_); + ItemStack itemstack = this.mc.thePlayer.inventory.getItemStack(); + + manager.mouseDragged(p_146273_1_, p_146273_2_, p_146273_3_, p_146273_4_); + + if (this.clickedSlot != null && this.mc.gameSettings.touchscreen) + { + if (p_146273_3_ == 0 || p_146273_3_ == 1) + { + if (this.draggedStack == null) + { + if (slot != this.clickedSlot) + { + this.draggedStack = this.clickedSlot.getStack().copy(); + } + } + else if (this.draggedStack.stackSize > 1 && slot != null && Container.func_94527_a(slot, this.draggedStack, false)) + { + long i1 = Minecraft.getSystemTime(); + + if (this.field_146985_D == slot) + { + if (i1 - this.field_146986_E > 500L) + { + this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, 0, 0); + this.handleMouseClick(slot, slot.slotNumber, 1, 0); + this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, 0, 0); + this.field_146986_E = i1 + 750L; + --this.draggedStack.stackSize; + } + } + else + { + this.field_146985_D = slot; + this.field_146986_E = i1; + } + } + } + } + else if (this.field_147007_t && slot != null && itemstack != null && itemstack.stackSize > this.field_147008_s.size() && Container.func_94527_a(slot, itemstack, true) && slot.isItemValid(itemstack) && this.inventorySlots.canDragIntoSlot(slot)) + { + this.field_147008_s.add(slot); + this.func_146980_g(); + } + } + + /** + * Called when the mouse is moved or a mouse button is released. Signature: (mouseX, mouseY, which) which==-1 is + * mouseMove, which==0 or which==1 is mouseUp + */ + protected void mouseMovedOrUp(int p_146286_1_, int p_146286_2_, int p_146286_3_) + { + if(manager.overrideMouseUp(p_146286_1_, p_146286_2_, p_146286_3_)) + return; + + Slot slot = this.getSlotAtPosition(p_146286_1_, p_146286_2_); + int l = this.guiLeft; + int i1 = this.guiTop; + boolean flag = p_146286_1_ < l || p_146286_2_ < i1 || p_146286_1_ >= l + this.xSize || p_146286_2_ >= i1 + this.ySize; + int j1 = -1; + + if (slot != null) + { + j1 = slot.slotNumber; + } + + if (flag) + { + j1 = -999; + } + + Slot slot1; + Iterator iterator; + + if (this.field_146993_M && slot != null && p_146286_3_ == 0 && this.inventorySlots.func_94530_a((ItemStack)null, slot)) + { + if (isShiftKeyDown()) + { + if (slot != null && slot.inventory != null && this.field_146994_N != null) + { + iterator = this.inventorySlots.inventorySlots.iterator(); + + while (iterator.hasNext()) + { + slot1 = (Slot)iterator.next(); + + if (slot1 != null && slot1.canTakeStack(this.mc.thePlayer) && slot1.getHasStack() && slot1.inventory == slot.inventory && Container.func_94527_a(slot1, this.field_146994_N, true)) + { + this.handleMouseClick(slot1, slot1.slotNumber, p_146286_3_, 1); + } + } + } + } + else + { + this.handleMouseClick(slot, j1, p_146286_3_, 6); + } + + this.field_146993_M = false; + this.field_146997_J = 0L; + } + else + { + if (this.field_147007_t && this.field_146988_G != p_146286_3_) + { + this.field_147007_t = false; + this.field_147008_s.clear(); + this.field_146995_H = true; + return; + } + + if (this.field_146995_H) + { + this.field_146995_H = false; + return; + } + + boolean flag1; + + if (this.clickedSlot != null && this.mc.gameSettings.touchscreen) + { + if (p_146286_3_ == 0 || p_146286_3_ == 1) + { + if (this.draggedStack == null && slot != this.clickedSlot) + { + this.draggedStack = this.clickedSlot.getStack(); + } + + flag1 = Container.func_94527_a(slot, this.draggedStack, false); + + if (j1 != -1 && this.draggedStack != null && flag1) + { + this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, p_146286_3_, 0); + this.handleMouseClick(slot, j1, 0, 0); + + if (this.mc.thePlayer.inventory.getItemStack() != null) + { + this.handleMouseClick(this.clickedSlot, this.clickedSlot.slotNumber, p_146286_3_, 0); + this.field_147011_y = p_146286_1_ - l; + this.field_147010_z = p_146286_2_ - i1; + this.returningStackDestSlot = this.clickedSlot; + this.returningStack = this.draggedStack; + this.returningStackTime = Minecraft.getSystemTime(); + } + else + { + this.returningStack = null; + } + } + else if (this.draggedStack != null) + { + this.field_147011_y = p_146286_1_ - l; + this.field_147010_z = p_146286_2_ - i1; + this.returningStackDestSlot = this.clickedSlot; + this.returningStack = this.draggedStack; + this.returningStackTime = Minecraft.getSystemTime(); + } + + this.draggedStack = null; + this.clickedSlot = null; + } + } + else if (this.field_147007_t && !this.field_147008_s.isEmpty()) + { + this.handleMouseClick((Slot)null, -999, Container.func_94534_d(0, this.field_146987_F), 5); + iterator = this.field_147008_s.iterator(); + + while (iterator.hasNext()) + { + slot1 = (Slot)iterator.next(); + this.handleMouseClick(slot1, slot1.slotNumber, Container.func_94534_d(1, this.field_146987_F), 5); + } + + this.handleMouseClick((Slot)null, -999, Container.func_94534_d(2, this.field_146987_F), 5); + } + else if (this.mc.thePlayer.inventory.getItemStack() != null) + { + if (p_146286_3_ == this.mc.gameSettings.keyBindPickBlock.getKeyCode() + 100) + { + this.handleMouseClick(slot, j1, p_146286_3_, 3); + } + else + { + flag1 = j1 != -999 && (Keyboard.isKeyDown(42) || Keyboard.isKeyDown(54)); + + if (flag1) + { + this.field_146994_N = slot != null && slot.getHasStack() ? slot.getStack() : null; + } + + manager.handleMouseClick(slot, j1, p_146286_3_, flag1 ? 1 : 0); + } + } + else if(p_146286_3_ >= 0) + manager.mouseUp(p_146286_1_, p_146286_2_, p_146286_3_); + } + + if (this.mc.thePlayer.inventory.getItemStack() == null) + { + this.field_146997_J = 0L; + } + + this.field_147007_t = false; + } + + /** + * Returns if the passed mouse position is over the specified slot. + */ + private boolean isMouseOverSlot(Slot p_146981_1_, int p_146981_2_, int p_146981_3_) + { + return this.func_146978_c(p_146981_1_.xDisplayPosition, p_146981_1_.yDisplayPosition, 16, 16, p_146981_2_, p_146981_3_); + } + + protected boolean func_146978_c(int p_146978_1_, int p_146978_2_, int p_146978_3_, int p_146978_4_, int p_146978_5_, int p_146978_6_) + { + int k1 = this.guiLeft; + int l1 = this.guiTop; + p_146978_5_ -= k1; + p_146978_6_ -= l1; + return p_146978_5_ >= p_146978_1_ - 1 && p_146978_5_ < p_146978_1_ + p_146978_3_ + 1 && p_146978_6_ >= p_146978_2_ - 1 && p_146978_6_ < p_146978_2_ + p_146978_4_ + 1; + } + + protected void handleMouseClick(Slot p_146984_1_, int p_146984_2_, int p_146984_3_, int p_146984_4_) + { + if (p_146984_1_ != null) + { + p_146984_2_ = p_146984_1_.slotNumber; + } + + manager.handleSlotClick(p_146984_2_, p_146984_3_, p_146984_4_); + } + + /** + * Fired when a key is typed. This is the equivalent of KeyListener.keyTyped(KeyEvent e). + */ + protected void keyTyped(char par1, int par2) + { + if(manager.lastKeyTyped(par2, par1)) + return; + + if (par2 == 1 || par2 == this.mc.gameSettings.keyBindInventory.getKeyCode()) + { + this.mc.thePlayer.closeScreen(); + } + + this.checkHotbarKeys(par2); + + if (this.theSlot != null && this.theSlot.getHasStack()) + { + if (par2 == this.mc.gameSettings.keyBindPickBlock.getKeyCode()) + { + this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, 0, 3); + } + else if (par2 == this.mc.gameSettings.keyBindDrop.getKeyCode()) + { + this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, isCtrlKeyDown() ? 1 : 0, 4); + } + } + } + + /** + * This function is what controls the hotbar shortcut check when you press a number key when hovering a stack. + */ + protected boolean checkHotbarKeys(int p_146983_1_) + { + if (this.mc.thePlayer.inventory.getItemStack() == null && this.theSlot != null) + { + for (int j = 0; j < 9; ++j) + { + if (p_146983_1_ == this.mc.gameSettings.keyBindsHotbar[j].getKeyCode()) + { + this.handleMouseClick(this.theSlot, this.theSlot.slotNumber, j, 2); + return true; + } + } + } + + return false; + } + + /** + * Called when the screen is unloaded. Used to disable keyboard repeat events + */ + public void onGuiClosed() + { + if (this.mc.thePlayer != null) + { + this.inventorySlots.onContainerClosed(this.mc.thePlayer); + } + } + + /** + * Returns true if this GUI should pause the game when it is displayed in single-player + */ + public boolean doesGuiPauseGame() + { + return false; + } + + /** + * Called from the main game loop to update the screen. + */ + public void updateScreen() + { + super.updateScreen(); + manager.updateScreen(); + + if (!this.mc.thePlayer.isEntityAlive() || this.mc.thePlayer.isDead) + { + this.mc.thePlayer.closeScreen(); + } + } + + public void setWorldAndResolution(Minecraft mc, int i, int j) + { + super.setWorldAndResolution(mc, i, j); + if(mc.currentScreen == this) + { + manager = new GuiContainerManager(this); + manager.load(); + } + } + + public void handleKeyboardInput() + { + manager.handleKeyboardInput(); + } + + public void handleMouseInput() + { + super.handleMouseInput(); + manager.handleMouseWheel(); + } +} \ No newline at end of file diff --git a/resources/assets/nei/asm/blocks.asm b/resources/assets/nei/asm/blocks.asm new file mode 100644 index 00000000..3b6fe59a --- /dev/null +++ b/resources/assets/nei/asm/blocks.asm @@ -0,0 +1,341 @@ +list spawnerPlaced +ILOAD 2 +PUTSTATIC codechicken/nei/ItemMobSpawner.placedX:I +ILOAD 3 +PUTSTATIC codechicken/nei/ItemMobSpawner.placedY:I +ILOAD 4 +PUTSTATIC codechicken/nei/ItemMobSpawner.placedZ:I +RETURN + +list d_spawnerWorld +ACONST_NULL + +list spawnerWorld +ALOAD 0 +INVOKEVIRTUAL net/minecraft/tileentity/MobSpawnerBaseLogic.getSpawnerWorld()Lnet/minecraft/world/World; + +list n_commaFix +LDC * +INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)Ljava/lang/StringBuilder; +INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String; +ARETURN + +list commaFix +INVOKESTATIC codechicken/nei/NEIServerUtils.fixTrailingCommaList(Ljava/lang/StringBuilder;)Ljava/lang/StringBuilder; + +#begin GuiContainer patches + +list m_getManager +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ARETURN + +list m_setWorldAndResolution +ALOAD 0 +ALOAD 1 +ILOAD 2 +ILOAD 3 +INVOKESPECIAL net/minecraft/client/gui/GuiScreen.setWorldAndResolution (Lnet/minecraft/client/Minecraft;II)V +ALOAD 1 +GETFIELD net/minecraft/client/Minecraft.currentScreen : Lnet/minecraft/client/gui/GuiScreen; +ALOAD 0 +IF_ACMPNE LEND +ALOAD 0 +NEW codechicken/nei/guihook/GuiContainerManager +DUP +ALOAD 0 +INVOKESPECIAL codechicken/nei/guihook/GuiContainerManager. (Lnet/minecraft/client/gui/inventory/GuiContainer;)V +PUTFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.load ()V +LEND +RETURN + +list m_handleKeyboardInput +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.handleKeyboardInput ()V +RETURN + +list m_handleMouseInput +ALOAD 0 +INVOKESPECIAL net/minecraft/client/gui/GuiScreen.handleMouseInput ()V +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.handleMouseWheel ()V +RETURN + +list m_publicKeyTyped +ALOAD 0 +ILOAD 1 +ILOAD 2 +INVOKEVIRTUAL net/minecraft/client/gui/inventory/GuiContainer.func_73869_a(CI)V +RETURN + +list m_callKeyTyped +ALOAD 0 +ILOAD 1 +ILOAD 2 +INVOKEVIRTUAL net/minecraft/client/gui/inventory/GuiContainer.publicKeyTyped(CI)V +RETURN + +list preDraw +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.preDraw ()V + +list n_objectUnderMouse +INVOKEVIRTUAL net/minecraft/inventory/Slot.func_111238_b ()Z +IFEQ LSKIP + +list objectUnderMouse +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.objectUnderMouse (II)Z +IFNE LSKIP + +list n_renderObjects +INVOKEVIRTUAL net/minecraft/client/gui/inventory/GuiContainer.func_146979_b (II)V +SIPUSH 2896 +INVOKESTATIC org/lwjgl/opengl/GL11.glEnable (I)V + +list renderObjects +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.renderObjects (II)V + +list d_renderToolTip +ALOAD 8 +INVOKEVIRTUAL net/minecraft/entity/player/InventoryPlayer.func_70445_o ()Lnet/minecraft/item/ItemStack; +IFNONNULL LSKIP +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_147006_u : Lnet/minecraft/inventory/Slot; +IFNULL LSKIP +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_147006_u : Lnet/minecraft/inventory/Slot; +INVOKEVIRTUAL net/minecraft/inventory/Slot.func_75216_d ()Z +IFEQ LSKIP +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_147006_u : Lnet/minecraft/inventory/Slot; +INVOKEVIRTUAL net/minecraft/inventory/Slot.func_75211_c ()Lnet/minecraft/item/ItemStack; +ASTORE 10 +ALOAD 0 +ALOAD 10 +ILOAD 1 +ILOAD 2 +INVOKEVIRTUAL net/minecraft/client/gui/inventory/GuiContainer.func_146285_a (Lnet/minecraft/item/ItemStack;II)V +LSKIP + +list renderTooltips +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.renderToolTips (II)V + +list d_zLevel +LDC 200F + +list zLevel +LDC 500F + +list d_drawSlot +GETSTATIC net/minecraft/client/gui/inventory/GuiContainer.field_146296_j : Lnet/minecraft/client/renderer/entity/RenderItem; +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146289_q : Lnet/minecraft/client/gui/FontRenderer; +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146297_k : Lnet/minecraft/client/Minecraft; +INVOKEVIRTUAL net/minecraft/client/Minecraft.func_110434_K ()Lnet/minecraft/client/renderer/texture/TextureManager; +ALOAD 4 +ILOAD 2 +ILOAD 3 +INVOKEVIRTUAL net/minecraft/client/renderer/entity/RenderItem.func_82406_b (Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/client/renderer/texture/TextureManager;Lnet/minecraft/item/ItemStack;II)V +GETSTATIC net/minecraft/client/gui/inventory/GuiContainer.field_146296_j : Lnet/minecraft/client/renderer/entity/RenderItem; +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146289_q : Lnet/minecraft/client/gui/FontRenderer; +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146297_k : Lnet/minecraft/client/Minecraft; +INVOKEVIRTUAL net/minecraft/client/Minecraft.func_110434_K ()Lnet/minecraft/client/renderer/texture/TextureManager; +ALOAD 4 +ILOAD 2 +ILOAD 3 +ALOAD 8 +INVOKEVIRTUAL net/minecraft/client/renderer/entity/RenderItem.func_77021_b (Lnet/minecraft/client/gui/FontRenderer;Lnet/minecraft/client/renderer/texture/TextureManager;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V + +list drawSlot +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ALOAD 1 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.renderSlotUnderlay (Lnet/minecraft/inventory/Slot;)V +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ALOAD 1 +ALOAD 4 +ILOAD 2 +ILOAD 3 +ALOAD 8 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.drawSlotItem (Lnet/minecraft/inventory/Slot;Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ALOAD 1 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.renderSlotOverlay (Lnet/minecraft/inventory/Slot;)V + +list n_mouseClicked +INVOKESPECIAL net/minecraft/client/gui/GuiScreen.func_73864_a (III)V + +list mouseClicked +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +ILOAD 3 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.mouseClicked (III)Z +IFEQ LCONT +RETURN +LCONT + +list d_handleMouseClick +ALOAD 0 +ALOAD 5 +ILOAD 11 +ILOAD 3 +ILOAD 13 +INVOKEVIRTUAL net/minecraft/client/gui/inventory/GuiContainer.func_146984_a (Lnet/minecraft/inventory/Slot;III)V + +list handleMouseClick +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ALOAD 5 +ILOAD 11 +ILOAD 3 +ILOAD 13 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.handleMouseClick (Lnet/minecraft/inventory/Slot;III)V + +list n_mouseDragged +ASTORE 7 + +list mouseDragged +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +ILOAD 3 +LLOAD 4 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.mouseDragged (IIIJ)V + +list overrideMouseUp +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +ILOAD 3 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.overrideMouseUp (III)Z +IFEQ LCONT +RETURN +LCONT + +list d_handleMouseClick2 +ALOAD 0 +ALOAD 4 +ILOAD 8 +ILOAD 3 +ILOAD 11 +IFEQ L0 +ICONST_1 +GOTO LCONT +L0 +ICONST_0 +LCONT +INVOKEVIRTUAL net/minecraft/client/gui/inventory/GuiContainer.handleMouseClick (Lnet/minecraft/inventory/Slot;III)V + +list handleMouseClick2 +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ALOAD 4 +ILOAD 8 +ILOAD 3 +ILOAD 11 +IFEQ L0 +ICONST_1 +GOTO LCONT +L0 +ICONST_0 +LCONT +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.handleMouseClick (Lnet/minecraft/inventory/Slot;III)V + +list n_mouseUpGoto +IFNULL LSTART +ILOAD 3 +ALOAD 0 + +list n_mouseUp +LSKIP +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146297_k : Lnet/minecraft/client/Minecraft; +GETFIELD net/minecraft/client/Minecraft.field_71439_g : Lnet/minecraft/client/entity/EntityClientPlayerMP; +GETFIELD net/minecraft/client/entity/EntityClientPlayerMP.field_71071_by : Lnet/minecraft/entity/player/InventoryPlayer; +INVOKEVIRTUAL net/minecraft/entity/player/InventoryPlayer.func_70445_o ()Lnet/minecraft/item/ItemStack; +IFNONNULL L30 +ALOAD 0 +LCONST_0 +PUTFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146997_J : J + +list mouseUp +GOTO LSKIP +LSTART +ILOAD 3 +IFLT LSKIP +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 1 +ILOAD 2 +ILOAD 3 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.mouseUp (III)V + +list d_handleSlotClick +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146297_k : Lnet/minecraft/client/Minecraft; +GETFIELD net/minecraft/client/Minecraft.field_71442_b : Lnet/minecraft/client/multiplayer/PlayerControllerMP; +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_147002_h : Lnet/minecraft/inventory/Container; +GETFIELD net/minecraft/inventory/Container.field_75152_c : I +ILOAD 2 +ILOAD 3 +ILOAD 4 +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.field_146297_k : Lnet/minecraft/client/Minecraft; +GETFIELD net/minecraft/client/Minecraft.field_71439_g : Lnet/minecraft/client/entity/EntityClientPlayerMP; +INVOKEVIRTUAL net/minecraft/client/multiplayer/PlayerControllerMP.func_78753_a (IIIILnet/minecraft/entity/player/EntityPlayer;)Lnet/minecraft/item/ItemStack; +POP + +list handleSlotClick +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 2 +ILOAD 3 +ILOAD 4 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.handleSlotClick (III)V + +list lastKeyTyped +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +ILOAD 2 +ILOAD 1 +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.lastKeyTyped (IC)Z +IFEQ LCONT +RETURN +LCONT + +list n_updateScreen +ALOAD 0 +INVOKESPECIAL net/minecraft/client/gui/GuiScreen.updateScreen ()V + +list updateScreen +ALOAD 0 +GETFIELD net/minecraft/client/gui/inventory/GuiContainer.manager : Lcodechicken/nei/guihook/GuiContainerManager; +INVOKEVIRTUAL codechicken/nei/guihook/GuiContainerManager.updateScreen ()V \ No newline at end of file diff --git a/resources/assets/nei/lang/de_DE.lang b/resources/assets/nei/lang/de_DE.lang new file mode 100644 index 00000000..84b74c34 --- /dev/null +++ b/resources/assets/nei/lang/de_DE.lang @@ -0,0 +1,159 @@ +load=Lade +save=Speichere + +enchant=Verzaubern +enchant.level=Level +enchant.locked=Gesperrt +enchant.unlocked=Entsperrt + +inventory.options=Optionen +inventory.prev=Zurück +inventory.next=Weiter +inventory.item_subsets=Item-SubSets +inventory.delete.all=LÖSCHE ALLE ITEMS aus deinem aktuellen Inventarbildschirm +inventory.delete.enable=Ermögliche Lösch-Modus +inventory.delete.1=Schalte Lösch-Modus an +inventory.delete.0=Schalte Lösch-Modus aus +inventory.rain.enable=Ermögliche Regen +inventory.rain.1=Schalte Regen an +inventory.rain.0=Schalte Regen aus +inventory.magnet.enable=Ermögliche Magnetmodus +inventory.magnet.1=Schalte Magnetmodus an +inventory.magnet.0=Schalte Magnetmodus aus +inventory.dawn.enable=Ermögliche Morgen-Mittag +inventory.dawn.set=Setze Zeit auf Morgen +inventory.noon.enable=Ermögliche Mittag-Abend +inventory.noon.set=Setze Zeit auf Mittag +inventory.dusk.enable=Ermögliche Abend-Nacht +inventory.dusk.set=Setze Zeit auf Abend +inventory.midnight.enable=Ermögliche Nacht-Morgen +inventory.midnight.set=Setze Zeit auf Nacht +inventory.heal=Heile den Spieler +inventory.gamemode.0=Setze Spielmodus auf Überleben +inventory.gamemode.1=Setze Spielmodus auf Kreativ +inventory.gamemode.2=Setze Spielmodus auf Kreativ+ +inventory.gamemode.3=Setze Spielmodus auf Abenteuer + +chat.gamemode.0=Du spielst nun Überleben +chat.gamemode.1=Du spielst nun Kreativ +chat.gamemode.2=Du spielst nun Kreativ+ +chat.gamemode.3=Du spielst nun Abenteuer + +options=NEI-Optionen +options.back=Zurück +options.world=Welt +options.global=Global +options.global.tip.0=Optionen werden auf alle Welten angewandt +options.global.tip.1=Clicke W neben einer:Option , um das Übergehen: für diese Welt zu aktivieren +options.wbutton.tip.0=Nutzt globale Einstellungen +options.wbutton.tip.1=Übergeht globale Einstellungen + +options.keys=Tastenbelegung +options.keys.gui=Inventar +options.keys.gui.recipe=Rezept +options.keys.gui.usage=Nutzung +options.keys.gui.enchant=Verzauberungen +options.keys.gui.potion=Tränke +options.keys.gui.back=Vorheriges Rezept +options.keys.gui.prev=Vorherige Seite +options.keys.gui.next=Nächste Seite +options.keys.gui.hide=Verstelle NEI-Sichtbarkeit +options.keys.gui.search=Fokussiere Such-Leiste +options.keys.world=Welt +options.keys.world.chunkoverlay=Chunk-Grenzen-Overlay +options.keys.world.moboverlay=Mob-Spawn-Overlay +options.keys.world.highlight_tips=Highlight-Tooltips +options.keys.world.dawn=Morgen +options.keys.world.noon=Mittag +options.keys.world.dusk=Abend +options.keys.world.midnight=Nacht +options.keys.world.rain=Regen +options.keys.world.heal=Heilen +options.keys.world.creative=Spielmodus +options.keys.world.creative.tip=Wechsle Spielmodus + +options.inventory=Inventar +options.inventory.widgetsenabled.true=NEI Aktiviert +options.inventory.widgetsenabled.false=NEI Deaktiviert +options.inventory.cheatmode.0=Rezeptmodus +options.inventory.cheatmode.1=Mehrzweckmodus +options.inventory.cheatmode.2=Cheat-Modus +options.inventory.layoutstyle=Layout-Stil +options.inventory.profileRecipes=Profil-Rezepte +options.inventory.profileRecipes.true=Wahr +options.inventory.profileRecipes.false=Falsch +options.inventory.itemIDs=Item-IDs +options.inventory.itemIDs.0=Versteckt +options.inventory.itemIDs.1=Auto +options.inventory.itemIDs.2=Gezeigt +options.inventory.utilities=Nützliches +options.inventory.utilities.tip=Wähle Inhalte für den Mehrzweckmodus +options.inventory.utilities.time=Zeit +options.inventory.utilities.rain=Regen +options.inventory.utilities.heal=Heilen +options.inventory.utilities.delete=Löschem +options.inventory.utilities.magnet=Magnet +options.inventory.utilities.gamemode=Spielmodus +options.inventory.utilities.enchant=Verzaubern +options.inventory.utilities.potion=Tränke +options.inventory.utilities.item=Items +options.inventory.gamemodes=Spielmodi +options.inventory.gamemodes.tip=Wähle die Spielmodi, zu denen gewechselt werden kann. +options.inventory.gamemodes.creative=Kreativ +options.inventory.gamemodes.creative+=Kreativ+ +options.inventory.gamemodes.adventure=Abenteuer + +options.command=Befehle +options.command.creative=Spielmodus +options.command.creative.tip={0} = 1 für Kreativ, 0 für Überleben, {1} = Spieler +options.command.item=Item +options.command.item.tip={0} = Spieler, {1} = itemID, {2} = Anzahl, {3} = itemDamage +options.command.time=Zeit +options.command.time.tip={0} = Weltzeit +options.command.rain=Regen +options.command.rain.tip={0} = 1 für An, 0 für Aus +options.command.heal=Heilen +options.command.heal.tip={0} = Spieler + +options.world.highlight_tips=Highlight-Tooltips +options.world.highlight_tips.hide=Versteckt +options.world.highlight_tips.show=Gezeigt + +options.tools=Werkzeuge +options.tools.dump=Daten-Ablage +options.tools.dump.dump=Ablegen +options.tools.dump.dumped=%s-IDs wurden nach %s abgelegt +options.tools.dump.mode.0=Genutzt +options.tools.dump.mode.1=Frei +options.tools.dump.mode.2=Alles +options.tools.dump.item=Block/Item +options.tools.dump.items=Blöcke/Items +options.tools.dump.potion=Trank +options.tools.dump.potions=Tränke +options.tools.dump.enchantment=Verzauberungs +options.tools.dump.enchantments=Verzauberungen +options.tools.dump.biome=Biom +options.tools.dump.biomes=Biome +options.tools.dump.itempanel=Item-Panel +options.tools.dump.itempanel.dumped=Inhalte des Item-Panels wurden nach %s abgelegt +options.tools.dump.itempanel.mode.0=CSV +options.tools.dump.itempanel.mode.1=NBT + +layoutstyle.minecraft=Minecraft +layoutstyle.oldtmi=Altes TMI + +recipe.page=Seite %s/%s +recipe.shaped=Geformte Herstellung +recipe.shapeless=Formlose Herstellung +recipe.furnace=Schmelzen +recipe.fuel=Brennstoff +recipe.fuel.required=%s erfordert +recipe.fuel.processed=%s verarbeitet +recipe.fuel.produced=%s produziert +recipe.firework=Feuerwerk +recipe.firework.tooltip0=Farbstoffe fügen den Ladungen Farben hinzu +recipe.firework.tooltip1=Neu zu färben fügt der Ladung verblassende Farben hinzu +recipe.firework.tooltip2=Mehere Ladungen können von einer Rakete gespawnt werden +recipe.brewing=Brauen +recipe.profiler.crafting=Herstellungsprofil +recipe.profiler.usage=Nutzungsprofil \ No newline at end of file diff --git a/resources/assets/nei/lang/en_US.lang b/resources/assets/nei/lang/en_US.lang new file mode 100644 index 00000000..4cc1babe --- /dev/null +++ b/resources/assets/nei/lang/en_US.lang @@ -0,0 +1,168 @@ +nei.load=Load +nei.save=Save + +nei.enchant=Enchant +nei.enchant.level=Level +nei.enchant.locked=Locked +nei.enchant.unlocked=Unlocked + +nei.inventory.options=Options +nei.inventory.prev=Prev +nei.inventory.next=Next +nei.inventory.item_subsets=Item SubSets +nei.inventory.delete.all=DELETE ALL ITEMS from current inventory screen +nei.inventory.delete.one=Delete %s +nei.inventory.delete.all=Delete ALL %s +nei.inventory.delete.enable=Enable delete mode +nei.inventory.delete.1=Turn delete mode on +nei.inventory.delete.0=Turn delete mode off +nei.inventory.rain.enable=Enable rain +nei.inventory.rain.1=Turn rain on +nei.inventory.rain.0=Turn rain off +nei.inventory.magnet.enable=Enable magnet mode +nei.inventory.magnet.1=Turn magnet mode on +nei.inventory.magnet.0=Turn magnet mode off +nei.inventory.dawn.enable=Enable dawn-noon +nei.inventory.dawn.set=Set time to dawn +nei.inventory.noon.enable=Enable noon-dusk +nei.inventory.noon.set=Set time to noon +nei.inventory.dusk.enable=Enable dusk-midnight +nei.inventory.dusk.set=Set time to dusk +nei.inventory.midnight.enable=Enable midnight-dawn +nei.inventory.midnight.set=Set time to midnight +nei.inventory.heal=Heal the player +nei.inventory.gamemode.0=Set gamemode to survival +nei.inventory.gamemode.1=Set gamemode to creative +nei.inventory.gamemode.2=Set gamemode to creative+ +nei.inventory.gamemode.3=Set gamemode to adventure + +nei.chat.gamemode.0=You are now playing survival +nei.chat.gamemode.1=You are now playing creative +nei.chat.gamemode.2=You are now playing creative+ +nei.chat.gamemode.3=You are now playing adventure +nei.chat.rain.on=Rain turned on +nei.chat.rain.off=Rain turned off +nei.chat.time=Day %d. %d:00 +nei.chat.give.noitem=No such item. + +nei.options=NEI Options +nei.options.back=Back +nei.options.world=World +nei.options.global=Global +nei.options.global.tip.0=Options apply to all worlds +nei.options.global.tip.1=Click the W beside an:option to enable an:override for this world +nei.options.wbutton.tip.0=Using global settings +nei.options.wbutton.tip.1=Overriding global setting + +nei.options.keys=KeyBindings +nei.options.keys.gui=Inventory +nei.options.keys.gui.recipe=Recipe +nei.options.keys.gui.usage=Usage +nei.options.keys.gui.enchant=Enchantments +nei.options.keys.gui.potion=Potions +nei.options.keys.gui.back=Prev Recipe +nei.options.keys.gui.prev=Prev Page +nei.options.keys.gui.next=Next Page +nei.options.keys.gui.hide=Toggle NEI Visibility +nei.options.keys.gui.search=Focus Search Bar +nei.options.keys.world=World +nei.options.keys.world.chunkoverlay=Chunk Boundary Overlay +nei.options.keys.world.moboverlay=Mob Spawn Overlay +nei.options.keys.world.highlight_tips=Highlight Tooltips +nei.options.keys.world.dawn=Dawn +nei.options.keys.world.noon=Noon +nei.options.keys.world.dusk=Dusk +nei.options.keys.world.midnight=Midnight +nei.options.keys.world.rain=Rain +nei.options.keys.world.heal=Heal +nei.options.keys.world.creative=Gamemode +nei.options.keys.world.creative.tip=Cycle Gamemode + +nei.options.inventory=Inventory +nei.options.inventory.widgetsenabled.true=NEI Enabled +nei.options.inventory.widgetsenabled.false=NEI Disabled +nei.options.inventory.cheatmode.0=Recipe Mode +nei.options.inventory.cheatmode.1=Utility Mode +nei.options.inventory.cheatmode.2=Cheat Mode +nei.options.inventory.layoutstyle=Layout Style +nei.options.inventory.profileRecipes=Profile Recipes +nei.options.inventory.profileRecipes.true=True +nei.options.inventory.profileRecipes.false=False +nei.options.inventory.itemIDs=Item IDs +nei.options.inventory.itemIDs.0=Hidden +nei.options.inventory.itemIDs.1=Auto +nei.options.inventory.itemIDs.2=Shown +nei.options.inventory.utilities=Utilities +nei.options.inventory.utilities.tip=Select features for utility mode +nei.options.inventory.utilities.time=Time +nei.options.inventory.utilities.rain=Rain +nei.options.inventory.utilities.heal=Heal +nei.options.inventory.utilities.delete=Delete +nei.options.inventory.utilities.magnet=Magnet +nei.options.inventory.utilities.gamemode=Gamemode +nei.options.inventory.utilities.enchant=Enchanting +nei.options.inventory.utilities.potion=Potions +nei.options.inventory.utilities.item=Items +nei.options.inventory.gamemodes=Gamemodes +nei.options.inventory.gamemodes.tip=Select the gamemodes to cycle through +nei.options.inventory.gamemodes.creative=Creative +nei.options.inventory.gamemodes.creative+=Creative+ +nei.options.inventory.gamemodes.adventure=Adventure + +nei.options.command=Commands +nei.options.command.creative=Gamemode +nei.options.command.creative.tip={0} = 1 for creative, 0 for survival, {1} = player +nei.options.command.item=Item +nei.options.command.item.tip={0} = player, {1} = itemID, {2} = quantity, {3} = itemDamage +nei.options.command.time=Time +nei.options.command.time.tip={0} = worldtime +nei.options.command.rain=Rain +nei.options.command.rain.tip={0} = 1 for on, 0 for off +nei.options.command.heal=Heal +nei.options.command.heal.tip={0} = player + +nei.options.world.highlight_tips=Highlight Tooltips +nei.options.world.highlight_tips.hide=Hidden +nei.options.world.highlight_tips.show=Shown + +nei.options.tools=Tools +nei.options.tools.dump=Data Dumps +nei.options.tools.dump.dump=Dump +nei.options.tools.dump.dumped=%s IDs dumped to %s +nei.options.tools.dump.mode.0=Used +nei.options.tools.dump.mode.1=Free +nei.options.tools.dump.mode.2=All +nei.options.tools.dump.item=Item +nei.options.tools.dump.items=Items +nei.options.tools.dump.block=Block +nei.options.tools.dump.blocks=Blocks +nei.options.tools.dump.potion=Potion +nei.options.tools.dump.potions=Potions +nei.options.tools.dump.enchantment=Enchantment +nei.options.tools.dump.enchantments=Enchantments +nei.options.tools.dump.biome=Biome +nei.options.tools.dump.biomes=Biomes +nei.options.tools.dump.itempanel=Item Panel +nei.options.tools.dump.itempanel.dumped=Item Panel contents were dumped to %s +nei.options.tools.dump.itempanel.mode.0=CSV +nei.options.tools.dump.itempanel.mode.1=NBT +nei.options.tools.dump.itempanel.mode.2=Json + +nei.layoutstyle.minecraft=Minecraft +nei.layoutstyle.oldtmi=Old TMI + +nei.recipe.page=Page %s/%s +nei.recipe.shaped=Shaped Crafting +nei.recipe.shapeless=Shapeless Crafting +nei.recipe.furnace=Smelting +nei.recipe.fuel=Fuel +nei.recipe.fuel.required=%s required +nei.recipe.fuel.processed=%s processed +nei.recipe.fuel.produced=%s produced +nei.recipe.firework=Fireworks +nei.recipe.firework.tooltip0=Dyes add colours to the charges +nei.recipe.firework.tooltip1=Recolouring adds fade colours to the charge +nei.recipe.firework.tooltip2=Multiple charges can be spawned from one rocket +nei.recipe.brewing=Brewing +nei.recipe.profiler.crafting=Crafting Profiling +nei.recipe.profiler.usage=Usage Profiling \ No newline at end of file diff --git a/resources/assets/nei/lang/ru_RU.lang b/resources/assets/nei/lang/ru_RU.lang new file mode 100644 index 00000000..e6b13169 --- /dev/null +++ b/resources/assets/nei/lang/ru_RU.lang @@ -0,0 +1,159 @@ +load=Load +save=Save + +enchant=Зачаровывание +enchant.level=Уровень +enchant.locked=Открытые +enchant.unlocked=Закрытые + +inventory.options=Опции +inventory.prev=Предыдущая +inventory.next=Следующая +inventory.item_subsets=Подмножества предметов +inventory.delete.all=УДАЛИТЬ ВСЕ ПРЕДМЕТЫ из текущего инвентаря +inventory.delete.enable=Режим удаления +inventory.delete.1=Включить режим удаления +inventory.delete.0=Выключить режим удаления +inventory.rain.enable=Дождь +inventory.rain.1=Включить дождь +inventory.rain.0=Выключить дождь +inventory.magnet.enable=Режим магнита +inventory.magnet.1=Включить режим магнита +inventory.magnet.0=Выключить режим магнита +inventory.dawn.enable=Enable dawn-noon +inventory.dawn.set=Установить время на рассвет +inventory.noon.enable=Enable noon-dusk +inventory.noon.set=Установить время на полдень +inventory.dusk.enable=Enable dusk-midnight +inventory.dusk.set=Установить время на сумерки +inventory.midnight.enable=Enable midnight-dawn +inventory.midnight.set=Установить время на полночь +inventory.heal=Исцелить игрока +inventory.gamemode.0=Установить игровой режим на выживание +inventory.gamemode.1=Установить игровой режим на творческий +inventory.gamemode.2=Установить игровой режим на творческий+ +inventory.gamemode.3=Установить игровой режим на приключение + +chat.gamemode.0=Теперь вы играете в режиме выживание +chat.gamemode.1=Теперь вы играете в режиме творчество +chat.gamemode.2=Теперь вы играете в режиме творчество+ +chat.gamemode.3=Теперь вы играете в режиме приключение + +options=Опции NEI +options.back=Назад +options.world=Мировые +options.global=Глобальные +options.global.tip.0=Настройки применяются ко всем мирам +options.global.tip.1=Нажмите W рядом с:опцией, чтобы включить:перезапись для этого мира +options.wbutton.tip.0=Использование глобальных настроек +options.wbutton.tip.1=Перезаписывание глобальных настроек + +options.keys=Назначения клавиш +options.keys.gui=Инвентарь +options.keys.gui.recipe=Рецепт +options.keys.gui.usage=Использование +options.keys.gui.enchant=Чары +options.keys.gui.potion=Зелья +options.keys.gui.back=Предыдущий рецепт +options.keys.gui.prev=Предыдущая страница +options.keys.gui.next=Следующая страница +options.keys.gui.hide=Переключить видимость NEI +options.keys.gui.search=Сфокусироваться на панель поиска +options.keys.world=Мир +options.keys.world.chunkoverlay=Chunk Boundary Overlay +options.keys.world.moboverlay=Mob Spawn Overlay +options.keys.world.highlight_tips=Подсвечивать всплывающие подсказки +options.keys.world.dawn=Рассвет +options.keys.world.noon=Полдень +options.keys.world.dusk=Сумерки +options.keys.world.midnight=Полночь +options.keys.world.rain=Дождь +options.keys.world.heal=Исцеление +options.keys.world.creative=Игровой режим +options.keys.world.creative.tip=Круг игровых режимов + +options.inventory=Инвентарь +options.inventory.widgetsenabled.true=NEI включён +options.inventory.widgetsenabled.false=NEI выключен +options.inventory.cheatmode.0=Режим рецептов +options.inventory.cheatmode.1=Режим полезностей +options.inventory.cheatmode.2=Чит-режим +options.inventory.layoutstyle=Стиль расположения +options.inventory.profileRecipes=Profile Recipes +options.inventory.profileRecipes.true=True +options.inventory.profileRecipes.false=False +options.inventory.itemIDs=ID предметов +options.inventory.itemIDs.0=Спрятаны +options.inventory.itemIDs.1=Авто +options.inventory.itemIDs.2=Показаны +options.inventory.utilities=Полезности +options.inventory.utilities.tip=Выберете особенности для режима полезностей +options.inventory.utilities.time=Время +options.inventory.utilities.rain=Дождь +options.inventory.utilities.heal=Исцеление +options.inventory.utilities.delete=Удаление +options.inventory.utilities.magnet=Магнит +options.inventory.utilities.gamemode=Игровой режим +options.inventory.utilities.enchant=Зачарование +options.inventory.utilities.potion=Зелья +options.inventory.utilities.item=Предметы +options.inventory.gamemodes=Игровые режимы +options.inventory.gamemodes.tip=Выберете игровые режимы для переключения между ними +options.inventory.gamemodes.creative=Творческий +options.inventory.gamemodes.creative+=Творческий+ +options.inventory.gamemodes.adventure=Приключение + +options.command=Команды +options.command.creative=Игровой режим +options.command.creative.tip={0} = 1 для творческого, 0 для выживания, {1} = игрок +options.command.item=Item +options.command.item.tip={0} = player, {1} = itemID, {2} = quantity, {3} = itemDamage +options.command.time=Время +options.command.time.tip={0} = мировое время +options.command.rain=Дождь +options.command.rain.tip={0} = 1 для включения, 0 для выключения +options.command.heal=Исцелить +options.command.heal.tip={0} = игрок + +options.world.highlight_tips=Подсвечивать всплывающие подсказки +options.world.highlight_tips.hide=Спрятаны +options.world.highlight_tips.show=Показаны + +options.tools=Инструментарий +options.tools.dump=Дампы памяти +options.tools.dump.dump=Дамп +options.tools.dump.dumped=ID %s сдампленны в %s +options.tools.dump.mode.0=Используемые +options.tools.dump.mode.1=Свободные +options.tools.dump.mode.2=Все +options.tools.dump.item=Блока/Предмета +options.tools.dump.items=Блоков/Предметов +options.tools.dump.potion=Зелье +options.tools.dump.potions=Зелья +options.tools.dump.enchantment=Зачарование +options.tools.dump.enchantments=Зачарования +options.tools.dump.biome=Биом +options.tools.dump.biomes=Биомы +options.tools.dump.itempanel=Предметная панель +options.tools.dump.itempanel.dumped=Содержание предметной панели сдампленно в %s +options.tools.dump.itempanel.mode.0=CSV +options.tools.dump.itempanel.mode.1=NBT + +layoutstyle.minecraft=Minecraft +layoutstyle.oldtmi=Старый TMI + +recipe.page=Страница %s/%s +recipe.shaped=Форменный крафтинг +recipe.shapeless=Бесформенный крафтинг +recipe.furnace=Выплавка(обжарка) +recipe.fuel=Топливо +recipe.fuel.required=%s required +recipe.fuel.processed=%s processed +recipe.fuel.produced=%s produced +recipe.firework=Фейерверки +recipe.firework.tooltip0=Dyes add colours to the charges +recipe.firework.tooltip1=Recolouring adds fade colours to the charge +recipe.firework.tooltip2=Multiple charges can be spawned from one rocket +recipe.brewing=Зельеварение +recipe.profiler.crafting=Crafting Profiling +recipe.profiler.usage=Usage Profiling \ No newline at end of file diff --git a/resources/assets/nei/lang/tr_TR.lang b/resources/assets/nei/lang/tr_TR.lang new file mode 100644 index 00000000..3a3b9736 --- /dev/null +++ b/resources/assets/nei/lang/tr_TR.lang @@ -0,0 +1,159 @@ +load=Yükle +save=Kaydet + +enchant=Büyü +enchant.level=Level +enchant.locked=Kilitli +enchant.unlocked=Açık + +inventory.options=Ayarlar +inventory.prev=Geri +inventory.next=İleri +inventory.item_subsets=Item/Mod Listesi +inventory.delete.all=Mevcut envanterdeki tüm itemleri sil +inventory.delete.enable=Silme modunu aktif et +inventory.delete.1=Silme modunu aç +inventory.delete.0=Silme modunu kapat +inventory.rain.enable=yağmur aktif et +inventory.rain.1=Yağmur yağdır +inventory.rain.0=Yağmuru durdur +inventory.magnet.enable=Mıknatısı aktif et +inventory.magnet.1=Mıknatısı aç +inventory.magnet.0=Mıknatısı kapat +inventory.dawn.enable=Sabah-Öğle aktif et +inventory.dawn.set=Saati sabah(6:00) yap +inventory.noon.enable=Öğlen-akşam aktif et +inventory.noon.set=Saati öğlen(12:00) yap +inventory.dusk.enable=Akşam-Gece aktif et +inventory.dusk.set=Saati akşam(00:00) yap +inventory.midnight.enable=Gece-Sabah aktif et +inventory.midnight.set=Saati gece(00:00) yap +inventory.heal=Oyuncuya can ver +inventory.gamemode.0= Oyunu Hayatta kalma modu yap +inventory.gamemode.1= Oyunu Yaratıcı mod yap +inventory.gamemode.2= Oyunu Yaratıcı mod+ yap +inventory.gamemode.3= Oyunu Macera modu yap + +chat.gamemode.0=Hayatta kalma modunu oynuyorsunuz +chat.gamemode.1=Yaratıcı modu oynuyorsunuz +chat.gamemode.2=yaratıcı mod+ oynuyorsunuz +chat.gamemode.3=Macera modunu oynuyorsunuz + +options=NEI Ayarları +options.back=Geri +options.world=Dünya +options.global=Genel +options.global.tip.0=Ayarlar tüm dünyalar için kaydedilecek +options.global.tip.1=W tuşuna tıklayın:seçeneği aç:dünyada gör +options.wbutton.tip.0=Genel ayarları kullanıyorsunuz +options.wbutton.tip.1=Genel ayarların üstüne yazılıyor + +options.keys=Tuşlar +options.keys.gui=Envanter +options.keys.gui.recipe=Tarifler +options.keys.gui.usage=Kullanım yeri +options.keys.gui.enchant=Büylüler +options.keys.gui.potion=İksirler +options.keys.gui.back=Önceki tarif +options.keys.gui.prev=Önceki sayfa +options.keys.gui.next=Sonraki sayfa +options.keys.gui.hide=Nei görünürlük ayarı +options.keys.gui.search=Arama çubuğu odağı +options.keys.world=Dünya +options.keys.world.chunkoverlay=Chunk sınır yerleşimi +options.keys.world.moboverlay=Mob Spawn yerleşimi +options.keys.world.highlight_tips=Nesne ipucu +options.keys.world.dawn=Sabah +options.keys.world.noon=Öğlen +options.keys.world.dusk=Akşam +options.keys.world.midnight=Gece +options.keys.world.rain=Yağmur +options.keys.world.heal=Can +options.keys.world.creative=Oyun modu +options.keys.world.creative.tip=Cycle Gamemode + +options.inventory=Envarter +options.inventory.widgetsenabled.true=NEI Açık +options.inventory.widgetsenabled.false=NEI Kapalı +options.inventory.cheatmode.0=Tarif modu +options.inventory.cheatmode.1=Yardımcı mod +options.inventory.cheatmode.2=Hileli mod +options.inventory.layoutstyle=Tema +options.inventory.profileRecipes=Profil tarifleri +options.inventory.profileRecipes.true=Doğru +options.inventory.profileRecipes.false=Yanlış +options.inventory.itemIDs=Item IDleri +options.inventory.itemIDs.0=Gizli +options.inventory.itemIDs.1=Otomatik +options.inventory.itemIDs.2=Göster +options.inventory.utilities=Yardımcılar +options.inventory.utilities.tip=Yardımcıları seç +options.inventory.utilities.time=Saat +options.inventory.utilities.rain=Yağmur +options.inventory.utilities.heal=Can +options.inventory.utilities.delete=Sil +options.inventory.utilities.magnet=Mıknatıs +options.inventory.utilities.gamemode=Oyun modu +options.inventory.utilities.enchant=Büyüleme +options.inventory.utilities.potion=İksirler +options.inventory.utilities.item=Itemler +options.inventory.gamemodes=Oyun modu +options.inventory.gamemodes.tip=Select the gamemodes to cycle through +options.inventory.gamemodes.creative=Yaratıcı mod +options.inventory.gamemodes.creative+=Yaratıcı mod+ +options.inventory.gamemodes.adventure=Macera + +options.command=Komutlar +options.command.creative=Oyun modu +options.command.creative.tip={0} = 1 for creative, 0 for survival, {1} = player +options.command.item=Item +options.command.item.tip={0} = player, {1} = itemID, {2} = quantity, {3} = itemDamage +options.command.time=Zaman +options.command.time.tip={0} = worldtime +options.command.rain=Yağmur +options.command.rain.tip={0} = 1 for on, 0 for off +options.command.heal=Can +options.command.heal.tip={0} = player + +options.world.highlight_tips=Nesne ipucu +options.world.highlight_tips.hide=Kapalı +options.world.highlight_tips.show=Açık + +options.tools=Araçlar +options.tools.dump=Verileri Silme +options.tools.dump.dump=Sil +options.tools.dump.dumped=%s IDs silindi %s +options.tools.dump.mode.0=Kullanıldı +options.tools.dump.mode.1=Boş +options.tools.dump.mode.2=Hepsi +options.tools.dump.item=Blok/Item +options.tools.dump.items=Bloklar/Itemlar +options.tools.dump.potion=İksir +options.tools.dump.potions=İksirler +options.tools.dump.enchantment=Büyü +options.tools.dump.enchantments=Büyüler +options.tools.dump.biome=Biyom +options.tools.dump.biomes=Biyomlar +options.tools.dump.itempanel=Item Paneli +options.tools.dump.itempanel.dumped=Item panelinden %s kadar silindi +options.tools.dump.itempanel.mode.0=CSV +options.tools.dump.itempanel.mode.1=NBT + +layoutstyle.minecraft=Minecraft +layoutstyle.oldtmi=Eski TMI + +recipe.page=Sayfa %s/%s +recipe.shaped=Üretim +recipe.shapeless=Üretim +recipe.furnace=Pişirme +recipe.fuel=Yakıt +recipe.fuel.required=%s gerekli +recipe.fuel.processed=%s işlenmiş +recipe.fuel.produced=%s üretilmiş +recipe.firework=Havaifişek +recipe.firework.tooltip0=Renk ekle veya değiştir +recipe.firework.tooltip1=Rengi kaldır veya değiştir +recipe.firework.tooltip2=Fazlaca roket yap veya ışınla +recipe.brewing=İksir Standı +recipe.profiler.crafting=Üretme Profili +recipe.profiler.usage=Kullanma Profili \ No newline at end of file diff --git a/resources/assets/nei/lang/zh_CN.lang b/resources/assets/nei/lang/zh_CN.lang new file mode 100644 index 00000000..c2db1e0c --- /dev/null +++ b/resources/assets/nei/lang/zh_CN.lang @@ -0,0 +1,140 @@ +#zh_CN + +load=载入 +save=保存 + +enchant=附魔 +enchant.level=等级 +enchant.locked=锁定 +enchant.unlocked=解锁 + +inventory.options=选项 +inventory.prev=上一页 +inventory.next=下一页 +inventory.item_subsets=物品分类 +inventory.delete.all=清空物品栏 +inventory.delete.enable=激活删除设置 +inventory.delete.1=开启删除模式 +inventory.delete.0=关闭删除模式 +inventory.rain.enable=激活天气设置 +inventory.rain.1=开启雨雪 +inventory.rain.0=关闭雨雪 +inventory.magnet.enable=激活磁力设置 +inventory.magnet.1=开启磁力模式 +inventory.magnet.0=关闭磁力模式 +inventory.dawn.enable=激活破晓时间设置 +inventory.dawn.set=设置时间为破晓 +inventory.noon.enable=激活正午时间设置 +inventory.noon.set=设置时间为正午 +inventory.dusk.enable=激活黄昏时间设置 +inventory.dusk.set=设置时间为黄昏 +inventory.midnight.enable=激活午夜时间设置 +inventory.midnight.set=设置时间为午夜 +inventory.heal=治愈玩家并回满饱食度 +inventory.gamemode.0=设置为生存模式 +inventory.gamemode.1=设置为创造模式 +inventory.gamemode.2=设置为创造模式+ +inventory.gamemode.3=设置为冒险模式 + +chat.gamemode.0=生存模式开启 +chat.gamemode.1=创造模式开启 +chat.gamemode.2=创造模式+开启 +chat.gamemode.3=冒险模式开启 + +options=NEI选项 +options.back=后退 +options.world=世界 +options.global=全局 +options.global.tip.0=选项适用于所有世界 +options.global.tip.1=点击选项左侧W按钮可覆写该世界设置 +options.wbutton.tip.0=使用全局设置 +options.wbutton.tip.1=覆写全局设置 + +options.keys=按键绑定 +options.keys.gui=物品栏 +options.keys.gui.recipe=查看合成 +options.keys.gui.usage=查看用途 +options.keys.gui.enchant=附魔 +options.keys.gui.potion=药水 +options.keys.gui.back=上一个合成表 +options.keys.gui.prev=上一页 +options.keys.gui.next=下一页 +options.keys.gui.hide=隐藏/显示NEI界面 +options.keys.world=世界 +options.keys.world.chunkoverlay=区块(chunks)边界显示 +options.keys.world.moboverlay=刷怪区域显示 +options.keys.world.highlight_tips=显示选中方块名称 +options.keys.world.dawn=破晓 +options.keys.world.noon=正午 +options.keys.world.dusk=黄昏 +options.keys.world.midnight=午夜 +options.keys.world.rain=降雨 +options.keys.world.heal=治疗 +options.keys.world.creative=游戏模式 +options.keys.world.creative.tip=循环游戏模式 + +options.inventory=物品栏 +options.inventory.widgetsenabled.true=激活NEI +options.inventory.widgetsenabled.false=禁用NEI +options.inventory.cheatmode.0=合成模式 +options.inventory.cheatmode.1=实用模式 +options.inventory.cheatmode.2=作弊模式 +options.inventory.layoutstyle=界面风格 +options.inventory.profileRecipes=合成查阅性能分析 +options.inventory.profileRecipes.true=开启 +options.inventory.profileRecipes.false=关闭 +options.inventory.itemIDs=物品ID +options.inventory.itemIDs.0=隐藏 +options.inventory.itemIDs.1=自动 +options.inventory.itemIDs.2=显示 +options.inventory.utilities=按钮 +options.inventory.utilities.tip=选择实用模式的功能 +options.inventory.utilities.time=时间 +options.inventory.utilities.rain=降雨 +options.inventory.utilities.heal=治疗 +options.inventory.utilities.delete=删除 +options.inventory.utilities.magnet=磁铁 +options.inventory.utilities.gamemode=游戏模式 +options.inventory.utilities.enchant=附魔 +options.inventory.utilities.potion=酿造 +options.inventory.utilities.item=保存物品 +options.inventory.gamemodes=游戏模式 +options.inventory.gamemodes.tip=选择游戏模式循环调整时的选项 +options.inventory.gamemodes.creative=创造模式 +options.inventory.gamemodes.creative+=创造模式+ +options.inventory.gamemodes.adventure=冒险模式 + +options.command=指令 +options.command.creative=游戏模式 +options.command.creative.tip={0}=1为创造模式,0为生存模式,{1}=玩家 +options.command.item=物品 +options.command.item.tip={0}=玩家,{1}=物品ID,{2}=数量,{3}=物品耐久度 +options.command.time=时间 +options.command.time.tip={0}=世界时间 +options.command.rain=雨雪 +options.command.rain.tip={0}=1为开启雨雪,0为关闭雨雪 +options.command.heal=治疗 +options.command.heal.tip={0}=玩家 + +options.world.highlight_tips=高亮显示 +options.world.highlight_tips.hide=隐藏 +options.world.highlight_tips.show=显示 + +layoutstyle.minecraft=Minecraft风格 +layoutstyle.oldtmi=老式TMI风格 + +recipe.page=页数 %s/%s +recipe.shaped=有序合成 +recipe.shapeless=无序合成 +recipe.furnace=烧制 +recipe.fuel=燃料 +recipe.fuel.required=需要%s个 +recipe.fuel.processed=可烧制%s个 +recipe.fuel.produced=可制作%s个 +recipe.firework=烟花 +recipe.firework.tooltip0=添加多种染料可增加烟火之星的颜色 +recipe.firework.tooltip1=合成好的烟火之星和染料合成,可以添加色彩淡入效果 +recipe.firework.tooltip2=多个烟火之星可被用于合成单个烟花火箭 +recipe.brewing=酿造 +recipe.profiler.crafting=合成查询性能分析 +recipe.profiler.usage=用途查询性能分析 \ No newline at end of file diff --git a/resources/assets/nei/lang/zh_TW.lang b/resources/assets/nei/lang/zh_TW.lang new file mode 100644 index 00000000..5fa20b4b --- /dev/null +++ b/resources/assets/nei/lang/zh_TW.lang @@ -0,0 +1,159 @@ +load=讀取 +save=保存 + +enchant=附魔 +enchant.level=等級 +enchant.locked=開啟限制 +enchant.unlocked=解除限制 + +inventory.options=設定 +inventory.prev=上一頁 +inventory.next=下一頁 +inventory.item_subsets=物品分類表 +inventory.delete.all=刪除當前物品欄內所有物品 +inventory.delete.enable=開啟刪除模式設定 +inventory.delete.1=開啟刪除模式 +inventory.delete.0=關閉刪除模式 +inventory.rain.enable=開啟雨雪設定 +inventory.rain.1=開啟雨雪 +inventory.rain.0=關閉雨雪 +inventory.magnet.enable=開啟磁力模式設定 +inventory.magnet.1=開啟磁力模式 +inventory.magnet.0=關閉磁力模式 +inventory.dawn.enable=開啟黎明時間設定 +inventory.dawn.set=設定時間為黎明 +inventory.noon.enable=開啟中午時間設定 +inventory.noon.set=設定時間為中午 +inventory.dusk.enable=開啟傍晚時間設定 +inventory.dusk.set=設定時間為傍晚 +inventory.midnight.enable=開啟午夜時間設定 +inventory.midnight.set=設定時間為午夜 +inventory.heal=治療玩家並回滿飽食度 +inventory.gamemode.0=設定遊戲模式為生存 +inventory.gamemode.1=設定遊戲模式為創造 +inventory.gamemode.2=設定遊戲模式為創造+ +inventory.gamemode.3=設定遊戲模式為冒險 + +chat.gamemode.0=生存模式開啟 +chat.gamemode.1=創造模式開啟 +chat.gamemode.2=創造模式+開啟 +chat.gamemode.3=冒險模式開啟 + +options=NEI 選項 +options.back=後退 +options.world=世界 +options.global=全局 +options.global.tip.0=選項適用於所有世界 +options.global.tip.1=點擊旁邊的W可重寫該世界設置 +options.wbutton.tip.0=使用全局設定 +options.wbutton.tip.1=覆蓋全局設定 + +options.keys=按鍵設定 +options.keys.gui=物品欄 +options.keys.gui.recipe=合成表 +options.keys.gui.usage=用途 +options.keys.gui.enchant=附魔 +options.keys.gui.potion=藥水 +options.keys.gui.back=上一個合成表 +options.keys.gui.prev=上一頁 +options.keys.gui.next=下一頁 +options.keys.gui.hide=隱藏/顯示NEI界面 +options.keys.gui.search=焦點搜索欄 +options.keys.world=世界 +options.keys.world.chunkoverlay=區塊邊界顯示 +options.keys.world.moboverlay=怪物生成區域顯示 +options.keys.world.highlight_tips=高亮工具提示 +options.keys.world.dawn=黎明 +options.keys.world.noon=中午 +options.keys.world.dusk=傍晚 +options.keys.world.midnight=午夜 +options.keys.world.rain=雨雪 +options.keys.world.heal=治療 +options.keys.world.creative=遊戲模式 +options.keys.world.creative.tip=循環遊戲模式 + +options.inventory=NEI設定 +options.inventory.widgetsenabled.true=NEI開啟 +options.inventory.widgetsenabled.false=NEI關閉 +options.inventory.cheatmode.0=合成模式 +options.inventory.cheatmode.1=實用模式 +options.inventory.cheatmode.2=作弊模式 +options.inventory.layoutstyle=界面風格 +options.inventory.profileRecipes=合成查詢 +options.inventory.profileRecipes.true=開啟 +options.inventory.profileRecipes.false=關閉 +options.inventory.itemIDs=物品ID +options.inventory.itemIDs.0=隱藏 +options.inventory.itemIDs.1=自動 +options.inventory.itemIDs.2=顯示 +options.inventory.utilities=按鈕 +options.inventory.utilities.tip=選擇實用模式的功能 +options.inventory.utilities.time=時間 +options.inventory.utilities.rain=雨雪 +options.inventory.utilities.heal=治療 +options.inventory.utilities.delete=刪除 +options.inventory.utilities.magnet=磁力 +options.inventory.utilities.gamemode=遊戲模式 +options.inventory.utilities.enchant=附魔 +options.inventory.utilities.potion=釀造 +options.inventory.utilities.item=保存物品 +options.inventory.gamemodes=遊戲模式 +options.inventory.gamemodes.tip=選擇遊戲模式循環調整時的選項 +options.inventory.gamemodes.creative=創造模式 +options.inventory.gamemodes.creative+=創造模式+ +options.inventory.gamemodes.adventure=冒險模式 + +options.command=指令 +options.command.creative=遊戲模式 +options.command.creative.tip={0}=1為創造模式,0為生存模式,{1}=玩家 +options.command.give=物品 +options.command.give.tip={0}=玩家,{1}=物品ID,{2}=數量,{3}=物品耐久度 +options.command.time=時間 +options.command.time.tip={0}=世界時間 +options.command.rain=雨雪 +options.command.rain.tip={0}=1為開啟雨雪,0為關閉雨雪 +options.command.heal=治療 +options.command.heal.tip={0}=玩家 + +options.world.highlight_tips=高亮工具提示 +options.world.highlight_tips.hide=隱藏 +options.world.highlight_tips.show=顯示 + +options.tools=工具 +options.tools.dump=數據轉儲 +options.tools.dump.dump=轉儲 +options.tools.dump.dumped=%s ID 轉儲到 %s +options.tools.dump.mode.0=使用 +options.tools.dump.mode.1=自由 +options.tools.dump.mode.2=所有 +options.tools.dump.item=方塊/物品 +options.tools.dump.items=方塊/物品 +options.tools.dump.potion=藥水 +options.tools.dump.potions=藥水 +options.tools.dump.enchantment=附魔 +options.tools.dump.enchantments=附魔 +options.tools.dump.biome=生物群落 +options.tools.dump.biomes=生物群落 +options.tools.dump.itempanel=物品面板 +options.tools.dump.itempanel.dumped=物品面板內容轉儲為 %s +options.tools.dump.itempanel.mode.0=CSV +options.tools.dump.itempanel.mode.1=NBT + +layoutstyle.minecraft=Minecraft風格 +layoutstyle.oldtmi=舊TMI風格 + +recipe.page=頁數 %s/%s +recipe.shaped=成型工藝 +recipe.shapeless=成型染色工藝 +recipe.furnace=提煉 +recipe.fuel=燃料 +recipe.fuel.required=需要%s個 +recipe.fuel.processed=可燒製%s個 +recipe.fuel.produced=可製作%s個 +recipe.firework=煙花 +recipe.firework.tooltip0=多種染料可以增加火藥球的顏色 +recipe.firework.tooltip1=通過用完成的火藥球和染料合成,可以添加色彩淡出的效果 +recipe.firework.tooltip2=多種火藥球可以放進一個煙花火箭 +recipe.brewing=釀造 +recipe.profiler.crafting=合成查詢性能分析 +recipe.profiler.usage=用途查詢性能分析 \ No newline at end of file diff --git a/resources/assets/nei/textures/gui/inv.png b/resources/assets/nei/textures/gui/inv.png new file mode 100644 index 00000000..4b032b90 Binary files /dev/null and b/resources/assets/nei/textures/gui/inv.png differ diff --git a/resources/assets/nei/textures/gui/potion.png b/resources/assets/nei/textures/gui/potion.png new file mode 100644 index 00000000..ee450e29 Binary files /dev/null and b/resources/assets/nei/textures/gui/potion.png differ diff --git a/resources/assets/nei/textures/gui/recipebg.png b/resources/assets/nei/textures/gui/recipebg.png new file mode 100644 index 00000000..7a2bba3c Binary files /dev/null and b/resources/assets/nei/textures/gui/recipebg.png differ diff --git a/resources/assets/nei/textures/nei_sprites.png b/resources/assets/nei/textures/nei_sprites.png new file mode 100644 index 00000000..1fec7bd1 Binary files /dev/null and b/resources/assets/nei/textures/nei_sprites.png differ diff --git a/resources/nei_at.cfg b/resources/nei_at.cfg new file mode 100644 index 00000000..4cee2211 --- /dev/null +++ b/resources/nei_at.cfg @@ -0,0 +1,11 @@ +# NEI Access Transformer configuration file +public net.minecraft.client.gui.inventory.GuiContainer field_146999_f #xSize +public net.minecraft.client.gui.inventory.GuiContainer field_147000_g #ySize +public net.minecraft.client.gui.inventory.GuiContainer field_147003_i #guiLeft +public net.minecraft.client.gui.inventory.GuiContainer field_147009_r #guiTop +public net.minecraft.client.gui.inventory.GuiContainer func_146975_c(II)Lnet/minecraft/inventory/Slot; #getSlotAtPosition + +public net.minecraft.client.gui.GuiScreen field_146292_n #buttonList +public net.minecraft.entity.EntityList field_75624_e #classToIDMapping +public net.minecraft.client.renderer.Tessellator field_78415_z #isDrawing +public net.minecraft.client.multiplayer.PlayerControllerMP field_78779_k #currentGameType diff --git a/resources/neimod.info b/resources/neimod.info new file mode 100644 index 00000000..60bcb652 --- /dev/null +++ b/resources/neimod.info @@ -0,0 +1,15 @@ +[ +{ + "modid": "NotEnoughItems", + "name": "Not Enough Items", + "version": "${version}", + "mcversion": "${mc_version}", + "description": "Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more.", + "url": "http://www.minecraftforum.net/topic/909223", + "credits": "Alexandria - Original Idea", + "authors": [ "ChickenBones" ], + "dependencies": [ + "CodeChickenCore" + ] +} +] \ No newline at end of file diff --git a/src/codechicken/nei/Button.java b/src/codechicken/nei/Button.java new file mode 100644 index 00000000..aefd9788 --- /dev/null +++ b/src/codechicken/nei/Button.java @@ -0,0 +1,81 @@ +package codechicken.nei; + +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.util.ResourceLocation; + +import java.util.List; + +import static codechicken.lib.gui.GuiDraw.getStringWidth; + +public abstract class Button extends Widget +{ + public Button(String s) + { + label = s; + } + + public Button() + { + label = ""; + } + + public int contentWidth() + { + return getRenderIcon() == null ? getStringWidth(label) : getRenderIcon().width; + } + + @Override + public void draw(int mousex, int mousey) + { + LayoutManager.getLayoutStyle().drawButton(this, mousex, mousey); + } + + @Override + public boolean handleClick(int i, int j, int k) + { + if(k == 1 || k == 0) + if(onButtonPress(k == 1)) + NEIClientUtils.mc().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + return true; + } + + public abstract boolean onButtonPress(boolean rightclick); + + public Image getRenderIcon() + { + return icon; + } + + @Override + public List handleTooltip(int mx, int my, List tooltip) + { + if(!contains(mx, my)) + return tooltip; + + String tip = getButtonTip(); + if(tip != null) + tooltip.add(tip); + return tooltip; + } + + public String getButtonTip() + { + return null; + } + + public String getRenderLabel() + { + return label; + } + + public String label; + public Image icon; + + /** + * 0x4 = state flag, as opposed to 1 click + * 0 = normal + * 1 = on + * 2 = disabled + */ + public int state; +} diff --git a/src/codechicken/nei/ButtonCycled.java b/src/codechicken/nei/ButtonCycled.java new file mode 100644 index 00000000..eb1c5736 --- /dev/null +++ b/src/codechicken/nei/ButtonCycled.java @@ -0,0 +1,13 @@ +package codechicken.nei; + +public abstract class ButtonCycled extends Button +{ + @Override + public Image getRenderIcon() + { + return icons[index]; + } + + public int index; + public Image[] icons; +} diff --git a/src/codechicken/nei/ClientHandler.java b/src/codechicken/nei/ClientHandler.java new file mode 100644 index 00000000..0db0f3e8 --- /dev/null +++ b/src/codechicken/nei/ClientHandler.java @@ -0,0 +1,231 @@ +package codechicken.nei; + +import codechicken.core.ClientUtils; +import codechicken.lib.packet.PacketCustom; +import codechicken.nei.api.API; +import codechicken.nei.api.ItemInfo; +import cpw.mods.fml.client.CustomModLoadingErrorDisplayException; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.common.gameevent.TickEvent.Phase; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.*; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.common.MinecraftForge; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ClientHandler +{ + private static ClientHandler instance; + + private ArrayList SMPmagneticItems = new ArrayList(); + private World lastworld; + private GuiScreen lastGui; + + public void addSMPMagneticItem(int i, World world) { + WorldClient cworld = (WorldClient) world; + Entity e = cworld.getEntityByID(i); + if (e == null || !(e instanceof EntityItem)) { + return; + } + SMPmagneticItems.add((EntityItem) e); + } + + private void updateMagnetMode(World world, EntityPlayerSP player) { + if (!NEIClientConfig.getMagnetMode()) return; + + float distancexz = 16; + float distancey = 8; + double maxspeedxz = 0.5; + double maxspeedy = 0.5; + double speedxz = 0.05; + double speedy = 0.07; + + List items; + if (world.isRemote) { + items = SMPmagneticItems; + } else { + items = world.getEntitiesWithinAABB(EntityItem.class, player.boundingBox.expand(distancexz, distancey, distancexz)); + } + for (Iterator iterator = items.iterator(); iterator.hasNext(); ) { + EntityItem item = iterator.next(); + + if (item.delayBeforeCanPickup > 0) continue; + if (item.isDead && world.isRemote) iterator.remove(); + + if (!NEIClientUtils.canItemFitInInventory(player, item.getEntityItem())) continue; + + double dx = player.posX - item.posX; + double dy = player.posY + player.getEyeHeight() - item.posY; + double dz = player.posZ - item.posZ; + double absxz = Math.sqrt(dx * dx + dz * dz); + double absy = Math.abs(dy); + if (absxz > distancexz) { + continue; + } + + if (absxz > 1) { + dx /= absxz; + dz /= absxz; + } + + if (absy > 1) { + dy /= absy; + } + + double vx = item.motionX + speedxz * dx; + double vy = item.motionY + speedy * dy; + double vz = item.motionZ + speedxz * dz; + + double absvxz = Math.sqrt(vx * vx + vz * vz); + double absvy = Math.abs(vy); + + double rationspeedxz = absvxz / maxspeedxz; + if (rationspeedxz > 1) { + vx /= rationspeedxz; + vz /= rationspeedxz; + } + + double rationspeedy = absvy / maxspeedy; + if (rationspeedy > 1) { + vy /= rationspeedy; + } + + if (absvxz < 0.2 && absxz < 0.2 && world.isRemote) { + item.setDead(); + } + + item.setVelocity(vx, vy, vz); + } + } + + public static void load() { + try { + TMIUninstaller.deleteTMIUninstaller(); + if (TMIUninstaller.TMIInstalled()) { + TMIUninstaller.runTMIUninstaller(); + NEIClientUtils.mc().shutdownMinecraftApplet(); + } + } catch (Exception e) { + System.err.println("Error with TMI Uninstaller"); + e.printStackTrace(); + } + + instance = new ClientHandler(); + + PacketCustom.assignHandler(NEICPH.channel, new NEICPH()); + FMLCommonHandler.instance().bus().register(instance); + MinecraftForge.EVENT_BUS.register(instance); + + API.registerHighlightHandler(new DefaultHighlightHandler(), ItemInfo.Layout.HEADER); + HUDRenderer.load(); + WorldOverlayRenderer.load(); + } + + @SubscribeEvent + public void tickEvent(TickEvent.ClientTickEvent event) { + if(event.phase == Phase.END) + return; + + Minecraft mc = Minecraft.getMinecraft(); + if(mc.theWorld != null) { + loadWorld(mc.theWorld, false); + + if (!NEIClientConfig.isEnabled()) + return; + + KeyManager.tickKeyStates(); + + NEIController.updateUnlimitedItems(mc.thePlayer.inventory); + if (mc.currentScreen == null) + NEIController.processCreativeCycling(mc.thePlayer.inventory); + + updateMagnetMode(mc.theWorld, mc.thePlayer); + } + + GuiScreen gui = mc.currentScreen; + if (gui != lastGui) { + if (gui instanceof GuiMainMenu) + lastworld = null; + else if (gui instanceof GuiSelectWorld) + NEIClientConfig.reloadSaves(); + } + lastGui = gui; + } + + @SubscribeEvent + public void tickEvent(TickEvent.RenderTickEvent event) { + if(event.phase == Phase.END && NEIClientConfig.isEnabled()) + HUDRenderer.renderOverlay(); + } + + + @SubscribeEvent + public void renderLastEvent(RenderWorldLastEvent event) { + if (NEIClientConfig.isEnabled()) + WorldOverlayRenderer.render(event.partialTicks); + } + + + public void loadWorld(World world, boolean remote) { + if (world != lastworld) { + SMPmagneticItems.clear(); + WorldOverlayRenderer.reset(); + + if (!remote) { + NEIClientConfig.setHasSMPCounterPart(false); + NEIClientConfig.setInternalEnabled(false); + + if (!Minecraft.getMinecraft().isSingleplayer())//wait for server to initiate + NEIClientConfig.loadWorld("remote/" + ClientUtils.getServerIP().replace(':', '~')); + } + + lastworld = world; + } + } + + public static ClientHandler instance() { + return instance; + } + + public static RuntimeException throwCME(final String message) { + final GuiScreen errorGui = new GuiErrorScreen(null, null) + { + @Override + public void handleMouseInput() {} + + @Override + public void handleKeyboardInput() {} + + @Override + public void drawScreen(int par1, int par2, float par3) { + drawDefaultBackground(); + String[] s_msg = message.split("\n"); + for (int i = 0; i < s_msg.length; ++i) + drawCenteredString(fontRendererObj, s_msg[i], width / 2, height / 3 + 12 * i, 0xFFFFFFFF); + } + }; + + @SuppressWarnings("serial") + CustomModLoadingErrorDisplayException e = new CustomModLoadingErrorDisplayException() + { + @Override + public void initGui(GuiErrorScreen errorScreen, FontRenderer fontRenderer) { + Minecraft.getMinecraft().displayGuiScreen(errorGui); + } + + @Override + public void drawScreen(GuiErrorScreen errorScreen, FontRenderer fontRenderer, int mouseRelX, int mouseRelY, float tickTime) {} + }; + throw e; + } +} diff --git a/src/codechicken/nei/ContainerCreativeInv.java b/src/codechicken/nei/ContainerCreativeInv.java new file mode 100644 index 00000000..e528d742 --- /dev/null +++ b/src/codechicken/nei/ContainerCreativeInv.java @@ -0,0 +1,112 @@ +package codechicken.nei; + +import cpw.mods.fml.relauncher.Side; +import cpw.mods.fml.relauncher.SideOnly; +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.Slot; +import net.minecraft.item.ItemArmor; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IIcon; + +public class ContainerCreativeInv extends Container +{ + private class SlotArmor extends Slot + { + int armorType; + + public SlotArmor(IInventory inv, int x, int y, int slot, int armor) { + super(inv, x, y, slot); + armorType = armor; + } + + @Override + public int getSlotStackLimit() { + return 1; + } + + @Override + public boolean isItemValid(ItemStack stack) { + return stack != null && stack.getItem().isValidArmor(stack, armorType, player); + } + + @Override + @SideOnly(Side.CLIENT) + public IIcon getBackgroundIconIndex() { + return ItemArmor.func_94602_b(armorType); + } + } + + private class SlotBlockArmor extends SlotArmor + { + public SlotBlockArmor(IInventory inv, int x, int y, int slot, int armor) { + super(inv, x, y, slot, armor); + } + + @Override + public boolean isItemValid(ItemStack stack) { + return super.isItemValid(stack) || stack != null;// && Block.getBlockFromItem(stack.getItem()) != Blocks.air; + } + } + + public EntityPlayer player; + + public ContainerCreativeInv(EntityPlayer player, ExtendedCreativeInv extraInv) { + this.player = player; + InventoryPlayer invPlayer = player.inventory; + for (int row = 0; row < 6; row++) + for (int col = 0; col < 9; col++) + addSlotToContainer(new Slot(extraInv, col + row * 9, 8 + col * 18, 5 + row * 18)); + + for (int row = 0; row < 3; ++row) + for (int col = 0; col < 9; ++col) + addSlotToContainer(new Slot(invPlayer, col + row * 9 + 9, 8 + col * 18, 118 + row * 18)); + + for (int col = 0; col < 9; ++col) + addSlotToContainer(new Slot(invPlayer, col, 8 + col * 18, 176)); + + addSlotToContainer(new SlotBlockArmor(invPlayer, invPlayer.getSizeInventory() - 1, -15, 23, 0)); + for (int armorType = 1; armorType < 4; armorType++) + addSlotToContainer(new SlotArmor(invPlayer, invPlayer.getSizeInventory() - 1 - armorType, -15, 23 + armorType * 18, armorType)); + } + + @Override + public ItemStack transferStackInSlot(EntityPlayer par1EntityPlayer, int slotIndex) { + ItemStack transferredStack = null; + Slot slot = (Slot) inventorySlots.get(slotIndex); + + if (slot != null && slot.getHasStack()) { + ItemStack stack = slot.getStack(); + transferredStack = stack.copy(); + + if (stack.getItem() instanceof ItemArmor) { + ItemArmor armor = (ItemArmor) stack.getItem(); + if (!getSlot(90 + armor.armorType).getHasStack()) { + getSlot(90 + armor.armorType).putStack(transferredStack); + slot.putStack(null); + return transferredStack; + } + } + + if (slotIndex < 54) { + if (!this.mergeItemStack(stack, 54, 90, true)) + return null; + } else if (!this.mergeItemStack(stack, 0, 54, false)) { + return null; + } + + if (stack.stackSize == 0) + slot.putStack(null); + else + slot.onSlotChanged(); + } + + return transferredStack; + } + + public boolean canInteractWith(EntityPlayer var1) { + return true; + } +} diff --git a/src/codechicken/nei/ContainerEnchantmentModifier.java b/src/codechicken/nei/ContainerEnchantmentModifier.java new file mode 100644 index 00000000..1e169628 --- /dev/null +++ b/src/codechicken/nei/ContainerEnchantmentModifier.java @@ -0,0 +1,322 @@ +package codechicken.nei; + +import codechicken.lib.render.CCRenderState; +import net.minecraft.client.gui.Gui; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.ContainerEnchantment; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; + +/** + * This is crap code, don't ever do this. + */ +public class ContainerEnchantmentModifier extends ContainerEnchantment +{ + public static class EnchantmentHash + { + public EnchantmentHash(Enchantment e, int i, int l) { + enchantment = e; + state = i; + level = l; + } + + Enchantment enchantment; + int state; + int level; + } + + public ArrayList slotEnchantment = new ArrayList(); + int level = 5; + + public int scrollclicky = -1; + public float scrollpercent; + public int scrollmousey; + public float percentscrolled; + public int relx = 60; + public int rely = 14; + public int height = 57; + public int cwidth = 101; + public int slotheight = 19; + public GuiEnchantmentModifier parentscreen; + + public ContainerEnchantmentModifier(InventoryPlayer inventoryplayer, World world, int i, int j, int k) { + super(inventoryplayer, world, i, j, k); + } + + public int getNumSlots() { + return slotEnchantment.size(); + } + + public int getScrollBarHeight() { + int sbarh = (int) ((height / (float) getContentHeight()) * height); + if (sbarh > height) { + return height; + } else if (sbarh < height / 15) { + return height / 15; + } else { + return sbarh; + } + } + + public int getScrollBarWidth() { + return 7; + } + + public int getContentHeight() { + return slotheight * getNumSlots(); + } + + public int getScrolledSlots() { + int slots = getNumSlots(); + int shownslots = height / slotheight; + return (int) (percentscrolled * (slots - shownslots) + 0.5F); + } + + private int getClickedSlot(int mousey) { + return ((mousey - rely) / slotheight) + getScrolledSlots(); + } + + public void calculatePercentScrolled() { + int barempty = height - getScrollBarHeight(); + if (scrollclicky >= 0) { + int scrolldiff = scrollmousey - scrollclicky; + percentscrolled = scrolldiff / (float) barempty + scrollpercent; + } + if (percentscrolled < 0) { + percentscrolled = 0; + } + if (percentscrolled > 1) { + percentscrolled = 1; + } + int sbary = rely + (int) (barempty * percentscrolled + 0.5); + percentscrolled = (sbary - rely) / (float) barempty; + } + + public boolean clickScrollBar(int mousex, int mousey, int button) { + mousex -= parentscreen.guiLeft; + mousey -= parentscreen.guiTop; + + int barempty = height - getScrollBarHeight(); + int sbary = rely + (int) (barempty * percentscrolled + 0.5); + + if (button == 0 && + getScrollBarHeight() < height && //the scroll bar can move (not full length) + mousex >= relx + cwidth && mousex < relx + cwidth + getScrollBarWidth() && + mousey >= rely && mousey < rely + height)//in the scroll pane + { + if (mousey < sbary) { + percentscrolled = (mousey - rely) / (float) barempty; + calculatePercentScrolled(); + } else if (mousey > sbary + getScrollBarHeight()) { + percentscrolled = (mousey - rely - getScrollBarHeight() + 1) / (float) barempty; + calculatePercentScrolled(); + } else { + scrollclicky = mousey; + scrollpercent = percentscrolled; + scrollmousey = mousey; + } + return true; + } + return false; + } + + public void mouseUp(int mousex, int mousey, int button) { + if (scrollclicky >= 0 && button == 0)//we were scrolling and we released mouse + { + scrollclicky = -1; + } + } + + public boolean clickButton(int mousex, int mousey, int button) { + mousex -= parentscreen.guiLeft; + mousey -= parentscreen.guiTop; + if (mousex >= relx && mousex < relx + cwidth && + mousey >= rely && mousey <= rely + height)//in the box + { + int slot = getClickedSlot(mousey); + if (slot >= getNumSlots()) return false; + toggleSlotEnchantment(slot); + return true; + } + return false; + } + + private void toggleSlotEnchantment(int slot) { + EnchantmentHash e = slotEnchantment.get(slot); + if (e.state == 2) { + NEICPH.sendModifyEnchantment(e.enchantment.effectId, 0, false); + e.state = 0; + } else if (e.state == 1) { + return; + } else { + NEICPH.sendModifyEnchantment(e.enchantment.effectId, level, true); + e.state = 2; + } + updateEnchantmentOptions(GuiEnchantmentModifier.validateEnchantments()); + } + + public boolean addEnchantment(int e, int level) { + if (e < Enchantment.enchantmentsList.length && Enchantment.enchantmentsList[e] != null) { + ((Slot) inventorySlots.get(0)).getStack().addEnchantment(Enchantment.enchantmentsList[e], level); + return true; + } + return false; + } + + public void removeEnchantment(int e) { + ItemStack stack = ((Slot) inventorySlots.get(0)).getStack(); + NBTTagList nbttaglist = stack.getEnchantmentTagList(); + if (nbttaglist != null) { + for (int i = 0; i < nbttaglist.tagCount(); i++) { + int ID = nbttaglist.getCompoundTagAt(i).getShort("id"); + if (ID == e) { + nbttaglist.removeTag(i); + if (nbttaglist.tagCount() == 0) + stack.getTagCompound().removeTag("ench"); + if (stack.getTagCompound().hasNoTags()) + stack.setTagCompound(null); + return; + } + } + } + } + + public boolean canInteractWith(EntityPlayer entityplayer) { + return true; + } + + public void onCraftMatrixChanged(IInventory iinventory) { + if (parentscreen != null) + updateEnchantmentOptions(GuiEnchantmentModifier.validateEnchantments()); + } + + public void updateEnchantmentOptions(boolean validate) { + int numoptions = slotEnchantment.size(); + slotEnchantment.clear(); + + ItemStack toolstack = getSlot(0).getStack(); + if (toolstack == null) { + percentscrolled = 0; + return; + } + + Item item = toolstack.getItem(); + int enchantablity = item.getItemEnchantability(); + if (enchantablity == 0 && validate) { + percentscrolled = 0; + return; + } + + for (Enchantment e : Enchantment.enchantmentsList) { + if (e == null || e.type == null || (!e.type.canEnchantItem(item) && validate)) { + continue; + } + int state = 0; + int level = -1; + if (NEIServerUtils.stackHasEnchantment(toolstack, e.effectId)) { + state = 2; + level = NEIServerUtils.getEnchantmentLevel(toolstack, e.effectId); + } else if (NEIServerUtils.doesEnchantmentConflict(NEIServerUtils.getEnchantments(toolstack), e) && validate) { + state = 1; + } + slotEnchantment.add(new EnchantmentHash(e, state, level)); + } + if (numoptions != slotEnchantment.size()) { + percentscrolled = 0; + } + } + + public void drawSlots(GuiEnchantmentModifier gui) { + for (int slot = 0; slot < 3; slot++) { + int shade = 0; + String text = ""; + + int containerslot = slot + getScrolledSlots(); + if (containerslot + 1 > slotEnchantment.size()) { + shade = 1; + } else { + EnchantmentHash e = slotEnchantment.get(containerslot); + shade = e.state; + text = e.enchantment.getTranslatedName(e.level == -1 ? level : e.level); + if (gui.mc.fontRenderer.getStringWidth(text) > 95 && text.contains("Projectile")) { + text = text.replace("Projectile", "Proj"); + } + if (gui.mc.fontRenderer.getStringWidth(text) > 95 && text.contains("Protection")) { + text = text.replace("Protection", "Protect"); + } + if (gui.mc.fontRenderer.getStringWidth(text) > 95 && text.contains("Bane of")) { + text = text.replace("Bane of ", ""); + } + } + + CCRenderState.changeTexture("textures/gui/container/enchanting_table.png"); + GL11.glColor3f(1, 1, 1); + if (hasScrollBar()) { + gui.drawTexturedModalRect(relx, rely + slot * slotheight, 0, gui.ySize + slotheight * shade, cwidth - 30, slotheight); + gui.drawTexturedModalRect(relx + cwidth - 30, rely + slot * slotheight, cwidth - 23, gui.ySize + slotheight * shade, 30, slotheight); + } else { + gui.drawTexturedModalRect(relx, rely + slot * slotheight, 0, gui.ySize + slotheight * shade, cwidth + 7, slotheight); + } + + gui.getFontRenderer().drawString(text, relx + 4, rely + slot * slotheight + 5, textColourFromState(shade)); + } + } + + private boolean hasScrollBar() { + return getNumSlots() > 3; + } + + public void drawScrollBar(GuiEnchantmentModifier gui) { + if (!hasScrollBar()) return; + + int sbary = rely + (int) ((height - getScrollBarHeight()) * percentscrolled + 0.5); + int sbarx = relx + cwidth; + + Gui.drawRect(sbarx, rely, sbarx + getScrollBarWidth(), rely + height, 0xFF202020);//background + Gui.drawRect(sbarx, sbary, sbarx + getScrollBarWidth(), sbary + getScrollBarHeight(), 0xFF8B8B8B);//corners + Gui.drawRect(sbarx, sbary, sbarx + getScrollBarWidth() - 1, sbary + getScrollBarHeight() - 1, 0xFFF0F0F0);//topleft up + Gui.drawRect(sbarx + 1, sbary + 1, sbarx + getScrollBarWidth() - 1, sbary + getScrollBarHeight() - 1, 0xFF555555);//bottom right down + Gui.drawRect(sbarx + 1, sbary + 1, sbarx + getScrollBarWidth() - 2, sbary + getScrollBarHeight() - 2, 0xFFC6C6C6);//scrollbar + } + + private int textColourFromState(int shade) { + switch(shade) { + case 0: return 0x685e4a; + case 1: return 0x407f10; + default: return 0xffff80; + } + } + + public void onUpdate(int mousex, int mousey) { + processScrollMouse(mousey); + } + + public void processScrollMouse(int mousey) { + mousey -= parentscreen.guiTop; + + if (scrollclicky >= 0) { + int scrolldiff = mousey - scrollclicky; + int barupallowed = (int) ((height - getScrollBarHeight()) * scrollpercent + 0.5); + int bardownallowed = (height - getScrollBarHeight()) - barupallowed; + + if (-scrolldiff > barupallowed) { + scrollmousey = scrollclicky - barupallowed; + } else if (scrolldiff > bardownallowed) { + scrollmousey = scrollclicky + bardownallowed; + } else { + scrollmousey = mousey; + } + + calculatePercentScrolled(); + } + } +} diff --git a/src/codechicken/nei/ContainerPotionCreator.java b/src/codechicken/nei/ContainerPotionCreator.java new file mode 100644 index 00000000..e6b7c9a5 --- /dev/null +++ b/src/codechicken/nei/ContainerPotionCreator.java @@ -0,0 +1,162 @@ +package codechicken.nei; + +import codechicken.core.inventory.ContainerExtended; +import codechicken.core.inventory.SlotHandleClicks; +import codechicken.lib.inventory.InventoryNBT; +import codechicken.lib.inventory.InventoryUtils; +import codechicken.lib.packet.PacketCustom; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryBasic; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemPotion; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.potion.PotionEffect; + +public class ContainerPotionCreator extends ContainerExtended +{ + public class SlotPotion extends Slot + { + public SlotPotion(IInventory inv, int slotIndex, int x, int y) { + super(inv, slotIndex, x, y); + } + + @Override + public boolean isItemValid(ItemStack stack) { + return stack.getItem() instanceof ItemPotion; + } + + @Override + public void onSlotChanged() { + super.onSlotChanged(); + if (getHasStack()) { + ItemStack stack = getStack(); + if (!stack.hasTagCompound()) + stack.setTagCompound(new NBTTagCompound()); + if (!stack.getTagCompound().hasKey("CustomPotionEffects")) + stack.getTagCompound().setTag("CustomPotionEffects", new NBTTagList()); + } + } + } + + public class SlotPotionStore extends SlotHandleClicks + { + public SlotPotionStore(IInventory inv, int slotIndex, int x, int y) { + super(inv, slotIndex, x, y); + } + + @Override + public ItemStack slotClick(ContainerExtended container, EntityPlayer player, int button, int modifier) { + ItemStack held = player.inventory.getItemStack(); + if (button == 0 && modifier == 1) { + NEIClientUtils.cheatItem(getStack(), button, -1); + } else if (button == 1) { + putStack(null); + } else if (held != null) { + if (isItemValid(held)) { + putStack(InventoryUtils.copyStack(held, 1)); + player.inventory.setItemStack(null); + } + } else if (getHasStack()) + player.inventory.setItemStack(getStack()); + + return null; + } + + @Override + public boolean isItemValid(ItemStack stack) { + return stack.getItem() instanceof ItemPotion; + } + } + + public static class InventoryPotionStore extends InventoryNBT + { + public InventoryPotionStore() { + super(9, NEIClientConfig.global.nbt.getCompoundTag("potionStore")); + } + + @Override + public void markDirty() { + super.markDirty(); + NEIClientConfig.global.nbt.setTag("potionStore", tag); + NEIClientConfig.global.saveNBT(); + } + } + + InventoryPlayer playerInv; + InventoryBasic potionInv; + IInventory potionStoreInv; + + public ContainerPotionCreator(InventoryPlayer inventoryPlayer, IInventory potionStoreInv) { + playerInv = inventoryPlayer; + potionInv = new InventoryBasic("Potion", true, 1); + this.potionStoreInv = potionStoreInv; + + addSlotToContainer(new SlotPotion(potionInv, 0, 25, 102)); + for (int i = 0; i < 9; i++) + addSlotToContainer(new SlotPotionStore(potionStoreInv, i, 8 + i * 18, 14)); + bindPlayerInventory(inventoryPlayer, 8, 125); + } + + @Override + public boolean doMergeStackAreas(int slotIndex, ItemStack stack) { + if (slotIndex < 10) + return mergeItemStack(stack, 10, 46, true); + return mergeItemStack(stack, 0, 1, false); + } + + @Override + public boolean canInteractWith(EntityPlayer entityplayer) { + return true; + } + + @Override + public void onContainerClosed(EntityPlayer player) { + super.onContainerClosed(player); + + if (!player.worldObj.isRemote) + InventoryUtils.dropOnClose(player, potionInv); + } + + @SuppressWarnings("unchecked") + @Override + public void handleInputPacket(PacketCustom packet) { + ItemStack potion = potionInv.getStackInSlot(0); + if (potion == null) + return; + + boolean add = packet.readBoolean(); + int effectID = packet.readUByte(); + + NBTTagList effects = potion.getTagCompound().getTagList("CustomPotionEffects", 10); + NBTTagList newEffects = new NBTTagList(); + for(int i = 0; i < effects.tagCount(); i++) { + NBTTagCompound tag = effects.getCompoundTagAt(i); + PotionEffect e = PotionEffect.readCustomPotionEffectFromNBT(tag); + if(e.getPotionID() != effectID) + newEffects.appendTag(tag); + } + if(add) + newEffects.appendTag(new PotionEffect(effectID, packet.readInt(), packet.readUByte()).writeCustomPotionEffectToNBT(new NBTTagCompound())); + potion.getTagCompound().setTag("CustomPotionEffects", newEffects); + } + + public void setPotionEffect(int effectID, int duration, int amplifier) { + PacketCustom packet = NEICPH.createContainerPacket(); + packet.writeBoolean(true); + packet.writeByte(effectID); + packet.writeInt(duration); + packet.writeByte(amplifier); + packet.sendToServer(); + } + + public void removePotionEffect(int effectID) { + PacketCustom packet = NEICPH.createContainerPacket(); + packet.writeBoolean(false); + packet.writeByte(effectID); + packet.sendToServer(); + } +} \ No newline at end of file diff --git a/src/codechicken/nei/DefaultHighlightHandler.java b/src/codechicken/nei/DefaultHighlightHandler.java new file mode 100644 index 00000000..785e4c65 --- /dev/null +++ b/src/codechicken/nei/DefaultHighlightHandler.java @@ -0,0 +1,50 @@ +package codechicken.nei; + +import codechicken.nei.api.IHighlightHandler; +import codechicken.nei.api.ItemInfo; +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; + +import java.util.List; + +public class DefaultHighlightHandler implements IHighlightHandler +{ + @Override + public List handleTextData(ItemStack stack, World world, EntityPlayer player, MovingObjectPosition mop, List currenttip, ItemInfo.Layout layout) + { + String name = null; + try + { + String s = GuiContainerManager.itemDisplayNameShort(stack); + if(s != null && !s.endsWith("Unnamed")) + name = s; + + if(name != null) + currenttip.add(name); + } + catch(Exception e) + { + } + + if(stack.getItem() == Items.redstone) + { + int md = world.getBlockMetadata(mop.blockX, mop.blockY, mop.blockZ); + String s = ""+md; + if(s.length() < 2) + s=" "+s; + currenttip.set(currenttip.size()-1, name+" "+s); + } + + return currenttip; + } + + @Override + public ItemStack identifyHighlight(World world, EntityPlayer player, MovingObjectPosition mop) + { + return null; + } +} diff --git a/src/codechicken/nei/ExtendedCreativeInv.java b/src/codechicken/nei/ExtendedCreativeInv.java new file mode 100644 index 00000000..1a992b27 --- /dev/null +++ b/src/codechicken/nei/ExtendedCreativeInv.java @@ -0,0 +1,109 @@ +package codechicken.nei; + +import cpw.mods.fml.relauncher.Side; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +public class ExtendedCreativeInv implements IInventory +{ + PlayerSave playerSave; + Side side; + + public ExtendedCreativeInv(PlayerSave playerSave, Side side) { + this.playerSave = playerSave; + this.side = side; + } + + @Override + public int getSizeInventory() { + return 54; + } + + @Override + public ItemStack getStackInSlot(int slot) { + if (side.isClient()) + return NEIClientConfig.creativeInv[slot]; + return playerSave.creativeInv[slot]; + } + + @Override + public ItemStack decrStackSize(int slot, int size) { + ItemStack item = getStackInSlot(slot); + + if (item != null) { + if (item.stackSize <= size) { + ItemStack itemstack = item; + setInventorySlotContents(slot, null); + markDirty(); + return itemstack; + } + ItemStack itemstack1 = item.splitStack(size); + if (item.stackSize == 0) { + setInventorySlotContents(slot, null); + } + markDirty(); + return itemstack1; + } + return null; + } + + @Override + public ItemStack getStackInSlotOnClosing(int slot) { + synchronized (this) { + ItemStack stack = getStackInSlot(slot); + setInventorySlotContents(slot, null); + return stack; + } + } + + @Override + public void setInventorySlotContents(int slot, ItemStack stack) { + if (side.isClient()) + NEIClientConfig.creativeInv[slot] = stack; + else + playerSave.creativeInv[slot] = stack; + + markDirty(); + } + + @Override + public String getInventoryName() { + return "Extended Creative"; + } + + @Override + public int getInventoryStackLimit() { + return 64; + } + + @Override + public void markDirty() { + if (side.isServer()) + playerSave.setCreativeDirty(); + } + + @Override + public boolean isUseableByPlayer(EntityPlayer var1) { + return true; + } + + @Override + public void openInventory() { + } + + @Override + public void closeInventory() { + } + + @Override + public boolean isItemValidForSlot(int slot, ItemStack stack) { + return true; + } + + @Override + public boolean hasCustomInventoryName() { + return true; + } + +} diff --git a/src/codechicken/nei/FastTransferManager.java b/src/codechicken/nei/FastTransferManager.java new file mode 100644 index 00000000..bbd14437 --- /dev/null +++ b/src/codechicken/nei/FastTransferManager.java @@ -0,0 +1,338 @@ +package codechicken.nei; + +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +import java.util.*; + +import static codechicken.nei.NEIServerUtils.*; + +public class FastTransferManager +{ + /** + * Based on the general assumption that we want to fill top to bottom, left to right + */ + public static class SlotPositionComparator implements Comparator + { + Container container; + + public SlotPositionComparator(Container c) { + container = c; + } + + @Override + public int compare(Integer arg0, Integer arg1) { + Slot slot1 = container.getSlot(arg0); + Slot slot2 = container.getSlot(arg1); + + if (slot2.yDisplayPosition != slot1.yDisplayPosition) + return slot1.yDisplayPosition - slot2.yDisplayPosition; + return slot1.xDisplayPosition - slot2.xDisplayPosition; + } + } + + public LinkedList> slotZones = new LinkedList>(); + public HashMap slotZoneMap = new HashMap(); + + private void generateSlotMap(Container container, ItemStack stack) { + stack = stack.copy(); + stack.stackSize = 1; + + for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++) { + if (slotZoneMap.containsKey(slotNo) || !container.getSlot(slotNo).isItemValid(stack)) + continue; + + HashSet connectedSlots = new HashSet(); + findConnectedSlots(container, slotNo, connectedSlots); + + LinkedList zoneSlots = new LinkedList(connectedSlots); + Collections.sort(zoneSlots, new SlotPositionComparator(container)); + slotZones.add(zoneSlots); + + for (int i : zoneSlots) { + slotZoneMap.put(i, slotZones.size() - 1); + } + } + } + + private void findConnectedSlots(Container container, int slotNo, HashSet connectedSlots) { + connectedSlots.add(slotNo); + Slot slot = container.getSlot(slotNo); + final int threshold = 18; + + for (int i = 0; i < container.inventorySlots.size(); i++) { + if (connectedSlots.contains(i)) + continue; + + Slot slot1 = container.getSlot(i); + if (Math.abs(slot.xDisplayPosition - slot1.xDisplayPosition) <= threshold && Math.abs(slot.yDisplayPosition - slot1.yDisplayPosition) <= threshold) { + findConnectedSlots(container, i, connectedSlots); + } + } + } + + public static int findSlotWithItem(Container container, ItemStack teststack) { + for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++) { + ItemStack stack = container.getSlot(slotNo).getStack(); + if (stack != null && areStacksSameType(stack, teststack)) + return slotNo; + } + return -1; + } + + public static void clearSlots(Container container) { + for (int slotNo = 0; slotNo < container.inventorySlots.size(); slotNo++) + ((Slot) container.inventorySlots.get(slotNo)).putStack(null); + } + + public void performMassTransfer(GuiContainer window, int fromSlot, int toSlot, ItemStack heldStack) { + generateSlotMap(window.inventorySlots, heldStack); + + Integer fromZone = slotZoneMap.get(fromSlot); + Integer toZone = slotZoneMap.get(toSlot); + + if (fromZone == null || toZone == null || fromZone == toZone) + return; + + if (NEIClientUtils.getHeldItem() != null && !areStacksSameType(heldStack, NEIClientUtils.getHeldItem())) + return; + + if (!fillZoneWithHeldItem(window, toZone)) + return; + + for (int transferFrom : slotZones.get(fromZone)) { + ItemStack transferStack = window.inventorySlots.getSlot(transferFrom).getStack(); + + if (!areStacksSameType(heldStack, transferStack)) + continue; + + clickSlot(window, transferFrom); + if (!fillZoneWithHeldItem(window, toZone)) { + clickSlot(window, transferFrom); + return; + } + } + } + + /** + * @return The slot that one item from the source slot will end up in apon shift clicking, -1 if none. + */ + public int findShiftClickDestinationSlot(Container container, int fromSlot) { + LinkedList save = saveContainer(container); + + Slot slot = container.getSlot(fromSlot); + ItemStack stack = slot.getStack(); + if (stack == null) + return -1; + + stack.stackSize = 1; + slot.putStack(stack.copy()); + + LinkedList compareBefore = saveContainer(container); + container.slotClick(fromSlot, 0, 1, NEIClientUtils.mc().thePlayer); + LinkedList compareAfter = saveContainer(container); + + try { + //if(compareAfter.get(fromSlot) != null)//transfer failed + //return -1; + + for (int i = 0; i < compareBefore.size(); i++) { + if (i == fromSlot) + continue; + + ItemStack before = compareBefore.get(i); + ItemStack after = compareAfter.get(i); + + if (!areStacksIdentical(before, after) && after != null) { + if ((before == null && areStacksSameType(stack, after)) ||//transfered into this empty slot + (areStacksSameType(stack, after) && + after.stackSize - + before.stackSize > 0))//it added to this stack + return i; + } + } + + return -1; + } finally { + restoreContainer(container, save); + } + } + + public LinkedList saveContainer(Container container) { + LinkedList stacks = new LinkedList(); + for (int i = 0; i < container.inventorySlots.size(); i++) + stacks.add(copyStack(container.getSlot(i).getStack())); + + return stacks; + } + + public void restoreContainer(Container container, LinkedList items) { + for (int i = 0; i < container.inventorySlots.size(); i++) { + container.getSlot(i).putStack(items.get(i)); + } + + container.slotClick(-999, 0, 0, NEIClientUtils.mc().thePlayer); + } + + public void transferItem(GuiContainer window, int fromSlot) { + int toSlot = findShiftClickDestinationSlot(window.inventorySlots, fromSlot); + if (toSlot == -1) + return; + + Slot from = window.inventorySlots.getSlot(fromSlot); + + if (from.isItemValid(from.getStack())) + moveOneItem(window, fromSlot, toSlot); + else//slots that you can't put stuff in + moveOutputSet(window, fromSlot, toSlot); + } + + public void moveOutputSet(GuiContainer window, int fromSlot, int toSlot) { + if (NEIClientUtils.getHeldItem() != null) + return; + + clickSlot(window, fromSlot);//pickup fromSlot + if (NEIClientUtils.getHeldItem() == null)//maybe this container does auto transfers. No need to pick up the final item + return; + clickSlot(window, toSlot);//place one in toSlot + } + + public void moveOneItem(GuiContainer window, int fromSlot, int toSlot) { + clickSlot(window, fromSlot);//pickup fromSlot + clickSlot(window, toSlot, 1);//place one in toSlot + clickSlot(window, fromSlot);//place down in fromSlot + } + + public void retrieveItem(GuiContainer window, int toSlot) { + Slot slot = window.inventorySlots.getSlot(toSlot); + ItemStack slotStack = slot.getStack(); + if (slotStack == null || + slotStack.stackSize == slot.getSlotStackLimit() || + slotStack.stackSize == slotStack.getMaxStackSize()) + return; + + generateSlotMap(window.inventorySlots, slotStack); + + Integer destZone = slotZoneMap.get(toSlot); + if (destZone == null)//slots that don't accept + return; + + int firstZoneSlot = findShiftClickDestinationSlot(window.inventorySlots, toSlot); + int firstZone = -1; + if (firstZoneSlot != -1) { + Integer integer = slotZoneMap.get(firstZoneSlot); + if (integer != null) { + firstZone = integer; + if (retrieveItemFromZone(window, firstZone, toSlot)) + return; + } + } + + for (int zone = 0; zone < slotZones.size(); zone++) { + if (zone == destZone || zone == firstZone) + continue; + + if (retrieveItemFromZone(window, zone, toSlot)) + return; + } + + retrieveItemFromZone(window, destZone, toSlot); + } + + private boolean retrieveItemFromZone(GuiContainer window, int zone, int toSlot) { + ItemStack stack = window.inventorySlots.getSlot(toSlot).getStack(); + for (int i : slotZones.get(zone)) { + if (i == toSlot) + continue; + + Slot slot = window.inventorySlots.getSlot(i); + ItemStack stack1 = slot.getStack(); + + if (areStacksSameType(stack, stack1) && + stack1.stackSize != slot.getSlotStackLimit() && //get from full stacks on second pass + stack1.stackSize != stack1.getMaxStackSize()) { + moveOneItem(window, i, toSlot); + return true; + } + } + + for (int i : slotZones.get(zone)) { + if (i == toSlot) + continue; + + Slot slot = window.inventorySlots.getSlot(i); + ItemStack stack1 = slot.getStack(); + + if (areStacksSameType(stack, stack1)) { + moveOneItem(window, i, toSlot); + return true; + } + } + return false; + } + + public static void clickSlot(GuiContainer window, int slotIndex) { + clickSlot(window, slotIndex, 0); + } + + public static void clickSlot(GuiContainer window, int slotIndex, int button) { + clickSlot(window, slotIndex, button, 0); + } + + public static void clickSlot(GuiContainer window, int slotIndex, int button, int modifier) { + GuiContainerManager.getManager(window).handleSlotClick(slotIndex, button, modifier); + } + + private boolean fillZoneWithHeldItem(GuiContainer window, int zoneIndex) { + for (int transferTo : slotZones.get(zoneIndex)) { + ItemStack held = NEIClientUtils.getHeldItem(); + + if (held == null) + break; + + ItemStack inToSlot = window.inventorySlots.getSlot(transferTo).getStack(); + + if (!areStacksSameType(inToSlot, held)) + continue; + + clickSlot(window, transferTo); + } + + for (int transferTo : slotZones.get(zoneIndex))//repeat on empty slots + { + ItemStack held = NEIClientUtils.getHeldItem(); + + if (held == null) + break; + + ItemStack inToSlot = window.inventorySlots.getSlot(transferTo).getStack(); + + if (inToSlot != null) + continue; + + clickSlot(window, transferTo); + } + + return NEIClientUtils.getHeldItem() == null; + } + + public void throwAll(GuiContainer window, int pickedUpFromSlot) { + ItemStack held = NEIClientUtils.getHeldItem(); + if (held == null) + return; + + clickSlot(window, -999); + + generateSlotMap(window.inventorySlots, held); + for (int slotIndex : slotZones.get(slotZoneMap.get(pickedUpFromSlot))) { + Slot slot = window.inventorySlots.getSlot(slotIndex); + if (areStacksSameType(held, slot.getStack())) { + clickSlot(window, slotIndex); + clickSlot(window, -999); + } + } + } +} diff --git a/src/codechicken/nei/GuiEnchantmentModifier.java b/src/codechicken/nei/GuiEnchantmentModifier.java new file mode 100644 index 00000000..d2d5740a --- /dev/null +++ b/src/codechicken/nei/GuiEnchantmentModifier.java @@ -0,0 +1,99 @@ +package codechicken.nei; + +import codechicken.lib.render.CCRenderState; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +import static codechicken.nei.NEIClientUtils.translate; + +public class GuiEnchantmentModifier extends GuiContainer +{ + ContainerEnchantmentModifier container; + + public GuiEnchantmentModifier(InventoryPlayer inventoryplayer, World world, int i, int j, int k) { + super(new ContainerEnchantmentModifier(inventoryplayer, world, i, j, k)); + container = (ContainerEnchantmentModifier) inventorySlots; + container.parentscreen = this; + } + + @Override + protected void drawGuiContainerForegroundLayer(int par1, int par2) { + fontRendererObj.drawString(translate("enchant"), 12, 6, 0x404040); + fontRendererObj.drawString(translate("enchant.level"), 19, 20, 0x404040); + } + + protected void drawGuiContainerBackgroundLayer(float f, int i, int j) { + GL11.glColor4f(1, 1, 1, 1); + CCRenderState.changeTexture("textures/gui/container/enchanting_table.png"); + GL11.glTranslatef(guiLeft, guiTop, 0); + drawTexturedModalRect(0, 0, 0, 0, xSize, ySize); + + container.onUpdate(i, j); + container.drawSlots(this); + container.drawScrollBar(this); + + String levelstring = "" + container.level; + fontRendererObj.drawString(levelstring, 33 - fontRendererObj.getStringWidth(levelstring) / 2, 34, 0xFF606060); + + GL11.glTranslatef(-guiLeft, -guiTop, 0); + } + + public void initGui() { + super.initGui(); + + buttonList.add(new GuiNEIButton(0, width / 2 - 78, height / 2 - 52, 12, 12, "<")); + buttonList.add(new GuiNEIButton(1, width / 2 - 44, height / 2 - 52, 12, 12, ">")); + buttonList.add(new GuiNEIButton(2, width / 2 - 80, height / 2 - 15, 50, 12, lockDisplayString())); + } + + private String lockDisplayString() { + return validateEnchantments() ? translate("enchant.locked") : translate("enchant.unlocked"); + } + + public static boolean validateEnchantments() { + return NEIClientConfig.world.nbt.getBoolean("validateenchantments"); + } + + public static void toggleEnchantmentValidation() { + NEIClientConfig.world.nbt.setBoolean("validateenchantments", !validateEnchantments()); + NEIClientConfig.world.saveNBT(); + } + + protected void actionPerformed(GuiButton guibutton) { + if (guibutton.id == 0) { + changeLevel(-1); + } else if (guibutton.id == 1) { + changeLevel(1); + } else if (guibutton.id == 2) { + toggleEnchantmentValidation(); + container.updateEnchantmentOptions(validateEnchantments()); + guibutton.displayString = lockDisplayString(); + } + } + + private void changeLevel(int i) { + container.level += i; + ((GuiButton) buttonList.get(0)).enabled = container.level != 1; + ((GuiButton) buttonList.get(1)).enabled = container.level != 10; + } + + protected void mouseClicked(int i, int j, int k) { + if (container.clickButton(i, j, k)) return; + if (container.clickScrollBar(i, j, k)) return; + + super.mouseClicked(i, j, k); + } + + protected void mouseMovedOrUp(int i, int j, int k) { + container.mouseUp(i, j, k); + super.mouseMovedOrUp(i, j, k); + } + + public FontRenderer getFontRenderer() { + return fontRendererObj; + } +} diff --git a/src/codechicken/nei/GuiExtendedCreativeInv.java b/src/codechicken/nei/GuiExtendedCreativeInv.java new file mode 100644 index 00000000..5c658602 --- /dev/null +++ b/src/codechicken/nei/GuiExtendedCreativeInv.java @@ -0,0 +1,56 @@ +package codechicken.nei; + +import codechicken.lib.render.CCRenderState; +import codechicken.nei.api.INEIGuiHandler; +import codechicken.nei.api.TaggedInventoryArea; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Container; +import net.minecraft.item.ItemStack; +import org.lwjgl.opengl.GL11; + +import java.util.Arrays; +import java.util.List; + +public class GuiExtendedCreativeInv extends GuiContainer implements INEIGuiHandler +{ + public GuiExtendedCreativeInv(Container par1Container) { + super(par1Container); + ySize = 198; + } + + @Override + protected void drawGuiContainerBackgroundLayer(float var1, int var2, int var3) { + GL11.glColor4f(1, 1, 1, 1); + CCRenderState.changeTexture("nei:textures/gui/inv.png"); + + int x = guiLeft; + int y = guiTop - 4; + + drawTexturedModalRect(x - 23, y, 0, 0, 199, 204); + } + + @Override + public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) { + return currentVisibility; + } + + @Override + public Iterable getItemSpawnSlots(GuiContainer gui, ItemStack item) { + return NEIServerUtils.getRange(0, 54); + } + + @Override + public List getInventoryAreas(GuiContainer gui) { + return Arrays.asList(new TaggedInventoryArea("ExtendedCreativeInv", 0, 54, inventorySlots)); + } + + @Override + 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) { + return false; + } +} diff --git a/src/codechicken/nei/GuiNEIButton.java b/src/codechicken/nei/GuiNEIButton.java new file mode 100644 index 00000000..c63fa357 --- /dev/null +++ b/src/codechicken/nei/GuiNEIButton.java @@ -0,0 +1,41 @@ +package codechicken.nei; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +public class GuiNEIButton extends GuiButton +{ + protected static ResourceLocation guiTex = new ResourceLocation("textures/gui/widgets.png"); + + public GuiNEIButton(int i, int j, int k, int l, int i1, String s) + { + super(i, j, k, l, i1, s); + } + + public void drawButton(Minecraft minecraft, int i, int j) + { + if(!visible) + return; + + FontRenderer fontrenderer = minecraft.fontRenderer; + minecraft.renderEngine.bindTexture(guiTex); + GL11.glColor4f(1, 1, 1, 1); + boolean flag = i >= xPosition && j >= yPosition && i < xPosition + width && j < yPosition + height; + int k = getHoverState(flag); + drawTexturedModalRect(xPosition, yPosition, 0, 46 + k * 20, width / 2, height / 2);//top left + drawTexturedModalRect(xPosition + width / 2, yPosition, 200 - width / 2, 46 + k * 20, width / 2, height / 2);//top right + drawTexturedModalRect(xPosition, yPosition + height / 2, 0, 46 + k * 20 + 20 - height / 2, width / 2, height / 2);//bottom left + drawTexturedModalRect(xPosition + width / 2, yPosition + height / 2, 200 - width / 2, 46 + k * 20 + 20 - height / 2, width / 2, height / 2);//bottom right + mouseDragged(minecraft, i, j); + + if(!enabled) + drawCenteredString(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, 0xffa0a0a0); + else if(flag) + drawCenteredString(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, 0xffffa0); + else + drawCenteredString(fontrenderer, displayString, xPosition + width / 2, yPosition + (height - 8) / 2, 0xe0e0e0); + } +} diff --git a/src/codechicken/nei/GuiPotionCreator.java b/src/codechicken/nei/GuiPotionCreator.java new file mode 100644 index 00000000..4191b119 --- /dev/null +++ b/src/codechicken/nei/GuiPotionCreator.java @@ -0,0 +1,330 @@ +package codechicken.nei; + +import codechicken.core.gui.GuiCCButton; +import codechicken.core.gui.GuiCCTextField; +import codechicken.core.gui.GuiScrollSlot; +import codechicken.core.inventory.GuiContainerWidget; +import codechicken.lib.render.CCRenderState; +import codechicken.lib.render.FontUtils; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.StatCollector; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; + +public class GuiPotionCreator extends GuiContainerWidget +{ + public class GuiSlotPotionEffects extends GuiScrollSlot + { + public int selectedslot = -1; + public boolean enabled = true; + private ArrayList validPotions = new ArrayList(); + + public GuiSlotPotionEffects(int x, int y) { + super(x, y, 108, 76); + for (Potion p : Potion.potionTypes) + if (p != null) + validPotions.add(p); + setSmoothScroll(false); + setContentSize(x, y, height); + } + + @Override + public int getSlotHeight() { + return 19; + } + + @Override + public void drawSlotBox(float frame) { + drawRect(x, y, x + width, y + height, 0xFF000000); + } + + @Override + public void drawOverlay(float frame) { + } + + @Override + public boolean drawLineGuide() { + return false; + } + + @Override + public int getScrollBarWidth() { + return 7; + } + + @Override + protected void drawSlot(int slot, int x, int y, int mx, int my, boolean selected, float frame) { + GL11.glColor4f(1, 1, 1, 1); + Potion potion = validPotions.get(slot); + PotionEffect effect = getEffect(potion.id); + boolean blank = effect == null; + if (effect == null) + effect = new PotionEffect(potion.id, 1200, 0); + int shade = selectedslot == slot ? 2 : blank ? 1 : 0; + + CCRenderState.changeTexture("textures/gui/container/enchanting_table.png"); + drawTexturedModalRect(x, y, 0, 166 + getSlotHeight() * shade, width - 30, getSlotHeight()); + drawTexturedModalRect(x + width - 30, y, width - 23, 166 + getSlotHeight() * shade, 30, getSlotHeight()); + + if (potion.hasStatusIcon()) { + CCRenderState.changeTexture("textures/gui/container/inventory.png"); + int icon = potion.getStatusIconIndex(); + drawTexturedModalRect(x + 1, y + 1, 0 + icon % 8 * 18, 198 + icon / 8 * 18, 18, 18); + } + + String name = StatCollector.translateToLocal(potion.getName()); + String amp = effect.getAmplifier() > 0 ? " " + translateAmplifier(effect.getAmplifier()) : ""; + int textColour = shade == 0 ? 0x685e4a : shade == 1 ? 0x407f10 : 0xffff80; + if (fontRenderer.getStringWidth(name + amp) < width - 20) { + fontRenderer.drawString(name + amp, x + 20, y + 1, textColour); + } else { + fontRenderer.drawString(name, x + 20, y + 1, textColour); + FontUtils.drawRightString(amp, x + width - 10, y + 10, textColour); + } + + String duration = Potion.getDurationString(effect); + textColour = shade == 0 ? 0xA0A0A0 : shade == 1 ? 0x808080 : 0xCCCCCC; + fontRenderer.drawStringWithShadow(duration, x + 20, y + 10, textColour); + } + + private PotionEffect getEffect(int id) { + ItemStack potion = container.potionInv.getStackInSlot(0); + if (potion != null && potion.hasTagCompound() && potion.getTagCompound().hasKey("CustomPotionEffects")) { + NBTTagList potionTagList = potion.getTagCompound().getTagList("CustomPotionEffects", 10); + for (int i = 0; i < potionTagList.tagCount(); i++) { + PotionEffect effect = PotionEffect.readCustomPotionEffectFromNBT(potionTagList.getCompoundTagAt(i)); + if (effect.getPotionID() == id) + return effect; + } + } + return null; + } + + @Override + protected int getNumSlots() { + return validPotions.size(); + } + + @Override + protected boolean isSlotSelected(int slot) { + return slot == selectedslot; + } + + @Override + protected void slotClicked(int slot, int button, int mx, int my, boolean doubleclick) { + if (!enabled) + return; + + if (button == 0) { + select(slot); + applyEffect(); + } else if (button == 1) { + deselect(); + container.removePotionEffect(validPotions.get(slot).id); + } + } + + public void selectNext() { + if (selectedslot >= 0 && selectedslot + 1 < getNumSlots()) { + select(selectedslot + 1); + showSlot(selectedslot); + } + } + + public void selectPrev() { + if (selectedslot > 0) { + select(selectedslot - 1); + showSlot(selectedslot); + } + } + + public void setEnabled(boolean b) { + if (b == enabled) + return; + enabled = b; + if (!enabled) + deselect(); + } + + private void select(int slot) { + selectedslot = slot; + durationField.setEnabled(true); + PotionEffect effect = getEffect(validPotions.get(slot).id); + if (effect == null) + effect = new PotionEffect(validPotions.get(slot).id, 1200, 0); + durationField.setDurationTicks(effect.getDuration()); + amplifier = effect.getAmplifier(); + validateInputButtons(); + } + + private void deselect() { + selectedslot = -1; + durationField.setEnabled(false); + ampDown.setEnabled(false); + ampUp.setEnabled(false); + } + + public int selectedPotion() { + return validPotions.get(selectedslot).id; + } + } + + public class GuiDurationField extends GuiCCTextField + { + private String baseValue; + + public GuiDurationField(int x, int y, int width, int height) { + super(x, y, width, height, "100"); + setMaxStringLength(4); + setAllowedCharacters("0123456789"); + baseValue = getText(); + } + + public void setDurationTicks(int i) { + i /= 20; + String minutes = Integer.toString(i / 60); + String seconds = Integer.toString(i % 60); + if (seconds.length() == 1) + seconds = '0' + seconds; + setText(minutes + seconds); + } + + @Override + public void setEnabled(boolean b) { + super.setEnabled(b); + if (!isEnabled()) + setText("100"); + } + + @Override + public void onFocusChanged() { + if (isFocused()) + baseValue = getText(); + else { + if (!validateValue()) + setText(baseValue); + else + applyEffect(); + } + } + + @Override + public void onTextChanged(String oldText) { + validateInputButtons(); + } + + private boolean validateValue() { + try { + int i = Integer.parseInt(getText()); + return i > 1 && getDurationTicks() < Short.MAX_VALUE && i / 100 <= 60 && i % 100 < 60; + } catch (NumberFormatException nfe) { + return false; + } + } + + @Override + public void drawText() { + String s = getText(); + String seconds = s.substring(Math.max(0, s.length() - 2), Math.max(0, s.length() - 2) + Math.min(s.length(), 2)); + String minutes = s.length() < 3 ? "" : s.substring(0, s.length() - 2); + int ty = y + height / 2 - 4; + int tcolour = getTextColour(); + FontUtils.drawCenteredString(":", x + width / 2 + 1, ty, tcolour); + FontUtils.drawRightString(seconds, x + width - 3, ty, tcolour); + FontUtils.drawRightString(minutes, x + width / 2 - 1, ty, tcolour); + } + + @Override + public int getTextColour() { + return isFocused() ? 0xCCCCCC : 0x909090; + } + + public int getDurationTicks() { + int i = Integer.parseInt(getText()); + return ((i / 100) * 60 + (i % 100)) * 20; + } + } + + int amplifier = 0; + GuiCCButton ampDown; + GuiCCButton ampUp; + GuiSlotPotionEffects slotPotionEffects; + GuiDurationField durationField; + ContainerPotionCreator container; + + public GuiPotionCreator(InventoryPlayer inventoryplayer) { + super(new ContainerPotionCreator(inventoryplayer, new ContainerPotionCreator.InventoryPotionStore()), 176, 208); + container = (ContainerPotionCreator) inventorySlots; + } + + public void applyEffect() { + if (slotPotionEffects.selectedslot >= 0) + container.setPotionEffect(slotPotionEffects.selectedPotion(), durationField.getDurationTicks(), amplifier); + } + + public String translateAmplifier(int amplifier) { + switch (amplifier) { + case 0: + return "I"; + case 1: + return "II"; + case 2: + return "III"; + case 3: + return "IV"; + case 4: + return "V"; + } + return Integer.toString(amplifier); + } + + public void validateInputButtons() { + ampDown.setEnabled(amplifier > 0); + ampUp.setEnabled(amplifier < 3); + } + + @Override + protected void drawGuiContainerForegroundLayer(int par1, int par2) { + //fontRenderer.drawString("Potion", 12, 6, 0x404040); + } + + @Override + public void drawBackground() { + CCRenderState.changeTexture("nei:textures/gui/potion.png"); + drawTexturedModalRect(0, 0, 0, 0, xSize, ySize); + + FontUtils.drawCenteredString("Favourite Potions", xSize / 2, 4, 0x404040); + fontRendererObj.drawString("Duration", 12, 40, 0x404040); + fontRendererObj.drawString("Level", 19, 73, 0x404040); + FontUtils.drawCenteredString(translateAmplifier(amplifier), 33, 86, 0xFF606060); + } + + @Override + public void addWidgets() { + add(ampDown = new GuiCCButton(10, 84, 12, 12, "<").setActionCommand("ampDown")); + add(ampUp = new GuiCCButton(44, 84, 12, 12, ">").setActionCommand("ampUp")); + add(durationField = new GuiDurationField(15, 53, 35, 12)); + add(slotPotionEffects = new GuiSlotPotionEffects(60, 38)); + } + + @Override + public void updateScreen() { + super.updateScreen(); + slotPotionEffects.setEnabled(container.potionInv.getStackInSlot(0) != null); + } + + @Override + public void actionPerformed(String ident, Object... params) { + if (ident.equals("ampDown")) + amplifier--; + else if (ident.equals("ampUp")) + amplifier++; + applyEffect(); + validateInputButtons(); + } +} diff --git a/src/codechicken/nei/HUDRenderer.java b/src/codechicken/nei/HUDRenderer.java new file mode 100644 index 00000000..dd2042de --- /dev/null +++ b/src/codechicken/nei/HUDRenderer.java @@ -0,0 +1,96 @@ +package codechicken.nei; + +import codechicken.lib.config.ConfigTag; +import codechicken.nei.KeyManager.IKeyStateTracker; +import codechicken.nei.api.ItemInfo; +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition.MovingObjectType; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static codechicken.lib.gui.GuiDraw.*; + +public class HUDRenderer implements IKeyStateTracker +{ + @Override + public void tickKeyStates() { + if (KeyManager.keyStates.get("world.highlight_tips").down) { + ConfigTag tag = NEIClientConfig.getSetting("world.highlight_tips"); + tag.setBooleanValue(!tag.getBooleanValue()); + } + } + + public static void renderOverlay() { + Minecraft mc = Minecraft.getMinecraft(); + if (mc.currentScreen == null && + mc.theWorld != null && + !mc.gameSettings.keyBindPlayerList.getIsKeyPressed() && + NEIClientConfig.getBooleanSetting("world.highlight_tips") && + mc.objectMouseOver != null && + mc.objectMouseOver.typeOfHit == MovingObjectType.BLOCK) { + World world = mc.theWorld; + ArrayList items = ItemInfo.getIdentifierItems(world, mc.thePlayer, mc.objectMouseOver); + if (items.isEmpty()) + return; + + int minDamage = Integer.MAX_VALUE; + ItemStack stack = null; + for(ItemStack astack : items) { + if(astack.getItem() != null && astack.getItemDamage() < minDamage) { + stack = astack; + minDamage = stack.getItemDamage(); + } + } + + renderOverlay(stack, ItemInfo.getText(stack, world, mc.thePlayer, mc.objectMouseOver), getPositioning()); + } + } + + public static void renderOverlay(ItemStack stack, List textData, Point pos) { + int w = 0; + for (String s : textData) + w = Math.max(w, getStringWidth(s) + 29); + int h = Math.max(24, 10 + 10 * textData.size()); + + Dimension size = displaySize(); + int x = (size.width - w - 1) * pos.x / 10000; + int y = (size.height - h - 1) * pos.y / 10000; + + GL11.glDisable(GL12.GL_RESCALE_NORMAL); + RenderHelper.disableStandardItemLighting(); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_DEPTH_TEST); + + drawTooltipBox(x, y, w, h); + + int ty = (h - 8 * textData.size()) / 2; + for (int i = 0; i < textData.size(); i++) + drawString(textData.get(i), x + 24, y + ty + 10 * i, 0xFFA0A0A0, true); + + RenderHelper.enableGUIStandardItemLighting(); + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + + if (stack.getItem() != null) + GuiContainerManager.drawItem(x + 5, y + h / 2 - 8, stack); + } + + private static Point getPositioning() { + return new Point( + NEIClientConfig.getSetting("world.highlight_tips.x").getIntValue(), + NEIClientConfig.getSetting("world.highlight_tips.y").getIntValue()); + } + + public static void load() { + KeyManager.trackers.add(new HUDRenderer()); + } +} \ No newline at end of file diff --git a/src/codechicken/nei/Image.java b/src/codechicken/nei/Image.java new file mode 100644 index 00000000..5634a4f7 --- /dev/null +++ b/src/codechicken/nei/Image.java @@ -0,0 +1,17 @@ +package codechicken.nei; + +public class Image +{ + public int x; + public int y; + public int width; + public int height; + + public Image(int i, int j, int k, int l) + { + x = i; + y = j; + width = k; + height = l; + } +} diff --git a/src/codechicken/nei/InfiniteStackSizeHandler.java b/src/codechicken/nei/InfiniteStackSizeHandler.java new file mode 100644 index 00000000..a38a5a8a --- /dev/null +++ b/src/codechicken/nei/InfiniteStackSizeHandler.java @@ -0,0 +1,55 @@ +package codechicken.nei; + +import codechicken.lib.inventory.InventoryUtils; +import codechicken.nei.api.IInfiniteItemHandler; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; + +public class InfiniteStackSizeHandler implements IInfiniteItemHandler +{ + @Override + public void onPickup(ItemStack heldItem) + { + heldItem.stackSize = 1; + } + + @Override + public void onPlaceInfinite(ItemStack heldItem) + { + heldItem.stackSize = 111; + } + + @Override + public boolean canHandleItem(ItemStack stack) + { + return !stack.isItemStackDamageable(); + } + + @Override + public boolean isItemInfinite(ItemStack stack) + { + return stack.stackSize == -1 || stack.stackSize > 100; + } + + @Override + public void replenishInfiniteStack(InventoryPlayer inv, int slotNo) + { + ItemStack stack = inv.getStackInSlot(slotNo); + stack.stackSize = 111; + + for(int i = 0; i < inv.getSizeInventory(); i++) + { + if(i == slotNo) + continue; + + if(NEIServerUtils.areStacksSameType(stack, inv.getStackInSlot(i))) + inv.setInventorySlotContents(i, null); + } + } + + @Override + public ItemStack getInfiniteItem(ItemStack typeStack) + { + return InventoryUtils.copyStack(typeStack, -1); + } +} diff --git a/src/codechicken/nei/InfiniteToolHandler.java b/src/codechicken/nei/InfiniteToolHandler.java new file mode 100644 index 00000000..edf4b268 --- /dev/null +++ b/src/codechicken/nei/InfiniteToolHandler.java @@ -0,0 +1,38 @@ +package codechicken.nei; + +import codechicken.nei.api.IInfiniteItemHandler; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; + +public class InfiniteToolHandler implements IInfiniteItemHandler +{ + @Override + public void onPickup(ItemStack heldItem) { + heldItem.setItemDamage(0); + } + + @Override + public void onPlaceInfinite(ItemStack heldItem) { + heldItem.setItemDamage(-32000); + } + + @Override + public void replenishInfiniteStack(InventoryPlayer inv, int slotNo) { + inv.getStackInSlot(slotNo).setItemDamage(-32000); + } + + @Override + public boolean canHandleItem(ItemStack stack) { + return stack.getItem().isDamageable() && stack.getMaxStackSize() == 1; + } + + @Override + public boolean isItemInfinite(ItemStack stack) { + return stack.getItemDamage() < -30000; + } + + @Override + public ItemStack getInfiniteItem(ItemStack typeStack) { + return new ItemStack(typeStack.getItem(), 1, -32000); + } +} diff --git a/src/codechicken/nei/InventoryCraftingDummy.java b/src/codechicken/nei/InventoryCraftingDummy.java new file mode 100644 index 00000000..11866f22 --- /dev/null +++ b/src/codechicken/nei/InventoryCraftingDummy.java @@ -0,0 +1,20 @@ +package codechicken.nei; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.InventoryCrafting; + +public class InventoryCraftingDummy extends InventoryCrafting +{ + public InventoryCraftingDummy() + { + super(new Container() + { + @Override + public boolean canInteractWith(EntityPlayer entityplayer) + { + return true; + } + }, 3, 3); + } +} diff --git a/src/codechicken/nei/ItemList.java b/src/codechicken/nei/ItemList.java new file mode 100644 index 00000000..138b0766 --- /dev/null +++ b/src/codechicken/nei/ItemList.java @@ -0,0 +1,370 @@ +package codechicken.nei; + +import codechicken.nei.ItemPanel.ItemPanelObject; +import codechicken.nei.api.ItemInfo; +import codechicken.nei.guihook.GuiContainerManager; +import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.ListMultimap; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IIcon; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; + +public class ItemList +{ + public static List items = new ArrayList(); + public static ListMultimap itemMap = ArrayListMultimap.create(); + + private static boolean matching = false; + private static boolean loading = false; + private static boolean research = false; + private static boolean reload = false; + private static HashSet erroredItems = new HashSet(); + + private static interface ItemMatcher + { + public boolean matches(ItemStack item); + } + + /*private static class SubsetItemMatcher implements ItemMatcher + { + final List tags; + + public SubsetItemMatcher(List tags) + { + this.tags = tags; + } + + @Override + public boolean matches(ItemStack item) + { + for(SubSetRangeTag tag : tags) + if(tag.isItemInRange(item.getItem(), item.getItemDamage())) + return true; + return false; + } + }*/ + + private static class PatternItemMatcher implements ItemMatcher + { + Pattern pattern; + + public PatternItemMatcher(Pattern pattern) { + this.pattern = pattern; + } + + @Override + public boolean matches(ItemStack item) { + return pattern.matcher(EnumChatFormatting.getTextWithoutFormattingCodes(GuiContainerManager.concatenatedDisplayName(item, true).toLowerCase())).find(); + } + } + + private static class EverythingItemMatcher implements ItemMatcher + { + @Override + public boolean matches(ItemStack item) { + return true; + } + } + + private static class NothingItemMatcher implements ItemMatcher + { + @Override + public boolean matches(ItemStack item) { + return false; + } + } + + public static ItemMatcher getSearchMatcher() { + String matchstring = NEIClientConfig.getSearchExpression().toLowerCase(); + /*if(matchstring.startsWith("@") && matchstring.length() > 1) + { + LinkedList tags = new LinkedList(); + try + { + String pattern = matchstring.substring(1); + for(SubSetRangeTag tag : DropDownFile.dropDownInstance.allTags()) + if(CommonUtils.filterText(tag.qualifiedname).toLowerCase().contains(pattern)) + tags.add(tag); + if(tags.isEmpty()) + return new NothingItemMatcher(); + + return new SubsetItemMatcher(tags); + } + catch(PatternSyntaxException e) + { + return new NothingItemMatcher(); + } + }*/ + + { + matchstring = matchstring.replace(".", ""); + matchstring = matchstring.replace("?", "."); + matchstring = matchstring.replace("*", ".+?"); + Pattern pattern = null; + try { + pattern = Pattern.compile(matchstring); + } catch (PatternSyntaxException ignored) {} + if (pattern == null || pattern.toString().equals("")) + return new EverythingItemMatcher(); + + return new PatternItemMatcher(pattern); + } + } + + public static boolean itemMatchesSearch(ItemStack item) { + return getSearchMatcher().matches(item); + } + + public static interface IItemCounter + { + public Item getItem(); + + public Thread getThread(); + } + + @SuppressWarnings("serial") + public static class TimeoutException extends RuntimeException + { + public final Item itemID; + + public TimeoutException(String msg, Item lastItem) { + super(msg); + itemID = lastItem; + } + } + + public static class ThreadLoadMonitor extends Thread + { + IItemCounter loadingThread; + + public ThreadLoadMonitor(IItemCounter handle) { + super("NEI Load Monitor"); + loadingThread = handle; + } + + @SuppressWarnings("deprecation") + @Override + public void run() { + if(true) return; + Item lastItem = null; + long lastTime = System.currentTimeMillis(); + while (loadingThread.getThread().isAlive()) { + if (lastItem != loadingThread.getItem()) { + lastTime = System.currentTimeMillis(); + lastItem = loadingThread.getItem(); + } else if (System.currentTimeMillis() - lastTime > 2000 && lastItem != null) { + loadingThread.getThread().stop(new TimeoutException("Took to long to advance item", lastItem)); + } + try { + Thread.sleep(2000); + } catch (InterruptedException ie) {} + } + } + } + + public static class ThreadMatchSearch extends Thread implements IItemCounter + { + private Item item; + + public ThreadMatchSearch() { + super("NEI Item Searching Thread"); + matching = true; + } + + @Override + public Item getItem() { + return item; + } + + @Override + public Thread getThread() { + return this; + } + + @Override + public void run() { + //new ThreadLoadMonitor(this).start(); + try { + startMatch: + while (matching) { + try { + ArrayList visibleitems = new ArrayList(); + ItemMatcher matcher = getSearchMatcher(); + for (ItemStack stack : items) { + item = stack.getItem(); + if (research) { + research = false; + continue startMatch; + } + + /*if(stack.hasTagCompound() ? NEIClientConfig.vishash.isItemHidden(item, stack.stackTagCompound) : NEIClientConfig.vishash.isItemHidden(item, stack.getItemDamage())) + continue;*/ + + if (NEIClientConfig.bannedBlocks.contains(stack)) + continue; + + if (matcher.matches(stack)) + visibleitems.add(new ItemPanelStack(stack)); + } + ItemPanel.visibleitems = visibleitems; + } catch (TimeoutException e) { + System.err.println("Removing itemID: " + e.itemID + " from list."); + e.printStackTrace(); + erroredItems.add(e.itemID); + loadItems(); + } + matching = false; + } + } + finally { + matching = false; + } + } + } + + private static HashSet stackTraces = new HashSet(); + + public static class ThreadLoadItems extends Thread implements IItemCounter + { + private Item item; + + public ThreadLoadItems() { + super("NEI Item Loading Thread"); + loading = true; + } + + @Override + public Item getItem() { + return item; + } + + @Override + public Thread getThread() { + return this; + } + + @Override + public void run() { + new ThreadLoadMonitor(this).start(); + startSearch: + while (loading) { + try { + ArrayList items = new ArrayList(); + ArrayList permutations = new ArrayList(); + ListMultimap itemMap = ArrayListMultimap.create(); + + for (Item item : (Iterable) Item.itemRegistry) { + this.item = item; + if (reload) { + reload = false; + continue startSearch; + } + + if (item == null || ItemInfo.isHidden(item)) + continue; + + permutations.clear(); + permutations.addAll(ItemInfo.getItemOverrides(item)); + if(permutations.isEmpty()) { + try { + item.getSubItems(item, null, permutations); + } catch (Exception e) { + System.err.println("Removing itemID: " + item + " from list."); + e.printStackTrace(); + erroredItems.add(item); + continue; + } + } + if(permutations.isEmpty()) { + HashSet damageIconSet = new HashSet(); + for (int damage = 0; damage < 16; damage++) { + ItemStack itemstack = new ItemStack(item, 1, damage); + try { + IIcon icon = item.getIconIndex(itemstack); + String name = GuiContainerManager.concatenatedDisplayName(itemstack, false); + String s = name + "@" + (icon == null ? 0 : icon.hashCode()); + if (!damageIconSet.contains(s)) { + damageIconSet.add(s); + permutations.add(itemstack); + } + + } catch (Throwable t) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw)); + String stackTrace = itemstack + sw.toString(); + if (!stackTraces.contains(stackTrace)) { + System.err.println("NEI: Omitting #" + this.item + ":" + damage + " " + item.getClass().getSimpleName()); + t.printStackTrace(); + stackTraces.add(stackTrace); + } + } + } + } + + for(Iterator it = permutations.iterator(); it.hasNext(); ) + if(ItemInfo.isHidden(it.next())) + it.remove(); + + items.addAll(permutations); + itemMap.putAll(item, permutations); + } + + item = null; + + /*DropDownFile dropDownInstance = DropDownFile.dropDownInstance; + dropDownInstance.resetHashes(); + for(ItemStack stack : items) + { + if(reload) + { + reload = false; + continue startSearch; + } + dropDownInstance.addItemIfInRange(stack.getItem(), stack.getItemDamage(), stack.stackTagCompound); + } + dropDownInstance.updateState();*/ + ItemList.items = items; + ItemList.itemMap = itemMap; + if (reload) { + reload = false; + continue; + } + loading = false; + } catch (TimeoutException e) { + System.err.println("Removing itemID: " + e.itemID + " from list."); + e.printStackTrace(); + erroredItems.add(e.itemID); + } + } + updateSearch(); + } + } + + public static boolean isMatching() { + return matching; + } + + public static void updateSearch() { + if (matching) + research = true; + else + new ThreadMatchSearch().start(); + } + + public static void loadItems() { + if (loading) + reload = true; + else + new ThreadLoadItems().start(); + } +} diff --git a/src/codechicken/nei/ItemMobSpawner.java b/src/codechicken/nei/ItemMobSpawner.java new file mode 100644 index 00000000..11301a34 --- /dev/null +++ b/src/codechicken/nei/ItemMobSpawner.java @@ -0,0 +1,139 @@ +package codechicken.nei; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityLiving; +import net.minecraft.entity.monster.IMob; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.item.ItemStack; +import net.minecraft.tileentity.TileEntityMobSpawner; +import net.minecraft.util.IIcon; +import net.minecraft.world.World; +import net.minecraftforge.client.MinecraftForgeClient; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ItemMobSpawner extends ItemBlock +{ + private static Map entityHashMap; + private static Map IDtoNameMap; + public static int idPig; + private static boolean loaded; + + public ItemMobSpawner(World world) { + super(Blocks.mob_spawner); + + hasSubtypes = true; + MinecraftForgeClient.registerItemRenderer(this, new SpawnerRenderer()); + + entityHashMap = new HashMap(); + IDtoNameMap = new HashMap(); + loadSpawners(world); + } + + /** + * These are ASM translated from BlockMobSpawner + */ + public static int placedX; + public static int placedY; + public static int placedZ; + + @Override + public IIcon getIconFromDamage(int par1) { + return Blocks.mob_spawner.getBlockTextureFromSide(0); + } + + public boolean onItemUse(ItemStack itemstack, EntityPlayer entityplayer, World world, int x, int y, int z, int par7, float par8, float par9, float par10) { + if (super.onItemUse(itemstack, entityplayer, world, x, y, z, par7, par8, par9, par10) && world.isRemote) { + TileEntityMobSpawner tileentitymobspawner = (TileEntityMobSpawner) world.getTileEntity(placedX, placedY, placedZ); + if (tileentitymobspawner != null) { + setDefaultTag(itemstack); + String mobtype = IDtoNameMap.get(itemstack.getItemDamage()); + if (mobtype != null) { + NEICPH.sendMobSpawnerID(placedX, placedY, placedZ, mobtype); + tileentitymobspawner.func_145881_a().setEntityName(mobtype); + } + } + return true; + } + return false; + } + + @Override + public void addInformation(ItemStack itemstack, EntityPlayer par2EntityPlayer, List list, boolean par4) { + setDefaultTag(itemstack); + int meta = itemstack.getItemDamage(); + if (meta == 0) { + meta = idPig; + } + Entity e = getEntity(meta); + if (e == null) return; + list.add("\u00A7" + (e instanceof IMob ? "4" : "3") + IDtoNameMap.get(meta)); + } + + public static EntityLiving getEntity(int ID) { + EntityLiving entityliving = entityHashMap.get(ID); + if (entityliving == null) { + World world = NEIClientUtils.mc().theWorld; + loadSpawners(world); + try { + Class class1 = (Class) EntityList.IDtoClassMapping.get(ID); + if (class1 != null && EntityLiving.class.isAssignableFrom(class1)) { + entityliving = (EntityLiving) class1.getConstructor(new Class[]{World.class}).newInstance(new Object[]{world}); + } + } catch (Throwable t) { + t.printStackTrace(); + } + entityHashMap.put(ID, entityliving); + } + return entityliving; + } + + private void setDefaultTag(ItemStack itemstack) { + if (!IDtoNameMap.containsKey(itemstack.getItemDamage())) + itemstack.setItemDamage(idPig); + } + + public static void loadSpawners(World world) { + if (loaded) return; + loaded = true; + try { + HashMap, String> classToStringMapping = (HashMap, String>) EntityList.classToStringMapping; + HashMap, Integer> classToIDMapping = (HashMap, Integer>) EntityList.classToIDMapping; + for (Class eclass : classToStringMapping.keySet()) { + if (!EntityLiving.class.isAssignableFrom(eclass)) + continue; + try { + EntityLiving entityliving = (EntityLiving) eclass.getConstructor(new Class[]{World.class}).newInstance(new Object[]{world}); + entityliving.isChild(); + + int id = classToIDMapping.get(eclass); + String name = classToStringMapping.get(eclass); + + if (name.equals("EnderDragon")) + continue; + + IDtoNameMap.put(id, name); + + if (name.equals("Pig")) + idPig = id; + } catch (Throwable t) { + } + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @Override + public void getSubItems(Item item, CreativeTabs tab, List list) { + for(int i : IDtoNameMap.keySet()) + list.add(new ItemStack(item, 1, i)); + } +} diff --git a/src/codechicken/nei/ItemPanel.java b/src/codechicken/nei/ItemPanel.java new file mode 100644 index 00000000..40644797 --- /dev/null +++ b/src/codechicken/nei/ItemPanel.java @@ -0,0 +1,381 @@ +package codechicken.nei; + +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.api.GuiInfo; +import codechicken.nei.api.INEIGuiHandler; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.GuiCraftingRecipe; +import codechicken.nei.recipe.GuiRecipe; +import codechicken.nei.recipe.GuiUsageRecipe; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +import java.util.ArrayList; +import java.util.List; + +import static codechicken.lib.gui.GuiDraw.drawRect; + +public class ItemPanel extends Widget +{ + public class ItemPanelSlot + { + public ItemPanelObject contents; + public int slotIndex; + + public ItemPanelSlot(int index) + { + contents = visibleitems.get(index); + slotIndex = index; + } + + public ItemStack getItemStack() + { + return contents instanceof ItemPanelStack ? ((ItemPanelStack)contents).item : null; + } + } + + public static interface ItemPanelObject + { + void draw(int x, int y); + List handleTooltip(List tooltip); + } + + public void resize() + { + marginLeft = x + (width % 18) / 2; + marginTop = y + (height % 18) / 2; + columns = width / 18; + rows = height / 18; + + calculatePage(); + updateValidSlots(); + } + + private void calculatePage() { + if(itemsPerPage == 0) + numPages = 0; + else + numPages = (int)Math.ceil((float)visibleitems.size() / (float)itemsPerPage); + + if(firstIndex >= visibleitems.size()) + firstIndex = 0; + + if(numPages == 0) + page = 0; + else + page = firstIndex/itemsPerPage+1; + } + + private void updateValidSlots() { + GuiContainer gui = NEIClientUtils.getGuiContainer(); + validSlotMap = new boolean[rows*columns]; + itemsPerPage = 0; + for(int i = 0; i < validSlotMap.length; i++) + if(slotValid(gui, i)) { + validSlotMap[i] = true; + itemsPerPage++; + } + } + + private boolean slotValid(GuiContainer gui, int i) { + Rectangle4i rect = getSlotRect(i); + for(INEIGuiHandler handler : GuiInfo.guiHandlers) + if(handler.hideItemPanelSlot(gui, rect.x, rect.y, rect.w, rect.h)) + return false; + return true; + } + + public Rectangle4i getSlotRect(int i) { + return getSlotRect(i/columns, i%columns); + } + + public Rectangle4i getSlotRect(int row, int column) { + return new Rectangle4i(marginLeft+column*18, marginTop+row*18, 18, 18); + } + + @Override + public void draw(int mousex, int mousey) + { + if(itemsPerPage == 0) + return; + + GuiContainerManager.enableMatrixStackLogging(); + int index = firstIndex; + for(int i = 0; i < rows*columns && index < visibleitems.size(); i++) { + if(validSlotMap[i]) { + Rectangle4i rect = getSlotRect(i); + if(rect.contains(mousex, mousey)) + drawRect(rect.x, rect.y, rect.w, rect.h, 0xee555555);//highlight + + visibleitems.get(index).draw(rect.x, rect.y); + + index++; + } + } + GuiContainerManager.disableMatrixStackLogging(); + } + + @Override + public void postDraw(int mousex, int mousey) + { + if(draggedStack != null) + { + GuiContainerManager.drawItems.zLevel += 100; + GuiContainerManager.drawItem(mousex - 8, mousey - 8, draggedStack); + GuiContainerManager.drawItems.zLevel -= 100; + } + } + + @Override + public void mouseDragged(int mousex, int mousey, int button, long heldTime) + { + if(mouseDownSlot >= 0 && draggedStack == null && NEIClientUtils.getHeldItem() == null) + { + ItemPanelSlot mouseOverSlot = getSlotMouseOver(mousex, mousey); + ItemStack stack = new ItemPanelSlot(mouseDownSlot).getItemStack(); + if(stack != null && (mouseOverSlot == null || mouseOverSlot.slotIndex != mouseDownSlot || heldTime > 500)) + { + int amount = NEIClientConfig.getItemQuantity(); + if(amount == 0) + amount = stack.getMaxStackSize(); + + draggedStack = NEIServerUtils.copyStack(stack, amount); + } + } + } + + @Override + public boolean handleClick(int mousex, int mousey, int button) + { + if(handleDraggedClick(mousex, mousey, button)) + return true; + + if(NEIClientUtils.getHeldItem() != null) + { + for(INEIGuiHandler handler : GuiInfo.guiHandlers) + if(handler.hideItemPanelSlot(NEIClientUtils.getGuiContainer(), mousex, mousey, 1, 1)) + return false; + + if(NEIClientConfig.canPerformAction("delete") && NEIClientConfig.canPerformAction("item")) + { + if(button == 1) + NEIClientUtils.decreaseSlotStack(-999); + else + NEIClientUtils.deleteHeldItem(); + } + else + { + NEIClientUtils.dropHeldItem(); + } + return true; + } + + ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); + if(hoverSlot != null) + { + if(button == 2) + { + ItemStack stack = hoverSlot.getItemStack(); + if(stack != null) + { + int amount = NEIClientConfig.getItemQuantity(); + if(amount == 0) + amount = stack.getMaxStackSize(); + + draggedStack = NEIServerUtils.copyStack(stack, amount); + } + } + else + { + mouseDownSlot = hoverSlot.slotIndex; + } + return true; + } + return false; + } + + private boolean handleDraggedClick(int mousex, int mousey, int button) + { + if(draggedStack == null) + return false; + + GuiContainer gui = NEIClientUtils.getGuiContainer(); + boolean handled = false; + for(INEIGuiHandler handler : GuiInfo.guiHandlers) + if(handler.handleDragNDrop(gui, mousex, mousey, draggedStack, button)) + { + handled = true; + if(draggedStack.stackSize == 0) + { + draggedStack = null; + return true; + } + } + + if(handled) + return true; + + Slot overSlot = gui.getSlotAtPosition(mousex, mousey); + if(overSlot != null && overSlot.isItemValid(draggedStack)) + { + if(NEIClientConfig.canPerformAction("item")) + { + int contents = overSlot.getHasStack() ? overSlot.getStack().stackSize : 0; + int add = button == 0 ? draggedStack.stackSize : 1; + if(overSlot.getHasStack() && !NEIServerUtils.areStacksSameType(draggedStack, overSlot.getStack())) + contents = 0; + int total = Math.min(contents+add, Math.min(overSlot.getSlotStackLimit(), draggedStack.getMaxStackSize())); + + if(total > contents) + { + NEIClientUtils.setSlotContents(overSlot.slotNumber, NEIServerUtils.copyStack(draggedStack, total), true); + NEICPH.sendGiveItem(NEIServerUtils.copyStack(draggedStack, total), false, false); + draggedStack.stackSize-=total-contents; + } + if(draggedStack.stackSize == 0) + draggedStack = null; + } + else + { + draggedStack = null; + } + } + else if(mousex < gui.guiLeft || mousey < gui.guiTop || mousex >= gui.guiLeft+gui.xSize || mousey >= gui.guiTop+gui.ySize) + { + draggedStack = null; + } + + return true; + } + + @Override + public boolean handleClickExt(int mousex, int mousey, int button) + { + return handleDraggedClick(mousex, mousey, button); + } + + @Override + public void mouseUp(int mousex, int mousey, int button) + { + ItemPanelSlot hoverSlot = getSlotMouseOver(mousex, mousey); + if(hoverSlot != null && hoverSlot.slotIndex == mouseDownSlot && hoverSlot.getItemStack() != null && draggedStack == null) + { + ItemStack item = hoverSlot.getItemStack(); + if(NEIController.manager.window instanceof GuiRecipe || !NEIClientConfig.canPerformAction("item")) + { + if(button == 0) + GuiCraftingRecipe.openRecipeGui("item", item); + else if(button == 1) + GuiUsageRecipe.openRecipeGui("item", item); + + draggedStack = null; + mouseDownSlot = -1; + return; + } + + NEIClientUtils.cheatItem(item, button, -1); + } + + mouseDownSlot = -1; + } + + @Override + public boolean onMouseWheel(int i, int mousex, int mousey) + { + if(!contains(mousex, mousey)) + return false; + + scroll(-i); + return true; + } + + @Override + public boolean handleKeyPress(int keyID, char keyChar) + { + if(keyID == NEIClientConfig.getKeyBinding("gui.next")) + { + scroll(1); + return true; + } + if(keyID == NEIClientConfig.getKeyBinding("gui.prev")) + { + scroll(-1); + return true; + } + return false; + } + + @Override + public ItemStack getStackMouseOver(int mousex, int mousey) + { + ItemPanelSlot slot = getSlotMouseOver(mousex, mousey); + return slot == null ? null : slot.getItemStack(); + } + + public ItemPanelSlot getSlotMouseOver(int mousex, int mousey) + { + int index = firstIndex; + for(int i = 0; i < rows*columns && index < visibleitems.size(); i++) + if(validSlotMap[i]) { + if(getSlotRect(i).contains(mousex, mousey)) + return new ItemPanelSlot(index); + index++; + } + + return null; + } + + @Override + public List handleTooltip(int mx, int my, List tooltip) + { + if(getSlotMouseOver(mx, my) == null) + return tooltip; + + return getSlotMouseOver(mx, my).contents.handleTooltip(tooltip); + } + + public void scroll(int i) + { + if(itemsPerPage != 0) { + int oldIndex = firstIndex; + firstIndex += i*itemsPerPage; + if(firstIndex >= visibleitems.size()) + firstIndex = 0; + if(firstIndex < 0) + if(oldIndex > 0) + firstIndex = 0; + else + firstIndex = (visibleitems.size()-1)/itemsPerPage*itemsPerPage; + + calculatePage(); + } + } + + public int getPage() + { + return page; + } + + public int getNumPages() + { + return numPages; + } + + public static ArrayList visibleitems = new ArrayList(); + + public ItemStack draggedStack; + public int mouseDownSlot = -1; + + private int marginLeft; + private int marginTop; + private int rows; + private int columns; + + private boolean[] validSlotMap; + private int firstIndex; + private int itemsPerPage; + + private int page; + private int numPages; +} diff --git a/src/codechicken/nei/ItemPanelStack.java b/src/codechicken/nei/ItemPanelStack.java new file mode 100644 index 00000000..408c02d7 --- /dev/null +++ b/src/codechicken/nei/ItemPanelStack.java @@ -0,0 +1,29 @@ +package codechicken.nei; + +import codechicken.nei.ItemPanel.ItemPanelObject; +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.item.ItemStack; + +import java.util.List; + +public class ItemPanelStack implements ItemPanelObject +{ + public ItemStack item; + + public ItemPanelStack(ItemStack itemstack) + { + item = itemstack; + } + + @Override + public void draw(int x, int y) + { + GuiContainerManager.drawItem(x+1, y+1, item); + } + + @Override + public List handleTooltip(List tooltip) + { + return tooltip; + } +} diff --git a/src/codechicken/nei/ItemQuantityField.java b/src/codechicken/nei/ItemQuantityField.java new file mode 100644 index 00000000..5bd8edbe --- /dev/null +++ b/src/codechicken/nei/ItemQuantityField.java @@ -0,0 +1,56 @@ +package codechicken.nei; + +public class ItemQuantityField extends TextField +{ + public ItemQuantityField(String ident) + { + super(ident); + centered = true; + } + + @Override + public boolean isValid(String string) + { + if(string.equals("")) + return true; + + try + { + return Integer.parseInt(string) >= 0; + } + catch(NumberFormatException nfe) + { + return false; + } + } + + public int intValue() + { + return intValue(text()); + } + + public int intValue(String s) + { + try + { + return Integer.parseInt(s); + } + catch(NumberFormatException nfe) + { + return 0; + } + } + + @Override + public void loseFocus() + { + setText(Integer.toString(NEIClientConfig.getItemQuantity())); + } + + @Override + public void onTextChange(String oldText) + { + if(intValue(oldText) != intValue())//hacky recursion stopper + NEIClientUtils.setItemQuantity(intValue()); + } +} diff --git a/src/codechicken/nei/ItemStackMap.java b/src/codechicken/nei/ItemStackMap.java new file mode 100644 index 00000000..6dd10b45 --- /dev/null +++ b/src/codechicken/nei/ItemStackMap.java @@ -0,0 +1,230 @@ +package codechicken.nei; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import java.util.*; + +import static codechicken.lib.inventory.InventoryUtils.actualDamage; +import static codechicken.lib.inventory.InventoryUtils.newItemStack; +import static net.minecraftforge.oredict.OreDictionary.WILDCARD_VALUE; + +/** + * A maplike class for ItemStack keys with wildcard damage/NBT. Optimised for lookup + */ +public class ItemStackMap +{ + public static class StackMetaKey + { + public int damage; + public NBTTagCompound tag; + + public StackMetaKey(int damage, NBTTagCompound tag) { + this.damage = damage; + this.tag = tag; + } + + public StackMetaKey(ItemStack key) { + this(actualDamage(key), key.stackTagCompound); + } + + public int hashCode() { + return damage*31+Objects.hashCode(tag); + } + + public boolean equals(Object o) { + if(!(o instanceof StackMetaKey)) + return false; + StackMetaKey t = (StackMetaKey)o; + return damage == t.damage && Objects.equals(tag, t.tag); + } + } + + public static class Entry + { + public ItemStack key; + public T value; + + public Entry(ItemStack key, T value) { + this.key = key; + this.value = value; + } + } + + public class DetailMap + { + public T wildcard; + public HashMap damageMap; + public HashMap tagMap; + public HashMap metaMap; + + public T get(ItemStack key) { + if(wildcard != null) + return wildcard; + + if(damageMap != null) { + T ret = damageMap.get(actualDamage(key)); + if(ret != null) return ret; + } + if(tagMap != null) { + T ret = tagMap.get(key.stackTagCompound); + if(ret != null) return ret; + } + if(metaMap != null) + return metaMap.get(new StackMetaKey(key)); + + return null; + } + + public void put(ItemStack key, T value) { + switch(getKeyType(actualDamage(key), key.stackTagCompound)) { + case 0: + if(metaMap == null) metaMap = new HashMap(); + metaMap.put(new StackMetaKey(key), value); + break; + case 1: + if(tagMap == null) tagMap = new HashMap(); + tagMap.put(key.stackTagCompound, value); + break; + case 2: + if(damageMap == null) damageMap = new HashMap(); + damageMap.put(actualDamage(key), value); + break; + case 3: + wildcard = value; + break; + } + } + + public T remove(ItemStack key) { + switch(getKeyType(actualDamage(key), key.stackTagCompound)) { + case 0: + return metaMap != null ? metaMap.remove(new StackMetaKey(key)) : null; + case 1: + return tagMap != null ? tagMap.remove(key.stackTagCompound) : null; + case 2: + return damageMap != null ? damageMap.remove(actualDamage(key)) : null; + case 3: + T ret = wildcard; + wildcard = null; + return ret; + } + return null; + } + + public void addKeys(Item item, List list) { + if(wildcard != null) + list.add(newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG)); + if(damageMap != null) + for(int damage : damageMap.keySet()) + list.add(newItemStack(item, 1, damage, WILDCARD_TAG)); + if(tagMap != null) + for(NBTTagCompound tag : tagMap.keySet()) + list.add(newItemStack(item, 1, WILDCARD_VALUE, tag)); + if(metaMap != null) + for(StackMetaKey key : metaMap.keySet()) + list.add(newItemStack(item, 1, key.damage, key.tag)); + } + + public void addValues(LinkedList list) { + if(wildcard != null) + list.add(wildcard); + if(damageMap != null) + list.addAll(damageMap.values()); + if(tagMap != null) + list.addAll(tagMap.values()); + if(metaMap != null) + list.addAll(metaMap.values()); + } + + public void addEntries(Item item, LinkedList> list) { + if(wildcard != null) + list.add(new Entry(newItemStack(item, 1, WILDCARD_VALUE, WILDCARD_TAG), wildcard)); + if(damageMap != null) + for(Map.Entry entry : damageMap.entrySet()) + list.add(new Entry(newItemStack(item, 1, entry.getKey(), WILDCARD_TAG), entry.getValue())); + if(tagMap != null) + for(Map.Entry entry : tagMap.entrySet()) + list.add(new Entry(newItemStack(item, 1, WILDCARD_VALUE, entry.getKey()), entry.getValue())); + if(metaMap != null) + for(Map.Entry entry : metaMap.entrySet()) + list.add(new Entry(newItemStack(item, 1, entry.getKey().damage, entry.getKey().tag), entry.getValue())); + } + } + + public static int getKeyType(int damage, NBTTagCompound tag) { + int i = 0; + if(isWildcard(damage)) i = 1; + if(isWildcard(tag)) i |= 2; + return i; + } + + public static boolean isWildcard(int damage) { + return damage == WILDCARD_VALUE; + } + + public static boolean isWildcard(NBTTagCompound tag) { + return tag != null && tag.getBoolean("*"); + } + + public static NBTTagCompound WILDCARD_TAG; + + static { + WILDCARD_TAG = new NBTTagCompound(); + WILDCARD_TAG.setBoolean("*", true); + } + + protected HashMap itemMap = new HashMap(); + + public T get(ItemStack key) { + if(key == null || key.getItem() == null) + return null; + + DetailMap map = itemMap.get(key.getItem()); + return map == null ? null : map.get(key); + } + + public void put(ItemStack key, T value) { + if(key == null || key.getItem() == null) + return; + + DetailMap map = itemMap.get(key.getItem()); + if(map == null) + itemMap.put(key.getItem(), map = new DetailMap()); + map.put(key, value); + } + + public void clear() { + itemMap.clear(); + } + + public T remove(ItemStack key) { + if (key == null || key.getItem() == null) + return null; + + DetailMap map = itemMap.get(key.getItem()); + return map == null ? null : map.remove(key); + } + + public List keys() { + LinkedList list = new LinkedList(); + for(Map.Entry entry : itemMap.entrySet()) + entry.getValue().addKeys(entry.getKey(), list); + return list; + } + + public List values() { + LinkedList list = new LinkedList(); + for(DetailMap map : itemMap.values()) + map.addValues(list); + return list; + } + + public List> entries() { + LinkedList> list = new LinkedList>(); + for(Map.Entry entry : itemMap.entrySet()) + entry.getValue().addEntries(entry.getKey(), list); + return list; + } +} diff --git a/src/codechicken/nei/ItemStackSet.java b/src/codechicken/nei/ItemStackSet.java new file mode 100644 index 00000000..04a517e7 --- /dev/null +++ b/src/codechicken/nei/ItemStackSet.java @@ -0,0 +1,35 @@ +package codechicken.nei; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.util.List; + +public class ItemStackSet +{ + ItemStackMap underlying = new ItemStackMap(); + + public void add(ItemStack item) { + underlying.put(item, new Object()); + } + + public boolean remove(ItemStack item) { + return underlying.remove(item) != null; + } + + public boolean contains(ItemStack item) { + return underlying.get(item) != null; + } + + public boolean containsAll(Item item) { + return underlying.itemMap.containsKey(item) && underlying.itemMap.get(item).wildcard != null; + } + + public List values() { + return underlying.keys(); + } + + public void clear() { + underlying.clear(); + } +} diff --git a/src/codechicken/nei/KeyManager.java b/src/codechicken/nei/KeyManager.java new file mode 100644 index 00000000..9e39fea6 --- /dev/null +++ b/src/codechicken/nei/KeyManager.java @@ -0,0 +1,52 @@ +package codechicken.nei; + +import org.lwjgl.input.Keyboard; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Map.Entry; + +/** + * Good old down/held/up keystate tracker + */ +public class KeyManager +{ + public static interface IKeyStateTracker + { + public void tickKeyStates(); + } + + public static class KeyState + { + public boolean down; + public boolean held; + public boolean up; + } + + public static HashMap keyStates = new HashMap(); + public static LinkedList trackers = new LinkedList(); + + public static void tickKeyStates() + { + for(Entry entry : keyStates.entrySet()) + { + int keyCode = NEIClientConfig.getKeyBinding(entry.getKey()); + boolean down = keyCode != 0 && Keyboard.isKeyDown(keyCode); + KeyState state = entry.getValue(); + if(down) + { + state.down = !state.held; + state.up = false; + } + else + { + state.up = state.held; + state.down = false; + } + state.held = down; + } + + for(IKeyStateTracker tracker : trackers) + tracker.tickKeyStates(); + } +} diff --git a/src/codechicken/nei/Label.java b/src/codechicken/nei/Label.java new file mode 100644 index 00000000..2ba5e6e4 --- /dev/null +++ b/src/codechicken/nei/Label.java @@ -0,0 +1,32 @@ +package codechicken.nei; + +import static codechicken.lib.gui.GuiDraw.drawString; +import static codechicken.lib.gui.GuiDraw.drawStringC; + +public class Label extends Widget +{ + boolean centered; + int colour; + String text; + + public Label(String s, boolean center, int color) + { + text = s; + centered = center; + colour = color; + } + + public Label(String s, boolean center) + { + this(s, center, 0xFFFFFFFF); + } + + @Override + public void draw(int mousex, int mousey) + { + if(centered) + drawStringC(text, x, y, colour); + else + drawString(text, x, y, colour); + } +} diff --git a/src/codechicken/nei/LangProxy.java b/src/codechicken/nei/LangProxy.java new file mode 100644 index 00000000..d7bb9036 --- /dev/null +++ b/src/codechicken/nei/LangProxy.java @@ -0,0 +1,19 @@ +package codechicken.nei; + +import net.minecraft.util.StatCollector; + +public class LangProxy +{ + public final String namespace; + + public LangProxy(String namespace) { + this.namespace = namespace+"."; + } + + public String translate(String key) { + return StatCollector.translateToLocal(namespace+key); + } + public String format(String key, Object... params) { + return StatCollector.translateToLocalFormatted(namespace+key, params); + } +} diff --git a/src/codechicken/nei/LayoutManager.java b/src/codechicken/nei/LayoutManager.java new file mode 100644 index 00000000..d400289f --- /dev/null +++ b/src/codechicken/nei/LayoutManager.java @@ -0,0 +1,811 @@ +package codechicken.nei; + +import codechicken.lib.gui.GuiDraw; +import codechicken.nei.KeyManager.IKeyStateTracker; +import codechicken.nei.api.*; +import codechicken.nei.guihook.*; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiContainerCreative; +import net.minecraft.client.renderer.InventoryEffectRenderer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import org.lwjgl.opengl.GL11; + +import java.util.HashMap; +import java.util.List; +import java.util.TreeSet; + +import static codechicken.lib.gui.GuiDraw.*; +import static codechicken.nei.NEIClientConfig.*; +import static codechicken.nei.NEIClientUtils.*; + +public class LayoutManager implements IContainerInputHandler, IContainerTooltipHandler, IContainerDrawHandler, IContainerObjectHandler, IKeyStateTracker +{ + private static LayoutManager instance; + + private static Widget inputFocused; + /** + * Sorted bottom first + */ + private static TreeSet drawWidgets; + /** + * Sorted top first + */ + private static TreeSet controlWidgets; + + public static ItemPanel itemPanel; + public static Button dropDown; + public static TextField searchField; + + public static Button options; + + public static Button prev; + public static Button next; + public static Label pageLabel; + public static Button more; + public static Button less; + public static ItemQuantityField quantity; + + public static SaveLoadButton[] stateButtons; + public static Button[] deleteButtons; + + public static Button delete; + public static ButtonCycled gamemode; + public static Button rain; + public static Button magnet; + public static Button[] timeButtons = new Button[4]; + public static Button heal; + + public static IRecipeOverlayRenderer overlayRenderer; + + public static HashMap layoutStyles = new HashMap(); + + public static void load() { + API.addLayoutStyle(0, new LayoutStyleMinecraft()); + API.addLayoutStyle(1, new LayoutStyleTMIOld()); + + instance = new LayoutManager(); + KeyManager.trackers.add(instance); + GuiContainerManager.addInputHandler(instance); + GuiContainerManager.addTooltipHandler(instance); + GuiContainerManager.addDrawHandler(instance); + GuiContainerManager.addObjectHandler(instance); + init(); + } + + @Override + public void onPreDraw(GuiContainer gui) { + if (!isHidden() && isEnabled() && gui instanceof InventoryEffectRenderer)//Reset the gui to the center of the screen, for potion effect offsets etc + { + gui.guiLeft = (gui.width - gui.xSize) / 2; + gui.guiTop = (gui.height - gui.ySize) / 2; + + if (gui instanceof GuiContainerCreative && gui.buttonList.size() >= 2) { + GuiButton button1 = (GuiButton) gui.buttonList.get(0); + GuiButton button2 = (GuiButton) gui.buttonList.get(1); + button1.xPosition = gui.guiLeft; + button2.xPosition = gui.guiLeft + gui.xSize - 20; + } + } + } + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + if (isHidden()) + return; + + for (Widget widget : controlWidgets) + widget.onGuiClick(mousex, mousey); + } + + @Override + public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + if (isHidden()) + return false; + + if (!isEnabled()) + return options.contains(mousex, mousey) && options.handleClick(mousex, mousey, button); + + for (Widget widget : controlWidgets) { + widget.onGuiClick(mousex, mousey); + if (widget.contains(mousex, mousey) ? widget.handleClick(mousex, mousey, button) : widget.handleClickExt(mousex, mousey, button)) + return true; + } + + return false; + } + + @Override + public boolean objectUnderMouse(GuiContainer gui, int mousex, int mousey) { + if (!isHidden() && isEnabled()) { + for (Widget widget : controlWidgets) + if (widget.contains(mousex, mousey)) + return true; + } + + return false; + } + + public boolean keyTyped(GuiContainer gui, char keyChar, int keyID) { + if (isEnabled() && !isHidden()) { + if (inputFocused != null) + return inputFocused.handleKeyPress(keyID, keyChar); + + for (Widget widget : controlWidgets) + if (widget.handleKeyPress(keyID, keyChar)) + return true; + } + + return false; + } + + @Override + public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) { + } + + @Override + public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) { + if (keyID == getKeyBinding("gui.hide")) { + toggleBooleanSetting("inventory.hidden"); + return true; + } + if (isEnabled() && !isHidden()) { + for (Widget widget : controlWidgets) + if (inputFocused == null) + widget.lastKeyTyped(keyID, keyChar); + } + return false; + } + + public void onMouseUp(GuiContainer gui, int mx, int my, int button) { + if (!isHidden() && isEnabled()) { + for (Widget widget : controlWidgets) + widget.mouseUp(mx, my, button); + } + } + + @Override + public void onMouseDragged(GuiContainer gui, int mx, int my, int button, long heldTime) { + if (!isHidden() && isEnabled()) { + for (Widget widget : controlWidgets) + widget.mouseDragged(mx, my, button, heldTime); + } + } + + @Override + public ItemStack getStackUnderMouse(GuiContainer gui, int mousex, int mousey) { + if (!isHidden() && isEnabled()) { + for (Widget widget : controlWidgets) { + ItemStack stack = widget.getStackMouseOver(mousex, mousey); + if (stack != null) + return stack; + } + } + return null; + } + + public void renderObjects(GuiContainer gui, int mousex, int mousey) { + if (!isHidden()) { + layout(gui); + if (isEnabled()) { + getLayoutStyle().drawBackground(GuiContainerManager.getManager(gui)); + for (Widget widget : drawWidgets) + widget.draw(mousex, mousey); + } else { + options.draw(mousex, mousey); + } + + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_DEPTH_TEST); + } + } + + @Override + public void postRenderObjects(GuiContainer gui, int mousex, int mousey) { + if (!isHidden() && isEnabled()) { + for (Widget widget : drawWidgets) + widget.postDraw(mousex, mousey); + } + } + + @Override + public List handleTooltip(GuiContainer gui, int mousex, int mousey, List currenttip) { + if (!isHidden() && isEnabled() && GuiContainerManager.shouldShowTooltip(gui)) { + for (Widget widget : controlWidgets) + currenttip = widget.handleTooltip(mousex, mousey, currenttip); + } + return currenttip; + } + + @Override + public List handleItemDisplayName(GuiContainer gui, ItemStack stack, List currenttip) { + String overridename = ItemInfo.getNameOverride(stack); + if (overridename != null) + currenttip.set(0, overridename); + + String mainname = currenttip.get(0); + if (showIDs()) { + mainname += " " + Item.getIdFromItem(stack.getItem()); + if (stack.getItemDamage() != 0) + mainname += ":" + stack.getItemDamage(); + + currenttip.set(0, mainname); + } + + return currenttip; + } + + @Override + public List handleItemTooltip(GuiContainer gui, ItemStack itemstack, int mousex, int mousey, List currenttip) { + return currenttip; + } + + public static void layout(GuiContainer gui) { + VisiblityData visiblity = new VisiblityData(); + if (isHidden()) + visiblity.showNEI = false; + if (gui.height - gui.ySize <= 40) + visiblity.showSearchSection = false; + if (gui.guiLeft - 4 < 76) + visiblity.showWidgets = false; + + for (INEIGuiHandler handler : GuiInfo.guiHandlers) + handler.modifyVisiblity(gui, visiblity); + + visiblity.translateDependancies(); + + getLayoutStyle().layout(gui, visiblity); + + updateWidgetVisiblities(gui, visiblity); + } + + private static void init() { + itemPanel = new ItemPanel(); + dropDown = new Button("NEI Subsets") + { + @Override + public boolean onButtonPress(boolean rightclick) { + return false; + } + }; + searchField = new SearchField("search"); + + options = new Button("Options") + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + getOptionList().showGui(getGuiContainer()); + return true; + } + return false; + } + + @Override + public String getRenderLabel() { + return translate("inventory.options"); + } + }; + prev = new Button("Prev") + { + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + LayoutManager.itemPanel.scroll(-1); + return true; + } + return false; + } + + @Override + public String getRenderLabel() { + return translate("inventory.prev"); + } + }; + next = new Button("Next") + { + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + LayoutManager.itemPanel.scroll(1); + return true; + } + return false; + } + + @Override + public String getRenderLabel() { + return translate("inventory.next"); + } + }; + pageLabel = new Label("(0/0)", true); + more = new Button("+") + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (rightclick) + return false; + + int modifier = controlKey() ? 64 : shiftKey() ? 10 : 1; + + int quantity = getItemQuantity() + modifier; + if (quantity < 0) + quantity = 0; + + setItemQuantity(quantity); + return true; + } + }; + less = new Button("-") + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (rightclick) + return false; + + int modifier = controlKey() ? -64 : shiftKey() ? -10 : -1; + + int quantity = getItemQuantity() + modifier; + if (quantity < 0) + quantity = 0; + + setItemQuantity(quantity); + return true; + } + }; + quantity = new ItemQuantityField("quantity"); + + stateButtons = new SaveLoadButton[7]; + deleteButtons = new Button[7]; + + for (int i = 0; i < 7; i++) { + final int savestate = i; + stateButtons[i] = new SaveLoadButton("") + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (isStateSaved(savestate)) + loadState(savestate); + else + saveState(savestate); + return true; + } + + @Override + public void onTextChange() { + NBTTagCompound statelist = global.nbt.getCompoundTag("statename"); + global.nbt.setTag("statename", statelist); + + statelist.setString("" + savestate, label); + global.saveNBT(); + } + }; + deleteButtons[i] = new Button("x") + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + clearState(savestate); + return true; + } + return false; + } + }; + } + + delete = new Button() + { + @Override + public boolean onButtonPress(boolean rightclick) { + if ((state & 0x3) == 2) + return false; + + ItemStack held = getHeldItem(); + if (held != null) { + if (shiftKey()) { + deleteHeldItem(); + deleteItemsOfType(held); + } else if (rightclick) + decreaseSlotStack(-999); + else + deleteHeldItem(); + } else if (shiftKey()) + deleteEverything(); + else + NEIController.toggleDeleteMode(); + + return true; + } + + public String getButtonTip() { + if ((state & 0x3) != 2) { + if (shiftKey()) + return translate("inventory.delete.all"); + if (NEIController.canUseDeleteMode()) + return getStateTip("delete", state); + } + return null; + } + + @Override + public void postDraw(int mousex, int mousey) { + if(contains(mousex, mousey) && getHeldItem() != null && (state & 0x3) != 2) + GuiDraw.drawTip(mousex + 9, mousey, translate("inventory.delete." + (shiftKey() ? "all" : "one"), GuiContainerManager.itemDisplayNameShort(getHeldItem()))); + } + }; + gamemode = new ButtonCycled() + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + cycleGamemode(); + return true; + } + return false; + } + + public String getButtonTip() { + return translate("inventory.gamemode." + getNextGamemode()); + } + }; + gamemode.icons = new Image[3]; + rain = new Button() + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (handleDisabledButtonPress("rain", rightclick)) + return true; + + if (!rightclick) { + toggleRaining(); + return true; + } + return false; + } + + public String getButtonTip() { + return getStateTip("rain", state); + } + }; + magnet = new Button() + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + toggleMagnetMode(); + return true; + } + return false; + } + + public String getButtonTip() { + return getStateTip("magnet", state); + } + }; + for (int i = 0; i < 4; i++) { + final int zone = i; + timeButtons[i] = new Button() + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (handleDisabledButtonPress(NEIActions.timeZones[zone], rightclick)) + return true; + + if (!rightclick) { + setHourForward(zone * 6); + return true; + } + return false; + } + + @Override + public String getButtonTip() { + return getTimeTip(NEIActions.timeZones[zone], state); + } + + }; + } + heal = new Button() + { + @Override + public boolean onButtonPress(boolean rightclick) { + if (!rightclick) { + healPlayer(); + return true; + } + return false; + } + + @Override + public String getButtonTip() { + return translate("inventory.heal"); + } + }; + + delete.state |= 0x4; + gamemode.state |= 0x4; + rain.state |= 0x4; + magnet.state |= 0x4; + } + + private static String getStateTip(String name, int state) { + String sfx = (state & 0x3) == 2 ? "enable" : + (state & 0x3) == 1 ? "0" : "1"; + + return translate("inventory." + name + "." + sfx); + } + + private static String getTimeTip(String name, int state) { + String sfx = (state & 0x3) == 2 ? "enable" : "set"; + return translate("inventory." + name + "." + sfx); + } + + private static boolean handleDisabledButtonPress(String ident, boolean rightclick) { + if (!NEIActions.canDisable.contains(ident)) + return false; + if (rightclick != disabledActions.contains(ident)) + return setPropertyDisabled(ident, rightclick); + return false; + } + + private static boolean setPropertyDisabled(String ident, boolean disable) { + if (disable && NEIActions.base(ident).equals("time")) { + int count = 0; + for (int i = 0; i < 4; i++) { + if (disabledActions.contains(NEIActions.timeZones[i])) + count++; + } + if (count == 3) + return false; + } + if (hasSMPCounterPart()) + NEICPH.sendSetPropertyDisabled(ident, disable); + + return true; + } + + @Override + public void load(GuiContainer gui) { + if (isEnabled()) { + setInputFocused(null); + + ItemList.loadItems(); + overlayRenderer = null; + + getLayoutStyle().init(); + layout(gui); + } + + NEIController.load(gui); + + if (checkCreativeInv(gui)) { + if (gui.mc.currentScreen instanceof GuiContainerCreative)//makes cycle transititions seemless. Only closes if we are opening from fresh + gui.mc.displayGuiScreen(null); + return; + } + } + + @Override + public void refresh(GuiContainer gui) { + } + + public boolean checkCreativeInv(GuiContainer gui) { + if (gui instanceof GuiContainerCreative && invCreativeMode()) { + NEICPH.sendCreativeInv(true); + return true; + } else if (gui instanceof GuiExtendedCreativeInv && !invCreativeMode()) { + NEICPH.sendCreativeInv(false); + return true; + } + return false; + } + + public static void updateWidgetVisiblities(GuiContainer gui, VisiblityData visiblity) { + drawWidgets = new TreeSet(new WidgetZOrder(false)); + controlWidgets = new TreeSet(new WidgetZOrder(true)); + + if (!visiblity.showNEI) + return; + + addWidget(options); + if (visiblity.showItemPanel) { + addWidget(itemPanel); + addWidget(prev); + addWidget(next); + addWidget(pageLabel); + if (canPerformAction("item")) { + addWidget(more); + addWidget(less); + addWidget(quantity); + } + } + + if (visiblity.showSearchSection) { + addWidget(dropDown); + addWidget(searchField); + } + + if (canPerformAction("item") && visiblity.showStateButtons) { + for (int i = 0; i < 7; i++) { + addWidget(stateButtons[i]); + if (isStateSaved(i)) + addWidget(deleteButtons[i]); + } + } + if (visiblity.showUtilityButtons) { + if (canPerformAction("time")) { + for (int i = 0; i < 4; i++) + addWidget(timeButtons[i]); + } + if (canPerformAction("rain")) + addWidget(rain); + if (canPerformAction("heal")) + addWidget(heal); + if (canPerformAction("magnet")) + addWidget(magnet); + if (isValidGamemode("creative") || + isValidGamemode("creative+") || + isValidGamemode("adventure")) + addWidget(gamemode); + if (canPerformAction("delete")) + addWidget(delete); + } + } + + + public static LayoutStyle getLayoutStyle(int id) { + LayoutStyle style = layoutStyles.get(id); + if (style == null) + style = layoutStyles.get(0); + return style; + } + + public static LayoutStyle getLayoutStyle() { + return getLayoutStyle(NEIClientConfig.getLayoutStyle()); + } + + private static void addWidget(Widget widget) { + drawWidgets.add(widget); + controlWidgets.add(widget); + } + + @Override + public void guiTick(GuiContainer gui) { + if (checkCreativeInv(gui)) + return; + + if (!isEnabled()) + return; + + for (Widget widget : controlWidgets) + widget.update(); + } + + @Override + public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + if (isHidden() || !isEnabled()) + return false; + + for (Widget widget : controlWidgets) + if (widget.onMouseWheel(scrolled, mousex, mousey)) + return true; + + return false; + } + + @Override + public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + } + + @Override + public boolean shouldShowTooltip(GuiContainer gui) { + return itemPanel.draggedStack == null; + } + + public static Widget getInputFocused() { + return inputFocused; + } + + public static void setInputFocused(Widget widget) { + if (inputFocused != null) + inputFocused.loseFocus(); + + inputFocused = widget; + if (inputFocused != null) + inputFocused.gainFocus(); + } + + @Override + public void renderSlotUnderlay(GuiContainer gui, Slot slot) { + if (overlayRenderer != null) + overlayRenderer.renderOverlay(GuiContainerManager.getManager(gui), slot); + } + + @Override + public void renderSlotOverlay(GuiContainer window, Slot slot) { + ItemStack item = slot.getStack(); + if (world.nbt.getBoolean("searchinventories") && (item == null ? !getSearchExpression().equals("") : !ItemList.itemMatchesSearch(item))) { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glTranslatef(0, 0, 150); + drawRect(slot.xDisplayPosition, slot.yDisplayPosition, 16, 16, 0x80000000); + GL11.glTranslatef(0, 0, -150); + GL11.glEnable(GL11.GL_LIGHTING); + } + } + + public static void drawIcon(int x, int y, Image image) { + changeTexture("nei:textures/nei_sprites.png"); + GL11.glColor4f(1, 1, 1, 1); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + drawTexturedModalRect(x, y, image.x, image.y, image.width, image.height); + GL11.glDisable(GL11.GL_BLEND); + } + + public static void drawButtonBackground(int x, int y, int w, int h, boolean edges, int type) { + int wtiles = 0; + int ew = w;//end width + if (w / 2 > 100) { + wtiles = (w - 200) / 50 + 1; + ew = 200; + } + + int w1 = ew / 2; + int h1 = h / 2; + int w2 = (ew + 1) / 2; + int h2 = (h + 1) / 2; + + int x2 = x + w - w2; + int y2 = y + h - h2; + + int ty = 46 + type * 20; + int te = (edges ? 0 : 1);//tex edges + + int ty1 = ty + te; + int tx1 = te; + int tx3 = 75; + //halfway the 1 is for odd number adjustment + int ty2 = ty + 20 - h2 - te; + int tx2 = 200 - w2 - te; + + changeTexture("textures/gui/widgets.png"); + drawTexturedModalRect(x, y, tx1, ty1, w1, h1);//top left + drawTexturedModalRect(x, y2, tx1, ty2, w1, h2);//bottom left + + for (int tile = 0; tile < wtiles; tile++) { + int tilex = x + w1 + 50 * tile; + drawTexturedModalRect(tilex, y, tx3, ty1, 50, h1);//top + drawTexturedModalRect(tilex, y2, tx3, ty2, 50, h2);//bottom + } + + drawTexturedModalRect(x2, y, tx2, ty1, w2, h1);//top right + drawTexturedModalRect(x2, y2, tx2, ty2, w2, h2);//bottom right + } + + public static LayoutManager instance() { + return instance; + } + + @Override + public void tickKeyStates() { + if (Minecraft.getMinecraft().currentScreen != null) + return; + + if (KeyManager.keyStates.get("world.dawn").down) + timeButtons[0].onButtonPress(false); + if (KeyManager.keyStates.get("world.noon").down) + timeButtons[1].onButtonPress(false); + if (KeyManager.keyStates.get("world.dusk").down) + timeButtons[2].onButtonPress(false); + if (KeyManager.keyStates.get("world.midnight").down) + timeButtons[3].onButtonPress(false); + if (KeyManager.keyStates.get("world.rain").down) + rain.onButtonPress(false); + if (KeyManager.keyStates.get("world.heal").down) + heal.onButtonPress(false); + if (KeyManager.keyStates.get("world.creative").down) + gamemode.onButtonPress(false); + } +} diff --git a/src/codechicken/nei/LayoutStyleDefault.java b/src/codechicken/nei/LayoutStyleDefault.java new file mode 100644 index 00000000..9fa995f1 --- /dev/null +++ b/src/codechicken/nei/LayoutStyleDefault.java @@ -0,0 +1,153 @@ +package codechicken.nei; + +import codechicken.nei.api.LayoutStyle; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.nbt.NBTTagCompound; + +import static codechicken.lib.gui.GuiDraw.getStringWidth; +import static codechicken.nei.LayoutManager.*; +import static codechicken.nei.NEIClientConfig.*; + +public abstract class LayoutStyleDefault extends LayoutStyle +{ + @Override + public void layout(GuiContainer gui, VisiblityData visiblity) { + int windowWidth = gui.width; + int windowHeight = gui.height; + int containerWidth = gui.xSize; + int containerLeft = gui.guiLeft; + + reset(); + + prev.y = 2; + prev.height = 16; + prev.width = containerLeft / 3; + prev.x = (containerWidth + windowWidth) / 2 + 2; + next.x = windowWidth - prev.width - 2; + + next.y = prev.y; + next.width = prev.width; + next.height = prev.height; + pageLabel.x = containerLeft * 3 / 2 + containerWidth + 1; + pageLabel.y = prev.y + 5; + pageLabel.text = "(" + itemPanel.getPage() + "/" + itemPanel.getNumPages() + ")"; + + itemPanel.y = prev.height + prev.y; + itemPanel.x = (containerWidth + windowWidth) / 2 + 3; + itemPanel.width = windowWidth - 3 - itemPanel.x; + itemPanel.height = windowHeight - 15 - itemPanel.y; + if (!canPerformAction("item")) + itemPanel.height += 15; + itemPanel.resize(); + + more.width = more.height = less.width = less.height = 16; + less.x = prev.x; + more.x = windowWidth - less.width - 2; + more.y = less.y = windowHeight - more.height - 2; + + quantity.x = less.x + less.width + 2; + quantity.y = less.y; + quantity.width = more.x - quantity.x - 2; + quantity.height = less.height; + + options.x = isEnabled() ? 0 : 6; + options.y = isEnabled() ? windowHeight - 22 : windowHeight - 28; + options.width = 80; + options.height = 22; + + delete.state = 0x4; + if (NEIController.getDeleteMode()) + delete.state |= 1; + else if (!visiblity.enableDeleteMode) + delete.state |= 2; + + rain.state = 0x4; + if (disabledActions.contains("rain")) + rain.state |= 2; + else if (NEIClientUtils.isRaining()) + rain.state |= 1; + + gamemode.state = 0x4; + if (NEIClientUtils.getGamemode() != 0) { + gamemode.state |= 0x1; + gamemode.index = NEIClientUtils.getGamemode() - 1; + } else { + if (NEIClientUtils.isValidGamemode("creative")) + gamemode.index = 0; + else if (NEIClientUtils.isValidGamemode("creative+")) + gamemode.index = 1; + else if (NEIClientUtils.isValidGamemode("adventure")) + gamemode.index = 2; + } + + magnet.state = 0x4 | (getMagnetMode() ? 1 : 0); + + if (canPerformAction("delete")) + layoutButton(delete); + if (canPerformAction("rain")) + layoutButton(rain); + if (NEIClientUtils.isValidGamemode("creative") || + NEIClientUtils.isValidGamemode("creative+") || + NEIClientUtils.isValidGamemode("adventure")) + layoutButton(gamemode); + if (canPerformAction("magnet")) + layoutButton(magnet); + if (canPerformAction("time")) { + for (int i = 0; i < 4; i++) { + timeButtons[i].state = disabledActions.contains(NEIActions.timeZones[i]) ? 2 : 0; + layoutButton(timeButtons[i]); + } + } + if (canPerformAction("heal")) + layoutButton(heal); + + searchField.y = windowHeight - searchField.height - 2; + + dropDown.height = 20; + dropDown.width = prev.x - dropDown.x - 3; + searchField.height = 20; + searchField.width = 150; + searchField.x = (windowWidth - searchField.width) / 2; + + if (!visiblity.showItemSection) { + //TODO dropDown.setDropDown(0); + searchField.setFocus(false); + } + + int maxWidth = 0; + for (int i = 0; i < 7; i++) { + deleteButtons[i].width = 16; + deleteButtons[i].height = 16; + + NBTTagCompound statelist = global.nbt.getCompoundTag("statename"); + global.nbt.setTag("statename", statelist); + String name = statelist.getString("" + i); + if (statelist.getTag("" + i) == null) { + name = "" + (i + 1); + statelist.setString("" + i, name); + } + stateButtons[i].label = name; + stateButtons[i].saved = isStateSaved(i); + + int width = getStringWidth(stateButtons[i].getRenderLabel()) + 26; + if (width + 22 > containerLeft) + width = containerLeft - 22; + + if (width > maxWidth) + maxWidth = width; + } + + for (int i = 0; i < 7; i++) { + stateButtons[i].x = 0; + stateButtons[i].y = 58 + i * 22; + stateButtons[i].height = 20; + + stateButtons[i].x = 0; + stateButtons[i].width = maxWidth; + deleteButtons[i].x = stateButtons[i].width + 3; + deleteButtons[i].y = stateButtons[i].y + 2; + } + } + + public abstract void layoutButton(Button button); +} diff --git a/src/codechicken/nei/LayoutStyleMinecraft.java b/src/codechicken/nei/LayoutStyleMinecraft.java new file mode 100644 index 00000000..22eb5625 --- /dev/null +++ b/src/codechicken/nei/LayoutStyleMinecraft.java @@ -0,0 +1,89 @@ +package codechicken.nei; + +import org.lwjgl.opengl.GL11; + +import static codechicken.lib.gui.GuiDraw.drawStringC; +import static codechicken.nei.LayoutManager.*; + +public class LayoutStyleMinecraft extends LayoutStyleDefault +{ + int stateButtonCount; + int clickButtonCount; + + @Override + public String getName() { + return "minecraft"; + } + + @Override + public void init() { + delete.icon = new Image(144, 12, 12, 12); + gamemode.icons[0] = new Image(132, 12, 12, 12); + gamemode.icons[1] = new Image(156, 12, 12, 12); + gamemode.icons[2] = new Image(168, 12, 12, 12); + rain.icon = new Image(120, 12, 12, 12); + magnet.icon = new Image(180, 24, 12, 12); + timeButtons[0].icon = new Image(132, 24, 12, 12); + timeButtons[1].icon = new Image(120, 24, 12, 12); + timeButtons[2].icon = new Image(144, 24, 12, 12); + timeButtons[3].icon = new Image(156, 24, 12, 12); + heal.icon = new Image(168, 24, 12, 12); + dropDown.x = 90; + } + + @Override + public void reset() { + stateButtonCount = clickButtonCount = 0; + } + + @Override + public void layoutButton(Button button) { + if ((button.state & 0x4) != 0) { + button.x = 6 + stateButtonCount * 20; + button.y = 3; + stateButtonCount++; + } else { + button.x = 6 + (clickButtonCount % 4) * 20; + button.y = 3 + (1 + clickButtonCount / 4) * 18; + clickButtonCount++; + } + + button.height = 17; + button.width = button.contentWidth() + 6; + } + + @Override + public void drawButton(Button b, int mousex, int mousey) { + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glColor4f(1, 1, 1, 1); + + int tex; + if ((b.state & 0x3) == 2) + tex = 0; + else if ((b.state & 0x4) == 0 && b.contains(mousex, mousey) ||//not a state button and mouseover + (b.state & 0x3) == 1)//state active + tex = 2; + else + tex = 1; + LayoutManager.drawButtonBackground(b.x, b.y, b.width, b.height, true, tex); + + Image icon = b.getRenderIcon(); + if (icon == null) { + int colour = tex == 2 ? 0xffffa0 : + tex == 0 ? 0x601010 : 0xe0e0e0; + + drawStringC(b.getRenderLabel(), b.x + b.width / 2, b.y + (b.height - 8) / 2, colour); + } else { + GL11.glColor4f(1, 1, 1, 1); + + int iconx = b.x + (b.width - icon.width) / 2; + int icony = b.y + (b.height - icon.height) / 2; + LayoutManager.drawIcon(iconx, icony, icon); + } + } + + @Override + public boolean texturedButtons() { + return true; + } +} diff --git a/src/codechicken/nei/LayoutStyleTMIOld.java b/src/codechicken/nei/LayoutStyleTMIOld.java new file mode 100644 index 00000000..3b748a8e --- /dev/null +++ b/src/codechicken/nei/LayoutStyleTMIOld.java @@ -0,0 +1,127 @@ +package codechicken.nei; + +import codechicken.nei.guihook.GuiContainerManager; + +import static codechicken.lib.gui.GuiDraw.drawRect; +import static codechicken.lib.gui.GuiDraw.drawString; +import static codechicken.nei.LayoutManager.*; + +public class LayoutStyleTMIOld extends LayoutStyleDefault +{ + public static final Image stateOff = new Image(48, 0, 8, 12); + public static final Image stateOn = new Image(56, 0, 8, 12); + public static final Image stateDisabled = new Image(64, 0, 8, 12); + + int stateButtonCount; + int clickButtonCount; + + @Override + public String getName() + { + return "oldtmi"; + } + + @Override + public void init() + { + delete.icon = new Image(24, 12, 12, 12); + gamemode.icons[0] = new Image(12, 12, 12, 12); + gamemode.icons[1] = new Image(36, 12, 12, 12); + gamemode.icons[2] = new Image(48, 12, 12, 12); + rain.icon = new Image(0, 12, 12, 12); + magnet.icon = new Image(60, 24, 12, 12); + timeButtons[0].icon = new Image(12, 24, 12, 12); + timeButtons[1].icon = new Image(0, 24, 12, 12); + timeButtons[2].icon = new Image(24, 24, 12, 12); + timeButtons[3].icon = new Image(36, 24, 12, 12); + heal.icon = new Image(48, 24, 12, 12); + dropDown.x = 93; + } + + @Override + public void reset() + { + stateButtonCount = clickButtonCount = 0; + } + + @Override + public void layoutButton(Button button) + { + int offsetx = 2; + int offsety = 2; + + if((button.state & 0x4) != 0) + { + button.x = offsetx + stateButtonCount*22; + button.y = offsety; + stateButtonCount++; + } + else + { + button.x = offsetx + (clickButtonCount%4)*22; + button.y = offsety + (1+clickButtonCount/4)*17; + clickButtonCount++; + } + + button.height = 14; + button.width = button.contentWidth() + 2; + if((button.state & 0x4) != 0) + button.width += stateOff.width; + } + + @Override + public void drawBackground(GuiContainerManager gui) + { + if(clickButtonCount == 0 && stateButtonCount == 0) + return; + + int maxx = Math.max(stateButtonCount, clickButtonCount); + if(maxx > 4)maxx = 4; + int maxy = clickButtonCount == 0 ? 1 : (clickButtonCount / 4 + 2); + + drawRect(0, 0, 2+22*maxx, 1+maxy*17, 0xFF000000); + } + + @Override + public void drawButton(Button b, int mousex, int mousey) + { + int cwidth = b.contentWidth(); + if((b.state & 0x4) != 0) + cwidth += stateOff.width; + int textx = b.x + (b.width - cwidth) / 2; + int texty = b.y + (b.height - 8) / 2; + + drawRect(b.x, b.y, b.width, b.height, b.contains(mousex, mousey) ? 0xee401008 : 0xee000000); + + Image icon = b.getRenderIcon(); + if(icon == null) + { + drawString(b.getRenderLabel(), textx, texty, -1); + } + else + { + int icony = b.y + (b.height - icon.height) / 2; + LayoutManager.drawIcon(textx, icony, icon); + if((b.state & 0x3) == 2) + drawRect(textx, icony, icon.width, icon.height, 0x80000000); + + if((b.state & 0x4) != 0) + { + Image stateimage; + if((b.state & 0x3) == 1) + stateimage = stateOn; + else if((b.state & 0x3) == 2) + stateimage = stateDisabled; + else + stateimage = stateOff; + LayoutManager.drawIcon(textx+icon.width, icony, stateimage); + } + } + } + + @Override + public boolean texturedButtons() + { + return false; + } +} diff --git a/src/codechicken/nei/NEIActions.java b/src/codechicken/nei/NEIActions.java new file mode 100644 index 00000000..76371ce4 --- /dev/null +++ b/src/codechicken/nei/NEIActions.java @@ -0,0 +1,95 @@ +package codechicken.nei; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; + +public class NEIActions +{ + public static final int protocol = 0; + + public static HashMap nameActionMap = new HashMap(); + public static HashSet canDisable = new HashSet(); + + public static void addAction(String name, String base, boolean smpreq) + { + NEIActions action = new NEIActions(name, base, smpreq); + nameActionMap.put(name, action); + } + + private static void addAction(String name, String base) + { + addAction(name, base, false); + } + + public static void addAction(String name) + { + addAction(name, name); + } + + private static void addAction(String name, boolean smpreq) + { + addAction(name, name, smpreq); + } + + public static String base(String name) + { + NEIActions action = nameActionMap.get(name); + return action == null ? name : action.base; + } + + public static boolean smpRequired(String name) + { + return nameActionMap.get(name).smpreq; + } + + public static void init() + { + addAction("time"); + addAction("dawn", "time"); + addAction("noon", "time"); + addAction("dusk", "time"); + addAction("midnight", "time"); + addAction("creative"); + addAction("creative+", true); + addAction("adventure", "creative"); + addAction("rain"); + addAction("item"); + addAction("heal"); + addAction("delete", true); + addAction("magnet", true); + addAction("enchant", true); + addAction("potion", true); + addAction("itemnbt", "item", true); + + canDisable.add("dawn"); + canDisable.add("noon"); + canDisable.add("dusk"); + canDisable.add("midnight"); + canDisable.add("rain"); + } + + public static final String[] timeZones = new String[]{"dawn", "noon", "dusk", "midnight"}; + public static final String[] gameModes = new String[]{"survival", "creative", "creative+", "adventure"}; + + public String name; + public String base; + public boolean smpreq; + + public NEIActions(String name, String base, boolean smpreq) + { + this.name = name; + this.base = base; + this.smpreq = smpreq; + } + + public static List baseActions() + { + List list = new LinkedList(); + for(NEIActions a : nameActionMap.values()) + if(a.base.equals(a.name)) + list.add(a.name); + return list; + } +} diff --git a/src/codechicken/nei/NEICPH.java b/src/codechicken/nei/NEICPH.java new file mode 100644 index 00000000..f16cc8a1 --- /dev/null +++ b/src/codechicken/nei/NEICPH.java @@ -0,0 +1,249 @@ +package codechicken.nei; + +import codechicken.core.ClientUtils; +import codechicken.lib.inventory.InventoryUtils; +import codechicken.lib.packet.PacketCustom; +import codechicken.lib.packet.PacketCustom.IClientPacketHandler; +import cpw.mods.fml.relauncher.Side; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.world.World; + +public class NEICPH implements IClientPacketHandler +{ + public static final String channel = "NEI"; + + @Override + public void handlePacket(PacketCustom packet, Minecraft mc, INetHandlerPlayClient netHandler) { + switch (packet.getType()) { + case 1: + handleSMPCheck(packet.readUByte(), packet.readString(), mc.theWorld); + break; + case 10: + handleLoginState(packet); + break; + case 11: + handleActionDisabled(packet); + break; + case 12: + handleActionEnabled(packet); + break; + case 13: + ClientHandler.instance().addSMPMagneticItem(packet.readInt(), mc.theWorld); + break; + case 14: + handleGamemode(mc, packet.readUByte()); + break; + case 21: + ClientUtils.openSMPGui(packet.readUByte(), new GuiEnchantmentModifier(mc.thePlayer.inventory, mc.theWorld, 0, 0, 0)); + break; + case 23: + if (packet.readBoolean()) + ClientUtils.openSMPGui(packet.readUByte(), new GuiExtendedCreativeInv(new ContainerCreativeInv(mc.thePlayer, new ExtendedCreativeInv(null, Side.CLIENT)))); + else + mc.displayGuiScreen(new GuiInventory(mc.thePlayer)); + break; + case 24: + ClientUtils.openSMPGui(packet.readUByte(), new GuiPotionCreator(mc.thePlayer.inventory)); + break; + } + } + + private void handleGamemode(Minecraft mc, int mode) { + mc.playerController.setGameType(NEIServerUtils.getGameType(mode)); + } + + private void handleActionEnabled(PacketCustom packet) { + String name = packet.readString(); + if (packet.readBoolean()) + NEIClientConfig.enabledActions.add(name); + else + NEIClientConfig.enabledActions.remove(name); + } + + private void handleActionDisabled(PacketCustom packet) { + String name = packet.readString(); + if (packet.readBoolean()) + NEIClientConfig.disabledActions.add(name); + else + NEIClientConfig.disabledActions.remove(name); + } + + private void handleLoginState(PacketCustom packet) { + NEIClientConfig.permissableActions.clear(); + int num = packet.readUByte(); + for (int i = 0; i < num; i++) + NEIClientConfig.permissableActions.add(packet.readString()); + + NEIClientConfig.disabledActions.clear(); + num = packet.readUByte(); + for (int i = 0; i < num; i++) + NEIClientConfig.disabledActions.add(packet.readString()); + + NEIClientConfig.enabledActions.clear(); + num = packet.readUByte(); + for (int i = 0; i < num; i++) + NEIClientConfig.enabledActions.add(packet.readString()); + + NEIClientConfig.bannedBlocks.clear(); + num = packet.readInt(); + for(int i = 0; i < num; i++) + NEIClientConfig.bannedBlocks.add(packet.readItemStack()); + + if (NEIClientUtils.getGuiContainer() != null) + LayoutManager.instance().refresh(NEIClientUtils.getGuiContainer()); + } + + private void handleSMPCheck(int serverprotocol, String worldName, World world) { + if (serverprotocol > NEIActions.protocol) { + NEIClientUtils.printChatMessage(new ChatComponentTranslation("nei.chat.mismatch.client")); + } else if (serverprotocol < NEIActions.protocol) { + NEIClientUtils.printChatMessage(new ChatComponentTranslation("nei.chat.mismatch.server")); + } else { + try { + ClientHandler.instance().loadWorld(world, true); + NEIClientConfig.loadWorld(getSaveName(worldName)); + NEIClientConfig.setHasSMPCounterPart(true); + sendRequestLoginInfo(); + } catch (Exception nce) { + nce.printStackTrace(); + } + } + } + + private static String getSaveName(String worldName) { + if (Minecraft.getMinecraft().isSingleplayer()) + return "local/" + ClientUtils.getWorldSaveName(); + + return "remote/" + ClientUtils.getServerIP().replace(':', '~') + "/" + worldName; + } + + public static void sendGiveItem(ItemStack spawnstack, boolean infinite, boolean doSpawn) { + PacketCustom packet = new PacketCustom(channel, 1); + packet.writeItemStack(spawnstack, true); + packet.writeBoolean(infinite); + packet.writeBoolean(doSpawn); + packet.sendToServer(); + } + + public static void sendDeleteAllItems() { + PacketCustom packet = new PacketCustom(channel, 4); + packet.sendToServer(); + } + + public static void sendStateLoad(ItemStack[] state) { + sendDeleteAllItems(); + for (int slot = 0; slot < state.length; slot++) { + ItemStack item = state[slot]; + if (item == null) { + continue; + } + sendSetSlot(slot, item, false); + } + + PacketCustom packet = new PacketCustom(channel, 11); + packet.sendToServer(); + } + + public static void sendSetSlot(int slot, ItemStack stack, boolean container) { + PacketCustom packet = new PacketCustom(channel, 5); + packet.writeBoolean(container); + packet.writeShort(slot); + packet.writeItemStack(stack); + packet.sendToServer(); + } + + private static void sendRequestLoginInfo() { + PacketCustom packet = new PacketCustom(channel, 10); + packet.sendToServer(); + } + + public static void sendToggleMagnetMode() { + PacketCustom packet = new PacketCustom(channel, 6); + packet.sendToServer(); + } + + public static void sendSetTime(int hour) { + PacketCustom packet = new PacketCustom(channel, 7); + packet.writeByte(hour); + packet.sendToServer(); + } + + public static void sendHeal() { + PacketCustom packet = new PacketCustom(channel, 8); + packet.sendToServer(); + } + + public static void sendToggleRain() { + PacketCustom packet = new PacketCustom(channel, 9); + packet.sendToServer(); + } + + public static void sendOpenEnchantmentWindow() { + PacketCustom packet = new PacketCustom(channel, 21); + packet.sendToServer(); + } + + public static void sendModifyEnchantment(int enchID, int level, boolean add) { + PacketCustom packet = new PacketCustom(channel, 22); + packet.writeByte(enchID); + packet.writeByte(level); + packet.writeBoolean(add); + packet.sendToServer(); + } + + public static void sendSetPropertyDisabled(String name, boolean enable) { + PacketCustom packet = new PacketCustom(channel, 12); + packet.writeString(name); + packet.writeBoolean(enable); + packet.sendToServer(); + } + + public static void sendGamemode(int mode) { + new PacketCustom(channel, 13) + .writeByte(mode) + .sendToServer(); + } + + public static void sendCreativeInv(boolean open) { + PacketCustom packet = new PacketCustom(channel, 23); + packet.writeBoolean(open); + packet.sendToServer(); + } + + public static void sendCreativeScroll(int steps) { + PacketCustom packet = new PacketCustom(channel, 14); + packet.writeInt(steps); + packet.sendToServer(); + } + + public static void sendMobSpawnerID(int x, int y, int z, String mobtype) { + PacketCustom packet = new PacketCustom(channel, 15); + packet.writeCoord(x, y, z); + packet.writeString(mobtype); + packet.sendToServer(); + } + + public static PacketCustom createContainerPacket() { + return new PacketCustom(channel, 20); + } + + public static void sendOpenPotionWindow() { + ItemStack[] potionStore = new ItemStack[9]; + InventoryUtils.readItemStacksFromTag(potionStore, NEIClientConfig.global.nbt.getCompoundTag("potionStore").getTagList("items", 10)); + PacketCustom packet = new PacketCustom(channel, 24); + for (ItemStack stack : potionStore) + packet.writeItemStack(stack); + packet.sendToServer(); + } + + public static void sendDummySlotSet(int slotNumber, ItemStack stack) { + PacketCustom packet = new PacketCustom(channel, 25); + packet.writeShort(slotNumber); + packet.writeItemStack(stack, true); + packet.sendToServer(); + } +} diff --git a/src/codechicken/nei/NEIChestGuiHandler.java b/src/codechicken/nei/NEIChestGuiHandler.java new file mode 100644 index 00000000..98d30eff --- /dev/null +++ b/src/codechicken/nei/NEIChestGuiHandler.java @@ -0,0 +1,29 @@ +package codechicken.nei; + +import codechicken.nei.api.INEIGuiAdapter; +import codechicken.nei.api.TaggedInventoryArea; +import net.minecraft.client.gui.inventory.GuiChest; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.ContainerChest; +import net.minecraft.item.ItemStack; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class NEIChestGuiHandler extends INEIGuiAdapter +{ + public int chestSize(GuiContainer gui) { + return ((ContainerChest) gui.inventorySlots).getLowerChestInventory().getSizeInventory(); + } + + @Override + public Iterable getItemSpawnSlots(GuiContainer gui, ItemStack item) { + return gui instanceof GuiChest ? NEIServerUtils.getRange(0, chestSize(gui)) : Collections.emptyList(); + } + + @Override + public List getInventoryAreas(GuiContainer gui) { + return gui instanceof GuiChest ? Arrays.asList(new TaggedInventoryArea("Chest", 0, chestSize(gui), gui.inventorySlots)) : null; + } +} diff --git a/src/codechicken/nei/NEIClientConfig.java b/src/codechicken/nei/NEIClientConfig.java new file mode 100644 index 00000000..98ff85c9 --- /dev/null +++ b/src/codechicken/nei/NEIClientConfig.java @@ -0,0 +1,527 @@ +package codechicken.nei; + +import codechicken.core.*; +import codechicken.lib.config.ConfigFile; +import codechicken.lib.config.ConfigTag; +import codechicken.lib.config.ConfigTagParent; +import codechicken.nei.api.*; +import codechicken.nei.config.*; +import codechicken.nei.recipe.RecipeInfo; +import codechicken.obfuscator.ObfuscationRun; +import net.minecraft.client.AnvilConverterException; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.world.World; +import net.minecraft.world.storage.SaveFormatComparator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.lwjgl.input.Keyboard; + +import java.io.File; +import java.util.Collections; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; + +public class NEIClientConfig +{ + private static boolean configLoaded; + private static boolean enabledOverride; + + public static Logger logger = LogManager.getLogger("NotEnoughItems"); + public static File configDir = new File(CommonUtils.getMinecraftDir(), "config/NEI/"); + public static ConfigSet global = new ConfigSet( + new File("saves/NEI/client.dat"), + new ConfigFile(new File(configDir, "client.cfg"))); + public static ConfigSet world; + + //public static ItemVisibilityHash vishash; + + public static ItemStack creativeInv[]; + private static boolean statesSaved[] = new boolean[7]; + + public static boolean hasSMPCounterpart; + public static HashSet permissableActions = new HashSet(); + public static HashSet disabledActions = new HashSet(); + public static HashSet enabledActions = new HashSet(); + + public static ItemStackSet bannedBlocks = new ItemStackSet(); + + static { + if (global.config.getTag("checkUpdates").getBooleanValue(true)) + CCUpdateChecker.updateCheck("NotEnoughItems"); + linkOptionList(); + setDefaults(); + } + + private static void setDefaults() { + ConfigTagParent tag = global.config; + tag.setComment("Main configuration of NEI.\nMost of these options can be changed ingame.\nDeleting any element will restore it to it's default value"); + + tag.getTag("command").useBraces().setComment("Change these options if you have a different mod installed on the server that handles the commands differently, Eg. Bukkit Essentials"); + tag.setNewLineMode(1); + + tag.getTag("inventory.widgetsenabled").getBooleanValue(true); + API.addOption(new OptionToggleButton("inventory.widgetsenabled")); + + tag.getTag("inventory.hidden").getBooleanValue(false); + tag.getTag("inventory.cheatmode").getIntValue(2); + tag.getTag("inventory.lockmode").setComment("For those who can't help themselves.\nSet this to a mode and you will be unable to change it ingame").getIntValue(-1); + API.addOption(new OptionCycled("inventory.cheatmode", 3) + { + @Override + public boolean optionValid(int index) { + return getLockedMode() == -1 || getLockedMode() == index && NEIInfo.isValidMode(index); + } + }); + checkCheatMode(); + + tag.getTag("inventory.utilities").setDefaultValue("delete, magnet"); + API.addOption(new OptionUtilities("inventory.utilities")); + + tag.getTag("inventory.gamemodes").setDefaultValue("creative, creative+, adventure"); + API.addOption(new OptionGamemodes("inventory.gamemodes")); + + tag.getTag("inventory.layoutstyle").getIntValue(0); + API.addOption(new OptionCycled("inventory.layoutstyle", 0) + { + @Override + public String getPrefix() { + return translateN(name); + } + + @Override + public String getButtonText() { + return NEIClientUtils.translate("layoutstyle." + + LayoutManager.getLayoutStyle(renderTag().getIntValue()).getName()); + } + + @Override + public boolean cycle() { + LinkedList list = new LinkedList(); + for (Entry entry : LayoutManager.layoutStyles.entrySet()) + list.add(entry.getKey()); + + Collections.sort(list); + + int nextLayout = getTag().getIntValue(); + if (nextLayout == list.getLast())//loop list + nextLayout = -1; + for (Integer i : list) { + if (i > nextLayout) { + nextLayout = i; + break; + } + } + + getTag().setIntValue(nextLayout); + return true; + } + }); + tag.getTag("inventory.itemIDs").getIntValue(1); + API.addOption(new OptionCycled("inventory.itemIDs", 3, true)); + + tag.getTag("world.highlight_tips").getBooleanValue(false); + tag.getTag("world.highlight_tips.x").getIntValue(5000); + tag.getTag("world.highlight_tips.y").getIntValue(100); + API.addOption(new OptionHighlightTips("world.highlight_tips")); + + tag.getTag("inventory.profileRecipes").getBooleanValue(false); + API.addOption(new OptionToggleButton("inventory.profileRecipes", true)); + + tag.getTag("command.creative").setDefaultValue("/gamemode {0} {1}"); + API.addOption(new OptionTextField("command.creative")); + tag.getTag("command.item").setDefaultValue("/give {0} {1} {2} {3}"); + API.addOption(new OptionTextField("command.item")); + tag.getTag("command.time").setDefaultValue("/time set {0}"); + API.addOption(new OptionTextField("command.time")); + tag.getTag("command.rain").setDefaultValue("/toggledownfall"); + API.addOption(new OptionTextField("command.rain")); + tag.getTag("command.heal").setDefaultValue(""); + API.addOption(new OptionTextField("command.heal")); + + setDefaultKeyBindings(); + } + + private static void linkOptionList() { + getOptionList().bindConfig(new IConfigSetHolder() + { + @Override + public ConfigSet worldConfigSet() { + return world; + } + + @Override + public ConfigSet globalConfigSet() { + return global; + } + }); + } + + private static void setDefaultKeyBindings() { + API.addKeyBind("gui.recipe", Keyboard.KEY_R); + API.addKeyBind("gui.usage", Keyboard.KEY_U); + API.addKeyBind("gui.back", Keyboard.KEY_BACK); + API.addKeyBind("gui.enchant", Keyboard.KEY_X); + API.addKeyBind("gui.potion", Keyboard.KEY_P); + API.addKeyBind("gui.prev", Keyboard.KEY_PRIOR); + API.addKeyBind("gui.next", Keyboard.KEY_NEXT); + API.addKeyBind("gui.hide", Keyboard.KEY_O); + API.addKeyBind("gui.search", Keyboard.KEY_F); + API.addKeyBind("world.chunkoverlay", Keyboard.KEY_F9); + API.addKeyBind("world.moboverlay", Keyboard.KEY_F7); + API.addKeyBind("world.highlight_tips", Keyboard.KEY_NUMPAD0); + API.addKeyBind("world.dawn", 0); + API.addKeyBind("world.noon", 0); + API.addKeyBind("world.dusk", 0); + API.addKeyBind("world.midnight", 0); + API.addKeyBind("world.rain", 0); + API.addKeyBind("world.heal", 0); + API.addKeyBind("world.creative", 0); + } + + public static OptionList getOptionList() { + return OptionList.getOptionList("nei.options"); + } + + public static void loadWorld(String saveName) { + setInternalEnabled(true); + logger.debug("Loading "+(Minecraft.getMinecraft().isSingleplayer() ? "Local" : "Remote")+" World"); + bootNEI(ClientUtils.getWorld()); + + File saveDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/" + saveName); + boolean newWorld = !saveDir.exists(); + if (newWorld) + saveDir.mkdirs(); + + world = new ConfigSet(new File(saveDir, "NEI.dat"), new ConfigFile(new File(saveDir, "NEI.cfg"))); + onWorldLoad(newWorld); + } + + private static void onWorldLoad(boolean newWorld) { + world.config.setComment("World based configuration of NEI.\nMost of these options can be changed ingame.\nDeleting any element will restore it to it's default value"); + + setWorldDefaults(); + creativeInv = new ItemStack[54]; + LayoutManager.searchField.setText(getSearchExpression()); + LayoutManager.quantity.setText(Integer.toString(getItemQuantity())); + + if (newWorld && Minecraft.getMinecraft().isSingleplayer()) + world.config.getTag("inventory.cheatmode").setIntValue(NEIClientUtils.getGamemode() == 1 ? 2 : 0); + + NEIInfo.load(ClientUtils.getWorld()); + } + + private static void setWorldDefaults() { + NBTTagCompound nbt = world.nbt; + if (!nbt.hasKey("search")) nbt.setString("search", ""); + if (!nbt.hasKey("quantity")) nbt.setInteger("quantity", 0); + if (!nbt.hasKey("validateenchantments")) nbt.setBoolean("validateenchantments", false); + + world.saveNBT(); + } + + public static int getKeyBinding(String string) { + return getSetting("keys." + string).getIntValue(); + } + + public static void setDefaultKeyBinding(String string, int key) { + getSetting("keys." + string).getIntValue(key); + } + + public static void bootNEI(World world) { + if (configLoaded) + return; + + loadStates(); + //ItemVisibilityHash.loadStates(); + //vishash = new ItemVisibilityHash(); + ItemInfo.load(world); + GuiInfo.load(); + RecipeInfo.load(); + LayoutManager.load(); + NEIController.load(); + + configLoaded = true; + + ClassDiscoverer classDiscoverer = new ClassDiscoverer(new IStringMatcher() + { + public boolean matches(String test) { + return test.startsWith("NEI") && test.endsWith("Config.class"); + } + }, IConfigureNEI.class); + + classDiscoverer.findClasses(); + + for (Class class1 : classDiscoverer.classes) { + try { + IConfigureNEI config = (IConfigureNEI) class1.newInstance(); + config.loadConfig(); + NEIModContainer.plugins.add(config); + logger.debug("Loaded " + class1.getName()); + } catch (Exception e) { + logger.error("Failed to Load " + class1.getName()); + e.printStackTrace(); + } + } + } + + public static void loadStates() { + for (int state = 0; state < 7; state++) + statesSaved[state] = !global.nbt.getCompoundTag("save" + state).hasNoTags(); + } + + public static boolean isWorldSpecific(String setting) { + return world != null && world.config.containsTag(setting); + } + + public static boolean isStateSaved(int i) { + return statesSaved[i]; + } + + public static ConfigTag getSetting(String s) { + return isWorldSpecific(s) ? world.config.getTag(s) : global.config.getTag(s); + } + + public static boolean getBooleanSetting(String s) { + return getSetting(s).getBooleanValue(); + } + + public static boolean isHidden() { + return !enabledOverride || getBooleanSetting("inventory.hidden"); + } + + public static boolean isEnabled() { + return enabledOverride && getBooleanSetting("inventory.widgetsenabled"); + } + + public static void setEnabled(boolean flag) { + getSetting("inventory.widgetsenabled").setBooleanValue(flag); + } + + public static int getItemQuantity() { + return world.nbt.getInteger("quantity"); + } + + public static int getCheatMode() { + return getIntSetting("inventory.cheatmode"); + } + + private static void checkCheatMode() { + if (getLockedMode() != -1) + setIntSetting("inventory.cheatmode", getLockedMode()); + } + + public static int getLockedMode() { + return getIntSetting("inventory.lockmode"); + } + + public static int getLayoutStyle() { + return getIntSetting("inventory.layoutstyle"); + } + + public static String getStringSetting(String s) { + return getSetting(s).getValue(); + } + + public static boolean canDump() { + return getBooleanSetting("ID dump.itemIDs") || getBooleanSetting("ID dump.blockIDs") || getBooleanSetting("ID dump.unused itemIDs") || getBooleanSetting("ID dump.unused blockIDs"); + } + + public static boolean showIDs() { + int i = getIntSetting("inventory.itemIDs"); + return i == 2 || (i == 1 && isEnabled() && !isHidden()); + } + + public static void toggleBooleanSetting(String setting) { + ConfigTag tag = getSetting(setting); + tag.setBooleanValue(!tag.getBooleanValue()); + } + + public static void cycleSetting(String setting, int max) { + ConfigTag tag = getSetting(setting); + tag.setIntValue((tag.getIntValue() + 1) % max); + } + + public static int getIntSetting(String setting) { + return getSetting(setting).getIntValue(); + } + + public static void setIntSetting(String setting, int val) { + getSetting(setting).setIntValue(val); + } + + public static String getSearchExpression() { + return world.nbt.getString("search"); + } + + public static void setSearchExpression(String expression) { + world.nbt.setString("search", expression); + world.saveNBT(); + } + + public static boolean getMagnetMode() { + return enabledActions.contains("magnet"); + } + + public static boolean invCreativeMode() { + return enabledActions.contains("creative+") && canPerformAction("creative+"); + } + + public static boolean areDamageVariantsShown() { + return hasSMPCounterPart() || getSetting("command.item").getValue().contains("{3}"); + } + + public static void clearState(int state) { + statesSaved[state] = false; + global.nbt.setTag("save" + state, new NBTTagCompound()); + global.saveNBT(); + } + + public static void loadState(int state) { + if (!statesSaved[state]) { + return; + } + + NBTTagCompound statesave = global.nbt.getCompoundTag("save" + state); + GuiContainer currentContainer = NEIClientUtils.getGuiContainer(); + LinkedList saveAreas = new LinkedList(); + saveAreas.add(new TaggedInventoryArea(NEIClientUtils.mc().thePlayer.inventory)); + + for (INEIGuiHandler handler : GuiInfo.guiHandlers) { + List areaList = handler.getInventoryAreas(currentContainer); + if (areaList != null) + saveAreas.addAll(areaList); + } + + for (TaggedInventoryArea area : saveAreas) { + if (!statesave.hasKey(area.tagName)) + continue; + + for (int slot : area.slots) { + NEIClientUtils.setSlotContents(slot, null, area.isContainer()); + } + + NBTTagList areaTag = statesave.getTagList(area.tagName, 10); + for (int i = 0; i < areaTag.tagCount(); i++) { + NBTTagCompound stacksave = areaTag.getCompoundTagAt(i); + int slot = stacksave.getByte("Slot") & 0xFF; + if (!area.slots.contains(slot)) + continue; + + NEIClientUtils.setSlotContents(slot, ItemStack.loadItemStackFromNBT(stacksave), area.isContainer()); + } + } + } + + public static void saveState(int state) { + NBTTagCompound statesave = global.nbt.getCompoundTag("save" + state); + GuiContainer currentContainer = NEIClientUtils.getGuiContainer(); + LinkedList saveAreas = new LinkedList(); + saveAreas.add(new TaggedInventoryArea(NEIClientUtils.mc().thePlayer.inventory)); + + for (INEIGuiHandler handler : GuiInfo.guiHandlers) { + List areaList = handler.getInventoryAreas(currentContainer); + if (areaList != null) + saveAreas.addAll(areaList); + } + + for (TaggedInventoryArea area : saveAreas) { + NBTTagList areaTag = new NBTTagList(); + + for (int i : area.slots) { + ItemStack stack = area.getStackInSlot(i); + if (stack == null) + continue; + NBTTagCompound stacksave = new NBTTagCompound(); + stacksave.setByte("Slot", (byte) i); + stack.writeToNBT(stacksave); + areaTag.appendTag(stacksave); + } + statesave.setTag(area.tagName, areaTag); + } + + global.nbt.setTag("save" + state, statesave); + global.saveNBT(); + statesSaved[state] = true; + } + + public static boolean hasSMPCounterPart() { + return hasSMPCounterpart; + } + + public static void setHasSMPCounterPart(boolean flag) { + hasSMPCounterpart = flag; + permissableActions.clear(); + bannedBlocks.clear(); + disabledActions.clear(); + enabledActions.clear(); + } + + public static boolean canPerformAction(String name) { + if (!isEnabled()) + return false; + + if (!modePermitsAction(name)) + return false; + + String base = NEIActions.base(name); + if (hasSMPCounterpart) + return permissableActions.contains(base); + + if (NEIActions.smpRequired(name)) + return false; + + String cmd = getStringSetting("command." + base); + if (cmd == null || !cmd.startsWith("/")) + return false; + + return true; + } + + private static boolean modePermitsAction(String name) { + if (getCheatMode() == 0) return false; + if (getCheatMode() == 2) return true; + + String[] actions = getStringArrSetting("inventory.utilities"); + for (String action : actions) + if (action.equalsIgnoreCase(name)) + return true; + + return false; + } + + public static String[] getStringArrSetting(String s) { + return getStringSetting(s).replace(" ", "").split(","); + } + + public static void setInternalEnabled(boolean b) { + enabledOverride = b; + } + + public static void reloadSaves() { + File saveDir = new File(CommonUtils.getMinecraftDir(), "saves/NEI/local"); + if (!saveDir.exists()) + return; + + List saves; + try { + saves = Minecraft.getMinecraft().getSaveLoader().getSaveList(); + } catch (Exception e) { + e.printStackTrace(); + return; + } + HashSet saveFileNames = new HashSet(); + for (SaveFormatComparator save : saves) + saveFileNames.add(save.getFileName()); + + for (File file : saveDir.listFiles()) { + if (file.isDirectory() && !saveFileNames.contains(file.getName())) + ObfuscationRun.deleteDir(file, true); + } + } +} diff --git a/src/codechicken/nei/NEIClientUtils.java b/src/codechicken/nei/NEIClientUtils.java new file mode 100644 index 00000000..c0f3f4cf --- /dev/null +++ b/src/codechicken/nei/NEIClientUtils.java @@ -0,0 +1,371 @@ +package codechicken.nei; + +import codechicken.lib.inventory.InventoryRange; +import codechicken.lib.inventory.InventoryUtils; +import codechicken.nei.api.GuiInfo; +import codechicken.nei.api.IInfiniteItemHandler; +import codechicken.nei.api.INEIGuiHandler; +import codechicken.nei.api.ItemInfo; +import com.google.common.collect.Iterables; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.util.IChatComponent; +import org.lwjgl.input.Keyboard; + +import java.text.MessageFormat; +import java.text.NumberFormat; +import java.util.*; + +import static codechicken.nei.NEIClientConfig.*; + +public class NEIClientUtils extends NEIServerUtils +{ + public static LangProxy lang = new LangProxy("nei"); + + public static Minecraft mc() { + return Minecraft.getMinecraft(); + } + + public static String translate(String key, Object... params) { + return lang.format(key, params); + } + + public static void printChatMessage(IChatComponent msg) { + if (mc().ingameGUI != null) + mc().ingameGUI.getChatGUI().printChatMessage(msg); + } + + public static void deleteHeldItem() { + deleteSlotStack(-999); + } + + public static void dropHeldItem() { + mc().playerController.windowClick(((GuiContainer) mc().currentScreen).inventorySlots.windowId, -999, 0, 0, mc().thePlayer); + } + + public static void deleteSlotStack(int slotNumber) { + setSlotContents(slotNumber, null, true); + } + + public static void decreaseSlotStack(int slotNumber) { + ItemStack stack = slotNumber == -999 ? getHeldItem() : mc().thePlayer.openContainer.getSlot(slotNumber).getStack(); + if (stack == null) + return; + + if (stack.stackSize == 1) + deleteSlotStack(slotNumber); + else { + stack = stack.copy(); + stack.stackSize--; + setSlotContents(slotNumber, stack, true); + } + } + + public static void deleteEverything() { + NEICPH.sendDeleteAllItems(); + } + + public static void deleteItemsOfType(ItemStack type) { + Container c = getGuiContainer().inventorySlots; + for (int i = 0; i < c.inventorySlots.size(); i++) { + Slot slot = c.getSlot(i); + if (slot == null) + continue; + + ItemStack stack = slot.getStack(); + if (stack != null && stack.getItem() == type.getItem() && stack.getItemDamage() == type.getItemDamage()) { + setSlotContents(i, null, true); + slot.putStack(null); + } + } + } + + public static ItemStack getHeldItem() { + return mc().thePlayer.inventory.getItemStack(); + } + + public static void setSlotContents(int slot, ItemStack item, boolean containerInv) { + NEICPH.sendSetSlot(slot, item, containerInv); + + if (slot == -999) + mc().thePlayer.inventory.setItemStack(item); + } + + /** + * @param typeStack + * @param button + * @param mode -1 = normal cheats, 0 = no infinites, 1 = replenish stack + */ + public static void cheatItem(ItemStack typeStack, int button, int mode) { + if (!canPerformAction("item") || typeStack.hasTagCompound() && !canPerformAction("itemnbt")) + return; + + if (mode == -1 && button == 0 && NEIClientUtils.shiftKey()) { + for (IInfiniteItemHandler handler : ItemInfo.infiniteHandlers) { + if (!handler.canHandleItem(typeStack)) + continue; + + ItemStack stack = handler.getInfiniteItem(typeStack); + if (stack != null) { + giveStack(stack, stack.stackSize, true); + return; + } + } + cheatItem(typeStack, button, 0); + } else if (button == 1) { + giveStack(typeStack, 1); + } else { + if (mode == 1 && typeStack.stackSize < typeStack.getMaxStackSize()) { + giveStack(typeStack, typeStack.getMaxStackSize() - typeStack.stackSize); + } else { + int amount = getItemQuantity(); + if (amount == 0) + amount = typeStack.getMaxStackSize(); + giveStack(typeStack, amount); + } + } + } + + public static void giveStack(ItemStack itemstack) { + giveStack(itemstack, itemstack.stackSize); + } + + public static void giveStack(ItemStack itemstack, int i) { + giveStack(itemstack, i, false); + } + + public static void giveStack(ItemStack itemstack, int i, boolean infinite) { + ItemStack itemstack1 = copyStack(itemstack, i); + if (hasSMPCounterPart()) { + ItemStack typestack = copyStack(itemstack1, 1); + if (!infinite && !canItemFitInInventory(mc().thePlayer, itemstack1) && (mc().currentScreen instanceof GuiContainer)) { + GuiContainer gui = getGuiContainer(); + List> handlerSlots = new LinkedList>(); + for(INEIGuiHandler handler : GuiInfo.guiHandlers) + handlerSlots.add(handler.getItemSpawnSlots(gui, typestack)); + + int increment = typestack.getMaxStackSize(); + int given = 0; + for(int slotNo : Iterables.concat(handlerSlots)) { + Slot slot = gui.inventorySlots.getSlot(slotNo); + if(!slot.isItemValid(typestack) || !InventoryUtils.canStack(slot.getStack(), typestack)) + continue; + + int qty = Math.min(itemstack1.stackSize - given, increment); + int current = slot.getHasStack() ? slot.getStack().stackSize : 0; + qty = Math.min(qty, slot.getSlotStackLimit() - current); + + ItemStack newStack = copyStack(typestack, qty + current); + slot.putStack(newStack); + setSlotContents(slotNo, newStack, true); + given += qty; + if(given >= itemstack1.stackSize) + break; + } + if(given > 0) + NEICPH.sendGiveItem(copyStack(typestack, given), false, false); + } else + NEICPH.sendGiveItem(itemstack1, infinite, true); + } else { + for (int given = 0; given < itemstack1.stackSize; ) { + int qty = Math.min(itemstack1.stackSize - given, itemstack1.getMaxStackSize()); + sendCommand(getStringSetting("command.item"), mc().thePlayer.getCommandSenderName(), itemstack1.getItem().getUnlocalizedName(), qty, itemstack1.getItemDamage()); + given += qty; + } + } + } + + public static void updateUnlimitedItems() { + ItemStack itemstack = getHeldItem(); + if (itemstack != null && itemstack.stackSize > 64) + itemstack.stackSize = 1; + + ItemStack aitemstack[] = mc().thePlayer.inventory.mainInventory; + for (int slot = 0; slot < aitemstack.length; slot++) { + ItemStack itemstack1 = aitemstack[slot]; + if (itemstack1 == null) + continue; + + if (itemstack1.stackSize < 0 || itemstack1.stackSize > 64) + itemstack1.stackSize = 111; + + if (itemstack1.getItemDamage() > -32000 && itemstack1.getItemDamage() < -30000) + itemstack1.setItemDamage(-32000); + } + } + + public static boolean itemListContains(ItemStack test) { + for (ItemStack stack : ItemList.itemMap.get(test.getItem())) + if (areStacksIdentical(stack, test)) + return true; + + return false; + } + + public static boolean canItemFitInInventory(EntityPlayer player, ItemStack itemstack) { + return InventoryUtils.getInsertibleQuantity(new InventoryRange(player.inventory, 0, 36), itemstack) > 0; + } + + public static boolean shiftKey() { + return Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + } + + public static boolean controlKey() { + return Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); + } + + public static int getGamemode() { + if (invCreativeMode()) + return 2; + else if (mc().playerController.isInCreativeMode()) + return 1; + else if (mc().playerController.currentGameType.isAdventure()) + return 3; + else + return 0; + } + + public static boolean isValidGamemode(String s) { + return s.equals("survival") || + canPerformAction(s) && + Arrays.asList(getStringArrSetting("inventory.gamemodes")).contains(s); + } + + public static int getNextGamemode() { + int mode = getGamemode(); + int nmode = mode; + while (true) { + nmode = (nmode + 1) % NEIActions.gameModes.length; + if (nmode == mode || isValidGamemode(NEIActions.gameModes[nmode])) + break; + } + return nmode; + } + + public static void cycleGamemode() { + int mode = getGamemode(); + int nmode = getNextGamemode(); + if (mode == nmode) + return; + + if (hasSMPCounterPart()) + NEICPH.sendGamemode(nmode); + else + sendCommand(getStringSetting("command.creative"), getGameType(nmode), mc().thePlayer.getCommandSenderName()); + } + + public static long getTime() { + return mc().theWorld.getWorldInfo().getWorldTime(); + } + + public static void setTime(long l) { + mc().theWorld.getWorldInfo().setWorldTime(l); + } + + public static void setHourForward(int hour) { + long day = (getTime() / 24000L) * 24000L; + long newTime = day + 24000L + hour * 1000; + + if (hasSMPCounterPart()) + NEICPH.sendSetTime(hour); + else + sendCommand(getStringSetting("command.time"), newTime); + } + + public static void sendCommand(String command, Object... args) { + if (command.length() == 0) + return; + + NumberFormat numberformat = NumberFormat.getIntegerInstance(); + numberformat.setGroupingUsed(false); + MessageFormat messageformat = new MessageFormat(command); + for (int i = 0; i < args.length; i++) + if (args[i] instanceof Integer || args[i] instanceof Long) + messageformat.setFormatByArgumentIndex(i, numberformat); + + mc().thePlayer.sendChatMessage(messageformat.format(args)); + } + + public static boolean isRaining() { + return mc().theWorld.getWorldInfo().isRaining(); + } + + public static void toggleRaining() { + if (hasSMPCounterPart()) + NEICPH.sendToggleRain(); + else + sendCommand(getStringSetting("command.rain"), isRaining() ? 0 : 1); + } + + public static void healPlayer() { + if (hasSMPCounterPart()) + NEICPH.sendHeal(); + else + sendCommand(getStringSetting("command.heal"), mc().thePlayer.getCommandSenderName()); + } + + public static void toggleMagnetMode() { + if (hasSMPCounterPart()) + NEICPH.sendToggleMagnetMode(); + } + + public static ArrayList concatIntegersToRanges(List damages) { + ArrayList ranges = new ArrayList(); + if (damages.size() == 0) return ranges; + + Collections.sort(damages); + int start = -1; + int next = 0; + for (Integer i : damages) { + if (start == -1) { + start = next = i; + continue; + } + if (next + 1 != i) { + ranges.add(new int[]{start, next}); + start = next = i; + continue; + } + next = i; + } + ranges.add(new int[]{start, next}); + return ranges; + } + + public static ArrayList addIntegersToRanges(List ranges, List damages) { + for (int[] range : ranges) + for (int integer = range[0]; integer <= range[1]; integer++) + damages.add(integer); + + return concatIntegersToRanges(damages); + } + + public static boolean safeKeyDown(int keyCode) { + try { + return Keyboard.isKeyDown(keyCode); + } catch (IndexOutOfBoundsException e) { + return false; + } + } + + public static void setItemQuantity(int i) { + world.nbt.setInteger("quantity", i); + world.saveNBT(); + LayoutManager.quantity.setText(Integer.toString(i)); + } + + public static GuiContainer getGuiContainer() { + if (mc().currentScreen instanceof GuiContainer) + return (GuiContainer) mc().currentScreen; + + return null; + } + + public static boolean altKey() { + return Keyboard.isKeyDown(Keyboard.KEY_LMENU) || Keyboard.isKeyDown(Keyboard.KEY_RMENU); + } +} diff --git a/src/codechicken/nei/NEICompatibility.java b/src/codechicken/nei/NEICompatibility.java new file mode 100644 index 00000000..46466b9d --- /dev/null +++ b/src/codechicken/nei/NEICompatibility.java @@ -0,0 +1,5 @@ +package codechicken.nei; + +public class NEICompatibility +{ +} diff --git a/src/codechicken/nei/NEIController.java b/src/codechicken/nei/NEIController.java new file mode 100644 index 00000000..a8c25ea4 --- /dev/null +++ b/src/codechicken/nei/NEIController.java @@ -0,0 +1,271 @@ +package codechicken.nei; + +import codechicken.nei.api.*; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.guihook.IContainerInputHandler; +import codechicken.nei.guihook.IContainerSlotClickHandler; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiContainerCreative; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.inventory.SlotCrafting; +import net.minecraft.item.ItemStack; + +import java.awt.*; +import java.util.LinkedList; + +import static codechicken.lib.gui.GuiDraw.getMousePosition; + +public class NEIController implements IContainerSlotClickHandler, IContainerInputHandler +{ + private static NEIController instance = new NEIController(); + + public static GuiContainerManager manager; + public static FastTransferManager fastTransferManager; + + private static boolean deleteMode; + private static int pickedUpFromSlot; + private static IInfiniteItemHandler heldStackInfinite; + + private static int selectedItem; + + public static void load() { + GuiContainerManager.addSlotClickHandler(instance); + GuiContainerManager.addInputHandler(instance); + } + + public static void load(GuiContainer gui) { + manager = GuiContainerManager.getManager(gui); + deleteMode = false; + GuiInfo.clearGuiHandlers(); + fastTransferManager = null; + if (!NEIClientConfig.isEnabled()) + return; + + fastTransferManager = new FastTransferManager(); + if (gui instanceof INEIGuiHandler) + API.registerNEIGuiHandler((INEIGuiHandler) gui); + } + + ItemStack firstheld; + + public static void updateUnlimitedItems(InventoryPlayer inventory) { + if (!NEIClientConfig.canPerformAction("item") || !NEIClientConfig.hasSMPCounterPart()) + return; + + LinkedList beforeStacks = new LinkedList(); + for (int i = 0; i < inventory.getSizeInventory(); i++) + beforeStacks.add(NEIServerUtils.copyStack(inventory.getStackInSlot(i))); + + for (int i = 0; i < inventory.getSizeInventory(); i++) { + ItemStack stack = inventory.getStackInSlot(i); + if (stack == null) + continue; + + for (IInfiniteItemHandler handler : ItemInfo.infiniteHandlers) + if (handler.canHandleItem(stack) && handler.isItemInfinite(stack)) + handler.replenishInfiniteStack(inventory, i); + } + + for (int i = 0; i < inventory.getSizeInventory(); i++) { + ItemStack newstack = inventory.getStackInSlot(i); + + if (!NEIServerUtils.areStacksIdentical(beforeStacks.get(i), newstack)) { + inventory.setInventorySlotContents(i, beforeStacks.get(i));//restore in case of SMP fail + NEIClientUtils.setSlotContents(i, newstack, false);//sends via SMP handler ;) + } + } + } + + public static void processCreativeCycling(InventoryPlayer inventory) { + if (NEIClientConfig.invCreativeMode() && NEIClientUtils.controlKey()) { + if (selectedItem != inventory.currentItem) { + if (inventory.currentItem == selectedItem + 1 || (inventory.currentItem == 0 && selectedItem == 8))//foward + { + NEICPH.sendCreativeScroll(1); + inventory.currentItem = selectedItem; + } else if (inventory.currentItem == selectedItem - 1 || (inventory.currentItem == 8 && selectedItem == 0)) { + NEICPH.sendCreativeScroll(-1); + inventory.currentItem = selectedItem; + } + } + } + + selectedItem = inventory.currentItem; + } + + @Override + public void beforeSlotClick(GuiContainer gui, int slotIndex, int button, Slot slot, int modifier) { + if (!NEIClientConfig.isEnabled()) + return; + + firstheld = NEIClientUtils.getHeldItem(); + } + + @Override + public boolean handleSlotClick(GuiContainer gui, int slotIndex, int button, Slot slot, int modifier, boolean eventconsumed) { + if (eventconsumed || !NEIClientConfig.isEnabled()) + return eventconsumed; + + if (deleteMode && slotIndex >= 0 && slot != null) { + if (NEIClientUtils.shiftKey() && button == 0) { + ItemStack itemstack1 = slot.getStack(); + if (itemstack1 != null) + NEIClientUtils.deleteItemsOfType(itemstack1); + + } else if (button == 1) + NEIClientUtils.decreaseSlotStack(slot.slotNumber); + else + NEIClientUtils.deleteSlotStack(slot.slotNumber); + return true; + } + + if (button == 1 && slot instanceof SlotCrafting)//right click + { + for (int i1 = 0; i1 < 64; i1++)//click this slot 64 times + manager.handleSlotClick(slot.slotNumber, button, 0); + return true; + } + + if (slotIndex >= 0 && NEIClientUtils.shiftKey() && NEIClientUtils.getHeldItem() != null && !slot.getHasStack()) { + ItemStack held = NEIClientUtils.getHeldItem(); + manager.handleSlotClick(slot.slotNumber, button, 0); + if (slot.isItemValid(held) && !ItemInfo.fastTransferExemptions.contains(slot.getClass())) + fastTransferManager.performMassTransfer(gui, pickedUpFromSlot, slotIndex, held); + + return true; + } + + if (NEIClientUtils.controlKey() + && slot != null && slot.getStack() != null + && NEIClientConfig.canPerformAction("item") + && slot.isItemValid(slot.getStack())) { + NEIClientUtils.cheatItem(slot.getStack(), button, 1); + return true; + } + + if (slotIndex == -999 && NEIClientUtils.shiftKey() && button == 0) { + fastTransferManager.throwAll(gui, pickedUpFromSlot); + return true; + } + + return false; + } + + @Override + public void afterSlotClick(GuiContainer gui, int slotIndex, int button, Slot slot, int modifier) { + if (!NEIClientConfig.isEnabled()) + return; + + ItemStack nowHeld = NEIClientUtils.getHeldItem(); + + if (firstheld != nowHeld) + pickedUpFromSlot = slotIndex; + + if (NEIClientConfig.canPerformAction("item") && NEIClientConfig.hasSMPCounterPart()) { + if (heldStackInfinite != null && slot != null && slot.inventory == NEIClientUtils.mc().thePlayer.inventory) { + ItemStack stack = slot.getStack(); + if (stack != null) { + heldStackInfinite.onPlaceInfinite(stack); + } + NEIClientUtils.setSlotContents(slotIndex, stack, true); + } + + if (firstheld != nowHeld) + heldStackInfinite = null; + + if (firstheld != nowHeld && nowHeld != null) { + for (IInfiniteItemHandler handler : ItemInfo.infiniteHandlers) { + if (handler.canHandleItem(nowHeld) && handler.isItemInfinite(nowHeld)) { + handler.onPickup(nowHeld); + NEIClientUtils.setSlotContents(-999, nowHeld, true); + heldStackInfinite = handler; + break; + } + } + } + } + } + + @Override + public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyCode) { + if (!NEIClientConfig.isEnabled()) + return false; + + Slot slot = GuiContainerManager.getSlotMouseOver(gui); + if (slot == null) + return false; + + int slotIndex = slot.slotNumber; + + if (keyCode == NEIClientUtils.mc().gameSettings.keyBindDrop.getKeyCode() && NEIClientUtils.shiftKey()) { + FastTransferManager.clickSlot(gui, slotIndex); + fastTransferManager.throwAll(gui, slotIndex); + FastTransferManager.clickSlot(gui, slotIndex); + + return true; + } + + return false; + } + + @Override + public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + if (!NEIClientConfig.isEnabled()) + return false; + + Point mousePos = getMousePosition(); + Slot mouseover = manager.window.getSlotAtPosition(mousePos.x, mousePos.y); + if (mouseover != null && mouseover.getHasStack()) { + if (scrolled > 0) + fastTransferManager.transferItem(manager.window, mouseover.slotNumber); + else + fastTransferManager.retrieveItem(manager.window, mouseover.slotNumber); + return true; + } + return false; + } + + @Override + public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) { + return false; + } + + @Override + public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + return false; + } + + @Override + public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) { + } + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) { + } + + @Override + public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) { + } + + @Override + public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) { + } + + @Override + public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) { + } + + public static boolean canUseDeleteMode() { + return !(NEIClientUtils.getGuiContainer() instanceof GuiContainerCreative); + } + + public static void toggleDeleteMode() { + if(canUseDeleteMode()) + deleteMode = !deleteMode; + } + + public static boolean getDeleteMode() { + return deleteMode; + } +} diff --git a/src/codechicken/nei/NEICreativeGuiHandler.java b/src/codechicken/nei/NEICreativeGuiHandler.java new file mode 100644 index 00000000..ccd1a02b --- /dev/null +++ b/src/codechicken/nei/NEICreativeGuiHandler.java @@ -0,0 +1,22 @@ +package codechicken.nei; + +import codechicken.nei.api.INEIGuiAdapter; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.client.gui.inventory.GuiContainerCreative; +import net.minecraft.creativetab.CreativeTabs; + +public class NEICreativeGuiHandler extends INEIGuiAdapter +{ + @Override + public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) + { + if(!(gui instanceof GuiContainerCreative)) + return currentVisibility; + + if(((GuiContainerCreative)gui).func_147056_g() != CreativeTabs.tabInventory.getTabIndex()) + currentVisibility.showItemSection = currentVisibility.enableDeleteMode = false; + + return currentVisibility; + } + +} diff --git a/src/codechicken/nei/NEIDummySlotHandler.java b/src/codechicken/nei/NEIDummySlotHandler.java new file mode 100644 index 00000000..0c658e94 --- /dev/null +++ b/src/codechicken/nei/NEIDummySlotHandler.java @@ -0,0 +1,24 @@ +package codechicken.nei; + +import codechicken.core.inventory.ContainerExtended; +import codechicken.core.inventory.SlotDummy; +import codechicken.nei.api.INEIGuiAdapter; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; + +public class NEIDummySlotHandler extends INEIGuiAdapter +{ + @Override + public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button) + { + Slot slot = gui.getSlotAtPosition(mousex, mousey); + if(slot instanceof SlotDummy && slot.isItemValid(draggedStack) && gui.inventorySlots instanceof ContainerExtended) + { + ((SlotDummy)slot).slotClick(draggedStack, button, NEIClientUtils.shiftKey()); + NEICPH.sendDummySlotSet(slot.slotNumber, slot.getStack()); + return true; + } + return false; + } +} diff --git a/src/codechicken/nei/NEIModContainer.java b/src/codechicken/nei/NEIModContainer.java new file mode 100644 index 00000000..d5ca87b8 --- /dev/null +++ b/src/codechicken/nei/NEIModContainer.java @@ -0,0 +1,94 @@ +package codechicken.nei; + +import codechicken.core.CommonUtils; +import codechicken.core.launch.CodeChickenCorePlugin; +import codechicken.nei.api.IConfigureNEI; +import codechicken.nei.asm.NEICorePlugin; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.Subscribe; +import cpw.mods.fml.client.FMLFileResourcePack; +import cpw.mods.fml.client.FMLFolderResourcePack; +import cpw.mods.fml.common.DummyModContainer; +import cpw.mods.fml.common.LoadController; +import cpw.mods.fml.common.MetadataCollection; +import cpw.mods.fml.common.ModMetadata; +import cpw.mods.fml.common.event.FMLInitializationEvent; +import cpw.mods.fml.common.versioning.ArtifactVersion; +import cpw.mods.fml.common.versioning.VersionParser; +import cpw.mods.fml.common.versioning.VersionRange; +import net.minecraft.util.EnumChatFormatting; + +import java.io.File; +import java.util.*; + +public class NEIModContainer extends DummyModContainer +{ + public static LinkedList plugins = new LinkedList(); + + public NEIModContainer() { + super(MetadataCollection.from(MetadataCollection.class.getResourceAsStream("/neimod.info"), "NotEnoughItems").getMetadataForId("NotEnoughItems", null)); + getMetadata(); + } + + @Override + public Set getRequirements() { + Set deps = new HashSet(); + deps.add(VersionParser.parseVersionReference("CodeChickenCore@[0,)")); + return deps; + } + + @Override + public List getDependencies() { + return new LinkedList(getRequirements()); + } + + @Override + public ModMetadata getMetadata() { + ModMetadata meta = super.getMetadata(); + meta.description = "Recipe Viewer, Inventory Manager, Item Spawner, Cheats and more.\n"+ EnumChatFormatting.WHITE+"\n"; + + if (plugins.size() == 0) { + meta.description += EnumChatFormatting.RED+"No installed plugins."; + } else { + meta.description += EnumChatFormatting.GREEN+"Installed plugins: "; + for (int i = 0; i < plugins.size(); i++) { + if (i > 0) + meta.description += ", "; + IConfigureNEI plugin = plugins.get(i); + meta.description += plugin.getName() + " " + plugin.getVersion(); + } + meta.description += "."; + } + + return meta; + } + + @Override + public boolean registerBus(EventBus bus, LoadController controller) { + bus.register(this); + return true; + } + + @Subscribe + public void init(FMLInitializationEvent event) { + if (CommonUtils.isClient()) + ClientHandler.load(); + + ServerHandler.load(); + } + + @Override + public VersionRange acceptableMinecraftVersionRange() { + return VersionParser.parseRange(CodeChickenCorePlugin.mcVersion); + } + + /*@Override + public File getSource() { + return NEICorePlugin.location; + } + + @Override + public Class getCustomResourcePackClass() { + return getSource().isDirectory() ? FMLFolderResourcePack.class : FMLFileResourcePack.class; + }*/ +} diff --git a/src/codechicken/nei/NEISPH.java b/src/codechicken/nei/NEISPH.java new file mode 100644 index 00000000..bacf3da0 --- /dev/null +++ b/src/codechicken/nei/NEISPH.java @@ -0,0 +1,264 @@ +package codechicken.nei; + +import codechicken.core.CommonUtils; +import codechicken.core.IGuiPacketSender; +import codechicken.core.ServerUtils; +import codechicken.core.inventory.ContainerExtended; +import codechicken.core.inventory.SlotDummy; +import codechicken.lib.packet.PacketCustom; +import codechicken.lib.packet.PacketCustom.IServerPacketHandler; +import codechicken.lib.vec.BlockCoord; +import cpw.mods.fml.relauncher.Side; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.inventory.InventoryBasic; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import net.minecraft.network.play.INetHandlerPlayServer; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.tileentity.TileEntityMobSpawner; +import net.minecraft.world.World; + +import java.util.LinkedList; +import java.util.Set; + +public class NEISPH implements IServerPacketHandler +{ + @Override + public void handlePacket(PacketCustom packet, EntityPlayerMP sender, INetHandlerPlayServer netHandler) { + if (!NEIServerConfig.authenticatePacket(sender, packet)) + return; + + switch (packet.getType()) { + case 1: + handleGiveItem(sender, packet); + break; + case 4: + NEIServerUtils.deleteAllItems(sender); + break; + case 5: + setInventorySlot(sender, packet); + break; + case 6: + NEIServerUtils.toggleMagnetMode(sender); + break; + case 7: + NEIServerUtils.setHourForward(sender.worldObj, packet.readUByte(), true); + break; + case 8: + NEIServerUtils.healPlayer(sender); + break; + case 9: + NEIServerUtils.toggleRaining(sender.worldObj, true); + break; + case 10: + sendLoginState(sender); + break; + case 11: + sender.sendContainerAndContentsToPlayer(sender.openContainer, sender.openContainer.getInventory()); + break; + case 12: + handlePropertyChange(sender, packet); + break; + case 13: + NEIServerUtils.setGamemode(sender, packet.readUByte()); + break; + case 14: + NEIServerUtils.cycleCreativeInv(sender, packet.readInt()); + break; + case 15: + handleMobSpawnerID(sender.worldObj, packet.readCoord(), packet.readString()); + break; + case 20: + handleContainerPacket(sender, packet); + break; + case 21: + openEnchantmentGui(sender); + break; + case 22: + modifyEnchantment(sender, packet.readUByte(), packet.readUByte(), packet.readBoolean()); + break; + case 23: + processCreativeInv(sender, packet.readBoolean()); + break; + case 24: + openPotionGui(sender, packet); + break; + case 25: + handleDummySlotSet(sender, packet); + break; + } + } + + private void handleDummySlotSet(EntityPlayerMP sender, PacketCustom packet) { + int slotNumber = packet.readShort(); + ItemStack stack = packet.readItemStack(true); + + Slot slot = sender.openContainer.getSlot(slotNumber); + if (slot instanceof SlotDummy) + slot.putStack(stack); + } + + private void handleContainerPacket(EntityPlayerMP sender, PacketCustom packet) { + if (sender.openContainer instanceof ContainerExtended) + ((ContainerExtended) sender.openContainer).handleInputPacket(packet); + } + + private void handleMobSpawnerID(World world, BlockCoord coord, String mobtype) { + TileEntity tile = world.getTileEntity(coord.x, coord.y, coord.z); + if (tile instanceof TileEntityMobSpawner) { + ((TileEntityMobSpawner) tile).func_145881_a().setEntityName(mobtype); + tile.markDirty(); + world.markBlockForUpdate(coord.x, coord.y, coord.z); + } + } + + private void handlePropertyChange(EntityPlayerMP sender, PacketCustom packet) { + String name = packet.readString(); + if (NEIServerConfig.canPlayerPerformAction(sender.getCommandSenderName(), name)) + NEIServerConfig.disableAction(sender.dimension, name, packet.readBoolean()); + } + + private void processCreativeInv(EntityPlayerMP sender, boolean open) { + if (open) { + ServerUtils.openSMPContainer(sender, new ContainerCreativeInv(sender, new ExtendedCreativeInv(NEIServerConfig.forPlayer(sender.getCommandSenderName()), Side.SERVER)), new IGuiPacketSender() + { + @Override + public void sendPacket(EntityPlayerMP player, int windowId) { + PacketCustom packet = new PacketCustom(channel, 23); + packet.writeBoolean(true); + packet.writeByte(windowId); + packet.sendToPlayer(player); + } + }); + } else { + sender.closeContainer(); + PacketCustom packet = new PacketCustom(channel, 23); + packet.writeBoolean(false); + packet.sendToPlayer(sender); + } + } + + private void handleGiveItem(EntityPlayerMP player, PacketCustom packet) { + NEIServerUtils.givePlayerItem(player, packet.readItemStack(true), packet.readBoolean(), packet.readBoolean()); + } + + private void setInventorySlot(EntityPlayerMP player, PacketCustom packet) { + boolean container = packet.readBoolean(); + int slot = packet.readShort(); + ItemStack item = packet.readItemStack(); + + ItemStack old = NEIServerUtils.getSlotContents(player, slot, container); + boolean deleting = item == null || old != null && NEIServerUtils.areStacksSameType(item, old) && item.stackSize < old.stackSize; + if (NEIServerConfig.canPlayerPerformAction(player.getCommandSenderName(), deleting ? "delete" : "item")) + NEIServerUtils.setSlotContents(player, slot, item, container); + } + + private void modifyEnchantment(EntityPlayerMP player, int e, int lvl, boolean add) { + ContainerEnchantmentModifier containerem = (ContainerEnchantmentModifier) player.openContainer; + if (add) { + containerem.addEnchantment(e, lvl); + } else { + containerem.removeEnchantment(e); + } + } + + private void openEnchantmentGui(EntityPlayerMP player) { + ServerUtils.openSMPContainer(player, new ContainerEnchantmentModifier(player.inventory, player.worldObj, 0, 0, 0), new IGuiPacketSender() + { + @Override + public void sendPacket(EntityPlayerMP player, int windowId) { + PacketCustom packet = new PacketCustom(channel, 21); + packet.writeByte(windowId); + packet.sendToPlayer(player); + } + }); + } + + private void openPotionGui(EntityPlayerMP player, PacketCustom packet) { + InventoryBasic b = new InventoryBasic("potionStore", true, 9); + for (int i = 0; i < b.getSizeInventory(); i++) + b.setInventorySlotContents(i, packet.readItemStack()); + ServerUtils.openSMPContainer(player, new ContainerPotionCreator(player.inventory, b), new IGuiPacketSender() + { + @Override + public void sendPacket(EntityPlayerMP player, int windowId) { + PacketCustom packet = new PacketCustom(channel, 24); + packet.writeByte(windowId); + packet.sendToPlayer(player); + } + }); + } + + public static void sendActionDisabled(int dim, String name, boolean disable) { + new PacketCustom(channel, 11) + .writeString(name) + .writeBoolean(disable) + .sendToDimension(dim); + } + + public static void sendActionEnabled(EntityPlayerMP player, String name, boolean enable) { + new PacketCustom(channel, 12) + .writeString(name) + .writeBoolean(enable) + .sendToPlayer(player); + } + + private void sendLoginState(EntityPlayerMP player) { + LinkedList actions = new LinkedList(); + LinkedList disabled = new LinkedList(); + LinkedList enabled = new LinkedList(); + LinkedList bannedItems = new LinkedList(); + PlayerSave playerSave = NEIServerConfig.forPlayer(player.getCommandSenderName()); + + for (String name : NEIActions.nameActionMap.keySet()) { + if (NEIServerConfig.canPlayerPerformAction(player.getCommandSenderName(), name)) + actions.add(name); + if (NEIServerConfig.isActionDisabled(player.dimension, name)) + disabled.add(name); + if (playerSave.isActionEnabled(name)) + enabled.add(name); + } + for (ItemStackMap.Entry> entry : NEIServerConfig.bannedItems.entries()) + if (!NEIServerConfig.isPlayerInList(player.getCommandSenderName(), entry.value, true)) + bannedItems.add(entry.key); + + PacketCustom packet = new PacketCustom(channel, 10); + + packet.writeByte(actions.size()); + for (String s : actions) + packet.writeString(s); + + packet.writeByte(disabled.size()); + for (String s : disabled) + packet.writeString(s); + + packet.writeByte(enabled.size()); + for (String s : enabled) + packet.writeString(s); + + packet.writeInt(bannedItems.size()); + for (ItemStack stack : bannedItems) + packet.writeItemStack(stack); + + packet.sendToPlayer(player); + } + + public static void sendHasServerSideTo(EntityPlayerMP player) { + NEIServerConfig.logger.debug("Sending serverside check to: " + player.getCommandSenderName()); + PacketCustom packet = new PacketCustom(channel, 1); + packet.writeByte(NEIActions.protocol); + packet.writeString(CommonUtils.getWorldName(player.worldObj)); + + packet.sendToPlayer(player); + } + + public static void sendAddMagneticItemTo(EntityPlayerMP player, EntityItem item) { + PacketCustom packet = new PacketCustom(channel, 13); + packet.writeInt(item.getEntityId()); + + packet.sendToPlayer(player); + } + + public static final String channel = "NEI"; +} diff --git a/src/codechicken/nei/NEIServerConfig.java b/src/codechicken/nei/NEIServerConfig.java new file mode 100644 index 00000000..13395123 --- /dev/null +++ b/src/codechicken/nei/NEIServerConfig.java @@ -0,0 +1,285 @@ +package codechicken.nei; + +import codechicken.core.CommonUtils; +import codechicken.core.ServerUtils; +import codechicken.lib.config.ConfigFile; +import codechicken.lib.inventory.InventoryUtils; +import codechicken.lib.packet.PacketCustom; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.JsonToNBT; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.server.MinecraftServer; +import net.minecraft.world.World; +import net.minecraftforge.common.DimensionManager; +import org.apache.commons.io.IOUtils; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.File; +import java.io.FileReader; +import java.io.PrintWriter; +import java.util.*; + +public class NEIServerConfig +{ + private static MinecraftServer server; + + public static Logger logger = LogManager.getLogger("NotEnoughItems"); + public static File saveDir; + public static ConfigFile serverConfig; + public static Map dimTags = new HashMap(); + public static HashMap playerSaves = new HashMap(); + public static ItemStackMap> bannedItems = new ItemStackMap>(); + + public static void load(World world) { + if (MinecraftServer.getServer() != server) { + logger.debug("Loading NEI Server"); + server = MinecraftServer.getServer(); + saveDir = new File(DimensionManager.getCurrentSaveRootDirectory(), "NEI"); + + dimTags.clear(); + loadConfig(); + loadBannedItems(); + } + loadWorld(world); + } + + public static File getSaveDir(int dim) { + return new File(CommonUtils.getSaveLocation(dim), "NEI"); + } + + private static void loadWorld(World world) { + try { + File file = new File(getSaveDir(CommonUtils.getDimension(world)), "world.dat"); + NBTTagCompound tag = CompressedStreamTools.read(file); + if(tag == null) + tag = new NBTTagCompound(); + dimTags.put(CommonUtils.getDimension(world), tag); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void loadConfig() { + File file = new File(saveDir, "server.cfg"); + serverConfig = new ConfigFile(file); + + serverConfig.setNewLineMode(1); + serverConfig.getTag("permissions").useBraces(); + serverConfig.getTag("permissions").setComment("List of players who can use these features.\nEg. time=CodeChicken, Friend1"); + + setDefaultFeature("time"); + setDefaultFeature("rain"); + setDefaultFeature("heal"); + setDefaultFeature("magnet"); + setDefaultFeature("creative"); + setDefaultFeature("creative+"); + setDefaultFeature("adventure"); + setDefaultFeature("enchant"); + setDefaultFeature("potion"); + setDefaultFeature("save-state"); + setDefaultFeature("item"); + setDefaultFeature("delete"); + setDefaultFeature("notify-item", "CONSOLE, OP"); + } + + private static void setDefaultFeature(String featurename, String... names) { + if (names.length == 0) + names = new String[]{"OP"}; + + String list = ""; + for (int i = 0; i < names.length; i++) { + if (i >= 1) + list += ", "; + list += names[i]; + } + serverConfig.getTag("permissions." + featurename).setDefaultValue(list); + } + + private static void saveWorld(int dim) { + try { + File file = new File(getSaveDir(dim), "world.dat"); + CompressedStreamTools.write(dimTags.get(dim), file); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static boolean canPlayerPerformAction(String playername, String name) { + return isPlayerInList(playername, getPlayerList("permissions." + NEIActions.base(name)), true); + } + + public static boolean isPlayerInList(String playername, Set list, boolean allowCards) { + if (playername.equals("CONSOLE")) + return list.contains(playername); + + playername = playername.toLowerCase(); + + if (allowCards) { + if (list.contains("ALL")) + return true; + if ((ServerUtils.isPlayerOP(playername) || ServerUtils.isPlayerOwner(playername)) && list.contains("OP")) + return true; + } + + return list.contains(playername); + } + + public static boolean isActionDisabled(int dim, String name) { + return dimTags.get(dim).getBoolean("disabled" + name); + } + + public static void disableAction(int dim, String name, boolean disable) { + dimTags.get(dim).setBoolean("disabled" + name, disable); + NEISPH.sendActionDisabled(dim, name, disable); + saveWorld(dim); + } + + public static HashSet getPlayerList(String tag) { + String[] list = serverConfig.getTag(tag).getValue("").replace(" ", "").split(","); + return new HashSet(Arrays.asList(list)); + } + + public static void addPlayerToList(String playername, String tag) { + HashSet list = getPlayerList(tag); + + if (!playername.equals("CONSOLE") && !playername.equals("ALL") && !playername.equals("OP")) + playername = playername.toLowerCase(); + + list.add(playername); + savePlayerList(tag, list); + } + + public static void remPlayerFromList(String playername, String tag) { + HashSet list = getPlayerList(tag); + + if (!playername.equals("CONSOLE") && !playername.equals("ALL") && !playername.equals("OP")) + playername = playername.toLowerCase(); + + list.remove(playername); + savePlayerList(tag, list); + } + + private static void savePlayerList(String tag, Collection list) { + StringBuilder sb = new StringBuilder(); + int i = 0; + for (Iterator iterator = list.iterator(); iterator.hasNext(); i++) { + if (i != 0) + sb.append(", "); + + sb.append(iterator.next()); + } + + serverConfig.getTag(tag).setValue(sb.toString()); + } + + private static void loadBannedItems() { + bannedItems.clear(); + File file = new File(saveDir, "banneditems.cfg"); + if(!file.exists()) { + bannedItems.put(new ItemStack(Blocks.bedrock), new HashSet(Arrays.asList("NONE"))); + saveBannedItems(); + return; + } + try { + FileReader r = new FileReader(file); + int line = 0; + for(String s : IOUtils.readLines(r)) { + if(s.charAt(0) == '#' || s.trim().length() == 0) + continue; + int delim = s.lastIndexOf('='); + if(delim < 0) { + System.err.println("line "+line+": Missing ="); + continue; + } + try { + NBTTagCompound key = (NBTTagCompound) JsonToNBT.func_150315_a(s.substring(0, delim)); + Set values = new HashSet(); + for(String s2 : s.substring(delim+1).split(",")) + values.add(s2.trim()); + bannedItems.put(InventoryUtils.loadPersistant(key), values); + } catch (Exception e) { + System.err.println("line "+line+": "+e.getMessage()); + } + } + r.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static void saveBannedItems() { + File file = new File(saveDir, "banneditems.cfg"); + try { + if(!file.exists()) + file.createNewFile(); + + PrintWriter p = new PrintWriter(file); + p.println("#Saved in this format for external editing. The format isn't that hard to figure out. If you think you're up to it, modify it here!"); + + for (ItemStackMap.Entry> entry : bannedItems.entries()) { + NBTTagCompound key = InventoryUtils.savePersistant(entry.key, new NBTTagCompound()); + key.removeTag("Count"); + if(key.getByte("Damage") == 0) key.removeTag("Damage"); + + p.print(key.toString()); + p.print("=["); + int i = 0; + for (String s : entry.value) { + if(i++ != 0) p.print(", "); + p.print(s); + } + p.println("]"); + } + p.close(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public static PlayerSave forPlayer(String username) { + return playerSaves.get(username); + } + + public static void loadPlayer(EntityPlayer player) { + logger.debug("Loading Player: " + player.getGameProfile().getName()); + playerSaves.put(player.getCommandSenderName(), new PlayerSave(player.getCommandSenderName(), new File(saveDir, "players"))); + } + + public static void unloadPlayer(EntityPlayer player) { + logger.debug("Unloading Player: " + player.getCommandSenderName()); + PlayerSave playerSave = playerSaves.remove(player.getCommandSenderName()); + if (playerSave != null) + playerSave.save(); + } + + public static boolean authenticatePacket(EntityPlayerMP sender, PacketCustom packet) { + switch (packet.getType()) { + case 1: + return canPlayerPerformAction(sender.getCommandSenderName(), "item"); + case 4: + return canPlayerPerformAction(sender.getCommandSenderName(), "delete"); + case 6: + return canPlayerPerformAction(sender.getCommandSenderName(), "magnet"); + case 7: + return canPlayerPerformAction(sender.getCommandSenderName(), "time"); + case 8: + return canPlayerPerformAction(sender.getCommandSenderName(), "heal"); + case 9: + return canPlayerPerformAction(sender.getCommandSenderName(), "rain"); + case 14: + case 23: + return canPlayerPerformAction(sender.getCommandSenderName(), "creative+"); + case 21: + case 22: + return canPlayerPerformAction(sender.getCommandSenderName(), "enchant"); + case 24: + return canPlayerPerformAction(sender.getCommandSenderName(), "potion"); + } + return true; + } +} diff --git a/src/codechicken/nei/NEIServerUtils.java b/src/codechicken/nei/NEIServerUtils.java new file mode 100644 index 00000000..73e5b2ec --- /dev/null +++ b/src/codechicken/nei/NEIServerUtils.java @@ -0,0 +1,363 @@ +package codechicken.nei; + +import codechicken.core.CommonUtils; +import codechicken.core.ServerUtils; +import codechicken.lib.inventory.InventoryUtils; +import codechicken.lib.packet.PacketCustom; +import net.minecraft.command.ICommandSender; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.WorldSettings.GameType; +import net.minecraftforge.oredict.OreDictionary; + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; + +public class NEIServerUtils +{ + public static boolean isRaining(World world) { + return world.getWorldInfo().isRaining(); + } + + public static void toggleRaining(World world, boolean notify) { + boolean raining = !world.isRaining(); + if (!raining)//turn off + ((WorldServer) world).provider.resetRainAndThunder(); + else + world.getWorldInfo().setRaining(!isRaining(world)); + + if (notify) + ServerUtils.sendChatToAll(new ChatComponentTranslation("nei.chat.rain." + (raining ? "on" : "off"))); + } + + public static void healPlayer(EntityPlayer player) { + player.heal(20); + player.getFoodStats().addStats(20, 1); + player.extinguish(); + } + + public static long getTime(World world) { + return world.getWorldInfo().getWorldTime(); + } + + public static void setTime(long l, World world) { + world.getWorldInfo().setWorldTime(l); + } + + public static void setSlotContents(EntityPlayer player, int slot, ItemStack item, boolean containerInv) { + if (slot == -999) + player.inventory.setItemStack(item); + else if (containerInv) + player.openContainer.putStackInSlot(slot, item); + else + player.inventory.setInventorySlotContents(slot, item); + } + + public static ItemStack getSlotContents(EntityPlayer player, int slot, boolean containerInv) { + if (slot == -999) + return player.inventory.getItemStack(); + else if (containerInv) + return player.openContainer.getSlot(slot).getStack(); + else + return player.inventory.getStackInSlot(slot); + } + + @SuppressWarnings("unchecked") + public static void deleteAllItems(EntityPlayerMP player) { + for (Slot slot : (List) player.openContainer.inventorySlots) + slot.putStack(null); + + player.sendContainerAndContentsToPlayer(player.openContainer, player.openContainer.getInventory()); + } + + public static void setHourForward(World world, int hour, boolean notify) { + long day = (getTime(world) / 24000L) * 24000L; + long newTime = day + 24000L + hour * 1000; + setTime(newTime, world); + if (notify) + ServerUtils.sendChatToAll(new ChatComponentTranslation("nei.chat.time", getTime(world) / 24000L, hour)); + } + + public static void advanceDisabledTimes(World world) { + int dim = CommonUtils.getDimension(world); + int hour = (int) (getTime(world) % 24000) / 1000; + int newhour = hour; + while (NEIServerConfig.isActionDisabled(dim, NEIActions.timeZones[newhour / 6])) + newhour = ((newhour / 6 + 1) % 4) * 6; + + if (newhour != hour) + setHourForward(world, newhour, false); + } + + public static boolean canItemFitInInventory(EntityPlayer player, ItemStack itemstack) { + return InventoryUtils.insertItem(player.inventory, itemstack, true) == 0; + } + + public static void sendNotice(ICommandSender sender, IChatComponent msg, String permission) { + ChatComponentTranslation notice = new ChatComponentTranslation("chat.type.admin", sender.getCommandSenderName(), msg.createCopy()); + notice.getChatStyle().setColor(EnumChatFormatting.GRAY).setItalic(true); + + if (NEIServerConfig.canPlayerPerformAction("CONSOLE", permission)) + MinecraftServer.getServer().addChatMessage(notice); + + for (EntityPlayer p : ServerUtils.getPlayers()) + if(p == sender) + p.addChatComponentMessage(msg); + else if (NEIServerConfig.canPlayerPerformAction(p.getCommandSenderName(), permission)) + p.addChatComponentMessage(notice); + } + + /** + * @param stack1 The {@link ItemStack} being compared. + * @param stack2 The {@link ItemStack} to compare to. + * @return whether the two items are the same in terms of damage and itemID. + */ + public static boolean areStacksSameType(ItemStack stack1, ItemStack stack2) { + if (stack1 == null || stack2 == null) + return stack1 == stack2; + + return InventoryUtils.canStack(stack1, stack2); + } + + /** + * {@link ItemStack}s with damage -1 are wildcards allowing all damages. Eg all colours of wool are allowed to create Beds. + * + * @param stack1 The {@link ItemStack} being compared. + * @param stack2 The {@link ItemStack} to compare to. + * @return whether the two items are the same from the perspective of a crafting inventory. + */ + public static boolean areStacksSameTypeCrafting(ItemStack stack1, ItemStack stack2) { + if (stack1 == null || stack2 == null) + return false; + + return stack1.getItem() == stack2.getItem() && + (stack1.getItemDamage() == stack2.getItemDamage() || stack1.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack2.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack1.getItem().isDamageable()); + } + + /** + * A simple function for comparing ItemStacks in a compatible with comparators. + * + * @param stack1 The {@link ItemStack} being compared. + * @param stack2 The {@link ItemStack} to compare to. + * @return The ordering of stack1 relative to stack2. + */ + public static int compareStacks(ItemStack stack1, ItemStack stack2) { + if (stack1 == stack2) return 0;//catches both null + if (stack1 == null || stack2 == null) return stack1 == null ? -1 : 1;//null stack goes first + if (stack1.getItem() != stack2.getItem()) return Item.getIdFromItem(stack1.getItem()) - Item.getIdFromItem(stack2.getItem()); + if (stack1.stackSize != stack2.stackSize) return stack1.stackSize - stack2.stackSize; + return stack1.getItemDamage() - stack2.getItemDamage(); + } + + public static boolean areStacksIdentical(ItemStack stack1, ItemStack stack2) { + return compareStacks(stack1, stack2) == 0; + } + + public static IChatComponent setColour(IChatComponent msg, EnumChatFormatting colour) { + msg.getChatStyle().setColor(colour); + return msg; + } + + public static void givePlayerItem(EntityPlayerMP player, ItemStack stack, boolean infinite, boolean doGive) { + if (stack.getItem() == null) { + player.addChatComponentMessage(setColour(new ChatComponentTranslation("nei.chat.give.noitem"), EnumChatFormatting.WHITE)); + return; + } + + int given = stack.stackSize; + if(doGive) { + if (infinite) + player.inventory.addItemStackToInventory(stack); + else + given -= InventoryUtils.insertItem(player.inventory, stack, false); + } + + sendNotice(player, new ChatComponentTranslation("commands.give.success", stack.func_151000_E(), infinite ? "\u221E" : Integer.toString(given), player.getCommandSenderName()), "notify-item"); + player.openContainer.detectAndSendChanges(); + } + + public static ItemStack copyStack(ItemStack itemstack, int i) { + if (itemstack == null) + return null; + + itemstack.stackSize += i; + return itemstack.splitStack(i); + } + + public static ItemStack copyStack(ItemStack itemstack) { + if (itemstack == null) + return null; + + return copyStack(itemstack, itemstack.stackSize); + } + + public static void toggleMagnetMode(EntityPlayerMP player) { + PlayerSave playerSave = NEIServerConfig.forPlayer(player.getCommandSenderName()); + playerSave.enableAction("magnet", !playerSave.isActionEnabled("magnet")); + } + + public static int getCreativeMode(EntityPlayerMP player) { + if (NEIServerConfig.forPlayer(player.getCommandSenderName()).isActionEnabled("creative+")) + return 2; + else if (player.theItemInWorldManager.isCreative()) + return 1; + else if (player.theItemInWorldManager.getGameType().isAdventure()) + return 3; + else + return 0; + } + + public static GameType getGameType(int mode) { + switch (mode) { + case 0: + return GameType.SURVIVAL; + case 1: + case 2: + return GameType.CREATIVE; + case 3: + return GameType.ADVENTURE; + } + return null; + } + + public static void setGamemode(EntityPlayerMP player, int mode) { + if (mode < 0 || mode >= NEIActions.gameModes.length || + NEIActions.nameActionMap.containsKey(NEIActions.gameModes[mode]) && + !NEIServerConfig.canPlayerPerformAction(player.getCommandSenderName(), NEIActions.gameModes[mode])) + return; + + //change it on the server + player.theItemInWorldManager.setGameType(getGameType(mode)); + NEIServerConfig.forPlayer(player.getCommandSenderName()).enableAction("creative+", mode == 2); + + //tell the client to change it + new PacketCustom(NEISPH.channel, 14).writeByte(mode).sendToPlayer(player); + player.addChatMessage(new ChatComponentTranslation("nei.chat.gamemode." + mode)); + } + + public static void cycleCreativeInv(EntityPlayerMP player, int steps) { + InventoryPlayer inventory = player.inventory; + + //top down [row][col] + ItemStack[][] slots = new ItemStack[10][9]; + PlayerSave playerSave = NEIServerConfig.forPlayer(player.getCommandSenderName()); + + //get + System.arraycopy(inventory.mainInventory, 0, slots[9], 0, 9); + + for (int row = 0; row < 3; row++) + System.arraycopy(inventory.mainInventory, (row + 1) * 9, slots[row + 6], 0, 9); + + for (int row = 0; row < 6; row++) + System.arraycopy(playerSave.creativeInv, row * 9, slots[row], 0, 9); + + ItemStack[][] newslots = new ItemStack[10][]; + + //put back + for (int row = 0; row < 10; row++) + newslots[(row + steps + 10) % 10] = slots[row]; + + System.arraycopy(newslots[9], 0, inventory.mainInventory, 0, 9); + + for (int row = 0; row < 3; row++) + System.arraycopy(newslots[row + 6], 0, inventory.mainInventory, (row + 1) * 9, 9); + + for (int row = 0; row < 6; row++) + System.arraycopy(newslots[row], 0, playerSave.creativeInv, row * 9, 9); + + playerSave.setDirty(); + } + + public static List getEnchantments(ItemStack itemstack) { + ArrayList arraylist = new ArrayList(); + if (itemstack != null) { + NBTTagList nbttaglist = itemstack.getEnchantmentTagList(); + if (nbttaglist != null) + for (int i = 0; i < nbttaglist.tagCount(); i++) { + NBTTagCompound tag = nbttaglist.getCompoundTagAt(i); + arraylist.add(new int[]{tag.getShort("id"), tag.getShort("lvl")}); + } + } + return arraylist; + } + + public static boolean stackHasEnchantment(ItemStack itemstack, int e) { + List allenchantments = getEnchantments(itemstack); + for (int[] ai : allenchantments) + if (ai[0] == e) + return true; + + return false; + } + + public static int getEnchantmentLevel(ItemStack itemstack, int e) { + List allenchantments = getEnchantments(itemstack); + for (int[] ai : allenchantments) + if (ai[0] == e) + return ai[1]; + + return -1; + } + + public static boolean doesEnchantmentConflict(List enchantments, Enchantment e) { + for (int[] ai : enchantments) + if (!e.canApplyTogether(Enchantment.enchantmentsList[ai[0]])) + return true; + + return false; + } + + public static RuntimeException throwCME(String msg) { + if (CommonUtils.isClient()) + return ClientHandler.throwCME(msg); + + throw new RuntimeException(msg); + } + + @SuppressWarnings("unchecked") + public static ItemStack[] extractRecipeItems(Object obj) { + if (obj instanceof ItemStack) + return new ItemStack[]{(ItemStack) obj}; + if (obj instanceof ItemStack[]) + return (ItemStack[]) obj; + if (obj instanceof List) + return ((List) obj).toArray(new ItemStack[0]); + + throw new ClassCastException("not an ItemStack, ItemStack[] or List getRange(final int start, final int end) { + return new AbstractList() + { + @Override + public Integer get(int index) { + return start+index; + } + + @Override + public int size() { + return end-start; + } + }; + } + + public static StringBuilder fixTrailingCommaList(StringBuilder sb) { + if(sb.charAt(sb.length()-1) == ',') + sb.deleteCharAt(sb.length()-1); + return sb; + } +} diff --git a/src/codechicken/nei/OffsetPositioner.java b/src/codechicken/nei/OffsetPositioner.java new file mode 100644 index 00000000..a76f9f3a --- /dev/null +++ b/src/codechicken/nei/OffsetPositioner.java @@ -0,0 +1,28 @@ +package codechicken.nei; + +import codechicken.nei.api.IStackPositioner; + +import java.util.ArrayList; + +public class OffsetPositioner implements IStackPositioner +{ + public OffsetPositioner(int x, int y) + { + offsetx = x; + offsety = y; + } + + @Override + public ArrayList positionStacks(ArrayList ai) + { + for(PositionedStack stack : ai) + { + stack.relx+=offsetx; + stack.rely+=offsety; + } + return ai; + } + + public int offsetx; + public int offsety; +} diff --git a/src/codechicken/nei/PlayerSave.java b/src/codechicken/nei/PlayerSave.java new file mode 100644 index 00000000..55e3fa69 --- /dev/null +++ b/src/codechicken/nei/PlayerSave.java @@ -0,0 +1,111 @@ +package codechicken.nei; + +import codechicken.core.ServerUtils; +import codechicken.lib.inventory.InventoryUtils; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; + +import java.io.File; + +public class PlayerSave +{ + public String username; + + private File saveFile; + private NBTTagCompound nbt; + + public ItemStack[] creativeInv; + private boolean creativeInvDirty; + + private boolean isDirty; + private boolean wasOp; + + public PlayerSave(String playername, File saveLocation) { + username = playername; + wasOp = ServerUtils.isPlayerOP(playername); + + saveFile = new File(saveLocation, username + ".dat"); + if (!saveFile.getParentFile().exists()) + saveFile.getParentFile().mkdirs(); + load(); + } + + private void load() { + nbt = new NBTTagCompound(); + try { + if (!saveFile.exists()) + saveFile.createNewFile(); + if (saveFile.length() > 0) + nbt = CompressedStreamTools.read(saveFile); + } catch (Exception e) { + e.printStackTrace(); + } + + loadCreativeInv(); + } + + private void loadCreativeInv() { + creativeInv = new ItemStack[54]; + NBTTagList itemList = nbt.getTagList("creativeitems", 10); + if (itemList != null) + InventoryUtils.readItemStacksFromTag(creativeInv, itemList); + } + + public void save() { + if (!isDirty) + return; + + if (creativeInvDirty) + saveCreativeInv(); + + try { + CompressedStreamTools.write(nbt, saveFile); + isDirty = false; + } catch (Exception e) { + e.printStackTrace(); + } + } + + private void saveCreativeInv() { + NBTTagList invsave = InventoryUtils.writeItemStacksToTag(creativeInv); + nbt.setTag("creativeitems", invsave); + + creativeInvDirty = false; + } + + public void setCreativeDirty() { + creativeInvDirty = isDirty = true; + } + + public void setDirty() { + isDirty = true; + } + + public void updateOpChange(EntityPlayerMP player) { + boolean isOp = ServerUtils.isPlayerOP(username); + if (isOp != wasOp) { + NEISPH.sendHasServerSideTo(player); + wasOp = isOp; + } + } + + public boolean isActionEnabled(String name) { + return getEnabledActions().getBoolean(name); + } + + private NBTTagCompound getEnabledActions() { + NBTTagCompound tag = nbt.getCompoundTag("enabledActions"); + if (!nbt.hasKey("enabledActions")) + nbt.setTag("enabledActions", tag); + return tag; + } + + public void enableAction(String name, boolean enabled) { + getEnabledActions().setBoolean(name, enabled); + NEISPH.sendActionEnabled(ServerUtils.getPlayer(username), name, enabled); + setDirty(); + } +} diff --git a/src/codechicken/nei/PopupInputHandler.java b/src/codechicken/nei/PopupInputHandler.java new file mode 100644 index 00000000..fa8cd70f --- /dev/null +++ b/src/codechicken/nei/PopupInputHandler.java @@ -0,0 +1,69 @@ +package codechicken.nei; + +import codechicken.nei.guihook.IContainerInputHandler; +import net.minecraft.client.gui.inventory.GuiContainer; + +import static codechicken.nei.NEIClientConfig.canPerformAction; +import static codechicken.nei.NEIClientConfig.getKeyBinding; + +public class PopupInputHandler implements IContainerInputHandler +{ + @Override + public boolean keyTyped(GuiContainer gui, char keyChar, int keyCode) + { + return false; + } + + @Override + public boolean mouseClicked(GuiContainer gui, int mousex, int mousey, int button) + { + return false; + } + + @Override + public void onKeyTyped(GuiContainer gui, char keyChar, int keyID) + { + } + + @Override + public boolean lastKeyTyped(GuiContainer gui, char keyChar, int keyID) + { + if(keyID == getKeyBinding("gui.enchant") && canPerformAction("enchant")) + { + NEICPH.sendOpenEnchantmentWindow(); + return true; + } + if(keyID == getKeyBinding("gui.potion") && canPerformAction("potion")) + { + NEICPH.sendOpenPotionWindow(); + return true; + } + return false; + } + + @Override + public void onMouseClicked(GuiContainer gui, int mousex, int mousey, int button) + { + } + + @Override + public void onMouseUp(GuiContainer gui, int mousex, int mousey, int button) + { + } + + @Override + public boolean mouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) + { + return false; + } + + @Override + public void onMouseScrolled(GuiContainer gui, int mousex, int mousey, int scrolled) + { + } + + @Override + public void onMouseDragged(GuiContainer gui, int mousex, int mousey, int button, long heldTime) + { + } +} diff --git a/src/codechicken/nei/PositionedStack.java b/src/codechicken/nei/PositionedStack.java new file mode 100644 index 00000000..dbaaf378 --- /dev/null +++ b/src/codechicken/nei/PositionedStack.java @@ -0,0 +1,119 @@ +package codechicken.nei; + +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +import java.util.ArrayList; +import java.util.List; + +/** + * Simply an {@link ItemStack} with position. + * Mainly used in the recipe handlers. + */ +public class PositionedStack +{ + public int relx; + public int rely; + public ItemStack items[]; + //compatibility dummy + public ItemStack item; + + private boolean permutated = false; + + public PositionedStack(Object object, int x, int y, boolean genPerms) + { + items = NEIServerUtils.extractRecipeItems(object); + relx = x; + rely = y; + + if(genPerms) + generatePermutations(); + else + setPermutationToRender(0); + } + + public PositionedStack(Object object, int x, int y) + { + this(object, x, y, true); + } + + public void generatePermutations() + { + if(permutated) + return; + + ArrayList stacks = new ArrayList(); + for(ItemStack item : items) + { + if(item == null || item.getItem() == null) + continue; + + if(item.getItemDamage() == Short.MAX_VALUE) + { + List permutations = ItemList.itemMap.get(item.getItem()); + if(!permutations.isEmpty()) + { + for(ItemStack stack : permutations) + stacks.add(stack.copy()); + } + else + { + ItemStack base = new ItemStack(item.getItem(), item.stackSize); + base.stackTagCompound = item.stackTagCompound; + stacks.add(base); + } + continue; + } + + stacks.add(item.copy()); + } + items = stacks.toArray(new ItemStack[0]); + + if(items.length == 0) + items = new ItemStack[]{new ItemStack(Blocks.fire)}; + + permutated = true; + setPermutationToRender(0); + } + + public void setMaxSize(int i) + { + for(ItemStack item : items) + if(item.stackSize > i) + item.stackSize = i; + } + + public PositionedStack copy() + { + return new PositionedStack(items, relx, rely); + } + + public void setPermutationToRender(int index) + { + item = items[index].copy(); + if(item.getItem() == null) + item = new ItemStack(Blocks.fire); + else if(item.getItemDamage() == OreDictionary.WILDCARD_VALUE) + item.setItemDamage(0); + } + + public boolean contains(ItemStack ingredient) + { + for(ItemStack item : items) + if(NEIServerUtils.areStacksSameTypeCrafting(item, ingredient)) + return true; + + return false; + } + + public boolean contains(Item ingred) + { + for(ItemStack item : items) + if(item.getItem() == ingred) + return true; + + return false; + } +} diff --git a/src/codechicken/nei/SaveLoadButton.java b/src/codechicken/nei/SaveLoadButton.java new file mode 100644 index 00000000..8a5daac5 --- /dev/null +++ b/src/codechicken/nei/SaveLoadButton.java @@ -0,0 +1,123 @@ +package codechicken.nei; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.ChatAllowedCharacters; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.input.Keyboard; + +import static codechicken.lib.gui.GuiDraw.drawString; +import static codechicken.lib.gui.GuiDraw.getStringWidth; +import static codechicken.nei.NEIClientUtils.translate; + +public abstract class SaveLoadButton extends Button +{ + public SaveLoadButton(String s) + { + super(s); + } + + @Override + public boolean handleClick(int mousex, int mousey, int button) + { + if(button == 1) + { + label = ""; + onTextChange(); + focused = true; + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + return true; + } + return super.handleClick(mousex, mousey, button); + } + + public abstract void onTextChange(); + + @Override + public void onGuiClick(int i, int j) + { + if(!contains(i, j)) + focused = false; + } + + @Override + public boolean handleKeyPress(int keyID, char keyChar) + { + if(!focused) + return false; + + if(keyID == Keyboard.KEY_BACK) + { + if(label.length() > 0) + { + label = label.substring(0, label.length() - 1); + onTextChange(); + backdowntime = System.currentTimeMillis(); + } + } + else if(keyID == Keyboard.KEY_RETURN) + { + focused = false; + } + else if(keyChar == 22)//paste + { + String pastestring = GuiScreen.getClipboardString(); + if(pastestring == null) + pastestring = ""; + + label = label + pastestring; + onTextChange(); + } + else if(ChatAllowedCharacters.isAllowedCharacter(keyChar)) + { + label = label + keyChar; + onTextChange(); + } + return true; + } + + @Override + public void update() + { + cursorCounter++; + if(backdowntime > 0) + { + if(Keyboard.isKeyDown(Keyboard.KEY_BACK) && label.length() > 5) + { + if(System.currentTimeMillis() - backdowntime > 200 / (1+backs * 0.3F)) + { + label = label.substring(0, label.length() - 1); + onTextChange(); + backdowntime = System.currentTimeMillis(); + backs++; + } + } + else + { + backdowntime = 0; + backs = 0; + } + } + } + + @Override + public void draw(int mousex, int mousey) + { + super.draw(mousex, mousey); + if(focused && (cursorCounter / 6) % 2 == 0) + drawString("_", x + (width + getStringWidth(getRenderLabel())) / 2, y + (height - 8) / 2, 0xFFFFFFFF); + } + + @Override + public String getRenderLabel() + { + return translate(saved ? "load" : "save") + " " + label; + } + + public boolean saved; + public long backdowntime; + public int backs; + public int cursorCounter; + public boolean focused; +} diff --git a/src/codechicken/nei/SearchField.java b/src/codechicken/nei/SearchField.java new file mode 100644 index 00000000..fd59a1ea --- /dev/null +++ b/src/codechicken/nei/SearchField.java @@ -0,0 +1,59 @@ +package codechicken.nei; + +import net.minecraft.util.EnumChatFormatting; + +import static codechicken.lib.gui.GuiDraw.drawGradientRect; +import static codechicken.lib.gui.GuiDraw.drawRect; +import static codechicken.nei.NEIClientConfig.world; + +public class SearchField extends TextField +{ + public SearchField(String ident) { + super(ident); + } + + public static boolean searchInventories() { + return world.nbt.getBoolean("searchinventories"); + } + + @Override + public void drawBox() { + if (searchInventories()) + drawGradientRect(x, y, width, height, 0xFFFFFF00, 0xFFC0B000); + else + drawRect(x, y, width, height, 0xffA0A0A0); + drawRect(x + 1, y + 1, width - 2, height - 2, 0xFF000000); + } + + @Override + public boolean handleClick(int mousex, int mousey, int button) { + if (button == 0) { + if (focused() && (System.currentTimeMillis() - lastclicktime < 500))//double click + { + world.nbt.setBoolean("searchinventories", !searchInventories()); + world.saveNBT(); + } + lastclicktime = System.currentTimeMillis(); + } + return super.handleClick(mousex, mousey, button); + } + + @Override + public void onTextChange(String oldText) { + NEIClientConfig.setSearchExpression(text()); + ItemList.updateSearch(); + } + + @Override + public void lastKeyTyped(int keyID, char keyChar) { + if (keyID == NEIClientConfig.getKeyBinding("gui.search")) + setFocus(true); + } + + @Override + public String filterText(String s) { + return EnumChatFormatting.getTextWithoutFormattingCodes(s); + } + + long lastclicktime; +} diff --git a/src/codechicken/nei/ServerHandler.java b/src/codechicken/nei/ServerHandler.java new file mode 100644 index 00000000..7ddc890b --- /dev/null +++ b/src/codechicken/nei/ServerHandler.java @@ -0,0 +1,149 @@ +package codechicken.nei; + +import codechicken.core.CommonUtils; +import codechicken.lib.packet.PacketCustom; +import cpw.mods.fml.common.FMLCommonHandler; +import cpw.mods.fml.common.eventhandler.SubscribeEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerChangedDimensionEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedInEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerLoggedOutEvent; +import cpw.mods.fml.common.gameevent.PlayerEvent.PlayerRespawnEvent; +import cpw.mods.fml.common.gameevent.TickEvent; +import cpw.mods.fml.common.gameevent.TickEvent.Phase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.world.World; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.world.WorldEvent; + +import java.util.List; + +public class ServerHandler +{ + private static ServerHandler instance; + + public static void load() { + instance = new ServerHandler(); + + PacketCustom.assignHandler(NEICPH.channel, new NEISPH()); + FMLCommonHandler.instance().bus().register(instance); + MinecraftForge.EVENT_BUS.register(instance); + + NEIActions.init(); + } + + @SubscribeEvent + public void tickEvent(TickEvent.WorldTickEvent event) { + if (event.phase == Phase.START) + processDisabledProperties(event.world); + } + + @SubscribeEvent + public void loadEvent(WorldEvent.Load event) { + if(!event.world.isRemote) + NEIServerConfig.load(event.world); + } + + @SubscribeEvent + public void tickEvent(TickEvent.PlayerTickEvent event) { + if (event.phase == Phase.START && event.player instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) event.player; + PlayerSave save = NEIServerConfig.forPlayer(player.getCommandSenderName()); + if (save == null) + return; + updateMagneticPlayer(player, save); + save.updateOpChange(player); + save.save(); + } + } + + private void processDisabledProperties(World world) { + NEIServerUtils.advanceDisabledTimes(world); + if (NEIServerUtils.isRaining(world) && NEIServerConfig.isActionDisabled(CommonUtils.getDimension(world), "rain")) + NEIServerUtils.toggleRaining(world, false); + } + + private void updateMagneticPlayer(EntityPlayerMP player, PlayerSave save) { + if (!save.isActionEnabled("magnet") || player.isDead) + return; + + float distancexz = 16; + float distancey = 8; + double maxspeedxz = 0.5; + double maxspeedy = 0.5; + double speedxz = 0.05; + double speedy = 0.07; + List items = player.worldObj.getEntitiesWithinAABB(EntityItem.class, player.boundingBox.expand(distancexz, distancey, distancexz)); + for (EntityItem item : items) { + if (item.delayBeforeCanPickup > 0) continue; + if (!NEIServerUtils.canItemFitInInventory(player, item.getEntityItem())) continue; + if (item.delayBeforeCanPickup == 0) { + NEISPH.sendAddMagneticItemTo(player, item); + } + + double dx = player.posX - item.posX; + double dy = player.posY + player.getEyeHeight() - item.posY; + double dz = player.posZ - item.posZ; + double absxz = Math.sqrt(dx * dx + dz * dz); + double absy = Math.abs(dy); + if (absxz > distancexz) { + continue; + } + if (absxz < 1) { + item.onCollideWithPlayer(player); + } + + if (absxz > 1) { + dx /= absxz; + dz /= absxz; + } + + if (absy > 1) { + dy /= absy; + } + + double vx = item.motionX + speedxz * dx; + double vy = item.motionY + speedy * dy; + double vz = item.motionZ + speedxz * dz; + + double absvxz = Math.sqrt(vx * vx + vz * vz); + double absvy = Math.abs(vy); + + double rationspeedxz = absvxz / maxspeedxz; + if (rationspeedxz > 1) { + vx /= rationspeedxz; + vz /= rationspeedxz; + } + + double rationspeedy = absvy / maxspeedy; + if (rationspeedy > 1) { + vy /= rationspeedy; + } + + item.motionX = vx; + item.motionY = vy; + item.motionZ = vz; + } + } + + @SubscribeEvent + public void loginEvent(PlayerLoggedInEvent event) { + NEIServerConfig.loadPlayer(event.player); + NEISPH.sendHasServerSideTo((EntityPlayerMP) event.player); + } + + @SubscribeEvent + public void logoutEvent(PlayerLoggedOutEvent event) { + NEIServerConfig.unloadPlayer(event.player); + } + + @SubscribeEvent + public void dimChangeEvent(PlayerChangedDimensionEvent event) { + NEISPH.sendHasServerSideTo((EntityPlayerMP) event.player); + } + + @SubscribeEvent + public void loginEvent(PlayerRespawnEvent event) { + NEISPH.sendHasServerSideTo((EntityPlayerMP) event.player); + } +} diff --git a/src/codechicken/nei/SlotOP.java b/src/codechicken/nei/SlotOP.java new file mode 100644 index 00000000..62030b45 --- /dev/null +++ b/src/codechicken/nei/SlotOP.java @@ -0,0 +1,10 @@ +package codechicken.nei; + +public abstract class SlotOP +{ + public abstract String getDescription(); + + public abstract int[] getKeyBind(); + + public abstract void operate(); +} diff --git a/src/codechicken/nei/SpawnerRenderer.java b/src/codechicken/nei/SpawnerRenderer.java new file mode 100644 index 00000000..79765567 --- /dev/null +++ b/src/codechicken/nei/SpawnerRenderer.java @@ -0,0 +1,97 @@ +package codechicken.nei; + +import codechicken.core.ClientUtils; +import codechicken.lib.render.TextureUtils; +import net.minecraft.client.renderer.OpenGlHelper; +import net.minecraft.client.renderer.RenderBlocks; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.boss.BossStatus; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.client.IItemRenderer; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL12; + +public class SpawnerRenderer implements IItemRenderer +{ + @Override + public boolean handleRenderType(ItemStack item, ItemRenderType type) + { + return true; + } + + public void renderInventoryItem(RenderBlocks render, ItemStack item) + { + int meta = item.getItemDamage(); + + if(meta == 0) + { + meta = ItemMobSpawner.idPig; + } + String bossName = BossStatus.bossName; + int bossTimeout = BossStatus.statusBarTime; + try + { + World world = NEIClientUtils.mc().theWorld; + ItemMobSpawner.loadSpawners(world); + TextureUtils.bindAtlas(0); + render.renderBlockAsItem(Blocks.mob_spawner, 0, 1F); + GL11.glPushMatrix(); + + Entity entity = ItemMobSpawner.getEntity(meta); + if(entity != null) + { + entity.setWorld(world); + float f1 = 0.4375F; + if(entity.getShadowSize() > 1.5) + { + f1 = 0.1F; + } + GL11.glRotatef((float) (ClientUtils.getRenderTime()*10), 0.0F, 1.0F, 0.0F); + GL11.glRotatef(-20F, 1.0F, 0.0F, 0.0F); + GL11.glTranslatef(0.0F, -0.4F, 0.0F); + GL11.glScalef(f1, f1, f1); + entity.setLocationAndAngles(0, 0, 0, 0.0F, 0.0F); + RenderManager.instance.renderEntityWithPosYaw(entity, 0.0D, 0.0D, 0.0D, 0.0F, 0); + } + GL11.glPopMatrix(); + + GL11.glEnable(GL12.GL_RESCALE_NORMAL); + OpenGlHelper.setActiveTexture(OpenGlHelper.lightmapTexUnit); + GL11.glDisable(GL11.GL_TEXTURE_2D); + OpenGlHelper.setActiveTexture(OpenGlHelper.defaultTexUnit); + } + catch(Exception e) + { + if(Tessellator.instance.isDrawing) + Tessellator.instance.draw(); + } + BossStatus.bossName = bossName; + BossStatus.statusBarTime = bossTimeout; + } + + @SuppressWarnings("incomplete-switch") + @Override + public void renderItem(ItemRenderType type, ItemStack item, Object... data) + { + switch(type) + { + case EQUIPPED: + case EQUIPPED_FIRST_PERSON: + GL11.glTranslatef(0.5F, 0.5F, 0.5F); + case INVENTORY: + case ENTITY: + renderInventoryItem((RenderBlocks)data[0], item); + break; + } + } + + @Override + public boolean shouldUseRenderHelper(ItemRenderType type, ItemStack item, ItemRendererHelper helper) + { + return true; + } +} diff --git a/src/codechicken/nei/TMIUninstaller.java b/src/codechicken/nei/TMIUninstaller.java new file mode 100644 index 00000000..c298f1bc --- /dev/null +++ b/src/codechicken/nei/TMIUninstaller.java @@ -0,0 +1,279 @@ +package codechicken.nei; + +import net.minecraft.client.Minecraft; + +import javax.swing.*; +import java.awt.*; +import java.awt.LayoutManager; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.io.*; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +public class TMIUninstaller +{ + public static class InstallerGui extends JFrame + { + private static final long serialVersionUID = 1L; + private JTextField labelInfo; + private static final String PREFERRED_LOOK_AND_FEEL = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"; + + public InstallerGui() { + setTitle("TMI Uninstaller"); + initComponents(); + } + + private class ResizeListener implements LayoutManager + { + public void addLayoutComponent(String name, Component comp) { + } + + public void layoutContainer(Container parent) { + int w = getContentPane().getWidth(); + labelInfo.setBounds(10, 45, w - 20, 20); + labelInfo.setScrollOffset(1000); + labelInfo.update(getGraphics()); + } + + public Dimension minimumLayoutSize(Container parent) { + return new Dimension(150, 100); + } + + public Dimension preferredLayoutSize(Container parent) { + return new Dimension(250, 120); + } + + + public void removeLayoutComponent(Component comp) { + } + } + + private void initComponents() { + setLayout(new ResizeListener()); + add(getLabelInfo()); + setSize(358, 270); + } + + public class InstallerListener implements ActionListener + { + public void actionPerformed(ActionEvent e) { + } + } + + public JTextField getLabelInfo() { + if (labelInfo == null) { + labelInfo = new JTextField(); + labelInfo.setFont(new Font("Tahoma", Font.PLAIN, 13)); + labelInfo.setHorizontalAlignment(SwingConstants.CENTER); + labelInfo.setEditable(false); + labelInfo.setText("Uninstalling TMI"); + } + return labelInfo; + } + + public static void installLnF() { + try { + String lnfClassname = UIManager.getCrossPlatformLookAndFeelClassName(); + UIManager.setLookAndFeel(lnfClassname); + } catch (Exception e) { + System.err.println("Cannot install " + PREFERRED_LOOK_AND_FEEL + " on this platform:" + e.getMessage()); + } + } + } + + private static File jarFile; + public static InstallerGui mainframe; + + public static void main(String[] args) { + jarFile = new File(args[0]); + + InstallerGui.installLnF(); + mainframe = new InstallerGui(); + mainframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + mainframe.setLocationRelativeTo(null); + mainframe.pack(); + mainframe.setVisible(true); + + if (!jarFile.exists()) + mainframe.getLabelInfo().setText("Invalid Minecraft.jar"); + else + uninstall(); + } + + private static File getJarFile() { + URL url = Minecraft.class.getProtectionDomain().getCodeSource().getLocation(); + try { + if (url.getProtocol().equals("jar")) + url = new URL(url.getPath().substring(0, url.getPath().indexOf('!'))); + return new File(url.toURI()); + } catch (URISyntaxException e) { + return new File(url.getPath()); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + public static void deleteTMIUninstaller() throws IOException { + File file = new File(getJarFile().getParentFile(), "TMIUninstaller"); + if (file.exists()) { + NEIClientConfig.logger.info("Removing TMI Uninstaller"); + deleteDir(file, true); + } + } + + public static boolean TMIInstalled() { + File jarFile = getJarFile(); + if (!jarFile.getName().endsWith(".jar")) + return false; + + try { + ZipFile zip = new ZipFile(jarFile); + ZipEntry tmi = zip.getEntry("mod_TooManyItems.class"); + zip.close(); + return tmi != null; + } catch (Exception e) { + return false; + } + } + + public static void runTMIUninstaller() throws IOException { + File jarFile = getJarFile(); + File uninstDir = new File(jarFile.getParentFile(), "TMIUninstaller"); + if (!uninstDir.exists()) + uninstDir.mkdirs(); + + NEIClientConfig.logger.info("Installing Uninstaller: " + uninstDir.getPath()); + + FileInputStream fileinputstream = new FileInputStream(jarFile); + ZipInputStream zipinputstream = new ZipInputStream(fileinputstream); + do { + ZipEntry zipentry = zipinputstream.getNextEntry(); + if (zipentry == null) { + break; + } + String fullname = zipentry.getName().replace('\\', '/'); + if (!zipentry.isDirectory() && fullname.replace('/', '.').startsWith(TMIUninstaller.class.getCanonicalName())) { + File outFile = new File(uninstDir, fullname); + NEIClientConfig.logger.info("Extracting File: " + outFile.getPath()); + + if (!outFile.getParentFile().exists()) + outFile.getParentFile().mkdirs(); + + outFile.createNewFile(); + FileOutputStream fout = new FileOutputStream(outFile); + + byte[] buffer = new byte[65535]; + int read = 0; + while ((read = zipinputstream.read(buffer)) != -1)//write loop + { + fout.write(buffer, 0, read); + } + fout.close(); + } + } + while (true); + fileinputstream.close(); + + String javaBin = System.getProperty("java.home") + File.separator + "bin" + File.separator + "java"; + + String classpath = uninstDir.getAbsolutePath(); + String className = TMIUninstaller.class.getCanonicalName(); + + String jarPath = jarFile.getPath(); + + NEIClientConfig.logger.info("Running Process: " + javaBin + " -cp \"" + classpath + "\" \"" + className + "\" \"" + jarPath + "\""); + + ProcessBuilder builder = new ProcessBuilder(javaBin, "-cp", classpath, className, jarPath); + builder.start(); + } + + public static void deleteDir(File directory, boolean remove) throws IOException { + NEIClientConfig.logger.debug("Deleting Dir: " + directory.getPath()); + if (!directory.exists()) { + if (!remove) + directory.mkdirs(); + + return; + } + for (File file : directory.listFiles()) { + if (file.isDirectory()) { + deleteDir(file, true); + } else { + if (!file.delete()) { + throw new IOException("Delete Failed: " + file); + } + } + } + if (remove) { + try { + if (!directory.delete()) { + throw new IOException("Delete Failed: " + directory); + } + } catch (SecurityException e) { + throw e; + } + } + } + + public static void uninstall() { + File backupfile = new File(jarFile.getParentFile(), jarFile.getName() + ".bak"); + try { + if (!backupfile.exists()) + backupfile.createNewFile(); + + FileOutputStream backout = new FileOutputStream(backupfile); + FileInputStream jarin = new FileInputStream(jarFile); + backout.getChannel().transferFrom(jarin.getChannel(), 0, jarFile.length()); + + backout.close(); + jarin.close(); + + ZipInputStream zipin = new ZipInputStream(new FileInputStream(backupfile)); + ZipOutputStream zipout = new ZipOutputStream(new FileOutputStream(jarFile)); + byte[] buffer = new byte[20000]; + int read = 0; + while (true) { + ZipEntry entry = zipin.getNextEntry(); + if (entry == null) { + break; + } + if (entry.isDirectory()) continue; + String name = entry.getName(); + if (name.startsWith("TMI") || name.startsWith("_tmi") || name.startsWith("tmi.png") || name.startsWith("mod_TooManyItems")) { + continue; + } + zipout.putNextEntry(new ZipEntry(name)); + InputStream in = zipin; + while ((read = in.read(buffer)) != -1) { + zipout.write(buffer, 0, read); + } + zipout.closeEntry(); + zipin.closeEntry(); + } + zipin.close(); + zipout.close(); + + mainframe.getLabelInfo().setText("Uninstall Completed. Close this and restart minecraft."); + } catch (Exception e) { + e.printStackTrace(); + mainframe.getLabelInfo().setText("Invalid Minecraft.jar"); + try { + FileInputStream backin = new FileInputStream(backupfile); + FileOutputStream jarout = new FileOutputStream(jarFile); + jarout.getChannel().transferFrom(backin.getChannel(), 0, backupfile.length()); + + backin.close(); + jarout.close(); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } +} diff --git a/src/codechicken/nei/TextField.java b/src/codechicken/nei/TextField.java new file mode 100644 index 00000000..2bf4e627 --- /dev/null +++ b/src/codechicken/nei/TextField.java @@ -0,0 +1,182 @@ +package codechicken.nei; + +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.util.ChatAllowedCharacters; +import org.lwjgl.input.Keyboard; + +import static codechicken.lib.gui.GuiDraw.*; + +public abstract class TextField extends Widget +{ + public TextField(String ident) + { + identifier = ident; + } + + public int getTextColour() + { + return focused() ? 0xFFE0E0E0 : 0xFF909090; + } + + public void drawBox() + { + drawRect(x, y, width, height, 0xffA0A0A0); + drawRect(x + 1, y + 1, width - 2, height - 2, 0xFF000000); + } + + @Override + public void draw(int mousex, int mousey) + { + drawBox(); + + String drawtext = text; + + if(text.length() > getMaxTextLength()) + { + int startOffset = drawtext.length() - getMaxTextLength(); + if(startOffset < 0 || startOffset > drawtext.length()) + startOffset = 0; + drawtext = drawtext.substring(startOffset); + } + + if(focused() && (cursorCounter / 6) % 2 == 0) + drawtext = drawtext + '_'; + + int textWidth = getStringWidth(text); + int textx = centered ? x+(width-textWidth)/2 : x + 4; + int texty = y + (height + 1) / 2 - 3; + + drawString(drawtext, textx, texty, getTextColour()); + } + + @Override + public void onGuiClick(int mousex, int mousey) + { + if(!contains(mousex, mousey)) + setFocus(false); + } + + @Override + public boolean handleClick(int mousex, int mousey, int button) + { + if(button == 1) + setText(""); + setFocus(true); + return true; + } + + @Override + public boolean handleKeyPress(int keyID, char keyChar) + { + if(!focused()) + return false; + + if(keyID == Keyboard.KEY_BACK) + { + if(text.length() > 0) + { + setText(text.substring(0, text.length() - 1)); + backdowntime = System.currentTimeMillis(); + } + } + else if(keyID == Keyboard.KEY_RETURN || keyID == Keyboard.KEY_ESCAPE) + { + setFocus(false); + onExit(); + } + else if(keyChar == 22)//paste + { + String pastestring = GuiScreen.getClipboardString(); + if(pastestring == null) + pastestring = ""; + + if(isValid(text + pastestring)) + setText(text + pastestring); + } + else if(isValid(text+keyChar)) + setText(text+keyChar); + + return true; + } + + public void onExit() + { + } + + public abstract void onTextChange(String oldText); + + public boolean isValid(String string) + { + // Solve the problem that Minecraft can't post Chinese characters + return ChatAllowedCharacters.isAllowedCharacter(string.charAt(string.length()-1)); + } + + @Override + public void update() + { + cursorCounter++; + if(backdowntime > 0) + { + if(Keyboard.isKeyDown(Keyboard.KEY_BACK) && text.length() > 0) + { + if(System.currentTimeMillis() - backdowntime > 200 / (1+backs * 0.3F)) + { + setText(text.substring(0, text.length() - 1)); + backdowntime = System.currentTimeMillis(); + backs++; + } + } + else + { + backdowntime = 0; + backs = 0; + } + } + } + + public void setText(String s) + { + String oldText = text; + text = filterText(s); + onTextChange(oldText); + } + + public String filterText(String s) + { + return s; + } + + private int getMaxTextLength() + { + return width / 6 - 2; + } + + public void setFocus(boolean focus) + { + if(focus) + { + LayoutManager.setInputFocused(this); + } + else if(focused()) + { + LayoutManager.setInputFocused(null); + } + } + + public boolean focused() + { + return LayoutManager.getInputFocused() == this; + } + + public String text() + { + return text; + } + + private String text = ""; + public boolean centered; + public long backdowntime; + public int backs; + public String identifier; + public int cursorCounter; +} diff --git a/src/codechicken/nei/VisiblityData.java b/src/codechicken/nei/VisiblityData.java new file mode 100644 index 00000000..f5753aa8 --- /dev/null +++ b/src/codechicken/nei/VisiblityData.java @@ -0,0 +1,38 @@ +package codechicken.nei; + +public class VisiblityData +{ + public boolean showUtilityButtons = true; + public boolean showStateButtons = true; + /** + * Item panel and associated buttons + */ + public boolean showItemPanel = true; + /** + * Item and search section + */ + public boolean showItemSection = true; + /** + * Dropdown and Item search field + */ + public boolean showSearchSection = true; + /** + * All widgets except options button + */ + public boolean showWidgets = true; + /** + * The entire NEI interface, aka hidden + */ + public boolean showNEI = true; + public boolean enableDeleteMode = true; + + public void translateDependancies() + { + if(!showNEI) + showWidgets = false; + if(!showWidgets) + showItemSection = showUtilityButtons = showStateButtons = false; + if(!showItemSection) + showSearchSection = showItemPanel = false; + } +} diff --git a/src/codechicken/nei/Widget.java b/src/codechicken/nei/Widget.java new file mode 100644 index 00000000..77a56910 --- /dev/null +++ b/src/codechicken/nei/Widget.java @@ -0,0 +1,72 @@ +package codechicken.nei; + +import net.minecraft.item.ItemStack; + +import java.util.List; + +public abstract class Widget +{ + public Widget() { + } + + public abstract void draw(int mousex, int mousey); + + public void postDraw(int mousex, int mousey) { + } + + public boolean handleClick(int mousex, int mousey, int button) { + return true; + } + + public void onGuiClick(int mousex, int mousey) { + } + + public void mouseUp(int mousex, int mousey, int button) { + + } + + public boolean handleKeyPress(int keyID, char keyChar) { + return false; + } + + public void lastKeyTyped(int keyID, char keyChar) { + } + + public boolean handleClickExt(int mousex, int mousey, int button) { + return false; + } + + public boolean onMouseWheel(int i, int mousex, int mousey) { + return false; + } + + public void update() { + } + + public boolean contains(int posx, int posy) { + return posx >= x && posx < x + width && posy >= y && posy < y + height; + } + + public ItemStack getStackMouseOver(int mousex, int mousey) { + return null; + } + + public void mouseDragged(int mx, int my, int button, long heldTime) { + } + + public List handleTooltip(int mx, int my, List tooltip) { + return tooltip; + } + + public void loseFocus() { + } + + public void gainFocus() { + } + + public int x; + public int y; + public int z; + public int width; + public int height; +} diff --git a/src/codechicken/nei/WidgetZOrder.java b/src/codechicken/nei/WidgetZOrder.java new file mode 100644 index 00000000..e6679f01 --- /dev/null +++ b/src/codechicken/nei/WidgetZOrder.java @@ -0,0 +1,18 @@ +package codechicken.nei; + +import java.util.Comparator; + +public class WidgetZOrder + implements Comparator +{ + boolean topfirst; + public WidgetZOrder(boolean topfirst) + { + this.topfirst = topfirst; + } + + public int compare(Widget w1, Widget w2) + { + return w1.z != w2.z ? ((topfirst ? w1.z > w2.z : w1.z < w2.z) ? 1 : -1) : 1; + } +} diff --git a/src/codechicken/nei/WorldOverlayRenderer.java b/src/codechicken/nei/WorldOverlayRenderer.java new file mode 100644 index 00000000..2bac5899 --- /dev/null +++ b/src/codechicken/nei/WorldOverlayRenderer.java @@ -0,0 +1,222 @@ +package codechicken.nei; + +import codechicken.lib.math.MathHelper; +import codechicken.lib.render.RenderUtils; +import codechicken.nei.KeyManager.IKeyStateTracker; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EnumCreatureType; +import net.minecraft.entity.passive.EntityPig; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.world.EnumSkyBlock; +import net.minecraft.world.SpawnerAnimals; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraft.world.chunk.Chunk; +import org.lwjgl.opengl.GL11; + +public class WorldOverlayRenderer implements IKeyStateTracker +{ + public static int mobOverlay = 0; + public static int chunkOverlay = 0; + + public static void reset() { + mobOverlay = 0; + chunkOverlay = 0; + } + + @Override + public void tickKeyStates() { + if (Minecraft.getMinecraft().currentScreen != null) + return; + + if (KeyManager.keyStates.get("world.moboverlay").down) + mobOverlay = (mobOverlay + 1) % 2; + if (KeyManager.keyStates.get("world.chunkoverlay").down) + chunkOverlay = (chunkOverlay + 1) % 3; + } + + public static void render(float frame) { + GL11.glPushMatrix(); + Entity entity = Minecraft.getMinecraft().renderViewEntity; + RenderUtils.translateToWorldCoords(entity, frame); + + renderChunkBounds(entity); + renderMobSpawnOverlay(entity); + GL11.glPopMatrix(); + } + + private static void renderMobSpawnOverlay(Entity entity) { + if (mobOverlay == 0) + return; + + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glLineWidth(1.5F); + GL11.glBegin(GL11.GL_LINES); + + GL11.glColor4f(1, 0, 0, 1); + int curSpawnMode = 2; + + World world = entity.worldObj; + int x1 = (int) entity.posX; + int z1 = (int) entity.posZ; + int y1 = (int) MathHelper.clip(entity.posY, 16, world.getHeight() - 16); + + for (int x = x1 - 16; x <= x1 + 16; x++) + for (int z = z1 - 16; z <= z1 + 16; z++) { + Chunk chunk = world.getChunkFromBlockCoords(x, z); + BiomeGenBase biome = world.getBiomeGenForCoords(x, z); + if (biome.getSpawnableList(EnumCreatureType.monster).isEmpty() || biome.getSpawningChance() <= 0) + continue; + + for (int y = y1 - 16; y < y1 + 16; y++) { + int spawnMode = getSpawnMode(chunk, x, y, z); + if (spawnMode == 0) + continue; + + if (spawnMode != curSpawnMode) { + if (spawnMode == 1) + GL11.glColor4f(1, 1, 0, 1); + else + GL11.glColor4f(1, 0, 0, 1); + curSpawnMode = spawnMode; + } + + GL11.glVertex3d(x, y + 0.004, z); + GL11.glVertex3d(x + 1, y + 0.004, z + 1); + GL11.glVertex3d(x + 1, y + 0.004, z); + GL11.glVertex3d(x, y + 0.004, z + 1); + } + } + + GL11.glEnd(); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + private static Entity dummyEntity = new EntityPig(null); + private static AxisAlignedBB aabb = AxisAlignedBB.getBoundingBox(0, 0, 0, 0, 0, 0); + private static int getSpawnMode(Chunk chunk, int x, int y, int z) { + if (!SpawnerAnimals.canCreatureTypeSpawnAtLocation(EnumCreatureType.monster, chunk.worldObj, x, y, z) || + chunk.getSavedLightValue(EnumSkyBlock.Block, x & 15, y, z & 15) >= 8) + return 0; + + aabb.minX = x + 0.2; + aabb.maxX = x + 0.8; + aabb.minY = y + 0.01; + aabb.maxY = y + 1.8; + aabb.minZ = z + 0.2; + aabb.maxZ = z + 0.8; + if (!chunk.worldObj.checkNoEntityCollision(aabb) || + !chunk.worldObj.getCollidingBoundingBoxes(dummyEntity, aabb).isEmpty() || + chunk.worldObj.isAnyLiquid(aabb)) + return 0; + + if (chunk.getSavedLightValue(EnumSkyBlock.Sky, x & 15, y, z & 15) >= 8) + return 1; + return 2; + } + + private static void renderChunkBounds(Entity entity) { + if (chunkOverlay == 0) + return; + + GL11.glDisable(GL11.GL_TEXTURE_2D); + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glLineWidth(1.5F); + GL11.glBegin(GL11.GL_LINES); + + for (int cx = -4; cx <= 4; cx++) + for (int cz = -4; cz <= 4; cz++) { + double x1 = (entity.chunkCoordX + cx) << 4; + double z1 = (entity.chunkCoordZ + cz) << 4; + double x2 = x1 + 16; + double z2 = z1 + 16; + + double dy = 128; + double y1 = Math.floor(entity.posY - dy / 2); + double y2 = y1 + dy; + if (y1 < 0) { + y1 = 0; + y2 = dy; + } + + if (y1 > entity.worldObj.getHeight()) { + y2 = entity.worldObj.getHeight(); + y1 = y2 - dy; + } + + double dist = Math.pow(1.5, -(cx * cx + cz * cz)); + + GL11.glColor4d(0.9, 0, 0, dist); + if (cx >= 0 && cz >= 0) { + GL11.glVertex3d(x2, y1, z2); + GL11.glVertex3d(x2, y2, z2); + } + if (cx >= 0 && cz <= 0) { + GL11.glVertex3d(x2, y1, z1); + GL11.glVertex3d(x2, y2, z1); + } + if (cx <= 0 && cz >= 0) { + GL11.glVertex3d(x1, y1, z2); + GL11.glVertex3d(x1, y2, z2); + } + if (cx <= 0 && cz <= 0) { + GL11.glVertex3d(x1, y1, z1); + GL11.glVertex3d(x1, y2, z1); + } + + if (chunkOverlay == 2 && cx == 0 && cz == 0) { + dy = 32; + y1 = Math.floor(entity.posY - dy / 2); + y2 = y1 + dy; + if (y1 < 0) { + y1 = 0; + y2 = dy; + } + + if (y1 > entity.worldObj.getHeight()) { + y2 = entity.worldObj.getHeight(); + y1 = y2 - dy; + } + + GL11.glColor4d(0, 0.9, 0, 0.4); + for (double y = (int) y1; y <= y2; y++) { + GL11.glVertex3d(x2, y, z1); + GL11.glVertex3d(x2, y, z2); + GL11.glVertex3d(x1, y, z1); + GL11.glVertex3d(x1, y, z2); + GL11.glVertex3d(x1, y, z2); + GL11.glVertex3d(x2, y, z2); + GL11.glVertex3d(x1, y, z1); + GL11.glVertex3d(x2, y, z1); + } + for (double h = 1; h <= 15; h++) { + GL11.glVertex3d(x1 + h, y1, z1); + GL11.glVertex3d(x1 + h, y2, z1); + GL11.glVertex3d(x1 + h, y1, z2); + GL11.glVertex3d(x1 + h, y2, z2); + GL11.glVertex3d(x1, y1, z1 + h); + GL11.glVertex3d(x1, y2, z1 + h); + GL11.glVertex3d(x2, y1, z1 + h); + GL11.glVertex3d(x2, y2, z1 + h); + } + } + } + + GL11.glEnd(); + GL11.glEnable(GL11.GL_LIGHTING); + GL11.glEnable(GL11.GL_TEXTURE_2D); + GL11.glDisable(GL11.GL_BLEND); + } + + public static void load() { + KeyManager.trackers.add(new WorldOverlayRenderer()); + } +} diff --git a/src/codechicken/nei/api/API.java b/src/codechicken/nei/api/API.java new file mode 100644 index 00000000..c26815ea --- /dev/null +++ b/src/codechicken/nei/api/API.java @@ -0,0 +1,195 @@ +package codechicken.nei.api; + +import codechicken.nei.KeyManager; +import codechicken.nei.KeyManager.KeyState; +import codechicken.nei.LayoutManager; +import codechicken.nei.NEIClientConfig; +import codechicken.nei.OffsetPositioner; +import codechicken.nei.config.Option; +import codechicken.nei.config.OptionKeyBind; +import codechicken.nei.recipe.*; +import net.minecraft.block.Block; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Slot; +import net.minecraft.item.ItemStack; +import org.lwjgl.input.Keyboard; + +/** + * This is the main class that handles item property configuration. + * WARNING: DO NOT access this class until the world has been loaded + * These methods should be called from INEIConfig implementors + */ +public class API +{ + /** + * Register a new Crafting Recipe handler; + * + * @param handler The handler to register + */ + public static void registerRecipeHandler(ICraftingHandler handler) { + GuiCraftingRecipe.registerRecipeHandler(handler); + } + + /** + * Register a new Usage Recipe handler; + * + * @param handler The handler to register + */ + public static void registerUsageHandler(IUsageHandler handler) { + GuiUsageRecipe.registerUsageHandler(handler); + } + + /** + * Add a gui to the default overlay renderer with the default position + * + * @param classz The class of your gui + * @param ident The identification string, currently + * {crafting, crafting2x2, smelting, fuel, brewing} + */ + public static void registerGuiOverlay(Class classz, String ident) { + registerGuiOverlay(classz, ident, 5, 11); + } + + /** + * Add a gui to the default overlay renderer with an offset + * + * @param classz The class of your gui + * @param ident The identification string, currently + * {crafting, crafting2x2, smelting, fuel, brewing} + * @param x x-offset + * @param y y-offset + */ + public static void registerGuiOverlay(Class classz, String ident, int x, int y) { + registerGuiOverlay(classz, ident, new OffsetPositioner(x, y)); + } + + /** + * Add a gui to the default overlay renderer + * + * @param classz The class of your gui + * @param ident The identification string, currently + * {crafting, crafting2x2, smelting, fuel, brewing} + * @param positioner A Stack Repositioner for moving the items to the right place + */ + public static void registerGuiOverlay(Class classz, String ident, IStackPositioner positioner) { + RecipeInfo.registerGuiOverlay(classz, ident, positioner); + } + + /** + * @param classz The class of your gui + * @param handler The handler to register + * @param ident The recipe identification string + */ + public static void registerGuiOverlayHandler(Class classz, IOverlayHandler handler, String ident) { + RecipeInfo.registerOverlayHandler(classz, handler, ident); + } + + /** + * Set the offset to be added to items to translate them into recipe coords on the actual gui, default is 5, 11. Primarily RecipeTransferRects + * + * @param classz The class of your gui + * @param x + * @param y + */ + public static void setGuiOffset(Class classz, int x, int y) { + RecipeInfo.setGuiOffset(classz, x, y); + } + + public static void registerNEIGuiHandler(INEIGuiHandler handler) { + GuiInfo.guiHandlers.add(handler); + } + + /** + * Hide an item from the item panel + * Damage values of OreDictionary.WILDCARD_VALUE and null NBT tags function as wildcards for their respective variables + */ + public static void hideItem(ItemStack item) { + ItemInfo.hiddenItems.add(item); + } + + /** + * Add or replace the name normally shown on the item tooltip + */ + public static void setOverrideName(ItemStack item, String name) { + ItemInfo.nameOverrides.put(item, name); + } + + /** + * Adds an item to the item panel. Any items added using this function will override the default search pattern. + * @param item an item with data + */ + public static void addItemListEntry(ItemStack item) { + ItemInfo.itemOverrides.put(item.getItem(), item); + } + + /** + * Add a custom KeyBinding to be configured in the Controls menu. + * @param ident An identifier for your key, eg "shoot" + * @param defaultKey The default value, commonly obtained from {@link Keyboard} + */ + public static void addKeyBind(String ident, int defaultKey) { + NEIClientConfig.setDefaultKeyBinding(ident, defaultKey); + KeyManager.keyStates.put(ident, new KeyState()); + addOption(new OptionKeyBind(ident)); + } + + public static void addOption(Option option) { + NEIClientConfig.getOptionList().addOption(option); + } + + /** + * Add a new Layout Style for the NEI interface + * @param styleID The Unique ID to be used for storing your style in the config and cycling through avaliable styles + * @param style The style to add. + */ + public static void addLayoutStyle(int styleID, LayoutStyle style) { + LayoutManager.layoutStyles.put(styleID, style); + } + + /** + * Registers a new Infinite Item Handler. + * + * @param handler The handler to be registered. + */ + public static void addInfiniteItemHandler(IInfiniteItemHandler handler) { + ItemInfo.infiniteHandlers.addFirst(handler); + } + + /** + * Registers a new Infinite Item Handler. + * + * @param block The block to handle, null for all. + * @param handler The handler to be registered. + */ + public static void registerHighlightIdentifier(Block block, IHighlightHandler handler) { + ItemInfo.highlightIdentifiers.put(block, handler); + } + + /** + * Tells NEI not to perform any Fast Transfer operations on slots of a particular class + * + * @param slotClass The class of slot to be exempted + */ + public static void addFastTransferExemptSlot(Class slotClass) { + ItemInfo.fastTransferExemptions.add(slotClass); + } + + /** + * Register a new text handler for the block highlight tooltip with a layout specification (HEADER, BODY or FOOTER). + * + * @param handler + * @param layout A HUDAugmenterRegistry.Layout entry. HEADER is displayed before BODY which is displayed before FOOTER. + */ + public static void registerHighlightHandler(IHighlightHandler handler, ItemInfo.Layout... layout) { + ItemInfo.registerHighlightHandler(handler, layout); + } + + /** + * Register a mode handler for overriding NEI recipe/utility/cheat mode settings. + * + * @param handler + */ + public static void registerModeHandler(INEIModeHandler handler) { + NEIInfo.modeHandlers.add(handler); + } +} diff --git a/src/codechicken/nei/api/DefaultOverlayRenderer.java b/src/codechicken/nei/api/DefaultOverlayRenderer.java new file mode 100644 index 00000000..894e2efe --- /dev/null +++ b/src/codechicken/nei/api/DefaultOverlayRenderer.java @@ -0,0 +1,44 @@ +package codechicken.nei.api; + +import codechicken.nei.PositionedStack; +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.inventory.Slot; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.List; + +public class DefaultOverlayRenderer implements IRecipeOverlayRenderer +{ + public DefaultOverlayRenderer(List ai, IStackPositioner positioner) + { + positioner = this.positioner = positioner; + ingreds = new ArrayList(); + for(PositionedStack stack : ai) + ingreds.add(stack.copy()); + ingreds = positioner.positionStacks(ingreds); + } + + @Override + public void renderOverlay(GuiContainerManager gui, Slot slot) + { + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(770, 1); + GL11.glColor4d(0.6, 0.6, 0.6, 0.7); + + GuiContainerManager.setColouredItemRender(true); + for(PositionedStack stack : ingreds) + { + if(stack.relx == slot.xDisplayPosition && stack.rely == slot.yDisplayPosition) + GuiContainerManager.drawItem(stack.relx, stack.rely, stack.item); + } + GuiContainerManager.setColouredItemRender(false); + + GL11.glColor4f(1, 1, 1, 1); + GL11.glDisable(GL11.GL_BLEND); + GL11.glEnable(GL11.GL_LIGHTING); + } + + IStackPositioner positioner; + ArrayList ingreds; +} diff --git a/src/codechicken/nei/api/GuiInfo.java b/src/codechicken/nei/api/GuiInfo.java new file mode 100644 index 00000000..11f71ee5 --- /dev/null +++ b/src/codechicken/nei/api/GuiInfo.java @@ -0,0 +1,26 @@ +package codechicken.nei.api; + +import codechicken.nei.NEIChestGuiHandler; +import codechicken.nei.NEICreativeGuiHandler; +import codechicken.nei.NEIDummySlotHandler; +import net.minecraft.client.gui.inventory.GuiContainer; + +import java.util.Iterator; +import java.util.LinkedList; + +public class GuiInfo +{ + public static LinkedList guiHandlers = new LinkedList(); + + public static void load() { + API.registerNEIGuiHandler(new NEICreativeGuiHandler()); + API.registerNEIGuiHandler(new NEIChestGuiHandler()); + API.registerNEIGuiHandler(new NEIDummySlotHandler()); + } + + public static void clearGuiHandlers() { + for (Iterator iterator = guiHandlers.iterator(); iterator.hasNext(); ) + if (iterator.next() instanceof GuiContainer) + iterator.remove(); + } +} diff --git a/src/codechicken/nei/api/IConfigureNEI.java b/src/codechicken/nei/api/IConfigureNEI.java new file mode 100644 index 00000000..598d5ee3 --- /dev/null +++ b/src/codechicken/nei/api/IConfigureNEI.java @@ -0,0 +1,13 @@ +package codechicken.nei.api; + +/** + * An nei configuration entry point should implement this class and have name "NEIConfig" + * loadConfig will only be called when NEI is installed. + */ +public interface IConfigureNEI +{ + public void loadConfig(); + + public String getName(); + public String getVersion(); +} diff --git a/src/codechicken/nei/api/IGuiContainerOverlay.java b/src/codechicken/nei/api/IGuiContainerOverlay.java new file mode 100644 index 00000000..73cc6322 --- /dev/null +++ b/src/codechicken/nei/api/IGuiContainerOverlay.java @@ -0,0 +1,8 @@ +package codechicken.nei.api; + +import net.minecraft.client.gui.inventory.GuiContainer; + +public interface IGuiContainerOverlay +{ + public GuiContainer getFirstScreen(); +} diff --git a/src/codechicken/nei/api/IHighlightHandler.java b/src/codechicken/nei/api/IHighlightHandler.java new file mode 100644 index 00000000..15fdb02d --- /dev/null +++ b/src/codechicken/nei/api/IHighlightHandler.java @@ -0,0 +1,15 @@ +package codechicken.nei.api; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.world.World; + +import java.util.List; + +public interface IHighlightHandler +{ + public ItemStack identifyHighlight(World world, EntityPlayer player, MovingObjectPosition mop); + + public List handleTextData(ItemStack itemStack, World world, EntityPlayer player, MovingObjectPosition mop, List currenttip, ItemInfo.Layout layout); +} diff --git a/src/codechicken/nei/api/IInfiniteItemHandler.java b/src/codechicken/nei/api/IInfiniteItemHandler.java new file mode 100644 index 00000000..bae6a831 --- /dev/null +++ b/src/codechicken/nei/api/IInfiniteItemHandler.java @@ -0,0 +1,16 @@ +package codechicken.nei.api; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.item.ItemStack; + +public interface IInfiniteItemHandler +{ + void onPickup(ItemStack heldItem); + void onPlaceInfinite(ItemStack heldItem); + + boolean canHandleItem(ItemStack stack); + boolean isItemInfinite(ItemStack stack); + + public void replenishInfiniteStack(InventoryPlayer inventory, int slotNo); + public ItemStack getInfiniteItem(ItemStack typeStack); +} diff --git a/src/codechicken/nei/api/INEIGuiAdapter.java b/src/codechicken/nei/api/INEIGuiAdapter.java new file mode 100644 index 00000000..6ee6413a --- /dev/null +++ b/src/codechicken/nei/api/INEIGuiAdapter.java @@ -0,0 +1,43 @@ +package codechicken.nei.api; + +import codechicken.nei.VisiblityData; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.item.ItemStack; + +import java.util.Collections; +import java.util.List; + +/** + * Lets you just override those things you want to + */ +public class INEIGuiAdapter implements INEIGuiHandler +{ + @Override + public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility) + { + return currentVisibility; + } + + @Override + public Iterable getItemSpawnSlots(GuiContainer gui, ItemStack item) { + return Collections.emptyList(); + } + + @Override + public List getInventoryAreas(GuiContainer gui) + { + return null; + } + + @Override + 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) + { + return false; + } +} diff --git a/src/codechicken/nei/api/INEIGuiHandler.java b/src/codechicken/nei/api/INEIGuiHandler.java new file mode 100644 index 00000000..55b1111a --- /dev/null +++ b/src/codechicken/nei/api/INEIGuiHandler.java @@ -0,0 +1,48 @@ +package codechicken.nei.api; + +import codechicken.nei.VisiblityData; +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.item.ItemStack; + +import java.util.List; + +/** + * If this is implemented on a gui, it will be automatically registered + */ +public interface INEIGuiHandler +{ + public VisiblityData modifyVisiblity(GuiContainer gui, VisiblityData currentVisibility); + + /** + * NEI will give the specified item to the InventoryRange returned if the player's inventory is full. + * return null for no range + */ + public Iterable getItemSpawnSlots(GuiContainer gui, ItemStack item); + + /** + * @return A list of TaggedInventoryAreas that will be used with the savestates. + */ + public List getInventoryAreas(GuiContainer gui); + + /** + * Handles clicks while an itemstack has been dragged from the item panel. Use this to set configurable slots and the like. + * Changes made to the stackSize of the dragged stack will be kept + * @param gui The current gui instance + * @param mousex The x position of the mouse + * @param mousey The y position of the mouse + * @param draggedStack The stack being dragged from the item panel + * @param button The button presed + * @return True if the drag n drop was handled. False to resume processing through other routes. The held stack will be deleted if draggedStack.stackSize == 0 + */ + public boolean handleDragNDrop(GuiContainer gui, int mousex, int mousey, ItemStack draggedStack, int button); + + /** + * Used to prevent the item panel from drawing on top of other gui elements. + * @param x The x coordinate of the rectangle bounding the slot + * @param y The y coordinate of the rectangle bounding the slot + * @param w The w coordinate of the rectangle bounding the slot + * @param h The h coordinate of the rectangle bounding the slot + * @return true if the item panel slot within the specified rectangle should not be rendered. + */ + public boolean hideItemPanelSlot(GuiContainer gui, int x, int y, int w, int h); +} diff --git a/src/codechicken/nei/api/INEIModeHandler.java b/src/codechicken/nei/api/INEIModeHandler.java new file mode 100644 index 00000000..9019764d --- /dev/null +++ b/src/codechicken/nei/api/INEIModeHandler.java @@ -0,0 +1,6 @@ +package codechicken.nei.api; + +public interface INEIModeHandler +{ + public boolean isModeValid(int mode); +} diff --git a/src/codechicken/nei/api/IOverlayHandler.java b/src/codechicken/nei/api/IOverlayHandler.java new file mode 100644 index 00000000..80271f4a --- /dev/null +++ b/src/codechicken/nei/api/IOverlayHandler.java @@ -0,0 +1,9 @@ +package codechicken.nei.api; + +import codechicken.nei.recipe.IRecipeHandler; +import net.minecraft.client.gui.inventory.GuiContainer; + +public interface IOverlayHandler +{ + public void overlayRecipe(GuiContainer firstGui, IRecipeHandler recipe, int recipeIndex, boolean shift); +} diff --git a/src/codechicken/nei/api/IRecipeOverlayRenderer.java b/src/codechicken/nei/api/IRecipeOverlayRenderer.java new file mode 100644 index 00000000..8e659263 --- /dev/null +++ b/src/codechicken/nei/api/IRecipeOverlayRenderer.java @@ -0,0 +1,9 @@ +package codechicken.nei.api; + +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.inventory.Slot; + +public interface IRecipeOverlayRenderer +{ + public void renderOverlay(GuiContainerManager gui, Slot slot); +} diff --git a/src/codechicken/nei/api/IStackPositioner.java b/src/codechicken/nei/api/IStackPositioner.java new file mode 100644 index 00000000..8d95fcb9 --- /dev/null +++ b/src/codechicken/nei/api/IStackPositioner.java @@ -0,0 +1,14 @@ +package codechicken.nei.api; + +import codechicken.nei.PositionedStack; + +import java.util.ArrayList; + +/** + * For repositioning recipes in overlay renderers. + * + */ +public interface IStackPositioner +{ + public ArrayList positionStacks(ArrayList ai); +} diff --git a/src/codechicken/nei/api/ItemInfo.java b/src/codechicken/nei/api/ItemInfo.java new file mode 100644 index 00000000..e0585b22 --- /dev/null +++ b/src/codechicken/nei/api/ItemInfo.java @@ -0,0 +1,431 @@ +package codechicken.nei.api; + +import codechicken.core.featurehack.GameDataManipulator; +import codechicken.nei.*; +import codechicken.nei.config.ArrayDumper; +import codechicken.nei.config.ItemPanelDumper; +import codechicken.nei.config.RegistryDumper; +import codechicken.nei.guihook.GuiContainerManager; +import codechicken.nei.recipe.RecipeItemInputHandler; +import com.google.common.collect.ArrayListMultimap; +import net.minecraft.block.Block; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.entity.EntityList; +import net.minecraft.entity.EntityList.EntityEggInfo; +import net.minecraft.entity.monster.EntityIronGolem; +import net.minecraft.entity.monster.EntitySnowman; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.potion.Potion; +import net.minecraft.util.MovingObjectPosition; +import net.minecraft.util.RegistryNamespaced; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraftforge.common.BiomeDictionary; +import net.minecraftforge.common.IShearable; +import net.minecraftforge.oredict.OreDictionary; + +import java.util.*; + +/** + * This is an internal class for storing information about items, to be accessed by the API + */ +public class ItemInfo +{ + public static enum Layout + { + HEADER, BODY, FOOTER + } + + public static final HashMap> highlightHandlers = new HashMap>(); + public static final ItemStackMap nameOverrides = new ItemStackMap(); + public static final ItemStackSet hiddenItems = new ItemStackSet(); + public static final ItemStackSet finiteItems = new ItemStackSet(); + public static final ArrayListMultimap itemOverrides = ArrayListMultimap.create(); + + public static final LinkedList infiniteHandlers = new LinkedList(); + public static final ArrayListMultimap highlightIdentifiers = ArrayListMultimap.create(); + public static final HashSet> fastTransferExemptions = new HashSet>(); + + public static final HashMap itemOwners = new HashMap(); + + static { + for (Layout layout : Layout.values()) + ItemInfo.highlightHandlers.put(layout, new ArrayList()); + } + + public static boolean isHidden(ItemStack stack) { + return hiddenItems.contains(stack); + } + + public static boolean isHidden(Item item) { + return hiddenItems.containsAll(item); + } + + public static String getNameOverride(ItemStack stack) { + return nameOverrides.get(stack); + } + + public static boolean canBeInfinite(ItemStack stack) { + return !finiteItems.contains(stack); + } + + public static List getItemOverrides(Item item) { + return itemOverrides.get(item); + } + + public static void load(World world) { + addVanillaBlockProperties(); + addDefaultDropDowns(); + searchItems(); + parseModItems(); + addMobSpawnerItem(world); + addSpawnEggs(); + addInfiniteHandlers(); + addInputHandlers(); + addIDDumps(); + } + + private static void addIDDumps() { + API.addOption(new RegistryDumper("tools.dump.item") + { + @Override + public String[] header() { + return new String[]{"Name", "ID", "Has Block", "Mod", "Class"}; + } + + @Override + public String[] dump(Item item, int id, String name) { + return new String[]{ + name, + Integer.toString(id), + Boolean.toString(Block.getBlockFromItem(item) != Blocks.air), + ItemInfo.itemOwners.get(item), + item.getClass().getCanonicalName() + }; + } + + @Override + public RegistryNamespaced registry() { + return Item.itemRegistry; + } + }); + API.addOption(new RegistryDumper("tools.dump.block") + { + @Override + public String[] header() { + return new String[]{"Name", "ID", "Has Item", "Mod", "Class"}; + } + + @Override + public String[] dump(Block item, int id, String name) { + return new String[]{ + name, + Integer.toString(id), + Boolean.toString(Item.getItemFromBlock(item) != null), + ItemInfo.itemOwners.get(item), + item.getClass().getCanonicalName() + }; + } + + @Override + public RegistryNamespaced registry() { + return Block.blockRegistry; + } + }); + API.addOption(new ArrayDumper("tools.dump.potion") + { + public String[] header() { + return new String[]{"ID", "Unlocalised name", "Class"}; + } + + @Override + public String[] dump(Potion potion, int id) { + return new String[]{ + Integer.toString(id), + potion.getName(), + potion.getClass().getCanonicalName() + }; + } + + @Override + public Potion[] array() { + return Potion.potionTypes; + } + }); + API.addOption(new ArrayDumper("tools.dump.enchantment") + { + public String[] header() { + return new String[]{"ID", "Unlocalised name", "Type", "Min Level", "Max Level", "Class"}; + } + + @Override + public String[] dump(Enchantment ench, int id) { + return new String[]{ + Integer.toString(id), + ench.getName(), + ench.type.toString(), + Integer.toString(ench.getMinLevel()), + Integer.toString(ench.getMaxLevel()), + ench.getClass().getCanonicalName() + }; + } + + @Override + public Enchantment[] array() { + return Enchantment.enchantmentsList; + } + }); + API.addOption(new ArrayDumper("tools.dump.biome") + { + @Override + public String[] header() { + return new String[]{"ID", "Name", "Temperature", "Rainfall", "Spawn Chance", "Root Height", "Height Variation", "Types", "Class"}; + } + + @Override + public String[] dump(BiomeGenBase biome, int id) { + BiomeDictionary.Type[] types = BiomeDictionary.getTypesForBiome(biome); + StringBuilder s_types = new StringBuilder(); + for (BiomeDictionary.Type t : types) { + if (s_types.length() > 0) + s_types.append(", "); + s_types.append(t.name()); + } + + return new String[]{ + Integer.toString(id), + biome.biomeName, + Float.toString(biome.getFloatTemperature(0, 0, 0)), + Float.toString(biome.getFloatRainfall()), + Float.toString(biome.getSpawningChance()), + Float.toString(biome.rootHeight), + Float.toString(biome.heightVariation), + s_types.toString(), + biome.getClass().getCanonicalName() + }; + } + + @Override + public BiomeGenBase[] array() { + return BiomeGenBase.getBiomeGenArray(); + } + }); + API.addOption(new ItemPanelDumper("tools.dump.itempanel")); + } + + private static void parseModItems() { + //TODO GameRegistry.findUniqueIdentifierFor() + } + + private static void addInputHandlers() { + GuiContainerManager.addInputHandler(new RecipeItemInputHandler()); + GuiContainerManager.addInputHandler(new PopupInputHandler()); + } + + private static void addMobSpawnerItem(World world) { + GameDataManipulator.replaceItem(Block.getIdFromBlock(Blocks.mob_spawner), new ItemMobSpawner(world)); + } + + private static void addInfiniteHandlers() { + API.addInfiniteItemHandler(new InfiniteStackSizeHandler()); + API.addInfiniteItemHandler(new InfiniteToolHandler()); + } + + private static void addVanillaBlockProperties() { + API.setOverrideName(new ItemStack(Blocks.flowing_water), "Water Source"); + API.setOverrideName(new ItemStack(Blocks.water), "Water Still"); + API.setOverrideName(new ItemStack(Blocks.flowing_lava), "Lava Source"); + API.setOverrideName(new ItemStack(Blocks.lava), "Lava Still"); + API.setOverrideName(new ItemStack(Blocks.end_portal), "End Portal"); + API.setOverrideName(new ItemStack(Blocks.end_portal_frame), "End Portal Frame"); + API.hideItem(new ItemStack(Blocks.double_stone_slab, 1, OreDictionary.WILDCARD_VALUE)); + API.hideItem(new ItemStack(Blocks.double_wooden_slab, 1, OreDictionary.WILDCARD_VALUE)); + API.hideItem(new ItemStack(Blocks.carrots)); + API.hideItem(new ItemStack(Blocks.potatoes)); + API.hideItem(new ItemStack(Blocks.cocoa)); + } + + private static void addDefaultDropDowns() { + /*API.addSetRange("Blocks", new MultiItemRange("[0-32000]") + { + @Override + public void addItemIfInRange(int item, int damage, NBTTagCompound compound) { + if (item < Block.blocksList.length && (Block.blocksList[item] != null && Block.blocksList[item].blockMaterial != Material.air)) + super.addItemIfInRange(item, damage, compound); + } + }); + API.addSetRange("Items", new MultiItemRange("[0-32000]") + { + @Override + public void addItemIfInRange(int item, int damage, NBTTagCompound compound) { + if (item >= Block.blocksList.length || Block.blocksList[item] == null || Block.blocksList[item].blockMaterial == Material.air) + super.addItemIfInRange(item, damage, compound); + } + }); + API.addSetRange("Blocks.MobSpawners", new MultiItemRange("[52]"));*/ + } + + //TODO + private static void searchItems() { + /*MultiItemRange tools = new MultiItemRange(); + MultiItemRange picks = new MultiItemRange(); + MultiItemRange shovels = new MultiItemRange(); + MultiItemRange axes = new MultiItemRange(); + MultiItemRange hoes = new MultiItemRange(); + MultiItemRange swords = new MultiItemRange(); + MultiItemRange chest = new MultiItemRange(); + MultiItemRange helmets = new MultiItemRange(); + MultiItemRange legs = new MultiItemRange(); + MultiItemRange boots = new MultiItemRange(); + MultiItemRange other = new MultiItemRange(); + MultiItemRange ranged = new MultiItemRange(); + MultiItemRange food = new MultiItemRange(); + MultiItemRange potioningredients = new MultiItemRange(); + + MultiItemRange[] creativeTabRanges = new MultiItemRange[CreativeTabs.creativeTabArray.length]; + for (CreativeTabs tab : CreativeTabs.creativeTabArray) + creativeTabRanges[tab.getTabIndex()] = new MultiItemRange(); + + for (Item item : (Iterable) Item.itemRegistry) { + if (item == null) + continue; + + CreativeTabs itemTab = item.getCreativeTab(); + if (itemTab != null) + creativeTabRanges[itemTab.getTabIndex()].add(item); + + if (item.isDamageable()) { + tools.add(item); + if (item instanceof ItemPickaxe) { + picks.add(item); + } else if (item instanceof ItemSpade) { + shovels.add(item); + } else if (item instanceof ItemAxe) { + axes.add(item); + } else if (item instanceof ItemHoe) { + hoes.add(item); + } else if (item instanceof ItemSword) { + swords.add(item); + } else if (item instanceof ItemArmor) { + switch (((ItemArmor) item).armorType) { + case 0: + helmets.add(item); + break; + case 1: + chest.add(item); + break; + case 2: + legs.add(item); + break; + case 3: + boots.add(item); + break; + } + } else if (item == Items.arrow || item == Items.bow) { + ranged.add(item); + } else if (item == Items.fishing_rod || item == Items.flint_and_steel || item == Items.shears) { + other.add(item); + } + } + + if (item instanceof ItemFood) { + food.add(item); + } + + if (item.isPotionIngredient()) { + BrewingRecipeHandler.ingredients.add(item); + potioningredients.add(item); + } + } + API.addSetRange("Items.Tools.Pickaxes", picks); + API.addSetRange("Items.Tools.Shovels", shovels); + API.addSetRange("Items.Tools.Axes", axes); + API.addSetRange("Items.Tools.Hoes", hoes); + API.addSetRange("Items.Tools.Other", other); + API.addSetRange("Items.Weapons.Swords", swords); + API.addSetRange("Items.Weapons.Ranged", ranged); + API.addSetRange("Items.Armor.ChestPlates", chest); + API.addSetRange("Items.Armor.Leggings", legs); + API.addSetRange("Items.Armor.Helmets", helmets); + API.addSetRange("Items.Armor.Boots", boots); + API.addSetRange("Items.Food", food); + API.addSetRange("Items.Potions.Ingredients", potioningredients); + + for (CreativeTabs tab : CreativeTabs.creativeTabArray) { + if (creativeTabRanges[tab.getTabIndex()].ranges.size() > 0) + API.addSetRange("CreativeTabs." + LangUtil.translateG(tab.getTranslatedTabLabel()), creativeTabRanges[tab.getTabIndex()]); + }*/ + } + + private static void addSpawnEggs() + { + addEntityEgg(EntitySnowman.class, 0xEEFFFF, 0xffa221); + addEntityEgg(EntityIronGolem.class, 0xC5C2C1, 0xffe1cc); + } + + private static void addEntityEgg(Class entity, int i, int j) { + int id = (Integer)EntityList.classToIDMapping.get(entity); + EntityList.entityEggs.put(id, new EntityEggInfo(id, i, j)); + } + + public static ArrayList getIdentifierItems(World world, EntityPlayer player, MovingObjectPosition hit) { + int x = hit.blockX; + int y = hit.blockY; + int z = hit.blockZ; + Block mouseoverBlock = world.getBlock(x, y, z); + + ArrayList items = new ArrayList(); + + ArrayList handlers = new ArrayList(); + if (highlightIdentifiers.containsKey(null)) + handlers.addAll(highlightIdentifiers.get(null)); + if (highlightIdentifiers.containsKey(mouseoverBlock)) + handlers.addAll(highlightIdentifiers.get(mouseoverBlock)); + for (IHighlightHandler ident : handlers) { + ItemStack item = ident.identifyHighlight(world, player, hit); + if (item != null) + items.add(item); + } + + if (items.size() > 0) + return items; + + ItemStack pick = mouseoverBlock.getPickBlock(hit, world, x, y, z); + if (pick != null) + items.add(pick); + + try { + items.addAll(mouseoverBlock.getDrops(world, x, y, z, world.getBlockMetadata(x, y, z), 0)); + } catch (Exception ignored) {} + if (mouseoverBlock instanceof IShearable) { + IShearable shearable = (IShearable) mouseoverBlock; + if (shearable.isShearable(new ItemStack(Items.shears), world, x, y, z)) + items.addAll(shearable.onSheared(new ItemStack(Items.shears), world, x, y, z, 0)); + } + + if (items.size() == 0) + items.add(0, new ItemStack(mouseoverBlock, 1, world.getBlockMetadata(x, y, z))); + + return items; + } + + public static void registerHighlightHandler(IHighlightHandler handler, ItemInfo.Layout... layouts) { + for (ItemInfo.Layout layout : layouts) + ItemInfo.highlightHandlers.get(layout).add(handler); + } + + public static List getText(ItemStack itemStack, World world, EntityPlayer player, MovingObjectPosition mop) { + List retString = new ArrayList(); + + for (ItemInfo.Layout layout : ItemInfo.Layout.values()) + for (IHighlightHandler handler : ItemInfo.highlightHandlers.get(layout)) + retString = handler.handleTextData(itemStack, world, player, mop, retString, layout); + + return retString; + } +} diff --git a/src/codechicken/nei/api/LayoutStyle.java b/src/codechicken/nei/api/LayoutStyle.java new file mode 100644 index 00000000..11346b6f --- /dev/null +++ b/src/codechicken/nei/api/LayoutStyle.java @@ -0,0 +1,20 @@ +package codechicken.nei.api; + +import codechicken.nei.Button; +import codechicken.nei.VisiblityData; +import codechicken.nei.guihook.GuiContainerManager; +import net.minecraft.client.gui.inventory.GuiContainer; + +public abstract class LayoutStyle +{ + public abstract void init(); + public abstract void reset(); + public abstract void layout(GuiContainer gui, VisiblityData visibility); + public abstract String getName(); + + public void drawBackground(GuiContainerManager gui) + { + } + public abstract void drawButton(Button button, int mousex, int mousey); + public abstract boolean texturedButtons(); +} diff --git a/src/codechicken/nei/api/NEIInfo.java b/src/codechicken/nei/api/NEIInfo.java new file mode 100644 index 00000000..561145eb --- /dev/null +++ b/src/codechicken/nei/api/NEIInfo.java @@ -0,0 +1,29 @@ +package codechicken.nei.api; + +import codechicken.nei.NEIClientConfig; +import codechicken.nei.config.OptionCycled; +import net.minecraft.world.World; + +import java.util.LinkedList; + +public class NEIInfo +{ + public static final LinkedList modeHandlers = new LinkedList(); + + public static void load(World world) { + OptionCycled modeOption = (OptionCycled) NEIClientConfig.getOptionList().getOption("inventory.cheatmode"); + modeOption.parent.synthesizeEnvironment(); + if(!modeOption.optionValid(modeOption.value())) { + modeOption.copyGlobals(); + modeOption.cycle(); + } + } + + public static boolean isValidMode(int mode) { + for(INEIModeHandler handler : modeHandlers) + if(!handler.isModeValid(mode)) + return false; + + return true; + } +} diff --git a/src/codechicken/nei/api/TaggedInventoryArea.java b/src/codechicken/nei/api/TaggedInventoryArea.java new file mode 100644 index 00000000..b50d2e23 --- /dev/null +++ b/src/codechicken/nei/api/TaggedInventoryArea.java @@ -0,0 +1,48 @@ +package codechicken.nei.api; + +import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; + +import java.util.HashSet; + +public class TaggedInventoryArea +{ + public HashSet slots = new HashSet(); + public String tagName; + /** + * Only for player inventories. + */ + private IInventory inventory; + /** + * Other inventories + */ + private Container container; + + public TaggedInventoryArea(InventoryPlayer invPlayer) + { + this("InventoryPlayer", 0, 39, null); + inventory = invPlayer; + } + + public TaggedInventoryArea(String name, int first, int last, Container container) + { + this.container = container; + tagName = name; + for(int i = first; i <= last; i++) + slots.add(i); + } + + public ItemStack getStackInSlot(int i) + { + if(inventory != null) + return inventory.getStackInSlot(i); + return container.getSlot(i).getStack(); + } + + public boolean isContainer() + { + return inventory == null; + } +} diff --git a/src/codechicken/nei/asm/NEICorePlugin.java b/src/codechicken/nei/asm/NEICorePlugin.java new file mode 100644 index 00000000..f3906c5b --- /dev/null +++ b/src/codechicken/nei/asm/NEICorePlugin.java @@ -0,0 +1,42 @@ +package codechicken.nei.asm; + +import codechicken.core.launch.CodeChickenCorePlugin; +import cpw.mods.fml.relauncher.IFMLCallHook; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin; +import cpw.mods.fml.relauncher.IFMLLoadingPlugin.TransformerExclusions; + +import java.util.Map; + +@TransformerExclusions(value = {"codechicken.nei.asm"}) +public class NEICorePlugin implements IFMLLoadingPlugin, IFMLCallHook +{ + @Override + public String[] getASMTransformerClass() { + CodeChickenCorePlugin.versionCheck(CodeChickenCorePlugin.mcVersion, "NotEnoughItems"); + return new String[]{"codechicken.nei.asm.NEITransformer"}; + } + + @Override + public String getModContainerClass() { + return "codechicken.nei.NEIModContainer"; + } + + @Override + public String getSetupClass() { + return "codechicken.nei.asm.NEICorePlugin"; + } + + @Override + public void injectData(Map data) { + } + + @Override + public String getAccessTransformerClass() { + return null; + } + + @Override + public Void call() { + return null; + } +} diff --git a/src/codechicken/nei/asm/NEITransformer.java b/src/codechicken/nei/asm/NEITransformer.java new file mode 100644 index 00000000..bfbb5a75 --- /dev/null +++ b/src/codechicken/nei/asm/NEITransformer.java @@ -0,0 +1,180 @@ +package codechicken.nei.asm; + +import codechicken.lib.asm.*; +import codechicken.lib.asm.ModularASMTransformer.*; +import cpw.mods.fml.relauncher.FMLLaunchHandler; +import net.minecraft.launchwrapper.IClassTransformer; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.tree.*; +import org.objectweb.asm.util.TraceClassVisitor; + +import java.io.*; +import java.util.Map; + +import static codechicken.lib.asm.InsnComparator.*; +import static org.objectweb.asm.ClassWriter.COMPUTE_FRAMES; +import static org.objectweb.asm.ClassWriter.COMPUTE_MAXS; +import static org.objectweb.asm.Opcodes.*; + +public class NEITransformer implements IClassTransformer +{ + private ModularASMTransformer transformer = new ModularASMTransformer(); + private Map asmblocks = ASMReader.loadResource("/assets/nei/asm/blocks.asm"); + + public NEITransformer() { + //Generates method to set the placed position of a mob spawner for the item callback. More portable than copying vanilla placement code + transformer.add(new MethodWriter(ACC_PUBLIC, + new ObfMapping("net/minecraft/block/BlockMobSpawner", "func_149689_a", "(Lnet/minecraft/world/World;IIILnet/minecraft/entity/EntityLivingBase;Lnet/minecraft/item/ItemStack;)V"), + asmblocks.get("spawnerPlaced"))); + + //Make MobSpawnerBaseLogic use getSpawnerWorld when creating new entities + transformer.add(new MethodReplacer(new ObfMapping("net/minecraft/tileentity/MobSpawnerBaseLogic", "func_98281_h", "()Lnet/minecraft/entity/Entity;"), + asmblocks.get("d_spawnerWorld"), asmblocks.get("spawnerWorld"))); + + //Removes trailing seperators from NBTTagList/Compound.toString because OCD + transformer.add(new MethodInjector(new ObfMapping("net/minecraft/nbt/NBTTagCompound", "toString", "()Ljava/lang/String;"), + asmblocks.get("n_commaFix"), asmblocks.get("commaFix"), true)); + transformer.add(new MethodInjector(new ObfMapping("net/minecraft/nbt/NBTTagList", "toString", "()Ljava/lang/String;"), + asmblocks.get("n_commaFix"), asmblocks.get("commaFix"), true)); + + String GuiContainer = "net/minecraft/client/gui/inventory/GuiContainer"; + //add manager field + transformer.add(new FieldWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "manager", "Lcodechicken/nei/guihook/GuiContainerManager;"))); + + //Fill out getManager in GuiContainerManager + transformer.add(new MethodWriter(ACC_PUBLIC | ACC_STATIC, + new ObfMapping("codechicken/nei/guihook/GuiContainerManager", "getManager", "(Lnet/minecraft/client/gui/inventory/GuiContainer;)Lcodechicken/nei/guihook/GuiContainerManager;"), + asmblocks.get("m_getManager"))); + + + //Generate load method + transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "func_146280_a", "(Lnet/minecraft/client/Minecraft;II)V"), asmblocks.get("m_setWorldAndResolution"))); + + //Generate handleKeyboardInput method + transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "func_146282_l", "()V"), asmblocks.get("m_handleKeyboardInput"))); + + //Generate handleKeyboardInput method + transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "func_146282_l", "()V"), asmblocks.get("m_handleKeyboardInput"))); + + //Generate handleKeyboardInput method + transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "func_146282_l", "()V"), asmblocks.get("m_handleKeyboardInput"))); + + //Generate handleMouseInput method + transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "func_146274_d", "()V"), asmblocks.get("m_handleMouseInput"))); + + //Generate public accessor for keyTyped + transformer.add(new MethodWriter(ACC_PUBLIC, new ObfMapping(GuiContainer, "publicKeyTyped", "(CI)V"), asmblocks.get("m_publicKeyTyped"))); + + //Fill out callKeyTyped in GuiContainerManager + transformer.add(new MethodWriter(ACC_PUBLIC | ACC_STATIC, + new ObfMapping("codechicken/nei/guihook/GuiContainerManager", "callKeyTyped", "(Lnet/minecraft/client/gui/inventory/GuiContainer;CI)V"), + asmblocks.get("m_callKeyTyped"))); + //Inject preDraw at the start of drawScreen + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73863_a", "(IIF)V"), asmblocks.get("preDraw"), true)); + + //Inject objectUnderMouse check before drawing slot highlights + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73863_a", "(IIF)V"), asmblocks.get("n_objectUnderMouse"), asmblocks.get("objectUnderMouse"), false)); + + //Inject renderObjects after drawGuiContainerForegroundLayer + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73863_a", "(IIF)V"), asmblocks.get("n_renderObjects"), asmblocks.get("renderObjects"), false)); + + //Replace default renderToolTip with delegate + transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_73863_a", "(IIF)V"), asmblocks.get("d_renderToolTip"), asmblocks.get("renderTooltips"))); + + //Replace zLevel = 200 with zLevel = 500 in drawItemStack + transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_146982_a", "(Lnet/minecraft/item/ItemStack;IILjava/lang/String;)V"), + asmblocks.get("d_zLevel"), asmblocks.get("zLevel"))); + + //Replace default renderItem with delegate and slot overlay/underlay + transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_146977_a", "(Lnet/minecraft/inventory/Slot;)V"), asmblocks.get("d_drawSlot"), asmblocks.get("drawSlot"))); + + //Inject mouseClicked hook after super call in mouseClicked + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73864_a", "(III)V"), asmblocks.get("n_mouseClicked"), asmblocks.get("mouseClicked"), false)); + + //Replace general handleMouseClicked call with delegate + transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_73864_a", "(III)V"), asmblocks.get("d_handleMouseClick"), asmblocks.get("handleMouseClick"))); + + //Inject mouseDragged hook after super call in mouseDragged + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_146273_a", "(IIIJ)V"), asmblocks.get("n_mouseDragged"), asmblocks.get("mouseDragged"), false)); + + //Inject overrideMouseUp at the start of mouseMovedOrUp + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_146286_b", "(III)V"), asmblocks.get("overrideMouseUp"), true)); + + //Replace general handleMouseClicked call with delegate + transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_146286_b", "(III)V"), asmblocks.get("d_handleMouseClick2"), asmblocks.get("handleMouseClick2"))); + + transformer.add(new MethodTransformer(new ObfMapping(GuiContainer, "func_146286_b", "(III)V")) + { + @Override + public void transform(MethodNode mv) { + ASMBlock gotoBlock = asmblocks.get("n_mouseUpGoto"); + ASMBlock needleBlock = asmblocks.get("n_mouseUp"); + ASMBlock injectionBlock = asmblocks.get("mouseUp"); + + gotoBlock.mergeLabels(injectionBlock); + findOnce(mv.instructions, gotoBlock.list).replace(gotoBlock.list.list); + + InsnListSection needle = findOnce(mv.instructions, needleBlock.list); + injectionBlock.mergeLabels(needleBlock.applyLabels(needle)); + needle.insertBefore(injectionBlock.list.list); + } + }); + + //Replace general handleSlotClick call with delegate + transformer.add(new MethodReplacer(new ObfMapping(GuiContainer, "func_146984_a", "(Lnet/minecraft/inventory/Slot;III)V"), + asmblocks.get("d_handleSlotClick"), asmblocks.get("handleSlotClick"))); + + //Inject lastKeyTyped at the start of keyTyped + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73869_a", "(CI)V"), asmblocks.get("lastKeyTyped"), true)); + + //Inject updateScreen hook after super call + transformer.add(new MethodInjector(new ObfMapping(GuiContainer, "func_73876_c", "()V"), asmblocks.get("n_updateScreen"), asmblocks.get("updateScreen"), false)); + } + + private ObfMapping c_GuiContainer = new ObfMapping("net/minecraft/client/gui/inventory/GuiContainer").toClassloading(); + /** + * Adds super.updateScreen() to non implementing GuiContainer subclasses + */ + public byte[] transformSubclasses(String name, byte[] bytes) { + if (ClassHeirachyManager.classExtends(name, c_GuiContainer.javaClass())) { + ClassNode cnode = ASMHelper.createClassNode(bytes); + + ObfMapping methodmap = new ObfMapping(cnode.superName, "func_73876_c", "()V").toClassloading(); + + InsnListSection supercall = new InsnListSection(); + supercall.add(new VarInsnNode(ALOAD, 0)); + supercall.add(methodmap.toInsn(INVOKESPECIAL)); + + boolean changed = false; + for (MethodNode mv : cnode.methods) { + if (methodmap.matches(mv)) { + if (matches(new InsnListSection(mv.instructions), supercall, getControlFlowLabels(mv.instructions)) == null) { + mv.instructions.insert(supercall.list); + ASMHelper.logger.debug("Inserted super call into " + methodmap); + changed = true; + } + } + } + + if (changed) + bytes = ASMHelper.createBytes(cnode, COMPUTE_MAXS | COMPUTE_FRAMES); + } + return bytes; + } + + @Override + public byte[] transform(String name, String tname, byte[] bytes) { + if (bytes == null) return null; + try { + if (FMLLaunchHandler.side().isClient()) + bytes = transformSubclasses(name, bytes); + + bytes = transformer.transform(name, bytes); + } catch (Exception e) { + throw new RuntimeException(e); + } + + return bytes; + } +} diff --git a/src/codechicken/nei/config/ArrayDumper.java b/src/codechicken/nei/config/ArrayDumper.java new file mode 100644 index 00000000..46c25437 --- /dev/null +++ b/src/codechicken/nei/config/ArrayDumper.java @@ -0,0 +1,31 @@ +package codechicken.nei.config; + +import java.util.LinkedList; + +public abstract class ArrayDumper extends DataDumper +{ + public ArrayDumper(String name) { + super(name); + } + + @Override + public Iterable dump(int mode) { + LinkedList list = new LinkedList(); + T[] array = array(); + for (int i = 0; i < array.length; i++) { + T obj = array[i]; + if (obj == null) { + if (mode == 1 || mode == 2) + list.add(new String[]{Integer.toString(i), null, null, null, null}); + } else { + if (mode == 0 || mode == 2) + list.add(dump(obj, i)); + } + } + return list; + } + + public abstract T[] array(); + + public abstract String[] dump(T obj, int id); +} \ No newline at end of file diff --git a/src/codechicken/nei/config/ConfigSet.java b/src/codechicken/nei/config/ConfigSet.java new file mode 100644 index 00000000..157c5bba --- /dev/null +++ b/src/codechicken/nei/config/ConfigSet.java @@ -0,0 +1,42 @@ +package codechicken.nei.config; + +import codechicken.lib.config.ConfigTagParent; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; + +import java.io.File; + +public class ConfigSet +{ + private File nbtFile; + public NBTTagCompound nbt; + public ConfigTagParent config; + + public ConfigSet(File nbtFile, ConfigTagParent config) { + this.nbtFile = nbtFile; + this.config = config; + loadNBT(); + } + + public void loadNBT() { + nbt = new NBTTagCompound(); + try { + if (!nbtFile.getParentFile().exists()) + nbtFile.getParentFile().mkdirs(); + if (!nbtFile.exists()) + nbtFile.createNewFile(); + if (nbtFile.length() > 0) + nbt = CompressedStreamTools.read(nbtFile); + } catch (Exception e) { + e.printStackTrace(); + } + } + + public void saveNBT() { + try { + CompressedStreamTools.write(nbt, nbtFile); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/codechicken/nei/config/DataDumper.java b/src/codechicken/nei/config/DataDumper.java new file mode 100644 index 00000000..9b366121 --- /dev/null +++ b/src/codechicken/nei/config/DataDumper.java @@ -0,0 +1,160 @@ +package codechicken.nei.config; + +import codechicken.core.CommonUtils; +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.LayoutManager; +import codechicken.nei.NEIClientUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.util.ChatComponentTranslation; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; + +import static codechicken.lib.gui.GuiDraw.drawString; +import static codechicken.lib.gui.GuiDraw.drawStringC; + +public abstract class DataDumper extends Option +{ + public DataDumper(String name) { + super(name); + } + + public abstract String[] header(); + + public abstract Iterable dump(int mode); + + public String renderName() { + return translateN(name + "s"); + } + + public void dumpFile() { + try { + File file = new File(CommonUtils.getMinecraftDir(), "dumps/" + getFileName(name.replaceFirst(".+\\.", ""))); + if (!file.getParentFile().exists()) + file.getParentFile().mkdirs(); + if (!file.exists()) + file.createNewFile(); + + dumpTo(file); + + NEIClientUtils.printChatMessage(dumpMessage(file)); + } catch (Exception e) { + System.err.println("Error dumping " + renderName() + " mode: " + getMode()); + e.printStackTrace(); + } + } + + public String getFileName(String prefix) { + return prefix + getFileExtension(); + } + + public String getFileExtension() { + return ".csv"; + } + + public IChatComponent dumpMessage(File file) { + return new ChatComponentTranslation("nei.options.tools.dump.dumped", + translateN(name), "dumps/" + file.getName()); + } + + public void dumpTo(File file) throws IOException { + int mode = getMode(); + PrintWriter w = new PrintWriter(file); + w.println(concat(header())); + for (String[] line : dump(mode)) + w.println(concat(line)); + w.close(); + } + + public static String concat(String[] header) { + StringBuilder sb = new StringBuilder(); + for (String s : header) { + if (sb.length() > 0) + sb.append(','); + if (s == null) + s = "null"; + if (s.indexOf(',') > 0 || s.indexOf('\"') > 0) + s = '\"' + s.replace("\"", "\"\"") + '\"'; + sb.append(s); + } + return sb.toString(); + } + + @Override + public void draw(int mousex, int mousey, float frame) { + drawPrefix(); + if(modeCount() > 1) + drawModeButton(mousex, mousey); + drawDumpButton(mousex, mousey); + } + + public void drawPrefix() { + drawString(renderName(), 10, 8, -1); + } + + public Rectangle4i dumpButtonSize() { + int width = 80; + return new Rectangle4i(slot.contentWidth() - width, 2, width, 20); + } + + public Rectangle4i modeButtonSize() { + int width = 60; + return new Rectangle4i(slot.contentWidth() - width - 10 - dumpButtonSize().w, 2, width, 20); + } + + public String dumpButtonText() { + return NEIClientUtils.lang.translate("options.tools.dump.dump"); + } + + public String modeButtonText() { + return NEIClientUtils.lang.translate("options.tools.dump.mode." + getMode()); + } + + public int getMode() { + return getTag().getIntValue(0); + } + + public void drawModeButton(int mousex, int mousey) { + GL11.glColor4f(1, 1, 1, 1); + Rectangle4i b = modeButtonSize(); + boolean hover = b.contains(mousex, mousey); + LayoutManager.drawButtonBackground(b.x, b.y, b.w, b.h, true, getButtonTex(hover)); + drawStringC(modeButtonText(), b.x, b.y, b.w, b.h, getTextColour(hover)); + } + + public void drawDumpButton(int mousex, int mousey) { + GL11.glColor4f(1, 1, 1, 1); + Rectangle4i b = dumpButtonSize(); + boolean hover = b.contains(mousex, mousey); + LayoutManager.drawButtonBackground(b.x, b.y, b.w, b.h, true, getButtonTex(hover)); + drawStringC(dumpButtonText(), b.x, b.y, b.w, b.h, getTextColour(hover)); + } + + public int getButtonTex(boolean hover) { + return hover ? 2 : 1; + } + + public int getTextColour(boolean hover) { + return hover ? 0xFFFFFFA0 : 0xFFE0E0E0; + } + + @Override + public void mouseClicked(int mousex, int mousey, int button) { + if (modeCount() > 1 && modeButtonSize().contains(mousex, mousey)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + getTag().setIntValue((getMode() + 1) % modeCount()); + } else if (dumpButtonSize().contains(mousex, mousey)) { + Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.func_147674_a(new ResourceLocation("gui.button.press"), 1.0F)); + dumpFile(); + } + } + + public int modeCount() { + return 3; + } +} diff --git a/src/codechicken/nei/config/GuiHighlightTips.java b/src/codechicken/nei/config/GuiHighlightTips.java new file mode 100644 index 00000000..b2587f62 --- /dev/null +++ b/src/codechicken/nei/config/GuiHighlightTips.java @@ -0,0 +1,149 @@ +package codechicken.nei.config; + +import codechicken.core.gui.GuiCCButton; +import codechicken.core.gui.GuiScreenWidget; +import codechicken.lib.math.MathHelper; +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.HUDRenderer; +import codechicken.nei.NEIClientUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumChatFormatting; +import org.lwjgl.input.Keyboard; + +import java.awt.*; +import java.util.Arrays; + +import static codechicken.lib.gui.GuiDraw.displaySize; +import static codechicken.lib.gui.GuiDraw.getMousePosition; + +public class GuiHighlightTips extends GuiScreenWidget +{ + private String name; + private GuiCCButton toggleButton; + private OptionHighlightTips opt; + private Point dragDown; + + public GuiHighlightTips(OptionHighlightTips opt) { + super(80, 20); + this.opt = opt; + name = opt.name; + } + + @Override + public boolean doesGuiPauseGame() { + return true; + } + + public void addWidgets() { + add(toggleButton = new GuiCCButton(0, 0, 80, 20, "").setActionCommand("show")); + updateNames(); + } + + @Override + public void actionPerformed(String ident, Object... params) { + if (ident.equals("show")) { + opt.getTag(name).setBooleanValue(!show()); + updateNames(); + } + } + + private void updateNames() { + toggleButton.text = NEIClientUtils.translate("options." + name + "." + (show() ? "show" : "hide")); + } + + private boolean show() { + return opt.getTag(name).getBooleanValue(); + } + + @Override + public void keyTyped(char c, int keycode) { + if (keycode == Keyboard.KEY_ESCAPE || keycode == Keyboard.KEY_BACK) { + Minecraft.getMinecraft().displayGuiScreen(opt.slot.getGui()); + return; + } + super.keyTyped(c, keycode); + } + + @Override + public void drawScreen(int mousex, int mousey, float f) { + super.drawScreen(mousex, mousey, f); + if (show()) + HUDRenderer.renderOverlay(new ItemStack(Blocks.redstone_block), Arrays.asList("RedstoneBlock", EnumChatFormatting.RED+"Sample"), renderPos()); + } + + public Point getPos() { + return new Point(opt.getTag(name + ".x").getIntValue(), opt.getTag(name + ".y").getIntValue()); + } + + public Dimension sampleSize()//copied from HUDManager when running with the sample for this gui + { + return new Dimension(101, 30); + } + + public Point getDrag() { + Point mouse = getMousePosition(); + Point drag = new Point(mouse.x - dragDown.x, mouse.y - dragDown.y); + Dimension size = displaySize(); + Dimension sample = sampleSize(); + drag.x *= 10000; + drag.y *= 10000; + drag.x /= (size.width - sample.width); + drag.y /= (size.height - sample.height); + Point pos = getPos(); + drag.x = (int) MathHelper.clip(drag.x, -pos.x, 10000 - pos.x); + drag.y = (int) MathHelper.clip(drag.y, -pos.y, 10000 - pos.y); + return drag; + } + + public Point renderPos() { + Point pos = getPos(); + if (dragDown != null) { + Point drag = getDrag(); + pos.x += drag.x; + pos.y += drag.y; + } + + for (int i = 25; i < 100; i += 25)//snapping + { + if (pos.x / 100 == i) + pos.x = i * 100; + if (pos.y / 100 == i) + pos.y = i * 100; + } + + return pos; + } + + @Override + protected void mouseMovedOrUp(int x, int y, int button) { + if (button == 0 && dragDown != null) { + setPos(renderPos()); + dragDown = null; + } + } + + public Rectangle4i selectionBox() { + Point pos = renderPos(); + Dimension size = displaySize(); + Dimension rect = sampleSize(); + return new Rectangle4i( + (size.width - rect.width) * pos.x / 10000, + (size.height - rect.height) * pos.y / 10000, + rect.width, rect.height); + } + + @Override + protected void mouseClicked(int x, int y, int button) { + if (button == 0 && selectionBox().contains(x, y)) + dragDown = getMousePosition(); + else + super.mouseClicked(x, y, button); + } + + private void setPos(Point p) { + opt.getTag(name + ".x").setIntValue(p.x); + opt.getTag(name + ".y").setIntValue(p.y); + } +} diff --git a/src/codechicken/nei/config/GuiOptionList.java b/src/codechicken/nei/config/GuiOptionList.java new file mode 100644 index 00000000..93295bc3 --- /dev/null +++ b/src/codechicken/nei/config/GuiOptionList.java @@ -0,0 +1,378 @@ +package codechicken.nei.config; + +import codechicken.core.gui.GuiCCButton; +import codechicken.core.gui.GuiScreenWidget; +import codechicken.core.gui.GuiScrollSlot; +import codechicken.lib.vec.Rectangle4i; +import codechicken.nei.LayoutManager; +import net.minecraft.client.Minecraft; +import net.minecraft.client.audio.PositionedSoundRecord; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.util.ResourceLocation; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import static codechicken.lib.gui.GuiDraw.*; +import static net.minecraft.util.StatCollector.translateToLocal; + +public class GuiOptionList extends GuiScreenWidget +{ + public class OptionScrollSlot extends GuiScrollSlot + { + public ArrayList