diff --git a/MineTweaker3-MC18-Main/.gitignore b/MineTweaker3-MC18-Main/.gitignore new file mode 100644 index 0000000..2c770e0 --- /dev/null +++ b/MineTweaker3-MC18-Main/.gitignore @@ -0,0 +1,22 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# idea +out +*.ipr +*.iws +*.iml +.idea + +# gradle +build +.gradle + +# other +eclipse +run diff --git a/MineTweaker3-MC18-Main/build.gradle b/MineTweaker3-MC18-Main/build.gradle new file mode 100644 index 0000000..df1cb15 --- /dev/null +++ b/MineTweaker3-MC18-Main/build.gradle @@ -0,0 +1,82 @@ +/* +// For those who want the bleeding edge +buildscript { + repositories { + jcenter() + maven { + name = "forge" + url = "http://files.minecraftforge.net/maven" + } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.0-SNAPSHOT' + } +} +apply plugin: 'net.minecraftforge.gradle.forge' +*/ + +// for people who want stable +plugins { + id "net.minecraftforge.gradle.forge" version "2.0.1" +} + +version = "1.0" +group= "com.yourname.modid" // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = "modid" + +minecraft { + version = "1.8-11.14.3.1506" + runDir = "run" + + // the mappings can be changed at any time, and must be in the following format. + // snapshot_YYYYMMDD snapshot are built nightly. + // stable_# stables are built at the discretion of the MCP team. + // Use non-default mappings at your own risk. they may not allways work. + // simply re-run your setup task after changing the mappings to update your workspace. + mappings = "snapshot_20141130" + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. +} + +dependencies { + // you may put jars on which you depend on in ./libs + // or you may define them like so.. + //compile "some.group:artifact:version:classifier" + //compile "some.group:artifact:version" + + // real examples + //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env + //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env + + // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime. + //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // the deobf configurations: 'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided, + // except that these dependencies get remapped to your current MCP mappings + //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev' + //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev' + + // for more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html + +} + +processResources +{ + // this will ensure that this task is redone when the versions change. + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft.version + + // replace stuff in mcmod.info, nothing else + from(sourceSets.main.resources.srcDirs) { + include 'mcmod.info' + + // replace version and mcversion + expand 'version':project.version, 'mcversion':project.minecraft.version + } + + // copy everything else, thats not the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} diff --git a/MineTweaker3-MC18-Main/gradle/wrapper/gradle-wrapper.jar b/MineTweaker3-MC18-Main/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..b5166da Binary files /dev/null and b/MineTweaker3-MC18-Main/gradle/wrapper/gradle-wrapper.jar differ diff --git a/MineTweaker3-MC18-Main/gradle/wrapper/gradle-wrapper.properties b/MineTweaker3-MC18-Main/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..6be9a83 --- /dev/null +++ b/MineTweaker3-MC18-Main/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat May 16 19:56:41 CDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.5-bin.zip diff --git a/MineTweaker3-MC18-Main/gradlew b/MineTweaker3-MC18-Main/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/MineTweaker3-MC18-Main/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/MineTweaker3-MC18-Main/gradlew.bat b/MineTweaker3-MC18-Main/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/MineTweaker3-MC18-Main/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/MineTweaker3-MC18-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java new file mode 100644 index 0000000..9501142 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/api/minecraft/MineTweakerMC.java @@ -0,0 +1,496 @@ +package minetweaker.api.minecraft; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.data.IData; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.IngredientUnknown; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.oredict.IOreDictEntry; +import minetweaker.api.player.IPlayer; +import minetweaker.api.world.IBiome; +import minetweaker.api.world.IDimension; +import minetweaker.mc18.block.MCBlockDefinition; +import minetweaker.mc18.block.MCSpecificBlock; +import minetweaker.mc18.block.MCWorldBlock; +import minetweaker.mc18.data.NBTConverter; +import minetweaker.mc18.item.MCItemStack; +import minetweaker.mc18.liquid.MCLiquidStack; +import minetweaker.mc18.oredict.MCOreDictEntry; +import minetweaker.mc18.player.MCPlayer; +import minetweaker.mc18.world.MCBiome; +import minetweaker.mc18.world.MCDimension; +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraft.world.biome.BiomeGenBase; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * MineTweaker - MineCraft API bridge. + * + * @author Stan Hebben + */ +public class MineTweakerMC { + private static final Map blockDefinitions = new HashMap(); + public static final IBiome[] biomes; + + static { + biomes = new IBiome[BiomeGenBase.getBiomeGenArray().length]; + for (int i = 0; i < BiomeGenBase.getBiomeGenArray().length; i++) { + if (BiomeGenBase.getBiomeGenArray()[i] != null) + biomes[i] = new MCBiome(BiomeGenBase.getBiomeGenArray()[i]); + } + } + + private MineTweakerMC() { + } + + /** + * Returns the Minecraft item for this MineTweaker item. + * + * @param item minetweaker item stack + * @return minecraft item stack + */ + public static ItemStack getItemStack(IItemStack item) { + if (item == null) + return null; + + Object internal = item.getInternal(); + if (internal == null || !(internal instanceof ItemStack)) { + MineTweakerAPI.logError("Not a valid item stack: " + item); + } + return (ItemStack) internal; + } + + /** + * Returns the Minecraft ingredient for this ingredient. This method is only + * useful for ingredients that represent a single item stack. + * + * @param ingredient item ingredient + * @return minecraft item stack + */ + public static ItemStack getItemStack(IIngredient ingredient) { + if (ingredient == null) + return null; + + List items = ingredient.getItems(); + if (items.size() != 1) { + MineTweakerAPI.logError("Not an ingredient with a single item: " + ingredient); + } + return getItemStack(items.get(0)); + } + + /** + * Returns the MineTweaker item stack for this item. + * + * @param item minecraft item stack + * @return minetweaker item stack + */ + public static IItemStack getIItemStack(ItemStack item) { + if (item == null) + return null; + + return new MCItemStack(item); + } + + /** + * Constructs an item stack with wildcard size. + * + * @param item minecraft item stack + * @return minetweaker stack + */ + public static IItemStack getIItemStackWildcardSize(ItemStack item) { + if (item == null) + return null; + + return new MCItemStack(item, true); + } + + /** + * Constructs an item stack with wildcard size. + * + * @param item + * @param meta + * @return minetweaker stack + */ + public static IItemStack getIItemStackWildcardSize(Item item, int meta) { + if (item == null) + return null; + + return new MCItemStack(new ItemStack(item, 1, meta), true); + } + + /** + * Constructs an item stack with wildcard damage. + * + * @param item stack item + * @param amount stack size + * @return minetweaker item stack + */ + public static IItemStack getIItemStackWildcard(Item item, int amount) { + if (item == null) + return null; + + return new MCItemStack(new ItemStack(item, 1, OreDictionary.WILDCARD_VALUE)); + } + + public static ItemStack[] getExamples(IIngredient ingredient) { + List examples = ingredient.getItems(); + ItemStack[] result = new ItemStack[examples.size()]; + for (int i = 0; i < examples.size(); i++) { + result[i] = MineTweakerMC.getItemStack(examples.get(i)); + } + return result; + } + + /** + * Constructs an item stack with given item, damage and amount. + * + * @param item stack item + * @param damage stack damage + * @param amount stack amount + * @return minetweaker item stack + */ + public static IItemStack getItemStack(Item item, int amount, int damage) { + if (item == null) + return null; + + return new MCItemStack(new ItemStack(item, amount, damage)); + } + + /** + * Converts an array of minetweaker item stacks into an array of minecraft + * item stacks. + * + * @param items minetweker item stacks + * @return minecraft item stacks + */ + public static ItemStack[] getItemStacks(IItemStack... items) { + if (items == null) + return null; + + ItemStack[] output = new ItemStack[items.length]; + for (int i = 0; i < items.length; i++) { + Object internal = items[i].getInternal(); + if (internal != null && internal instanceof ItemStack) { + output[i] = (ItemStack) internal; + } + } + return output; + } + + /** + * Converts a list of minetweaker item stacks into an array of minecraft + * item stacks. + * + * @param items minetweaker items + * @return minecraft items + */ + public static ItemStack[] getItemStacks(List items) { + if (items == null) + return null; + + ItemStack[] output = new ItemStack[items.size()]; + for (int i = 0; i < items.size(); i++) { + Object internal = items.get(i).getInternal(); + if (internal != null && internal instanceof ItemStack) { + output[i] = (ItemStack) internal; + } else { + MineTweakerAPI.logError("Invalid item stack: " + items.get(i)); + } + } + return output; + } + + /** + * Converts an array of minecraft item stacks into an array of minetweaker + * item stacks. + * + * @param items minecraft item stacks + * @return minetweaker item stacks + */ + public static IItemStack[] getIItemStacks(ItemStack... items) { + if (items == null) + return null; + + IItemStack[] result = new IItemStack[items.length]; + for (int i = 0; i < items.length; i++) { + result[i] = new MCItemStack(items[i]); + } + return result; + } + + /** + * Converts a list of minecraft item stacks into an array of minetweaker + * item stacks. + * + * @param items minecraft item stacks + * @return minetweaker item stacks + */ + public static IItemStack[] getIItemStacks(List items) { + if (items == null) + return null; + + IItemStack[] result = new IItemStack[items.size()]; + for (int i = 0; i < result.length; i++) { + result[i] = new MCItemStack(items.get(i)); + } + return result; + } + + /** + * Gets the ore dictionary entry with the given name. If the entry didn't + * exist yet, it will create it and return an empty entry. + * + * @param name ore entry name + * @return ore dictionary entry + */ + public static IOreDictEntry getOreDict(String name) { + return new MCOreDictEntry(name); + } + + /** + * Converts a Minecraft player into a MineTweaker player. + * + * @param player minecraft player + * @return minetweaker player + */ + public static IPlayer getIPlayer(EntityPlayer player) { + if (player == null) + return null; + + return new MCPlayer(player); + } + + /** + * Converts a MineTweaker player into a Minecraft player. + * + * @param player minetweaker player + * @return minecraft player + */ + public static EntityPlayer getPlayer(IPlayer player) { + if (player == null) + return null; + + if (!(player instanceof MCPlayer)) { + MineTweakerAPI.logError("Invalid player: " + player); + } + + return ((MCPlayer) player).getInternal(); + } + + /** + * Converts a Minecraft NBT to an IData instance. The IData instance is + * immutable (not modifyiable). + * + * @param nbt nbt data + * @return IData value + */ + public static IData getIData(NBTBase nbt) { + if (nbt == null) + return null; + + return NBTConverter.from(nbt, true); + } + + /** + * Converts a Minecraft NBT to a modifyable IData instance. + * + * @param nbt nbt data + * @return mutable IData value + */ + public static IData getIDataModifyable(NBTBase nbt) { + if (nbt == null) + return null; + + return NBTConverter.from(nbt, false); + } + + /** + * Converts an IData instance to an NBT value. + * + * @param data IData value + * @return nbt data + */ + public static NBTBase getNBT(IData data) { + if (data == null) + return null; + + return NBTConverter.from(data); + } + + /** + * Converts an IData instance to an NBT Tag compound. + * + * @param data IData value + * @return nbt compound data + */ + public static NBTTagCompound getNBTCompound(IData data) { + if (data == null) + return null; + + return (NBTTagCompound) NBTConverter.from(data); + } + + /** + * Retrieves the block at the given position. + * + * @param blocks block access + * @param x block x position + * @param y block y position + * @param z block z position + * @return block instance + */ + public static IBlock getBlock(IBlockAccess blocks, int x, int y, int z) { + return new MCWorldBlock(blocks, x, y, z); + } + + /** + * Retrieves the block definition for the given block. + * + * @param block block object + * @return block definition + */ + public static IBlockDefinition getBlockDefinition(Block block) { + if (!blockDefinitions.containsKey(block)) { + blockDefinitions.put(block, new MCBlockDefinition(block)); + } + return blockDefinitions.get(block); + } + + /** + * Retrieves the dimension instance for a given world. + * + * @param world world + * @return dimension + */ + public static IDimension getDimension(World world) { + if (world == null) + return null; + + return new MCDimension(world); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @return MT block instance + */ + public static IBlock getBlockAnyMeta(Block block) { + return new MCSpecificBlock(block, OreDictionary.WILDCARD_VALUE); + } + + /** + * Returns an instance of the given block. + * + * @param block MC block definition + * @param meta block meta value + * @return MT block instance + */ + public static IBlock getBlock(Block block, int meta) { + return new MCSpecificBlock(block, meta); + } + + /** + * Retrieves the block from an item stack. + * + * @param itemStack + * @return + */ + public static Block getBlock(IItemStack itemStack) { + return ((MCBlockDefinition) itemStack.asBlock().getDefinition()).getInternalBlock(); + } + + public static Block getBlock(IBlock block) { + return ((MCBlockDefinition) block.getDefinition()).getInternalBlock(); + } + + /** + * Retrieves the internal fluid stack of the given stack. + * + * @param stack MT liquid stack + * @return MCF fluid stack + */ + public static FluidStack getLiquidStack(ILiquidStack stack) { + if (stack == null) + return null; + + return (FluidStack) stack.getInternal(); + } + + /** + * Converts an array of MT liquid stacks into an array of MCF fluid stacks + * + */ + public static FluidStack[] getLiquidStacks(ILiquidStack[] stacks) { + if (stacks == null) { + return null; + } + + FluidStack[] res = new FluidStack[stacks.length]; + + for (int i = 0; i < stacks.length; i++) { + ILiquidStack liquidStack = stacks[i]; + res[i] = getLiquidStack(liquidStack); + } + return res; + } + + private static final HashMap oreDictArrays = new HashMap(); + + public static IOreDictEntry getOreDictEntryFromArray(List array) { + if (!oreDictArrays.containsKey(array)) { + for (String ore : OreDictionary.getOreNames()) { + if (OreDictionary.getOres(ore) == array) { + oreDictArrays.put(array, MineTweakerAPI.oreDict.get(ore)); + } + } + } + + return oreDictArrays.get(array); + } + + /** + * Converts a Minecraft ingredient to a MineTweaker ingredient. + * + * @param ingredient minecraft ingredient + * @return minetweaker ingredient + */ + public static IIngredient getIIngredient(Object ingredient) { + if (ingredient == null) { + return null; + } else if (ingredient instanceof String) { + return MineTweakerAPI.oreDict.get((String) ingredient); + } else if (ingredient instanceof Item) { + return getIItemStack(new ItemStack((Item) ingredient, 1, 0)); + } else if (ingredient instanceof ItemStack) { + return getIItemStack((ItemStack) ingredient); + } else if (ingredient instanceof List) { + IOreDictEntry entry = getOreDictEntryFromArray((List) ingredient); + + if (entry == null) { + return IngredientUnknown.INSTANCE; + } + + return entry; + } else if (ingredient instanceof FluidStack) { + return new MCLiquidStack((FluidStack) ingredient); + } else { + throw new IllegalArgumentException("Not a valid ingredient: " + ingredient); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/FMLEventHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/FMLEventHandler.java new file mode 100644 index 0000000..f544987 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/FMLEventHandler.java @@ -0,0 +1,56 @@ +package minetweaker.mc18; + +import minetweaker.MineTweakerAPI; +import minetweaker.MineTweakerImplementationAPI; +import minetweaker.api.event.PlayerCraftedEvent; +import minetweaker.api.event.PlayerLoggedInEvent; +import minetweaker.api.event.PlayerLoggedOutEvent; +import minetweaker.api.event.PlayerSmeltedEvent; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.player.IPlayer; +import minetweaker.mc18.network.MineTweakerLoadScriptsPacket; +import minetweaker.mc18.recipes.MCCraftingInventory; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; + +/** + * + * @author Stan + */ +public class FMLEventHandler { + @SubscribeEvent + public void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent ev) { + if (ev.player instanceof EntityPlayerMP) { + EntityPlayerMP player = (EntityPlayerMP) ev.player; + MineTweakerMod.NETWORK.sendTo(new MineTweakerLoadScriptsPacket(MineTweakerAPI.tweaker.getScriptData()), player); + } + + MineTweakerImplementationAPI.events.publishPlayerLoggedIn(new PlayerLoggedInEvent(MineTweakerMC.getIPlayer(ev.player))); + } + + @SubscribeEvent + public void onPlayerItemCrafted(PlayerEvent.ItemCraftedEvent ev) { + IPlayer iPlayer = MineTweakerMC.getIPlayer(ev.player); + if (MineTweakerMod.INSTANCE.recipes.hasTransformerRecipes()) { + MineTweakerMod.INSTANCE.recipes.applyTransformations(MCCraftingInventory.get(ev.craftMatrix, ev.player), iPlayer); + } + + if (MineTweakerImplementationAPI.events.hasPlayerCrafted()) { + MineTweakerImplementationAPI.events.publishPlayerCrafted(new PlayerCraftedEvent(iPlayer, MineTweakerMC.getIItemStack(ev.crafting), MCCraftingInventory.get(ev.craftMatrix, ev.player))); + } + } + + @SubscribeEvent + public void onPlayerItemSmelted(PlayerEvent.ItemSmeltedEvent ev) { + if (MineTweakerImplementationAPI.events.hasPlayerSmelted()) { + MineTweakerImplementationAPI.events.publishPlayerSmelted(new PlayerSmeltedEvent(MineTweakerMC.getIPlayer(ev.player), MineTweakerMC.getIItemStack(ev.smelting))); + } + } + + @SubscribeEvent + public void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent ev) { + MineTweakerImplementationAPI.events.publishPlayerLoggedOut(new PlayerLoggedOutEvent(MineTweakerMC.getIPlayer(ev.player))); + } + +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/ForgeEventHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/ForgeEventHandler.java new file mode 100644 index 0000000..11874be --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/ForgeEventHandler.java @@ -0,0 +1,50 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18; + +import minetweaker.MineTweakerImplementationAPI; +import minetweaker.api.formatting.IFormattedText; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.tooltip.IngredientTooltips; +import minetweaker.mc18.formatting.IMCFormattedString; +import net.minecraftforge.event.entity.player.ItemTooltipEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import org.lwjgl.input.Keyboard; + +/** + * + * @author Stan + */ +public class ForgeEventHandler { + @SubscribeEvent + public void onPlayerInteract(PlayerInteractEvent ev) { + minetweaker.api.event.PlayerInteractEvent event = new minetweaker.api.event.PlayerInteractEvent( + MineTweakerMC.getIPlayer(ev.entityPlayer), + MineTweakerMC.getDimension(ev.world), + ev.pos.getX(), ev.pos.getY(), ev.pos.getZ() + ); + + MineTweakerImplementationAPI.events.publishPlayerInteract(event); + } + + @SubscribeEvent + public void onItemTooltip(ItemTooltipEvent ev) { + IItemStack itemStack = MineTweakerMC.getIItemStack(ev.itemStack); + for (IFormattedText tooltip : IngredientTooltips.getTooltips(itemStack)) { + ev.toolTip.add(((IMCFormattedString) tooltip).getTooltipString()); + } + + if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { + for (IFormattedText tooltip : IngredientTooltips.getShiftTooltips(itemStack)) { + ev.toolTip.add(((IMCFormattedString) tooltip).getTooltipString()); + } + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/GuiCannotRemodify.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/GuiCannotRemodify.java new file mode 100644 index 0000000..5b84a46 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/GuiCannotRemodify.java @@ -0,0 +1,60 @@ +package minetweaker.mc18; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; + +/** + * This screen is shown when a client has been modified with a permanent + * modification and the player logs into a game with a different script. It asks + * the player to restart the game. + * + * @author Stan Hebben + */ +public class GuiCannotRemodify extends GuiScreen { + private final String message1; + private final String message2; + private final String message3; + + public GuiCannotRemodify(String message1, String message2, String message3) { + this.message1 = message1; + this.message2 = message2; + this.message3 = message3; + } + + @Override + public void initGui() { + this.buttonList.clear(); + this.buttonList.add( + new GuiButton(0, this.width / 2 - 100, this.height / 4 + 120 + 12, "Close") + ); + } + + @Override + public void drawScreen(int par1, int par2, float par3) { + this.drawDefaultBackground(); + this.drawCenteredString( + this.fontRendererObj, + message1, + this.width / 2, this.height / 2 - 40, + 11184810); + this.drawCenteredString( + this.fontRendererObj, + message2, + this.width / 2, this.height / 2 - 20, + 11184810); + this.drawCenteredString( + this.fontRendererObj, + message3, + this.width / 2, this.height / 2 - 0, + 11184810); + + super.drawScreen(par1, par2, par3); + } + + @Override + protected void actionPerformed(GuiButton par1GuiButton) { + if (par1GuiButton.id == 0) { + System.exit(0); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MCPlatformFunctions.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MCPlatformFunctions.java new file mode 100644 index 0000000..ff857c4 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MCPlatformFunctions.java @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18; + +import static minetweaker.mc18.MineTweakerMod.NETWORK; +import minetweaker.IPlatformFunctions; +import minetweaker.api.chat.IChatMessage; +import minetweaker.api.item.IItemDefinition; +import minetweaker.mc18.chat.MCChatMessage; +import minetweaker.mc18.item.MCItemDefinition; +import minetweaker.mc18.network.MineTweakerLoadScriptsPacket; +import net.minecraft.item.Item; + +/** + * + * @author Stan + */ +public class MCPlatformFunctions implements IPlatformFunctions { + public static final MCPlatformFunctions INSTANCE = new MCPlatformFunctions(); + + private MCPlatformFunctions() { + } + + @Override + public IChatMessage getMessage(String message) { + return new MCChatMessage(message); + } + + @Override + public void distributeScripts(byte[] data) { + NETWORK.sendToAll(new MineTweakerLoadScriptsPacket(data)); + } + + @Override + public IItemDefinition getItemDefinition(int id) { + Item item = Item.getItemById(id); + if (item == null) + return null; + String sid = (String) Item.itemRegistry.getNameForObject(item); + return new MCItemDefinition(sid, item); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MineTweakerMod.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MineTweakerMod.java new file mode 100644 index 0000000..f2e20e3 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MineTweakerMod.java @@ -0,0 +1,183 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18; + +import java.io.File; + +import minetweaker.MineTweakerAPI; +import minetweaker.MineTweakerImplementationAPI; +import minetweaker.api.logger.FileLogger; +import minetweaker.mc18.brackets.ItemBracketHandler; +import minetweaker.mc18.client.MCClient; +import minetweaker.mc18.formatting.MCFormatter; +import minetweaker.mc18.furnace.FuelTweaker; +import minetweaker.mc18.furnace.MCFurnaceManager; +import minetweaker.mc18.game.MCGame; +import minetweaker.mc18.mods.MCLoadedMods; +import minetweaker.mc18.network.MineTweakerCopyClipboardHandler; +import minetweaker.mc18.network.MineTweakerCopyClipboardPacket; +import minetweaker.mc18.network.MineTweakerLoadScriptsHandler; +import minetweaker.mc18.network.MineTweakerLoadScriptsPacket; +import minetweaker.mc18.network.MineTweakerOpenBrowserHandler; +import minetweaker.mc18.network.MineTweakerOpenBrowserPacket; +import minetweaker.mc18.oredict.MCOreDict; +import minetweaker.mc18.recipes.MCRecipeManager; +import minetweaker.mc18.server.MCServer; +import minetweaker.mc18.util.MineTweakerHacks; +import minetweaker.mc18.util.MineTweakerPlatformUtils; +import minetweaker.mc18.vanilla.MCVanilla; +import minetweaker.runtime.IScriptProvider; +import minetweaker.runtime.providers.ScriptProviderCascade; +import minetweaker.runtime.providers.ScriptProviderCustom; +import minetweaker.runtime.providers.ScriptProviderDirectory; +import net.minecraft.block.Block; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.event.FMLInterModComms; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerAboutToStartEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.event.FMLServerStoppedEvent; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import net.minecraftforge.fml.relauncher.Side; + +/** + * Main mod class. Performs some general logic, initialization of the API and + * FML event handling. + * + * @author Stan Hebben + */ +@Mod(modid = MineTweakerMod.MODID, version = "3.0.9B") +public class MineTweakerMod { + public static final String MODID = "MineTweaker3"; + public static final String MCVERSION = "1.8"; + + public static final SimpleNetworkWrapper NETWORK = NetworkRegistry.INSTANCE.newSimpleChannel(MODID); + + private static final String[] REGISTRIES = { + "minetweaker.mods.ic2.ClassRegistry", + "minetweaker.mods.nei.ClassRegistry", + "minetweaker.mods.mfr.ClassRegistry", + "minetweaker.mods.gregtech.ClassRegistry", + "minetweaker.mods.buildcraft.ClassRegistry" + }; + private static final String[] REGISTRY_DESCRIPTIONS = { + "IC2 mod support", + "NEI mod support", + "MFR mod support", + "GregTech mod support", + "Buildcraft mod support" + }; + + static { + NETWORK.registerMessage(MineTweakerLoadScriptsHandler.class, MineTweakerLoadScriptsPacket.class, 0, Side.CLIENT); + NETWORK.registerMessage(MineTweakerOpenBrowserHandler.class, MineTweakerOpenBrowserPacket.class, 1, Side.CLIENT); + NETWORK.registerMessage(MineTweakerCopyClipboardHandler.class, MineTweakerCopyClipboardPacket.class, 2, Side.CLIENT); + } + + @Mod.Instance(MODID) + public static MineTweakerMod INSTANCE; + + public final MCRecipeManager recipes; + private final IScriptProvider scriptsGlobal; + private final ScriptProviderCustom scriptsIMC; + + public MineTweakerMod() { + MineTweakerImplementationAPI.init( + new MCOreDict(), + recipes = new MCRecipeManager(), + new MCFurnaceManager(), + MCGame.INSTANCE, + new MCLoadedMods(), + new MCFormatter(), + new MCVanilla()); + + MineTweakerImplementationAPI.logger.addLogger(new FileLogger(new File("minetweaker.log"))); + MineTweakerImplementationAPI.platform = MCPlatformFunctions.INSTANCE; + + File globalDir = new File("scripts"); + if (!globalDir.exists()) + globalDir.mkdirs(); + + scriptsIMC = new ScriptProviderCustom("intermod"); + scriptsGlobal = new ScriptProviderDirectory(globalDir); + MineTweakerImplementationAPI.setScriptProvider(scriptsGlobal); + } + + // ########################## + // ### FML Event Handlers ### + // ########################## + + @EventHandler + public void onIMCEvent(FMLInterModComms.IMCEvent event) { + for (final FMLInterModComms.IMCMessage imcMessage : event.getMessages()) { + if (imcMessage.key.equalsIgnoreCase("addMineTweakerScript")) { + if (imcMessage.isStringMessage()) { + scriptsIMC.add(imcMessage.getSender() + "::imc", imcMessage.getStringValue()); + } else if (imcMessage.isNBTMessage()) { + NBTTagCompound message = imcMessage.getNBTValue(); + scriptsIMC.add(imcMessage.getSender() + "::" + message.getString("name"), message.getString("content")); + } + } + } + } + + @EventHandler + public void onLoad(FMLPreInitializationEvent ev) { + MinecraftForge.EVENT_BUS.register(new ForgeEventHandler()); + FMLCommonHandler.instance().bus().register(new FMLEventHandler()); + } + + @EventHandler + public void onPostInit(FMLPostInitializationEvent ev) { + MineTweakerAPI.registerClassRegistry(MineTweakerRegistry.class); + + for (int i = 0; i < REGISTRIES.length; i++) { + MineTweakerAPI.registerClassRegistry(REGISTRIES[i], REGISTRY_DESCRIPTIONS[i]); + } + + FuelTweaker.INSTANCE.register(); + + } + + @EventHandler + public void onServerAboutToStart(FMLServerAboutToStartEvent ev) { + // starts before loading worlds + // perfect place to start MineTweaker! + + if (MineTweakerPlatformUtils.isClient()) { + MineTweakerAPI.client = new MCClient(); + } + + File scriptsDir = new File(MineTweakerHacks.getWorldDirectory(ev.getServer()), "scripts"); + if (!scriptsDir.exists()) { + scriptsDir.mkdir(); + } + + IScriptProvider scriptsLocal = new ScriptProviderDirectory(scriptsDir); + IScriptProvider cascaded = new ScriptProviderCascade(scriptsIMC, scriptsGlobal, scriptsLocal); + + MineTweakerImplementationAPI.setScriptProvider(cascaded); + MineTweakerImplementationAPI.onServerStart(new MCServer(ev.getServer())); + } + + @EventHandler + public void onServerStarting(FMLServerStartingEvent ev) { + + } + + @EventHandler + public void onServerStopped(FMLServerStoppedEvent ev) { + MineTweakerImplementationAPI.onServerStop(); + MineTweakerImplementationAPI.setScriptProvider(scriptsGlobal); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MineTweakerRegistry.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MineTweakerRegistry.java new file mode 100644 index 0000000..87c8181 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/MineTweakerRegistry.java @@ -0,0 +1,19 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18; + +import java.util.List; + +/** + * + * @author Stan + */ +public class MineTweakerRegistry { + public static void getClasses(List classes) { + // method stub, actual content is generated by build process + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetBlockHardnessAction.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetBlockHardnessAction.java new file mode 100644 index 0000000..d84f5ce --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetBlockHardnessAction.java @@ -0,0 +1,84 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.actions; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.relauncher.ReflectionHelper; + +/** + * + * @author Jared + */ +public class SetBlockHardnessAction implements IUndoableAction { + + private final ItemStack stack; + private final float hardness; + private final float oldHardness; + + public SetBlockHardnessAction(ItemStack stack, float hardness) { + this.stack = stack; + this.hardness = hardness; + this.oldHardness = ReflectionHelper.getPrivateValue(Block.class, Block.getBlockFromItem(stack.getItem()), "blockHardness"); + } + + @Override + public void apply() { + if (isBlock(stack)) { + set(stack, hardness); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + if (isBlock(stack)) + set(stack, oldHardness); + } + + @Override + public String describe() { + if (isBlock(stack)) { + return "Setting hardness of " + stack.getDisplayName() + " to " + hardness; + } + return "Unable to set hardness of " + stack.getDisplayName() + " because it is an Item"; + } + + @Override + public String describeUndo() { + if (isBlock(stack)) { + return "Reverting hardness of " + stack.getDisplayName() + " to " + oldHardness; + } + return "Unable to revert hardness of " + stack.getDisplayName() + " because it is an Item"; + } + + private static void set(ItemStack stack, float hardness) { + if (isBlock(stack)) { + Block block = Block.getBlockFromItem(stack.getItem()); + block.setHardness(hardness); + } else { + MineTweakerAPI.logError("Item is not a block"); + } + } + + public static boolean isBlock(ItemStack stack) { + String name = (String) Block.blockRegistry.getNameForObject(Block.getBlockFromItem(stack.getItem())); + return !name.equalsIgnoreCase("minecraft:air") && Block.blockRegistry.containsKey(name); + + } + + @Override + public Object getOverrideKey() { + return null; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetStackSizeAction.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetStackSizeAction.java new file mode 100644 index 0000000..300e25a --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetStackSizeAction.java @@ -0,0 +1,61 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.actions; + +import minetweaker.IUndoableAction; +import net.minecraft.item.ItemStack; + +/** + * + * @author Jared + */ +public class SetStackSizeAction implements IUndoableAction { + + private final ItemStack stack; + private final int size; + private final int oldSize; + + public SetStackSizeAction(ItemStack stack, int size) { + this.stack = stack; + this.size = size; + this.oldSize = stack.getMaxStackSize(); + } + + @Override + public void apply() { + set(stack, size); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + set(stack, oldSize); + } + + @Override + public String describe() { + return "Setting max stack size of " + stack.getDisplayName() + " to " + size; + } + + @Override + public String describeUndo() { + return "Reverting max stack size of " + stack.getDisplayName() + " to " + oldSize; + } + + private static void set(ItemStack stack, int size) { + stack.getItem().setMaxStackSize(size); + } + + @Override + public Object getOverrideKey() { + return null; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetTranslationAction.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetTranslationAction.java new file mode 100644 index 0000000..c8882f3 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/actions/SetTranslationAction.java @@ -0,0 +1,67 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.actions; + +import java.io.ByteArrayInputStream; +import java.nio.charset.Charset; + +import minetweaker.IUndoableAction; +import minetweaker.mc18.util.MineTweakerHacks; +import net.minecraft.util.StringTranslate; + +/** + * + * @author Stan + */ +public class SetTranslationAction implements IUndoableAction { + private static final StringTranslate INSTANCE = MineTweakerHacks.getStringTranslateInstance(); + private static final Charset UTF8 = Charset.forName("utf-8"); + + private final String key; + private final String newValue; + private final String oldValue; + + public SetTranslationAction(String key, String value) { + this.key = key; + newValue = value; + oldValue = INSTANCE.translateKey(key); + } + + @Override + public void apply() { + set(key, newValue); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + set(key, oldValue); + } + + @Override + public String describe() { + return "Translating " + key + " to " + newValue; + } + + @Override + public String describeUndo() { + return "Reverting " + key + " to " + oldValue; + } + + private static void set(String key, String value) { + StringTranslate.inject(new ByteArrayInputStream((key + "=" + value).getBytes(UTF8))); + } + + @Override + public Object getOverrideKey() { + return null; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCBlockDefinition.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCBlockDefinition.java new file mode 100644 index 0000000..43d5ff7 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCBlockDefinition.java @@ -0,0 +1,36 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.block; + +import minetweaker.api.block.IBlockDefinition; +import net.minecraft.block.Block; + +/** + * + * @author Stan + */ +public class MCBlockDefinition implements IBlockDefinition { + private final Block block; + + public MCBlockDefinition(Block block) { + this.block = block; + } + + public Block getInternalBlock() { + return block; + } + + @Override + public String getId() { + return (String) Block.blockRegistry.getNameForObject(block); + } + + @Override + public String getDisplayName() { + return block.getLocalizedName(); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCItemBlock.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCItemBlock.java new file mode 100644 index 0000000..fa2f109 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCItemBlock.java @@ -0,0 +1,72 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.block; + +import java.util.Collections; +import java.util.List; + +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCItemBlock implements IBlock { + private final ItemStack item; + + public MCItemBlock(ItemStack item) { + this.item = item; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(Block.getBlockFromItem(item.getItem())); + } + + @Override + public int getMeta() { + return item.getItemDamage(); + } + + @Override + public IData getTileData() { + if (item.getTagCompound()== null) + return null; + + return MineTweakerMC.getIData(item.getTagCompound()); + } + + @Override + public String getDisplayName() { + return item.getDisplayName(); + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCSpecificBlock.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCSpecificBlock.java new file mode 100644 index 0000000..06a3be8 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCSpecificBlock.java @@ -0,0 +1,79 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.block; + +import java.util.Collections; +import java.util.List; + +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCSpecificBlock implements IBlock { + private final Block block; + private final int meta; + + public MCSpecificBlock(Block block, int meta) { + this.block = block; + this.meta = meta; + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(block); + } + + @Override + public int getMeta() { + return meta; + } + + @Override + public IData getTileData() { + return null; + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return block.getDefinition() == getDefinition() + && (meta == OreDictionary.WILDCARD_VALUE || block.getMeta() == meta); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } + + @Override + public String getDisplayName() { + return block.getLocalizedName(); + } + + @Override + public String toString() { + return ""; + } + + private static String getBlockId(Block block) + { + return (String) Block.blockRegistry.getNameForObject(block); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCWorldBlock.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCWorldBlock.java new file mode 100644 index 0000000..c13553a --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/block/MCWorldBlock.java @@ -0,0 +1,96 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.block; + +import java.util.Collections; +import java.util.List; + +import minetweaker.api.block.BlockPatternOr; +import minetweaker.api.block.IBlock; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.block.IBlockPattern; +import minetweaker.api.data.IData; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.world.IBlockAccess; +import net.minecraft.world.World; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCWorldBlock implements IBlock { + private final IBlockAccess blocks; + private final int x; + private final int y; + private final int z; + private final BlockPos position; + + public MCWorldBlock(IBlockAccess blocks, int x, int y, int z) { + this.blocks = blocks; + this.x = x; + this.y = y; + this.z = z; + this.position = new BlockPos(x, y, z); + } + + @Override + public IBlockDefinition getDefinition() { + return MineTweakerMC.getBlockDefinition(blocks.getBlockState(position).getBlock()); + } + + @Override + public int getMeta() { + return blocks.getBlockState(position).getBlock().getMetaFromState(blocks.getBlockState(position)); + } + + @Override + public IData getTileData() { + TileEntity tileEntity = blocks.getTileEntity(position); + + if (tileEntity == null) + return null; + + NBTTagCompound nbt = new NBTTagCompound(); + tileEntity.writeToNBT(nbt); + return MineTweakerMC.getIData(nbt); + } + + @Override + public String getDisplayName() { + Block block = blocks.getBlockState(position).getBlock(); + Item item = Item.getItemFromBlock(block); + if (item != null) { + return (new ItemStack(item, 1, getMeta())).getDisplayName(); + } else { + return block.getLocalizedName(); + } + } + + @Override + public List getBlocks() { + return Collections.singletonList(this); + } + + @Override + public boolean matches(IBlock block) { + return getDefinition() == block.getDefinition() + && (getMeta() == OreDictionary.WILDCARD_VALUE || getMeta() == block.getMeta()) + && (getTileData() == null || (block.getTileData() != null && block.getTileData().contains(getTileData()))); + } + + @Override + public IBlockPattern or(IBlockPattern pattern) { + return new BlockPatternOr(this, pattern); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/ItemBracketHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/ItemBracketHandler.java new file mode 100644 index 0000000..6e4b031 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/ItemBracketHandler.java @@ -0,0 +1,142 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.brackets; + +import static minetweaker.api.minecraft.MineTweakerMC.getIItemStackWildcardSize; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import minetweaker.IBracketHandler; +import minetweaker.MineTweakerAPI; +import minetweaker.annotations.BracketHandler; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.IngredientAny; +import net.minecraft.item.Item; +import net.minecraftforge.oredict.OreDictionary; +import stanhebben.zenscript.ZenTokener; +import stanhebben.zenscript.compiler.IEnvironmentGlobal; +import stanhebben.zenscript.expression.ExpressionCallStatic; +import stanhebben.zenscript.expression.ExpressionInt; +import stanhebben.zenscript.expression.ExpressionString; +import stanhebben.zenscript.expression.partial.IPartialExpression; +import stanhebben.zenscript.parser.Token; +import stanhebben.zenscript.symbols.IZenSymbol; +import stanhebben.zenscript.type.ZenType; +import stanhebben.zenscript.type.natives.IJavaMethod; +import stanhebben.zenscript.util.ZenPosition; + +/** + * + * @author Stan + */ +@BracketHandler(priority = 100) +public class ItemBracketHandler implements IBracketHandler { + private static final Map itemNames; + + static { + itemNames = new HashMap(); + for (String itemName : (Set) Item.itemRegistry.getKeys()) { + itemNames.put(itemName.replace(" ", ""), (Item) Item.itemRegistry.getObject(itemName)); + System.out.println(itemName + " : " + (Item) Item.itemRegistry.getObject(itemName)); + + } + } + + public static IItemStack getItem(String name, int meta) { + // Item item = (Item) Item.itemRegistry.getObject(name); + Item item = itemNames.get(name); + if (item != null) { + return getIItemStackWildcardSize(item, meta); + } else { + return null; + } + } + + private final IZenSymbol symbolAny; + private final IJavaMethod method; + + public ItemBracketHandler() { + symbolAny = MineTweakerAPI.getJavaStaticFieldSymbol(IngredientAny.class, "INSTANCE"); + method = MineTweakerAPI.getJavaMethod( + ItemBracketHandler.class, + "getItem", + String.class, int.class); + } + + @Override + public IZenSymbol resolve(IEnvironmentGlobal environment, List tokens) { + // any symbol + if (tokens.size() == 1 && tokens.get(0).getValue().equals("*")) { + return symbolAny; + } + + // detect special cases: + // item: at the start means item-specific syntax + // :xxx with xxx an integer means sub-item syntax + // :* means any-subitem-syntax + int fromIndex = 0; + int toIndex = tokens.size(); + int meta = 0; + + if (tokens.size() > 2) { + if (tokens.get(0).getValue().equals("item") && tokens.get(1).getValue().equals(":")) { + fromIndex = 2; + } + if (tokens.get(tokens.size() - 1).getType() == ZenTokener.T_INTVALUE + && tokens.get(tokens.size() - 2).getValue().equals(":")) { + toIndex = tokens.size() - 2; + meta = Integer.parseInt(tokens.get(tokens.size() - 1).getValue()); + } else if (tokens.get(tokens.size() - 1).getValue().equals("*") + && tokens.get(tokens.size() - 2).getValue().equals(":")) { + toIndex = tokens.size() - 2; + meta = OreDictionary.WILDCARD_VALUE; + } + } + + return find(environment, tokens, fromIndex, toIndex, meta); + } + + private IZenSymbol find(IEnvironmentGlobal environment, List tokens, int startIndex, int endIndex, int meta) { + StringBuilder valueBuilder = new StringBuilder(); + for (int i = startIndex; i < endIndex; i++) { + Token token = tokens.get(i); + valueBuilder.append(token.getValue()); + } + + String itemName = valueBuilder.toString(); + if (itemNames.containsKey(itemName)) { + return new ItemReferenceSymbol(environment, itemName, meta); + } + + return null; + } + + private class ItemReferenceSymbol implements IZenSymbol { + private final IEnvironmentGlobal environment; + private final String name; + private final int meta; + + public ItemReferenceSymbol(IEnvironmentGlobal environment, String name, int meta) { + this.environment = environment; + this.name = name; + this.meta = meta; + } + + @Override + public IPartialExpression instance(ZenPosition position) { + return new ExpressionCallStatic( + position, + environment, + method, + new ExpressionString(position, name), + new ExpressionInt(position, meta, ZenType.INT)); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/LiquidBracketHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/LiquidBracketHandler.java new file mode 100644 index 0000000..b2dedde --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/LiquidBracketHandler.java @@ -0,0 +1,88 @@ +package minetweaker.mc18.brackets; + +import java.util.List; + +import minetweaker.IBracketHandler; +import minetweaker.annotations.BracketHandler; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.mc18.liquid.MCLiquidStack; +import minetweaker.runtime.GlobalRegistry; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fluids.FluidStack; +import stanhebben.zenscript.compiler.IEnvironmentGlobal; +import stanhebben.zenscript.expression.ExpressionCallStatic; +import stanhebben.zenscript.expression.ExpressionString; +import stanhebben.zenscript.expression.partial.IPartialExpression; +import stanhebben.zenscript.parser.Token; +import stanhebben.zenscript.symbols.IZenSymbol; +import stanhebben.zenscript.type.natives.IJavaMethod; +import stanhebben.zenscript.type.natives.JavaMethod; +import stanhebben.zenscript.util.ZenPosition; + +/** + * + * @author Stan + */ +@BracketHandler +public class LiquidBracketHandler implements IBracketHandler { + public static ILiquidStack getLiquid(String name) { + Fluid fluid = FluidRegistry.getFluid(name); + if (fluid != null) { + return new MCLiquidStack(new FluidStack(fluid, 1)); + } else { + return null; + } + } + + @Override + public IZenSymbol resolve(IEnvironmentGlobal environment, List tokens) { + if (tokens.size() > 2) { + if (tokens.get(0).getValue().equals("liquid") && tokens.get(1).getValue().equals(":")) { + return find(environment, tokens, 2, tokens.size()); + } + } + + return null; + } + + private IZenSymbol find(IEnvironmentGlobal environment, List tokens, int startIndex, int endIndex) { + StringBuilder valueBuilder = new StringBuilder(); + for (int i = startIndex; i < endIndex; i++) { + Token token = tokens.get(i); + valueBuilder.append(token.getValue()); + } + + Fluid fluid = FluidRegistry.getFluid(valueBuilder.toString()); + if (fluid != null) { + return new LiquidReferenceSymbol(environment, valueBuilder.toString()); + } + + return null; + } + + private class LiquidReferenceSymbol implements IZenSymbol { + private final IEnvironmentGlobal environment; + private final String name; + + public LiquidReferenceSymbol(IEnvironmentGlobal environment, String name) { + this.environment = environment; + this.name = name; + } + + @Override + public IPartialExpression instance(ZenPosition position) { + IJavaMethod method = JavaMethod.get( + GlobalRegistry.getTypeRegistry(), + LiquidBracketHandler.class, + "getLiquid", + String.class); + + return new ExpressionCallStatic( + position, + environment, + method, + new ExpressionString(position, name)); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/OreBracketHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/OreBracketHandler.java new file mode 100644 index 0000000..5b9ecd7 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/brackets/OreBracketHandler.java @@ -0,0 +1,81 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.brackets; + +import java.util.List; + +import minetweaker.IBracketHandler; +import minetweaker.annotations.BracketHandler; +import minetweaker.api.oredict.IOreDictEntry; +import minetweaker.mc18.oredict.MCOreDictEntry; +import minetweaker.runtime.GlobalRegistry; +import stanhebben.zenscript.compiler.IEnvironmentGlobal; +import stanhebben.zenscript.expression.ExpressionCallStatic; +import stanhebben.zenscript.expression.ExpressionString; +import stanhebben.zenscript.expression.partial.IPartialExpression; +import stanhebben.zenscript.parser.Token; +import stanhebben.zenscript.symbols.IZenSymbol; +import stanhebben.zenscript.type.natives.IJavaMethod; +import stanhebben.zenscript.type.natives.JavaMethod; +import stanhebben.zenscript.util.ZenPosition; + +/** + * + * @author Stan + */ +@BracketHandler +public class OreBracketHandler implements IBracketHandler { + public static IOreDictEntry getOre(String name) { + return new MCOreDictEntry(name); + } + + @Override + public IZenSymbol resolve(IEnvironmentGlobal environment, List tokens) { + if (tokens.size() > 2) { + if (tokens.get(0).getValue().equals("ore") && tokens.get(1).getValue().equals(":")) { + return find(environment, tokens, 2, tokens.size()); + } + } + + return null; + } + + private IZenSymbol find(IEnvironmentGlobal environment, List tokens, int startIndex, int endIndex) { + StringBuilder valueBuilder = new StringBuilder(); + for (int i = startIndex; i < endIndex; i++) { + Token token = tokens.get(i); + valueBuilder.append(token.getValue()); + } + + return new OreReferenceSymbol(environment, valueBuilder.toString()); + } + + private class OreReferenceSymbol implements IZenSymbol { + private final IEnvironmentGlobal environment; + private final String name; + + public OreReferenceSymbol(IEnvironmentGlobal environment, String name) { + this.environment = environment; + this.name = name; + } + + @Override + public IPartialExpression instance(ZenPosition position) { + IJavaMethod method = JavaMethod.get( + GlobalRegistry.getTypeRegistry(), + OreBracketHandler.class, + "getOre", + String.class); + + return new ExpressionCallStatic( + position, + environment, + method, + new ExpressionString(position, name)); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/chat/MCChatMessage.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/chat/MCChatMessage.java new file mode 100644 index 0000000..0e6d4ec --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/chat/MCChatMessage.java @@ -0,0 +1,37 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.chat; + +import minetweaker.api.chat.IChatMessage; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +/** + * + * @author Stan + */ +public class MCChatMessage implements IChatMessage { + private final IChatComponent data; + + public MCChatMessage(String message) { + data = new ChatComponentText(message); + } + + public MCChatMessage(IChatComponent data) { + this.data = data; + } + + @Override + public IChatMessage add(IChatMessage other) { + return new MCChatMessage(data.appendSibling((IChatComponent) other.getInternal())); + } + + @Override + public Object getInternal() { + return data; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/client/MCClient.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/client/MCClient.java new file mode 100644 index 0000000..feb3088 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/client/MCClient.java @@ -0,0 +1,29 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.client; + +import minetweaker.api.client.IClient; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.player.IPlayer; +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.client.FMLClientHandler; + +/** + * + * @author Stan + */ +public class MCClient implements IClient { + @Override + public IPlayer getPlayer() { + return MineTweakerMC.getIPlayer(Minecraft.getMinecraft().thePlayer); + } + + @Override + public String getLanguage() { + return FMLClientHandler.instance().getCurrentLanguage(); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/data/NBTConverter.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/data/NBTConverter.java new file mode 100644 index 0000000..d1e0270 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/data/NBTConverter.java @@ -0,0 +1,172 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.data; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import minetweaker.api.data.DataByte; +import minetweaker.api.data.DataByteArray; +import minetweaker.api.data.DataDouble; +import minetweaker.api.data.DataFloat; +import minetweaker.api.data.DataInt; +import minetweaker.api.data.DataIntArray; +import minetweaker.api.data.DataList; +import minetweaker.api.data.DataLong; +import minetweaker.api.data.DataMap; +import minetweaker.api.data.DataShort; +import minetweaker.api.data.DataString; +import minetweaker.api.data.IData; +import minetweaker.api.data.IDataConverter; +import minetweaker.mc18.util.MineTweakerHacks; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagByte; +import net.minecraft.nbt.NBTTagByteArray; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagDouble; +import net.minecraft.nbt.NBTTagFloat; +import net.minecraft.nbt.NBTTagInt; +import net.minecraft.nbt.NBTTagIntArray; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.nbt.NBTTagLong; +import net.minecraft.nbt.NBTTagShort; +import net.minecraft.nbt.NBTTagString; + +/** + * + * @author Stan + */ +public class NBTConverter implements IDataConverter { + private static final NBTConverter INSTANCE = new NBTConverter(); + + public static NBTBase from(IData data) { + return data.convert(INSTANCE); + } + + public static IData from(NBTBase nbt, boolean immutable) { + if (nbt == null) + return null; + + switch (nbt.getId()) { + case 1: // byte + return new DataByte(((NBTBase.NBTPrimitive) nbt).getByte()); + case 2: // short + return new DataShort(((NBTBase.NBTPrimitive) nbt).getShort()); + case 3: // int + return new DataInt(((NBTBase.NBTPrimitive) nbt).getInt()); + case 4: // long + return new DataLong(((NBTBase.NBTPrimitive) nbt).getLong()); + case 5: // float + return new DataFloat(((NBTBase.NBTPrimitive) nbt).getFloat()); + case 6: // double + return new DataDouble(((NBTBase.NBTPrimitive) nbt).getDouble()); + case 7: // byte[] + return new DataByteArray(((NBTTagByteArray) nbt).getByteArray(), immutable); + case 8: // string + return new DataString(((NBTTagString) nbt).getString()); + case 9: { // list + List values = new ArrayList(); + List original = MineTweakerHacks.getTagList((NBTTagList) nbt); + for (NBTBase value : original) { + values.add(from(value, immutable)); + } + return new DataList(values, immutable); + } + case 10: { // compound + Map values = new HashMap(); + NBTTagCompound original = (NBTTagCompound) nbt; + for (String key : (Set) original.getKeySet()) { + values.put(key, from(original.getTag(key), immutable)); + } + return new DataMap(values, immutable); + } + case 11: // int[] + return new DataIntArray(((NBTTagIntArray) nbt).getIntArray(), immutable); + default: + throw new RuntimeException("Unknown tag type: " + nbt.getId()); + } + } + + public static void updateMap(NBTTagCompound nbt, IData data) { + NBTUpdater updater = new NBTUpdater(nbt); + data.convert(updater); + } + + public NBTConverter() { + } + + @Override + public NBTBase fromBool(boolean value) { + return new NBTTagInt(value ? 1 : 0); + } + + @Override + public NBTBase fromByte(byte value) { + return new NBTTagByte(value); + } + + @Override + public NBTBase fromShort(short value) { + return new NBTTagShort(value); + } + + @Override + public NBTBase fromInt(int value) { + return new NBTTagInt(value); + } + + @Override + public NBTBase fromLong(long value) { + return new NBTTagLong(value); + } + + @Override + public NBTBase fromFloat(float value) { + return new NBTTagFloat(value); + } + + @Override + public NBTBase fromDouble(double value) { + return new NBTTagDouble(value); + } + + @Override + public NBTBase fromString(String value) { + return new NBTTagString(value); + } + + @Override + public NBTBase fromList(List values) { + NBTTagList result = new NBTTagList(); + for (IData value : values) { + result.appendTag(from(value)); + } + return result; + } + + @Override + public NBTBase fromMap(Map values) { + NBTTagCompound result = new NBTTagCompound(); + for (Map.Entry entry : values.entrySet()) { + result.setTag(entry.getKey(), from(entry.getValue())); + } + return result; + } + + @Override + public NBTBase fromByteArray(byte[] value) { + return new NBTTagByteArray(value); + } + + @Override + public NBTBase fromIntArray(int[] value) { + return new NBTTagIntArray(value); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/data/NBTUpdater.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/data/NBTUpdater.java new file mode 100644 index 0000000..7c46069 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/data/NBTUpdater.java @@ -0,0 +1,48 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.data; + +import java.util.Map; + +import minetweaker.api.data.IData; +import minetweaker.api.data.IDataConverter; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; + +/** + * + * @author Stan + */ +public class NBTUpdater extends NBTConverter implements IDataConverter { + private final NBTTagCompound nbt; + + public NBTUpdater(NBTTagCompound compound) { + this.nbt = compound; + } + + @Override + public NBTBase fromMap(Map map) { + for (Map.Entry entry : map.entrySet()) { + if (nbt.hasKey(entry.getKey())) { + if (entry.getValue() == null) { + nbt.removeTag(entry.getKey()); + } else { + if (nbt.getTag(entry.getKey()).getId() == 10) { + NBTTagCompound tag = (NBTTagCompound) nbt.getTag(entry.getKey()); + nbt.setTag(entry.getKey(), entry.getValue().convert(new NBTUpdater(nbt))); + } else { + nbt.setTag(entry.getKey(), NBTConverter.from(entry.getValue())); + } + } + } else if (entry.getValue() != null) { + nbt.setTag(entry.getKey(), from(entry.getValue())); + } + } + + return nbt; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/entity/MCEntityDefinition.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/entity/MCEntityDefinition.java new file mode 100644 index 0000000..f366061 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/entity/MCEntityDefinition.java @@ -0,0 +1,32 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.entity; + +import minetweaker.api.entity.IEntityDefinition; +import net.minecraftforge.fml.common.registry.EntityRegistry; + +/** + * + * @author Stan + */ +public class MCEntityDefinition implements IEntityDefinition { + private final EntityRegistry.EntityRegistration registration; + + public MCEntityDefinition(EntityRegistry.EntityRegistration registration) { + this.registration = registration; + } + + @Override + public String getId() { + return registration.getEntityClass().getName(); + } + + @Override + public String getName() { + return registration.getEntityName(); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedMarkupString.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedMarkupString.java new file mode 100644 index 0000000..b467a06 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedMarkupString.java @@ -0,0 +1,44 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.formatting; + +import minetweaker.api.formatting.IFormattedText; +import net.minecraft.util.EnumChatFormatting; + +/** + * + * @author Stan + */ +public class FormattedMarkupString implements IMCFormattedString { + private final EnumChatFormatting markup; + private final IMCFormattedString contents; + + public FormattedMarkupString(EnumChatFormatting markup, IMCFormattedString contents) { + this.markup = markup; + this.contents = contents; + } + + @Override + public String getTooltipString() { + return markup + contents.getTooltipString(markup.toString()); + } + + @Override + public String getTooltipString(String context) { + return markup + contents.getTooltipString(context + markup); + } + + @Override + public IFormattedText add(IFormattedText other) { + return cat(other); + } + + @Override + public IFormattedText cat(IFormattedText other) { + return new FormattedStringJoin(this, (IMCFormattedString) other); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedString.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedString.java new file mode 100644 index 0000000..be738e0 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedString.java @@ -0,0 +1,41 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.formatting; + +import minetweaker.api.formatting.IFormattedText; + +/** + * + * @author Stan + */ +public class FormattedString implements IMCFormattedString { + private final String value; + + public FormattedString(String value) { + this.value = value; + } + + @Override + public String getTooltipString() { + return value; + } + + @Override + public String getTooltipString(String context) { + return value; + } + + @Override + public IFormattedText add(IFormattedText other) { + return cat(other); + } + + @Override + public IFormattedText cat(IFormattedText other) { + return new FormattedStringJoin(this, (IMCFormattedString) other); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedStringJoin.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedStringJoin.java new file mode 100644 index 0000000..1452c14 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/FormattedStringJoin.java @@ -0,0 +1,68 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.formatting; + +import java.util.Arrays; + +import minetweaker.api.formatting.IFormattedText; +import net.minecraft.util.EnumChatFormatting; + +/** + * + * @author Stan + */ +public class FormattedStringJoin implements IMCFormattedString { + private final IMCFormattedString[] values; + + public FormattedStringJoin(IMCFormattedString first, IMCFormattedString second) { + values = new IMCFormattedString[] { first, second }; + } + + public FormattedStringJoin(IMCFormattedString[] values) { + this.values = values; + } + + @Override + public String getTooltipString() { + StringBuilder result = new StringBuilder(); + for (IMCFormattedString value : values) { + result.append(value.getTooltipString()); + } + return result.toString(); + } + + @Override + public String getTooltipString(String context) { + boolean first = true; + + StringBuilder result = new StringBuilder(); + for (IMCFormattedString value : values) { + if (first) { + first = false; + } else { + result.append(context); + } + + result.append(value.getTooltipString()); + result.append(EnumChatFormatting.RESET); + } + + return result.toString(); + } + + @Override + public IFormattedText add(IFormattedText other) { + return cat(other); + } + + @Override + public IFormattedText cat(IFormattedText other) { + IMCFormattedString[] newValues = Arrays.copyOf(values, values.length + 1); + newValues[values.length] = (IMCFormattedString) other; + return new FormattedStringJoin(newValues); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/IMCFormattedString.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/IMCFormattedString.java new file mode 100644 index 0000000..b91b71d --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/IMCFormattedString.java @@ -0,0 +1,19 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.formatting; + +import minetweaker.api.formatting.IFormattedText; + +/** + * + * @author Stan + */ +public interface IMCFormattedString extends IFormattedText { + public String getTooltipString(); + + public String getTooltipString(String context); +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/MCFormatter.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/MCFormatter.java new file mode 100644 index 0000000..57690a8 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/formatting/MCFormatter.java @@ -0,0 +1,128 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.formatting; + +import minetweaker.api.formatting.IFormattedText; +import minetweaker.api.formatting.IFormatter; +import net.minecraft.util.EnumChatFormatting; + +/** + * + * @author Stan + */ +public class MCFormatter implements IFormatter { + + @Override + public IFormattedText string(String text) { + return new FormattedString(text); + } + + @Override + public IFormattedText black(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.BLACK, (IMCFormattedString) text); + } + + @Override + public IFormattedText darkBlue(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.DARK_BLUE, (IMCFormattedString) text); + } + + @Override + public IFormattedText darkGreen(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.DARK_GREEN, (IMCFormattedString) text); + } + + @Override + public IFormattedText darkAqua(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.DARK_AQUA, (IMCFormattedString) text); + } + + @Override + public IFormattedText darkRed(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.DARK_RED, (IMCFormattedString) text); + } + + @Override + public IFormattedText darkPurple(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.DARK_PURPLE, (IMCFormattedString) text); + } + + @Override + public IFormattedText gold(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.GOLD, (IMCFormattedString) text); + } + + @Override + public IFormattedText gray(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.GRAY, (IMCFormattedString) text); + } + + @Override + public IFormattedText darkGray(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.DARK_GRAY, (IMCFormattedString) text); + } + + @Override + public IFormattedText blue(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.BLUE, (IMCFormattedString) text); + } + + @Override + public IFormattedText green(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.GREEN, (IMCFormattedString) text); + } + + @Override + public IFormattedText aqua(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.AQUA, (IMCFormattedString) text); + } + + @Override + public IFormattedText red(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.RED, (IMCFormattedString) text); + } + + @Override + public IFormattedText lightPurple(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.LIGHT_PURPLE, (IMCFormattedString) text); + } + + @Override + public IFormattedText yellow(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.YELLOW, (IMCFormattedString) text); + } + + @Override + public IFormattedText white(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.WHITE, (IMCFormattedString) text); + } + + @Override + public IFormattedText obfuscated(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.OBFUSCATED, (IMCFormattedString) text); + } + + @Override + public IFormattedText bold(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.BOLD, (IMCFormattedString) text); + } + + @Override + public IFormattedText strikethrough(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.STRIKETHROUGH, (IMCFormattedString) text); + } + + @Override + public IFormattedText underline(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.UNDERLINE, (IMCFormattedString) text); + } + + @Override + public IFormattedText italic(IFormattedText text) { + return new FormattedMarkupString(EnumChatFormatting.ITALIC, (IMCFormattedString) text); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/FuelTweaker.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/FuelTweaker.java new file mode 100644 index 0000000..9809536 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/FuelTweaker.java @@ -0,0 +1,95 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.furnace; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; + +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.fml.common.IFuelHandler; +import net.minecraftforge.fml.common.registry.GameRegistry; + +public class FuelTweaker { + public static final FuelTweaker INSTANCE = new FuelTweaker(); + + private List original; + private final HashMap> quickList = new HashMap>(); + + private FuelTweaker() { + } + + public void register() { + try { + Field fuelHandlers = GameRegistry.class.getDeclaredField("fuelHandlers"); + fuelHandlers.setAccessible(true); + original = (List) fuelHandlers.get(null); + List modified = new ArrayList(); + modified.add(new OverridingFuelHandler()); + fuelHandlers.set(null, modified); + } catch (NoSuchFieldException ex) { + System.out.println("[MineTweaker] Error: could not get GameRegistry fuel handlers field. Cannot use custom fuel values."); + } catch (SecurityException ex) { + System.out.println("[MineTweaker] Error: could not alter GameRegistry fuel handlers field. Cannot use custom fuel values."); + } catch (IllegalAccessException ex) { + System.out.println("[MineTweaker] Error: could not alter GameRegistry fuel handlers field. Cannot use custom fuel values."); + } + } + + public void addFuelPattern(SetFuelPattern pattern) { + List items = pattern.getPattern().getItems(); + if (items == null) { + MineTweakerAPI.logError("Cannot set fuel for <*>"); + return; + } + + for (IItemStack item : pattern.getPattern().getItems()) { + ItemStack itemStack = MineTweakerMC.getItemStack(item); + Item mcItem = itemStack.getItem(); + if (!quickList.containsKey(mcItem)) { + quickList.put(mcItem, new ArrayList()); + } + quickList.get(mcItem).add(pattern); + } + } + + public void removeFuelPattern(SetFuelPattern pattern) { + for (IItemStack item : pattern.getPattern().getItems()) { + ItemStack itemStack = MineTweakerMC.getItemStack(item); + Item mcItem = itemStack.getItem(); + if (quickList.containsKey(mcItem)) { + quickList.get(mcItem).remove(pattern); + } + } + } + + private class OverridingFuelHandler implements IFuelHandler { + @Override + public int getBurnTime(ItemStack fuel) { + if (quickList.containsKey(fuel.getItem())) { + IItemStack stack = MineTweakerMC.getIItemStack(fuel); + + for (SetFuelPattern override : quickList.get(fuel.getItem())) { + if (override.getPattern().matches(stack)) { + return override.getValue(); + } + } + } + + int max = 0; + for (IFuelHandler handler : original) { + max = Math.max(max, handler.getBurnTime(fuel)); + } + return max; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/MCFurnaceManager.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/MCFurnaceManager.java new file mode 100644 index 0000000..5f8f93e --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/MCFurnaceManager.java @@ -0,0 +1,214 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.furnace; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import static minetweaker.api.minecraft.MineTweakerMC.getItemStacks; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.recipes.IFurnaceManager; +import minetweaker.mc18.item.MCItemStack; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraftforge.fml.common.registry.GameRegistry; + +/** + * + * @author Stan + */ +public class MCFurnaceManager implements IFurnaceManager { + public MCFurnaceManager() { + + } + + @Override + public void remove(IIngredient output, IIngredient input) { + if (output == null) + throw new IllegalArgumentException("output cannot be null"); + + Map smeltingList = FurnaceRecipes.instance().getSmeltingList(); + + List toRemove = new ArrayList(); + List toRemoveValues = new ArrayList(); + for (Map.Entry entry : smeltingList.entrySet()) { + if (output.matches(new MCItemStack(entry.getValue())) + && (input == null || input.matches(new MCItemStack(entry.getKey())))) { + toRemove.add(entry.getKey()); + toRemoveValues.add(entry.getValue()); + } + } + + if (toRemove.isEmpty()) { + MineTweakerAPI.logWarning("No furnace recipes for " + output.toString()); + } else { + MineTweakerAPI.apply(new RemoveAction(toRemove, toRemoveValues)); + } + } + + @Override + public void addRecipe(IItemStack output, IIngredient input, double xp) { + List items = input.getItems(); + if (items == null) { + MineTweakerAPI.logError("Cannot turn " + input.toString() + " into a furnace recipe"); + } + + ItemStack[] items2 = getItemStacks(items); + ItemStack output2 = getItemStack(output); + MineTweakerAPI.apply(new AddRecipeAction(input, items2, output2, xp)); + } + + @Override + public void setFuel(IIngredient item, int fuel) { + MineTweakerAPI.apply(new SetFuelAction(new SetFuelPattern(item, fuel))); + } + + @Override + public int getFuel(IItemStack item) { + return GameRegistry.getFuelValue(getItemStack(item)); + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class RemoveAction implements IUndoableAction { + private final List items; + private final List values; + + public RemoveAction(List items, List values) { + this.items = items; + this.values = values; + } + + @Override + public void apply() { + for (ItemStack item : items) { + FurnaceRecipes.instance().getSmeltingList().remove(item); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (int i = 0; i < items.size(); i++) { + FurnaceRecipes.instance().getSmeltingList().put(items.get(i), values.get(i)); + } + } + + @Override + public String describe() { + return "Removing " + items.size() + " furnace recipes"; + } + + @Override + public String describeUndo() { + return "Restoring " + items.size() + " furnace recipes"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class AddRecipeAction implements IUndoableAction { + private final IIngredient ingredient; + private final ItemStack[] input; + private final ItemStack output; + private final double xp; + + public AddRecipeAction(IIngredient ingredient, ItemStack[] input, ItemStack output, double xp) { + this.ingredient = ingredient; + this.input = input; + this.output = output; + this.xp = xp; + } + + @Override + public void apply() { + for (ItemStack inputStack : input) { + FurnaceRecipes.instance().addSmeltingRecipe(inputStack, output, (float) xp); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (ItemStack inputStack : input) { + FurnaceRecipes.instance().getSmeltingList().remove(inputStack); + } + } + + @Override + public String describe() { + return "Adding furnace recipe for " + ingredient; + } + + @Override + public String describeUndo() { + return "Removing furnace recipe for " + ingredient; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class SetFuelAction implements IUndoableAction { + private final SetFuelPattern pattern; + + public SetFuelAction(SetFuelPattern pattern) { + this.pattern = pattern; + } + + @Override + public void apply() { + FuelTweaker.INSTANCE.addFuelPattern(pattern); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + FuelTweaker.INSTANCE.removeFuelPattern(pattern); + } + + @Override + public String describe() { + return "Setting fuel for " + pattern.getPattern(); + } + + @Override + public String describeUndo() { + return "Removing fuel for " + pattern.getPattern(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/SetFuelPattern.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/SetFuelPattern.java new file mode 100644 index 0000000..31d8098 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/furnace/SetFuelPattern.java @@ -0,0 +1,21 @@ +package minetweaker.mc18.furnace; + +import minetweaker.api.item.IIngredient; + +public class SetFuelPattern { + private final IIngredient pattern; + private final int value; + + public SetFuelPattern(IIngredient pattern, int value) { + this.pattern = pattern; + this.value = value; + } + + public IIngredient getPattern() { + return pattern; + } + + public int getValue() { + return value; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/game/MCGame.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/game/MCGame.java new file mode 100644 index 0000000..ae134fa --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/game/MCGame.java @@ -0,0 +1,214 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.game; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlockDefinition; +import minetweaker.api.entity.IEntityDefinition; +import minetweaker.api.game.IGame; +import minetweaker.api.item.IItemDefinition; +import minetweaker.api.liquid.ILiquidDefinition; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.world.IBiome; +// TODO Find this +// import minetweaker.mc1710.GuiCannotRemodify; +import minetweaker.mc18.entity.MCEntityDefinition; +import minetweaker.mc18.item.MCItemDefinition; +import minetweaker.mc18.liquid.MCLiquidDefinition; +import minetweaker.mc18.util.MineTweakerHacks; +import minetweaker.mc18.util.MineTweakerPlatformUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.item.Item; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.fml.common.registry.EntityRegistry; +import net.minecraftforge.fml.common.registry.LanguageRegistry; + +/** + * + * @author Stan + */ +public class MCGame implements IGame { + private static final Map TRANSLATIONS = MineTweakerHacks.getTranslations(); + + public static final MCGame INSTANCE = new MCGame(); + + private boolean locked = false; + + private MCGame() { + } + + @Override + public List getItems() { + List result = new ArrayList(); + for (String item : (Set) Item.itemRegistry.getKeys()) { + result.add(new MCItemDefinition(item, (Item) Item.itemRegistry.getObject(item))); + } + return result; + } + + @Override + public List getBlocks() { + List result = new ArrayList(); + for (String block : (Set) Block.blockRegistry.getKeys()) { + result.add(MineTweakerMC.getBlockDefinition((Block) Block.blockRegistry.getObject(block))); + } + + return result; + } + + @Override + public List getLiquids() { + List result = new ArrayList(); + for (Map.Entry entry : FluidRegistry.getRegisteredFluids().entrySet()) { + result.add(new MCLiquidDefinition(entry.getValue())); + } + return result; + } + + @Override + public List getBiomes() { + List result = new ArrayList(); + for (IBiome biome : MineTweakerMC.biomes) { + if (biome != null) { + result.add(biome); + } + } + return result; + } + + @Override + public List getEntities() { + List result = new ArrayList(); + + for (EntityRegistry.EntityRegistration entityRegistration : MineTweakerHacks.getEntityClassRegistrations().values()) { + result.add(new MCEntityDefinition(entityRegistration)); + } + + return result; + } + + @Override + public void setLocalization(String key, String value) { + MineTweakerAPI.apply(new SetTranslation(null, key, value)); + } + + @Override + public void setLocalization(String lang, String key, String value) { + MineTweakerAPI.apply(new SetTranslation(lang, key, value)); + } + + @Override + public String localize(String key) { + return LanguageRegistry.instance().getStringLocalization(key); + } + + @Override + public String localize(String key, String lang) { + return LanguageRegistry.instance().getStringLocalization(key, lang); + } + + @Override + public void lock() + { + locked = true; + } + + @Override + public boolean isLocked() + { + return locked; + } + + @Override + public void signalLockError() + { + MineTweakerAPI.getLogger().logError("Reload of scripts blocked (script lock)"); + + if (Minecraft.isGuiEnabled()) { + // Commented out due to unresolved import + /** + * Minecraft.getMinecraft().displayGuiScreen( new GuiCannotRemodify( + * "Minecraft has been tweaked for another server", + * "with modifications that cannot be rolled back.", + * "Please restart your game.")); + **/ + } + } + + // ###################### + // ### Action classes ### + // ###################### + + /** + * Ported from ModTweaker. + * + * @author Joshiejack + */ + private static class SetTranslation implements IUndoableAction { + private String original; + private final String lang; + private final String key; + private final String text; + private boolean added; + + public SetTranslation(String lang, String key, String text) { + this.lang = lang; + this.key = key; + this.text = text; + } + + @Override + public void apply() { + if (lang == null || MineTweakerPlatformUtils.isLanguageActive(lang)) { + original = TRANSLATIONS.get(key); + TRANSLATIONS.put(key, text); + added = true; + } else { + added = false; + } + } + + @Override + public boolean canUndo() { + return TRANSLATIONS != null; + } + + @Override + public void undo() { + if (added) { + if (original == null) { + TRANSLATIONS.remove(key); + } else { + TRANSLATIONS.put(key, original); + } + } + } + + @Override + public String describe() { + return "Setting localization for the key: " + key + " to " + text; + } + + @Override + public String describeUndo() { + return "Setting localization for the key: " + key + " to " + original; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/item/MCItemDefinition.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/item/MCItemDefinition.java new file mode 100644 index 0000000..fa843e0 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/item/MCItemDefinition.java @@ -0,0 +1,90 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.item; + +import java.util.ArrayList; +import java.util.List; + +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IItemDefinition; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.oredict.IOreDictEntry; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCItemDefinition implements IItemDefinition { + private final String id; + private final Item item; + + public MCItemDefinition(String id, Item item) { + this.id = id; + this.item = item; + } + + @Override + public String getId() { + return id; + } + + @Override + public String getName() { + return item.getUnlocalizedName(); + } + + @Override + public IItemStack makeStack(int meta) { + return MineTweakerMC.getIItemStackWildcardSize(new ItemStack(item, 1, meta)); + } + + @Override + public List getOres() { + List result = new ArrayList(); + + for (String key : OreDictionary.getOreNames()) { + for (ItemStack is : OreDictionary.getOres(key)) { + if (is.getItem() == item) { + result.add(MineTweakerAPI.oreDict.get(key)); + break; + } + } + } + + return result; + } + + // ############################# + // ### Object implementation ### + // ############################# + + @Override + public int hashCode() { + int hash = 7; + hash = 37 * hash + (this.item != null ? this.item.hashCode() : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final MCItemDefinition other = (MCItemDefinition) obj; + if (this.item != other.item && (this.item == null || !this.item.equals(other.item))) { + return false; + } + return true; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/item/MCItemStack.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/item/MCItemStack.java new file mode 100644 index 0000000..69d337b --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/item/MCItemStack.java @@ -0,0 +1,391 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.item; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import minetweaker.MineTweakerAPI; +import minetweaker.api.block.IBlock; +import minetweaker.api.data.DataMap; +import minetweaker.api.data.IData; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemCondition; +import minetweaker.api.item.IItemDefinition; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientItem; +import minetweaker.api.item.IngredientOr; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.oredict.IOreDictEntry; +import minetweaker.api.player.IPlayer; +import minetweaker.mc18.actions.SetBlockHardnessAction; +import minetweaker.mc18.actions.SetStackSizeAction; +import minetweaker.mc18.actions.SetTranslationAction; +import minetweaker.mc18.block.MCItemBlock; +import minetweaker.mc18.data.NBTConverter; +import minetweaker.mc18.liquid.MCLiquidStack; +import minetweaker.util.ArrayUtil; +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidStack; +import net.minecraftforge.fml.relauncher.ReflectionHelper; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCItemStack implements IItemStack { + private final ItemStack stack; + private final List items; + private IData tag = null; + private boolean wildcardSize; + + public MCItemStack(ItemStack itemStack) { + if (itemStack == null) + throw new IllegalArgumentException("stack cannot be null"); + + stack = itemStack.copy(); + items = Collections.singletonList(this); + } + + public MCItemStack(ItemStack itemStack, boolean wildcardSize) { + this(itemStack); + + this.wildcardSize = wildcardSize; + } + + private MCItemStack(ItemStack itemStack, IData tag) { + if (itemStack == null) + throw new IllegalArgumentException("stack cannot be null"); + + stack = itemStack; + items = Collections.singletonList(this); + this.tag = tag; + } + + private MCItemStack(ItemStack itemStack, IData tag, boolean wildcardSize) { + stack = itemStack; + items = Collections.singletonList(this); + this.tag = tag; + this.wildcardSize = wildcardSize; + } + + @Override + public IItemDefinition getDefinition() { + return new MCItemDefinition((String) Item.itemRegistry.getNameForObject(stack.getItem()), stack.getItem()); + } + + @Override + public String getName() { + return stack.getUnlocalizedName(); + } + + @Override + public String getDisplayName() { + return stack.getDisplayName(); + } + + @Override + public void setDisplayName(String name) { + MineTweakerAPI.apply(new SetTranslationAction(getName() + ".name", name)); + } + + @Override + public int getMaxStackSize() { + return stack.getMaxStackSize(); + } + + @Override + public void setMaxStackSize(int size) { + MineTweakerAPI.apply(new SetStackSizeAction((ItemStack) getInternal(), size)); + } + + @Override + public float getBlockHardness() { + return ReflectionHelper.getPrivateValue(Block.class, Block.getBlockFromItem(stack.getItem()), "blockHardness"); + } + + @Override + public void setBlockHardness(float hardness) { + MineTweakerAPI.apply(new SetBlockHardnessAction(stack, hardness)); + } + + @Override + public int getDamage() { + return stack.getItemDamage(); + } + + @Override + public IData getTag() { + if (tag == null) { + if (stack.getTagCompound() == null) { + return DataMap.EMPTY; + } + + tag = NBTConverter.from(stack.getTagCompound(), true); + } + return tag; + } + + @Override + public int getMaxDamage() { + return stack.getMaxDamage(); + } + + @Override + public ILiquidStack getLiquid() { + FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(stack); + return liquid == null ? null : new MCLiquidStack(liquid); + } + + @Override + public IIngredient anyDamage() { + if (stack.getItem().getHasSubtypes()) { + MineTweakerAPI.logWarning("subitems don't have damaged states"); + return this; + } else { + ItemStack result = new ItemStack(stack.getItem(), stack.stackSize, OreDictionary.WILDCARD_VALUE); + result.setTagCompound(stack.getTagCompound()); + return new MCItemStack(result, tag); + } + } + + @Override + public IItemStack withDamage(int damage) { + if (stack.getItem().getHasSubtypes()) { + MineTweakerAPI.logWarning("subitems don't have damaged states"); + return this; + } else { + ItemStack result = new ItemStack(stack.getItem(), stack.stackSize, damage); + result.setTagCompound(stack.getTagCompound()); + return new MCItemStack(result, tag); + } + } + + @Override + public IItemStack anyAmount() { + ItemStack result = new ItemStack(stack.getItem(), 1, stack.getItemDamage()); + result.setTagCompound(stack.getTagCompound()); + return new MCItemStack(result, tag, true); + } + + @Override + public IItemStack withAmount(int amount) { + ItemStack result = new ItemStack(stack.getItem(), amount, stack.getItemDamage()); + result.setTagCompound(stack.getTagCompound()); + return new MCItemStack(result, tag); + } + + @Override + public IItemStack withTag(IData tag) { + ItemStack result = new ItemStack(stack.getItem(), stack.stackSize, stack.getItemDamage()); + if (tag == null) { + result.setTagCompound(null); + } else { + result.setTagCompound((NBTTagCompound) NBTConverter.from(tag)); + } + return new MCItemStack(result, tag); + } + + @Override + public IItemStack updateTag(IData tagUpdate) { + if (tag == null) { + if (stack.getTagCompound() == null) { + return withTag(tagUpdate); + } + + tag = NBTConverter.from(stack.getTagCompound(), true); + } + + IData updated = tag.update(tagUpdate); + return withTag(updated); + } + + @Override + public String getMark() { + return null; + } + + @Override + public int getAmount() { + return stack.stackSize; + } + + @Override + public List getItems() { + return items; + } + + @Override + public List getLiquids() { + return Collections.emptyList(); + } + + @Override + public IItemStack amount(int amount) { + return withAmount(amount); + } + + @Override + public WeightedItemStack percent(float chance) { + return new WeightedItemStack(this, chance * 0.01f); + } + + @Override + public WeightedItemStack weight(float chance) { + return new WeightedItemStack(this, chance); + } + + @Override + public IIngredient transform(IItemTransformer transformer) { + return new IngredientItem(this, null, ArrayUtil.EMPTY_CONDITIONS, new IItemTransformer[] { transformer }); + } + + @Override + public IIngredient only(IItemCondition condition) { + return new IngredientItem(this, null, new IItemCondition[] { condition }, ArrayUtil.EMPTY_TRANSFORMERS); + } + + @Override + public IIngredient marked(String mark) { + return new IngredientItem(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); + } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } + + @Override + public boolean matches(IItemStack item) { + ItemStack internal = getItemStack(item); + return internal.getItem() == stack.getItem() && (wildcardSize || internal.stackSize >= stack.stackSize) && (stack.getItemDamage() == OreDictionary.WILDCARD_VALUE || stack.getItemDamage() == internal.getItemDamage() || (!stack.getHasSubtypes() && !stack.getItem().isDamageable())); + } + + @Override + public boolean matches(ILiquidStack liquid) { + return false; + } + + @Override + public boolean contains(IIngredient ingredient) { + List iitems = ingredient.getItems(); + if (iitems == null || iitems.size() != 1) + return false; + return matches(iitems.get(0)); + } + + @Override + public IItemStack applyTransform(IItemStack item, IPlayer byPlayer) { + return item; + } + + @Override + public boolean hasTransformers() { + return false; + } + + @Override + public Object getInternal() { + return stack; + } + + @Override + public IBlock asBlock() { + String name = (String) Block.blockRegistry.getNameForObject(Block.getBlockFromItem(stack.getItem())); + if (Block.blockRegistry.containsKey(name)) { + return new MCItemBlock(stack); + } else { + throw new ClassCastException("This item is not a block"); + } + } + + @Override + public List getOres() { + List result = new ArrayList(); + + for (String key : OreDictionary.getOreNames()) { + for (ItemStack is : OreDictionary.getOres(key)) { + if (is.getItem() == stack.getItem() && (is.getItemDamage() == OreDictionary.WILDCARD_VALUE || is.getItemDamage() == stack.getItemDamage())) { + result.add(MineTweakerAPI.oreDict.get(key)); + break; + } + } + } + + return result; + } + + // ############################# + // ### Object implementation ### + // ############################# + + @Override + public int hashCode() { + int hash = 7; + hash = 41 * hash + stack.getItem().hashCode(); + hash = 41 * hash + stack.getItemDamage(); + hash = 41 * hash + stack.stackSize; + hash = 41 * hash + (stack.getTagCompound() == null ? 0 : stack.getTagCompound().hashCode()); + hash = 41 * hash + (this.wildcardSize ? 1 : 0); + return hash; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final MCItemStack other = (MCItemStack) obj; + if (this.stack.getItem() != other.stack.getItem()) + return false; + if (this.stack.getItemDamage() != other.stack.getItemDamage()) + return false; + if (this.stack.stackSize != other.stack.stackSize) + return false; + if (this.stack.getTagCompound() != other.stack.getTagCompound() && (this.stack == null || this.stack.equals(other.stack))) + return false; + if (this.wildcardSize != other.wildcardSize) + return false; + return true; + } + + @Override + public String toString() { + StringBuilder result = new StringBuilder(); + result.append('<'); + result.append(Item.itemRegistry.getNameForObject(stack.getItem())); + + if (stack.getItemDamage() == OreDictionary.WILDCARD_VALUE) { + result.append(":*"); + } else if (stack.getItemDamage() > 0) { + result.append(':').append(stack.getItemDamage()); + } + result.append('>'); + + if (stack.getTagCompound() != null) { + result.append(".withTag("); + result.append(NBTConverter.from(stack.getTagCompound(), wildcardSize).toString()); + result.append(")"); + } + + return result.toString(); + } + +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/liquid/MCLiquidDefinition.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/liquid/MCLiquidDefinition.java new file mode 100644 index 0000000..4499471 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/liquid/MCLiquidDefinition.java @@ -0,0 +1,424 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.liquid; + +import java.util.ArrayList; +import java.util.List; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IItemStack; +import minetweaker.api.liquid.ILiquidDefinition; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraftforge.fluids.Fluid; +import net.minecraftforge.fluids.FluidContainerRegistry; +import net.minecraftforge.fluids.FluidStack; + +/** + * + * @author Stan + */ +public class MCLiquidDefinition implements ILiquidDefinition { + private final Fluid fluid; + + public MCLiquidDefinition(Fluid fluid) { + this.fluid = fluid; + } + + @Override + public String getName() { + return fluid.getName(); + } + + @Override + public String getDisplayName() { + return fluid.getLocalizedName(); + } + + @Override + public ILiquidStack asStack(int millibuckets) { + return new MCLiquidStack(new FluidStack(fluid, millibuckets)); + } + + @Override + public int getLuminosity() { + return fluid.getLuminosity(); + } + + @Override + public void setLuminosity(int value) { + MineTweakerAPI.apply(new ActionSetLuminosity(value)); + } + + @Override + public int getDensity() { + return fluid.getDensity(); + } + + @Override + public void setDensity(int density) { + MineTweakerAPI.apply(new ActionSetDensity(density)); + } + + @Override + public int getTemperature() { + return fluid.getTemperature(); + } + + @Override + public void setTemperature(int temperature) { + MineTweakerAPI.apply(new ActionSetTemperature(temperature)); + } + + @Override + public int getViscosity() { + return fluid.getViscosity(); + } + + @Override + public void setViscosity(int viscosity) { + MineTweakerAPI.apply(new ActionSetViscosity(viscosity)); + } + + @Override + public boolean isGaseous() { + return fluid.isGaseous(); + } + + @Override + public void setGaseous(boolean gaseous) { + MineTweakerAPI.apply(new ActionSetGaseous(gaseous)); + } + + @Override + public List getContainers() { + List result = new ArrayList(); + for (FluidContainerRegistry.FluidContainerData data : FluidContainerRegistry.getRegisteredFluidContainerData()) { + if (data.fluid.getFluid() == fluid) { + result.add(MineTweakerMC.getIItemStack(data.filledContainer)); + } + } + return result; + } + + @Override + public void addContainer(IItemStack filled, IItemStack empty, int amount) { + MineTweakerAPI.apply(new AddContainerAction(filled, empty, amount)); + } + + @Override + public void removeContainer(IItemStack filled) { + // MineTweakerAPI.apply(new RemoveContainerAction(filled)); + MineTweakerAPI.logError("Cannot remove container items in MineCraft 1.7.X"); + } + + // ####################### + // ### Private methods ### + // ####################### + + /* + * private void removeContainerInner(IItemStack filled) { ItemStack + * filledItem = MineTweakerMC.getItemStack(filled); + * FluidContainerRegistry.FluidContainerData data = + * filledContainerMap.get(Arrays.asList(filledItem.itemID, + * filledItem.getItemDamage())); if (data != null) { + * filledContainerMap.remove(Arrays.asList(filledItem.itemID, + * filledItem.getItemDamage())); + * containerFluidMap.remove(Arrays.asList(data.emptyContainer.itemID, + * data.emptyContainer.getItemDamage())); + * + * // rebuild empty containers set emptyContainers.clear(); for + * (FluidContainerRegistry.FluidContainerData fdata : + * filledContainerMap.values()) { + * emptyContainers.add(Arrays.asList(fdata.emptyContainer.itemID, + * fdata.emptyContainer.getItemDamage())); } } + * MineTweakerAPI.logError("Removal of containers is not possible in 1.7.X" + * ); } + */ + + /* + * private FluidContainerRegistry.FluidContainerData getData(IItemStack + * filled) { ItemStack filledStack = MineTweakerMC.getItemStack(filled); + * return filledContainerMap.get(Arrays.asList(filledStack.itemID, + * filledStack.getItemDamage())); } + */ + + // ###################### + // ### Action classes ### + // ###################### + + private class AddContainerAction implements IUndoableAction { + private final IItemStack filled; + private final IItemStack empty; + private final int amount; + + public AddContainerAction(IItemStack filled, IItemStack empty, int amount) { + this.filled = filled; + this.empty = empty; + this.amount = amount; + } + + @Override + public void apply() { + FluidContainerRegistry.registerFluidContainer(new FluidStack(fluid, amount), MineTweakerMC.getItemStack(filled), MineTweakerMC.getItemStack(empty)); + } + + @Override + public boolean canUndo() { + return false; + // return true; + } + + @Override + public void undo() { + // removeContainerInner(filled); + } + + @Override + public String describe() { + return "Adding " + filled.getDisplayName() + " as liquid container for " + fluid.getLocalizedName(); + } + + @Override + public String describeUndo() { + return "Removing liquid container " + filled; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + /* + * private class RemoveContainerAction implements IUndoableAction { private + * final IItemStack filled; private final IItemStack empty; private final + * FluidStack amount; + * + * public RemoveContainerAction(IItemStack filled) { this.filled = filled; + * + * FluidContainerRegistry.FluidContainerData data = getData(filled); empty = + * MineTweakerMC.getIItemStack(data.emptyContainer); amount = data.fluid; } + * + * @Override public void apply() { removeContainerInner(filled); } + * + * @Override public boolean canUndo() { return true; } + * + * @Override public void undo() { + * FluidContainerRegistry.registerFluidContainer(amount, + * MineTweakerMC.getItemStack(filled), MineTweakerMC.getItemStack(empty)); } + * + * @Override public String describe() { return "Removing liquid container " + * + filled; } + * + * @Override public String describeUndo() { return + * "Restoring liquid container " + filled; } + * + * @Override public Object getOverrideKey() { return null; } } + */ + + private class ActionSetLuminosity implements IUndoableAction { + private final int oldValue; + private final int newValue; + + public ActionSetLuminosity(int newValue) { + oldValue = getLuminosity(); + this.newValue = newValue; + } + + @Override + public void apply() { + fluid.setLuminosity(newValue); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + fluid.setLuminosity(oldValue); + } + + @Override + public String describe() { + return "Setting " + fluid.getName() + " luminosity to " + newValue; + } + + @Override + public String describeUndo() { + return "Restoring " + fluid.getName() + " luminosity to " + oldValue; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private class ActionSetDensity implements IUndoableAction { + private final int oldValue; + private final int newValue; + + public ActionSetDensity(int newValue) { + oldValue = getDensity(); + this.newValue = newValue; + } + + @Override + public void apply() { + fluid.setDensity(newValue); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + fluid.setDensity(oldValue); + } + + @Override + public String describe() { + return "Setting " + fluid.getName() + " density to " + newValue; + } + + @Override + public String describeUndo() { + return "Restoring " + fluid.getName() + " density to " + oldValue; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private class ActionSetTemperature implements IUndoableAction { + private final int oldValue; + private final int newValue; + + public ActionSetTemperature(int newValue) { + oldValue = getTemperature(); + this.newValue = newValue; + } + + @Override + public void apply() { + fluid.setTemperature(newValue); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + fluid.setTemperature(oldValue); + } + + @Override + public String describe() { + return "Setting " + fluid.getName() + " temperature to " + newValue; + } + + @Override + public String describeUndo() { + return "Restoring " + fluid.getName() + " temperature to " + oldValue; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private class ActionSetViscosity implements IUndoableAction { + private final int oldValue; + private final int newValue; + + public ActionSetViscosity(int newValue) { + oldValue = getViscosity(); + this.newValue = newValue; + } + + @Override + public void apply() { + fluid.setViscosity(newValue); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + fluid.setViscosity(oldValue); + } + + @Override + public String describe() { + return "Setting " + fluid.getName() + " viscosity to " + newValue; + } + + @Override + public String describeUndo() { + return "Restoring " + fluid.getName() + " viscosity to " + oldValue; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private class ActionSetGaseous implements IUndoableAction { + private final boolean oldValue; + private final boolean newValue; + + public ActionSetGaseous(boolean newValue) { + oldValue = isGaseous(); + this.newValue = newValue; + } + + @Override + public void apply() { + fluid.setGaseous(newValue); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + fluid.setGaseous(oldValue); + } + + @Override + public String describe() { + return "Setting " + fluid.getName() + " gaseous to " + newValue; + } + + @Override + public String describeUndo() { + return "Restoring " + fluid.getName() + " gaseous to " + oldValue; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/liquid/MCLiquidStack.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/liquid/MCLiquidStack.java new file mode 100644 index 0000000..6b044ee --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/liquid/MCLiquidStack.java @@ -0,0 +1,210 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.liquid; + +import java.util.Collections; +import java.util.List; + +import minetweaker.api.data.IData; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemCondition; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientOr; +import minetweaker.api.liquid.ILiquidDefinition; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.player.IPlayer; +import minetweaker.mc18.data.NBTConverter; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraftforge.fluids.FluidStack; + +/** + * + * @author Stan + */ +public class MCLiquidStack implements ILiquidStack { + private final FluidStack stack; + private IData tag = null; + + public MCLiquidStack(FluidStack stack) { + this.stack = stack; + } + + private MCLiquidStack(FluidStack stack, IData tag) { + this.stack = stack; + this.tag = tag; + } + + @Override + public ILiquidDefinition getDefinition() { + return new MCLiquidDefinition(stack.getFluid()); + } + + @Override + public String getName() { + return stack.getFluid().getName(); + } + + @Override + public String getDisplayName() { + return stack.getFluid().getLocalizedName(); + } + + @Override + public int getAmount() { + return stack.amount; + } + + @Override + public IData getTag() { + if (tag == null) { + if (stack.tag == null) { + return null; + } + + tag = NBTConverter.from(stack.tag, true); + } + + return tag; + } + + @Override + public ILiquidStack withTag(IData data) { + FluidStack result = new FluidStack(stack.getFluid(), stack.amount); + result.tag = (NBTTagCompound) NBTConverter.from(data); + return new MCLiquidStack(result, data.immutable()); + } + + @Override + public ILiquidStack withAmount(int amount) { + FluidStack result = new FluidStack(stack.getFluid(), amount); + result.tag = stack.tag; + return new MCLiquidStack(result, tag); + } + + @Override + public int getLuminosity() { + return stack.getFluid().getLuminosity(stack); + } + + @Override + public int getDensity() { + return stack.getFluid().getDensity(stack); + } + + @Override + public int getTemperature() { + return stack.getFluid().getTemperature(stack); + } + + @Override + public int getViscosity() { + return stack.getFluid().getViscosity(stack); + } + + @Override + public boolean isGaseous() { + return stack.getFluid().isGaseous(stack); + } + + @Override + public Object getInternal() { + return stack; + } + + // ################################## + // ### IIngredient implementation ### + // ################################## + + @Override + public String getMark() + { + return null; + } + + @Override + public List getItems() + { + return Collections.emptyList(); + } + + @Override + public List getLiquids() + { + return Collections.singletonList(this); + } + + @Override + public IIngredient amount(int amount) + { + return withAmount(amount); + } + + @Override + public IIngredient or(IIngredient ingredient) + { + return new IngredientOr(this, ingredient); + } + + @Override + public IIngredient transform(IItemTransformer transformer) + { + throw new UnsupportedOperationException("Liquid stack can't have transformers"); + } + + @Override + public IIngredient only(IItemCondition condition) + { + throw new UnsupportedOperationException("Liquid stack can't have conditions"); + } + + @Override + public IIngredient marked(String mark) + { + throw new UnsupportedOperationException("Liquid stack can't be marked"); + } + + @Override + public boolean matches(IItemStack item) + { + return false; + } + + @Override + public boolean matches(ILiquidStack liquid) + { + return getDefinition().equals(liquid.getDefinition()) + && getAmount() <= liquid.getAmount(); + } + + @Override + public boolean contains(IIngredient ingredient) + { + if (!ingredient.getItems().isEmpty()) + return false; + + for (ILiquidStack liquid : ingredient.getLiquids()) + { + if (!matches(liquid)) + return false; + } + + return false; + } + + @Override + public IItemStack applyTransform(IItemStack item, IPlayer byPlayer) + { + return item; + } + + @Override + public boolean hasTransformers() + { + return false; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/mods/MCLoadedMods.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/mods/MCLoadedMods.java new file mode 100644 index 0000000..b9c0c64 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/mods/MCLoadedMods.java @@ -0,0 +1,46 @@ +package minetweaker.mc18.mods; + +import java.util.Iterator; +import java.util.List; + +import minetweaker.api.mods.ILoadedMods; +import minetweaker.api.mods.IMod; +import net.minecraftforge.fml.common.Loader; +import net.minecraftforge.fml.common.ModContainer; +import stanhebben.zenscript.util.MappingIterator; + +/** + * + * @author Stan + */ +public class MCLoadedMods implements ILoadedMods { + public MCLoadedMods() { + } + + @Override + public boolean contains(String name) { + return Loader.isModLoaded(name); + } + + @Override + public IMod get(String name) { + for (ModContainer mod : Loader.instance().getActiveModList()) { + if (mod.getModId().equals(name)) { + return new MCMod(mod); + } + } + + return null; + } + + @Override + public Iterator iterator() { + List mods = Loader.instance().getActiveModList(); + return new MappingIterator(mods.iterator()) { + @Override + public IMod map(ModContainer value) { + return new MCMod(value); + } + }; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/mods/MCMod.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/mods/MCMod.java new file mode 100644 index 0000000..344f8e1 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/mods/MCMod.java @@ -0,0 +1,42 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.mods; + +import minetweaker.api.mods.IMod; +import net.minecraftforge.fml.common.ModContainer; + +/** + * + * @author Stan + */ +public class MCMod implements IMod { + private final ModContainer mod; + + public MCMod(ModContainer mod) { + this.mod = mod; + } + + @Override + public String getId() { + return mod.getModId(); + } + + @Override + public String getName() { + return mod.getName(); + } + + @Override + public String getVersion() { + return mod.getVersion(); + } + + @Override + public String getDescription() { + return mod.getMetadata().description; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerCopyClipboardHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerCopyClipboardHandler.java new file mode 100644 index 0000000..29a970a --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerCopyClipboardHandler.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.network; + +import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * + * @author Stan + */ +public class MineTweakerCopyClipboardHandler implements IMessageHandler { + @Override + public IMessage onMessage(MineTweakerCopyClipboardPacket message, MessageContext ctx) { + if (Desktop.isDesktopSupported()) { + StringSelection stringSelection = new StringSelection(message.getData()); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(stringSelection, null); + } + + return null; + } +} \ No newline at end of file diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerCopyClipboardPacket.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerCopyClipboardPacket.java new file mode 100644 index 0000000..1a21bd4 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerCopyClipboardPacket.java @@ -0,0 +1,44 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.network; + +import static com.google.common.base.Charsets.UTF_8; +import io.netty.buffer.ByteBuf; + +import java.nio.ByteBuffer; + +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +/** + * + * @author Stan + */ +public class MineTweakerCopyClipboardPacket implements IMessage +{ + private String data; + + public MineTweakerCopyClipboardPacket() { + } + + public MineTweakerCopyClipboardPacket(String data) { + this.data = data; + } + + public String getData() { + return data; + } + + @Override + public void fromBytes(ByteBuf buf) { + data = UTF_8.decode(ByteBuffer.wrap(buf.array())).toString().trim(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBytes(UTF_8.encode(data).array()); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerLoadScriptsHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerLoadScriptsHandler.java new file mode 100644 index 0000000..6661f7d --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerLoadScriptsHandler.java @@ -0,0 +1,33 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.network; + +import minetweaker.MineTweakerAPI; +import minetweaker.MineTweakerImplementationAPI; +import minetweaker.mc18.client.MCClient; +import minetweaker.runtime.providers.ScriptProviderMemory; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * + * @author Stan + */ +public class MineTweakerLoadScriptsHandler implements IMessageHandler { + @Override + public IMessage onMessage(MineTweakerLoadScriptsPacket message, MessageContext ctx) { + if (MineTweakerAPI.server == null) { + MineTweakerAPI.client = new MCClient(); + + MineTweakerImplementationAPI.setScriptProvider(new ScriptProviderMemory(message.getData())); + MineTweakerImplementationAPI.reload(); + } + + return null; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerLoadScriptsPacket.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerLoadScriptsPacket.java new file mode 100644 index 0000000..1c83e2f --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerLoadScriptsPacket.java @@ -0,0 +1,43 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.network; + +import io.netty.buffer.ByteBuf; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +/** + * + * @author Stan + */ +public class MineTweakerLoadScriptsPacket implements IMessage { + private byte[] data; + + public MineTweakerLoadScriptsPacket() { + // used for deserialization + } + + public MineTweakerLoadScriptsPacket(byte[] data) { + this.data = data; + } + + public byte[] getData() { + return data; + } + + @Override + public void fromBytes(ByteBuf buf) { + int size = buf.readInt(); + data = new byte[size]; + buf.readBytes(data); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeInt(data.length); + buf.writeBytes(data); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerOpenBrowserHandler.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerOpenBrowserHandler.java new file mode 100644 index 0000000..b92cd38 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerOpenBrowserHandler.java @@ -0,0 +1,38 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.network; + +import java.awt.Desktop; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +/** + * + * @author Stan + */ +public class MineTweakerOpenBrowserHandler implements IMessageHandler { + @Override + public IMessage onMessage(MineTweakerOpenBrowserPacket message, MessageContext ctx) { + if (Desktop.isDesktopSupported()) { + Desktop desktop = Desktop.getDesktop(); + try { + desktop.browse(new URI(message.getUrl())); + } catch (IOException e) { + } catch (URISyntaxException e) { + } + } else { + System.out.println("Desktop not supported"); + } + + return null; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerOpenBrowserPacket.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerOpenBrowserPacket.java new file mode 100644 index 0000000..01ef93d --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/network/MineTweakerOpenBrowserPacket.java @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.network; + +import io.netty.buffer.ByteBuf; + +import java.nio.ByteBuffer; +import java.nio.charset.Charset; + +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; + +/** + * + * @author Stan + */ +public class MineTweakerOpenBrowserPacket implements IMessage { + private static final Charset UTF8 = Charset.forName("utf-8"); + + private String url; + + public MineTweakerOpenBrowserPacket() { + + } + + public MineTweakerOpenBrowserPacket(String url) { + this.url = url; + } + + public String getUrl() { + return url; + } + + @Override + public void fromBytes(ByteBuf buf) { + url = UTF8.decode(ByteBuffer.wrap(buf.array())).toString().trim(); + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBytes(UTF8.encode(url).array()); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/oredict/MCOreDict.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/oredict/MCOreDict.java new file mode 100644 index 0000000..85122b7 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/oredict/MCOreDict.java @@ -0,0 +1,39 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.oredict; + +import static minetweaker.api.minecraft.MineTweakerMC.getOreDict; + +import java.util.ArrayList; +import java.util.List; + +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.oredict.IOreDict; +import minetweaker.api.oredict.IOreDictEntry; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCOreDict implements IOreDict { + @Override + public IOreDictEntry get(String name) { + return getOreDict(name); + } + + @Override + public List getEntries() { + List entries = new ArrayList(); + for (String key : OreDictionary.getOreNames()) { + if (!OreDictionary.getOres(key).isEmpty()) { + entries.add(MineTweakerMC.getOreDict(key)); + } + } + return entries; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/oredict/MCOreDictEntry.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/oredict/MCOreDictEntry.java new file mode 100644 index 0000000..251440c --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/oredict/MCOreDictEntry.java @@ -0,0 +1,395 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.oredict; + +import static minetweaker.api.minecraft.MineTweakerMC.getIItemStackWildcardSize; +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemCondition; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.IItemTransformer; +import minetweaker.api.item.IngredientOr; +import minetweaker.api.item.IngredientStack; +import minetweaker.api.liquid.ILiquidStack; +import minetweaker.api.oredict.IOreDictEntry; +import minetweaker.api.oredict.IngredientOreDict; +import minetweaker.api.player.IPlayer; +import minetweaker.mc18.util.MineTweakerHacks; +import minetweaker.util.ArrayUtil; +import net.minecraft.item.ItemStack; +import net.minecraftforge.oredict.OreDictionary; + +/** + * + * @author Stan + */ +public class MCOreDictEntry implements IOreDictEntry { + private static final List> OREDICT_CONTENTS = MineTweakerHacks.getOreIdStacks(); + private static final List> OREDICT_CONTENTS_UN = MineTweakerHacks.getOreIdStacksUn(); + + private final String id; + + public MCOreDictEntry(String id) { + this.id = id; + } + + + // #################################### + // ### IOreDictEntry implementation ### + // #################################### + + @Override + public String getName() { + return id; + } + + @Override + public boolean isEmpty() { + return OreDictionary.getOres(getName()).isEmpty(); + } + + @Override + public void add(IItemStack item) { + ItemStack stack = getItemStack(item); + if (stack != null) { + MineTweakerAPI.apply(new ActionAddItem(id, stack)); + } + } + + @Override + public void addAll(IOreDictEntry entry) { + if (entry instanceof MCOreDictEntry) { + MineTweakerAPI.apply(new ActionAddAll(id, ((MCOreDictEntry) entry).id)); + } else { + MineTweakerAPI.logError("not a valid entry"); + } + } + + @Override + public void remove(IItemStack item) { + ItemStack result = null; + for (ItemStack itemStack : OreDictionary.getOres(getName())) { + if (item.matches(getIItemStackWildcardSize(itemStack))) { + result = itemStack; + break; + } + } + + if (result != null) { + MineTweakerAPI.apply(new ActionRemoveItem(id, result)); + } + } + + @Override + public boolean contains(IItemStack item) { + for (ItemStack itemStack : OreDictionary.getOres(getName())) { + if (getIItemStackWildcardSize(itemStack).matches(item)) { + return true; + } + } + + return false; + } + + @Override + public void mirror(IOreDictEntry other) { + if (other instanceof MCOreDictEntry) { + MineTweakerAPI.apply(new ActionMirror(id, ((MCOreDictEntry) other).id)); + } else { + MineTweakerAPI.logError("not a valid oredict entry"); + } + } + + @Override + public String getMark() { + return null; + } + + @Override + public int getAmount() { + return 1; + } + + @Override + public List getItems() { + List result = new ArrayList(); + for (ItemStack item : OreDictionary.getOres(getName())) { + result.add(getIItemStackWildcardSize(item)); + } + return result; + } + + @Override + public List getLiquids() { + return Collections.emptyList(); + } + + @Override + public IIngredient amount(int amount) { + return new IngredientStack(this, amount); + } + + @Override + public IIngredient transform(IItemTransformer transformer) { + return new IngredientOreDict(this, null, ArrayUtil.EMPTY_CONDITIONS, new IItemTransformer[] { transformer }); + } + + @Override + public IIngredient only(IItemCondition condition) { + return new IngredientOreDict(this, null, new IItemCondition[] { condition }, ArrayUtil.EMPTY_TRANSFORMERS); + } + + @Override + public IIngredient marked(String mark) { + return new IngredientOreDict(this, mark, ArrayUtil.EMPTY_CONDITIONS, ArrayUtil.EMPTY_TRANSFORMERS); + } + + @Override + public IIngredient or(IIngredient ingredient) { + return new IngredientOr(this, ingredient); + } + + @Override + public boolean matches(IItemStack item) { + return contains(item); + } + + @Override + public boolean matches(ILiquidStack liquid) { + return false; + } + + @Override + public boolean contains(IIngredient ingredient) { + List items = ingredient.getItems(); + for (IItemStack item : items) { + if (!matches(item)) + return false; + } + + return true; + } + + @Override + public IItemStack applyTransform(IItemStack item, IPlayer byPlayer) { + return item; + } + + @Override + public boolean hasTransformers() { + return false; + } + + @Override + public Object getInternal() { + return id; + } + + // ############################# + // ### Object implementation ### + // ############################# + + @Override + public String toString() { + return ""; + } + + @Override + public int hashCode() { + return id.hashCode(); + } + + @Override + public boolean equals(Object other) { + if (!(other instanceof MCOreDictEntry)) + return false; + return ((MCOreDictEntry) other).id == id; + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class ActionAddItem implements IUndoableAction { + private final String id; + private final ItemStack item; + + public ActionAddItem(String id, ItemStack item) { + this.id = id; + this.item = item; + } + + @Override + public void apply() { + OreDictionary.registerOre(id, item); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + OREDICT_CONTENTS.get(OREDICT_CONTENTS.indexOf(id)).remove(item); + } + + @Override + public String describe() { + return "Adding " + item.getDisplayName() + " to ore dictionary entry " + id; + } + + @Override + public String describeUndo() { + return "Removing " + item.getDisplayName() + " from ore dictionary entry " + id; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class ActionMirror implements IUndoableAction { + private final String idTarget; + private final String idSource; + + private final ArrayList targetCopy; + private final ArrayList targetCopyUn; + + public ActionMirror(String idTarget, String idSource) { + this.idTarget = idTarget; + this.idSource = idSource; + + targetCopy = OREDICT_CONTENTS.get(OREDICT_CONTENTS.indexOf(idTarget)); + targetCopyUn = OREDICT_CONTENTS_UN.get(OREDICT_CONTENTS_UN.indexOf(idTarget)); + } + + @Override + public void apply() { + OREDICT_CONTENTS.set(OREDICT_CONTENTS.indexOf(idTarget), OREDICT_CONTENTS.get(OREDICT_CONTENTS.indexOf(idSource))); + OREDICT_CONTENTS_UN.set(OREDICT_CONTENTS_UN.indexOf(idTarget), OREDICT_CONTENTS_UN.get(OREDICT_CONTENTS_UN.indexOf(idSource))); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + OREDICT_CONTENTS.set(OREDICT_CONTENTS.indexOf(idTarget), targetCopy); + OREDICT_CONTENTS_UN.set(OREDICT_CONTENTS_UN.indexOf(idTarget), targetCopyUn); + } + + @Override + public String describe() { + return "Mirroring " + idSource + " to " + idTarget; + } + + @Override + public String describeUndo() { + return "Undoing mirror of " + idSource+ " to " + idTarget; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class ActionRemoveItem implements IUndoableAction { + private final String id; + private final ItemStack item; + + public ActionRemoveItem(String id, ItemStack item) { + this.id = id; + this.item = item; + } + + @Override + public void apply() { + OREDICT_CONTENTS.get(OREDICT_CONTENTS.indexOf(id)).remove(item); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + OREDICT_CONTENTS.get(OREDICT_CONTENTS.indexOf(id)).add(item); + } + + @Override + public String describe() { + return "Removing " + item.getDisplayName() + " from ore dictionary entry " + id; + } + + @Override + public String describeUndo() { + return "Restoring " + item.getDisplayName() + " to ore dictionary entry " + id; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class ActionAddAll implements IUndoableAction { + private final String idTarget; + private final String idSource; + + public ActionAddAll(String idTarget, String idSource) { + this.idTarget = idTarget; + this.idSource = idSource; + } + + @Override + public void apply() { + for (ItemStack stack : OreDictionary.getOres(idSource)) { + OreDictionary.registerOre(idTarget, stack); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (ItemStack stack : OreDictionary.getOres(idSource)) { + OREDICT_CONTENTS.get(OREDICT_CONTENTS.indexOf(idTarget)).remove(stack); + } + } + + @Override + public String describe() { + return "Copying contents of ore dictionary entry " + idSource + " to " + idTarget; + } + + @Override + public String describeUndo() { + return "Removing contents of ore dictionary entry " + idSource + " from " + idTarget; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/player/MCPlayer.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/player/MCPlayer.java new file mode 100644 index 0000000..6893ce6 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/player/MCPlayer.java @@ -0,0 +1,146 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.player; + +import minetweaker.MineTweakerAPI; +import minetweaker.api.chat.IChatMessage; +import minetweaker.api.data.IData; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.player.IPlayer; +import minetweaker.mc18.MineTweakerMod; +import minetweaker.mc18.data.NBTConverter; +import minetweaker.mc18.network.MineTweakerCopyClipboardPacket; +import minetweaker.mc18.network.MineTweakerOpenBrowserPacket; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +/** + * + * @author Stan + */ +public class MCPlayer implements IPlayer { + private final EntityPlayer player; + + public MCPlayer(EntityPlayer player) { + this.player = player; + } + + public EntityPlayer getInternal() { + return player; + } + + @Override + public String getId() { + return null; // TODO: we should be having this for MC 1.7.10, right? + } + + @Override + public String getName() { + return player.getName(); + } + + @Override + public IData getData() { + return NBTConverter.from(player.getEntityData(), true); + } + + @Override + public void update(IData data) { + NBTConverter.updateMap(player.getEntityData(), data); + } + + @Override + public void sendChat(IChatMessage message) { + Object internal = message.getInternal(); + if (!(internal instanceof IChatComponent)) { + MineTweakerAPI.logError("not a valid chat message"); + return; + } + player.addChatMessage((IChatComponent) internal); + } + + @Override + public void sendChat(String message) { + player.addChatMessage(new ChatComponentText(message)); + } + + @Override + public int getHotbarSize() { + return 9; + } + + @Override + public IItemStack getHotbarStack(int i) { + return i < 0 || i >= 9 ? null : MineTweakerMC.getIItemStack(player.inventory.getStackInSlot(i)); + } + + @Override + public int getInventorySize() { + return player.inventory.getSizeInventory(); + } + + @Override + public IItemStack getInventoryStack(int i) { + return MineTweakerMC.getIItemStack(player.inventory.getStackInSlot(i)); + } + + @Override + public IItemStack getCurrentItem() { + return MineTweakerMC.getIItemStack(player.getCurrentEquippedItem()); + } + + @Override + public boolean isCreative() { + return player.capabilities.isCreativeMode; + } + + @Override + public boolean isAdventure() { + return !player.capabilities.allowEdit; + } + + @Override + public void openBrowser(String url) { + if (player instanceof EntityPlayerMP) { + MineTweakerMod.NETWORK.sendTo( + new MineTweakerOpenBrowserPacket(url), + (EntityPlayerMP) player); + } + } + + @Override + public void copyToClipboard(String value) { + if (player instanceof EntityPlayerMP) { + MineTweakerMod.NETWORK.sendTo( + new MineTweakerCopyClipboardPacket(value), + (EntityPlayerMP) player); + } + } + + @Override + public boolean equals(Object other) { + if (other.getClass() != this.getClass()) + return false; + + return ((MCPlayer) other).player == player; + } + + @Override + public int hashCode() { + int hash = 5; + hash = 23 * hash + (this.player != null ? this.player.hashCode() : 0); + return hash; + } + + @Override + public void give(IItemStack stack) { + player.inventory.addItemStackToInventory(MineTweakerMC.getItemStack(stack).copy()); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/MCCraftingInventory.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/MCCraftingInventory.java new file mode 100644 index 0000000..f384262 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/MCCraftingInventory.java @@ -0,0 +1,214 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getIItemStack; +import static minetweaker.api.minecraft.MineTweakerMC.getIPlayer; +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; + +import java.util.List; + +import minetweaker.api.item.IItemStack; +import minetweaker.api.player.IPlayer; +import minetweaker.api.recipes.ICraftingInventory; +import minetweaker.mc18.player.MCPlayer; +import minetweaker.mc18.util.MineTweakerHacks; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.IInventory; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.inventory.Slot; +import net.minecraft.inventory.SlotCrafting; +import net.minecraft.item.ItemStack; + +/** + * + * @author Stan + */ +public class MCCraftingInventory implements ICraftingInventory { + private static final ThreadLocal cache = new ThreadLocal(); + private static final ThreadLocal cache2 = new ThreadLocal(); + + public static MCCraftingInventory get(InventoryCrafting inventory) { + if (cache.get() == null || cache.get().inventory != inventory) { + MCCraftingInventory result = new MCCraftingInventory(inventory); + cache.set(result); + return result; + } else { + MCCraftingInventory result = cache.get(); + result.update(); + return result; + } + } + + public static MCCraftingInventory get(IInventory inventory, EntityPlayer player) { + if (cache2.get() == null || cache2.get().inventory != inventory || cache2.get().player != player) { + MCCraftingInventory result = new MCCraftingInventory(inventory, player); + cache2.set(result); + return result; + } else { + MCCraftingInventory result = cache2.get(); + result.update(); + return result; + } + } + + private int width; + private int height; + private final IInventory inventory; + private IItemStack[] stacks; + private ItemStack[] original; + private int stackCount; + private final IPlayer player; + private final EntityPlayer playerOrig; + + private MCCraftingInventory(InventoryCrafting inventory) { + this.inventory = inventory; + width = height = (int) Math.sqrt(inventory.getSizeInventory()); + stacks = new IItemStack[width * height]; + original = new ItemStack[stacks.length]; + stackCount = 0; + update(); + + Container container = MineTweakerHacks.getCraftingContainer(inventory); + if (container != null) { + List slots = container.inventorySlots; + if (!slots.isEmpty() && slots.get(0) instanceof SlotCrafting) { + SlotCrafting slotCrafting = (SlotCrafting) slots.get(0); + playerOrig = MineTweakerHacks.getCraftingSlotPlayer(slotCrafting); + player = getIPlayer(playerOrig); + } else { + playerOrig = null; + player = null; + } + } else { + playerOrig = null; + player = null; + } + } + + public MCCraftingInventory(IInventory inventory, EntityPlayer player) { + this.inventory = inventory; + width = height = (int) Math.sqrt(inventory.getSizeInventory()); + stacks = new IItemStack[width * height]; + original = new ItemStack[stacks.length]; + stackCount = 0; + update(); + + playerOrig = player; + this.player = player == null ? null : new MCPlayer(player); + } + + private void update() { + if (inventory.getSizeInventory() != original.length) { + width = height = (int) Math.sqrt(inventory.getSizeInventory()); + stacks = new IItemStack[inventory.getSizeInventory()]; + original = new ItemStack[stacks.length]; + stackCount = 0; + } + + for (int i = 0; i < inventory.getSizeInventory(); i++) { + if (changed(i)) { + // System.out.println("Slot " + i + " changed"); + original[i] = inventory.getStackInSlot(i); + if (inventory.getStackInSlot(i) != null) { + if (stacks[i] == null) + stackCount++; + stacks[i] = getIItemStack(original[i]); + } else { + if (stacks[i] != null) + stackCount--; + stacks[i] = null; + } + } + } + // System.out.println("Num stack count: " + stackCount); + } + + @Override + public IPlayer getPlayer() { + return player; + } + + @Override + public int getSize() { + return width * height; + } + + @Override + public int getWidth() { + return width; + } + + @Override + public int getHeight() { + return height; + } + + @Override + public int getStackCount() { + return stackCount; + } + + @Override + public IItemStack getStack(int i) { + return stacks[i]; + } + + @Override + public IItemStack getStack(int x, int y) { + return stacks[y * width + x]; + } + + @Override + public void setStack(int x, int y, IItemStack stack) { + // System.out.println("SetStack(" + x + ", " + y + ") " + stack); + + int ix = y * width + x; + if (stack != stacks[ix]) { + if (stack == null) { + stackCount--; + inventory.setInventorySlotContents(ix, null); + } else { + inventory.setInventorySlotContents(ix, getItemStack(stack)); + + if (stacks[ix] == null) { + stackCount++; + } + } + stacks[ix] = stack; + } + } + + @Override + public void setStack(int i, IItemStack stack) { + // System.out.println("SetStack(" + i + ") " + stack); + + if (stack != stacks[i]) { + if (stack == null) { + stackCount--; + inventory.setInventorySlotContents(i, null); + } else { + inventory.setInventorySlotContents(i, getItemStack(stack)); + + if (stacks[i] == null) { + stackCount++; + } + } + stacks[i] = stack; + } + } + + private boolean changed(int i) { + if (original[i] != inventory.getStackInSlot(i)) + return true; + if (original[i] != null && stacks[i].getAmount() != original[i].stackSize) + return true; + + return false; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/MCRecipeManager.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/MCRecipeManager.java new file mode 100644 index 0000000..202a608 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/MCRecipeManager.java @@ -0,0 +1,422 @@ +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getIItemStack; +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import static minetweaker.api.minecraft.MineTweakerMC.getOreDict; + +import java.util.ArrayList; +import java.util.List; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.player.IPlayer; +import minetweaker.api.recipes.ICraftingInventory; +import minetweaker.api.recipes.ICraftingRecipe; +import minetweaker.api.recipes.IRecipeFunction; +import minetweaker.api.recipes.IRecipeManager; +import minetweaker.api.recipes.ShapedRecipe; +import minetweaker.api.recipes.ShapelessRecipe; +import minetweaker.mc18.util.MineTweakerHacks; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.CraftingManager; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraft.item.crafting.ShapelessRecipes; +import net.minecraftforge.oredict.ShapedOreRecipe; +import net.minecraftforge.oredict.ShapelessOreRecipe; + +/** + * + * @author Stan + */ +public class MCRecipeManager implements IRecipeManager { + private final List recipes; + private final List transformerRecipes; + + public MCRecipeManager() { + recipes = (List) CraftingManager.getInstance().getRecipeList(); + transformerRecipes = new ArrayList(); + } + + public boolean hasTransformerRecipes() { + return transformerRecipes.size() > 0; + } + + public void applyTransformations(ICraftingInventory inventory, IPlayer byPlayer) { + for (ICraftingRecipe recipe : transformerRecipes) { + if (recipe.matches(inventory)) { + recipe.applyTransformers(inventory, byPlayer); + return; + } + } + } + + @Override + public List getRecipesFor(IIngredient ingredient) { + List results = new ArrayList(); + + for (IRecipe recipe : recipes) { + if (ingredient.matches(MineTweakerMC.getIItemStack(recipe.getRecipeOutput()))) { + ICraftingRecipe converted = RecipeConverter.toCraftingRecipe(recipe); + results.add(converted); + } + } + + return results; + } + + @Override + public List getAll() { + List results = new ArrayList(); + + for (IRecipe recipe : recipes) { + ICraftingRecipe converted = RecipeConverter.toCraftingRecipe(recipe); + results.add(converted); + } + + return results; + } + + @Override + public int remove(IIngredient output) { + List toRemove = new ArrayList(); + List removeIndex = new ArrayList(); + for (int i = 0; i < recipes.size(); i++) { + IRecipe recipe = recipes.get(i); + + // certain special recipes have no predefined output. ignore those + // since these cannot be removed with MineTweaker scripts + if (recipe.getRecipeOutput() != null) { + if (output.matches(getIItemStack(recipe.getRecipeOutput()))) { + toRemove.add(recipe); + removeIndex.add(i); + } + } + } + + MineTweakerAPI.apply(new ActionRemoveRecipes(toRemove, removeIndex)); + return toRemove.size(); + } + + @Override + public void addShaped(IItemStack output, IIngredient[][] ingredients, IRecipeFunction function) { + addShaped(output, ingredients, function, false); + } + + @Override + public void addShapedMirrored(IItemStack output, IIngredient[][] ingredients, IRecipeFunction function) { + addShaped(output, ingredients, function, true); + } + + @Override + public void addShapeless(IItemStack output, IIngredient[] ingredients, IRecipeFunction function) { + ShapelessRecipe recipe = new ShapelessRecipe(output, ingredients, function); + IRecipe irecipe = RecipeConverter.convert(recipe); + MineTweakerAPI.apply(new ActionAddRecipe(irecipe, recipe)); + } + + @Override + public int removeShaped(IIngredient output, IIngredient[][] ingredients) { + int ingredientsWidth = 0; + int ingredientsHeight = 0; + + if (ingredients != null) { + ingredientsHeight = ingredients.length; + + for (int i = 0; i < ingredients.length; i++) { + ingredientsWidth = Math.max(ingredientsWidth, ingredients[i].length); + } + } + + List toRemove = new ArrayList(); + List removeIndex = new ArrayList(); + outer: for (int i = 0; i < recipes.size(); i++) { + IRecipe recipe = recipes.get(i); + + if (recipe.getRecipeOutput() == null || !output.matches(getIItemStack(recipe.getRecipeOutput()))) { + continue; + } + + if (ingredients != null) { + if (recipe instanceof ShapedRecipes) { + ShapedRecipes srecipe = (ShapedRecipes) recipe; + if (ingredientsWidth != srecipe.recipeWidth || ingredientsHeight != srecipe.recipeHeight) { + continue; + } + + for (int j = 0; j < ingredientsHeight; j++) { + IIngredient[] row = ingredients[j]; + for (int k = 0; k < ingredientsWidth; k++) { + IIngredient ingredient = k > row.length ? null : row[k]; + ItemStack recipeIngredient = srecipe.recipeItems[j * srecipe.recipeWidth + k]; + + if (!matches(recipeIngredient, ingredient)) { + continue outer; + } + } + } + } else if (recipe instanceof ShapedOreRecipe) { + ShapedOreRecipe srecipe = (ShapedOreRecipe) recipe; + int recipeWidth = MineTweakerHacks.getShapedOreRecipeWidth(srecipe); + int recipeHeight = srecipe.getRecipeSize() / recipeWidth; + if (ingredientsWidth != recipeWidth || ingredientsHeight != recipeHeight) { + continue; + } + + for (int j = 0; j < ingredientsHeight; j++) { + IIngredient[] row = ingredients[j]; + for (int k = 0; k < ingredientsWidth; k++) { + IIngredient ingredient = k > row.length ? null : row[k]; + Object input = srecipe.getInput()[j * recipeWidth + k]; + if (!matches(input, ingredient)) { + continue outer; + } + } + } + } + } else { + if (recipe instanceof ShapedRecipes) { + + } else if (recipe instanceof ShapedOreRecipe) { + + } else { + continue; + } + } + + toRemove.add(recipe); + removeIndex.add(i); + } + + MineTweakerAPI.apply(new ActionRemoveRecipes(toRemove, removeIndex)); + return toRemove.size(); + } + + @Override + public int removeShapeless(IIngredient output, IIngredient[] ingredients, boolean wildcard) { + List toRemove = new ArrayList(); + List removeIndex = new ArrayList(); + outer: for (int i = 0; i < recipes.size(); i++) { + IRecipe recipe = recipes.get(i); + + if (recipe.getRecipeOutput() == null || !output.matches(getIItemStack(recipe.getRecipeOutput()))) { + continue; + } + + if (ingredients != null) { + if (recipe instanceof ShapelessRecipes) { + ShapelessRecipes srecipe = (ShapelessRecipes) recipe; + + if (ingredients.length > srecipe.getRecipeSize()) { + continue; + } else if (!wildcard && ingredients.length < srecipe.getRecipeSize()) { + continue; + } + + checkIngredient: for (int j = 0; j < ingredients.length; j++) { + for (int k = 0; k < srecipe.getRecipeSize(); k++) { + if (matches(srecipe.recipeItems.get(k), ingredients[j])) { + continue checkIngredient; + } + } + + continue outer; + } + } else if (recipe instanceof ShapelessOreRecipe) { + ShapelessOreRecipe srecipe = (ShapelessOreRecipe) recipe; + ArrayList inputs = srecipe.getInput(); + + if (inputs.size() < ingredients.length) { + continue; + } + if (!wildcard && inputs.size() > ingredients.length) { + continue; + } + + checkIngredient: for (int j = 0; j < ingredients.length; j++) { + for (int k = 0; k < srecipe.getRecipeSize(); k++) { + if (matches(inputs.get(k), ingredients[j])) { + continue checkIngredient; + } + } + + continue outer; + } + } + } else { + if (recipe instanceof ShapelessRecipes) { + + } else if (recipe instanceof ShapelessOreRecipe) { + + } else { + continue; + } + } + + toRemove.add(recipe); + removeIndex.add(i); + } + + MineTweakerAPI.apply(new ActionRemoveRecipes(toRemove, removeIndex)); + return toRemove.size(); + } + + @Override + public IItemStack craft(IItemStack[][] contents) { + Container container = new ContainerVirtual(); + + int width = 0; + int height = contents.length; + for (IItemStack[] row : contents) { + width = Math.max(width, row.length); + } + + ItemStack[] iContents = new ItemStack[width * height]; + for (int i = 0; i < height; i++) { + for (int j = 0; j < contents[i].length; j++) { + if (contents[i][j] != null) { + iContents[i * width + j] = getItemStack(contents[i][j]); + } + } + } + + InventoryCrafting inventory = new InventoryCrafting(container, width, height); + for (int i = 0; i < iContents.length; i++) { + inventory.setInventorySlotContents(i, iContents[i]); + } + ItemStack result = CraftingManager.getInstance().findMatchingRecipe(inventory, null); + if (result == null) { + return null; + } else { + return getIItemStack(result); + } + } + + private class ContainerVirtual extends Container { + @Override + public boolean canInteractWith(EntityPlayer var1) { + return false; + } + } + + private class ActionRemoveRecipes implements IUndoableAction { + private final List removingIndices; + private final List removingRecipes; + + public ActionRemoveRecipes(List recipes, List indices) { + this.removingIndices = indices; + this.removingRecipes = recipes; + } + + @Override + public void apply() { + for (int i = removingIndices.size() - 1; i >= 0; i--) { + recipes.remove((int) removingIndices.get(i)); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (int i = 0; i < removingIndices.size(); i++) { + int index = Math.min(recipes.size(), removingIndices.get(i)); + recipes.add(index, removingRecipes.get(i)); + } + } + + @Override + public String describe() { + return "Removing " + removingIndices.size() + " recipes"; + } + + @Override + public String describeUndo() { + return "Restoring " + removingIndices.size() + " recipes"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private class ActionAddRecipe implements IUndoableAction { + private final IRecipe recipe; + private final ICraftingRecipe craftingRecipe; + + public ActionAddRecipe(IRecipe recipe, ICraftingRecipe craftingRecipe) { + this.recipe = recipe; + this.craftingRecipe = craftingRecipe; + } + + @Override + public void apply() { + recipes.add(recipe); + if (craftingRecipe.hasTransformers()) { + transformerRecipes.add(craftingRecipe); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + recipes.remove(recipe); + if (craftingRecipe.hasTransformers()) { + transformerRecipes.remove(craftingRecipe); + } + } + + @Override + public String describe() { + return "Adding recipe for " + recipe.getRecipeOutput().getDisplayName(); + } + + @Override + public String describeUndo() { + return "Removing recipe for " + recipe.getRecipeOutput().getDisplayName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private void addShaped(IItemStack output, IIngredient[][] ingredients, IRecipeFunction function, boolean mirrored) { + ShapedRecipe recipe = new ShapedRecipe(output, ingredients, function, mirrored); + IRecipe irecipe = RecipeConverter.convert(recipe); + MineTweakerAPI.apply(new ActionAddRecipe(irecipe, recipe)); + } + + private static boolean matches(Object input, IIngredient ingredient) { + if ((input == null) != (ingredient == null)) { + return false; + } else if (ingredient != null) { + if (input instanceof ItemStack) { + if (!ingredient.matches(getIItemStack((ItemStack) input))) { + return false; + } + } else if (input instanceof String) { + if (!ingredient.contains(getOreDict((String) input))) { + return false; + } + } + } + + return true; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/RecipeConverter.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/RecipeConverter.java new file mode 100644 index 0000000..dde1e69 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/RecipeConverter.java @@ -0,0 +1,183 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; + +import java.util.ArrayList; +import java.util.Arrays; + +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.recipes.ICraftingRecipe; +import minetweaker.api.recipes.ShapedRecipe; +import minetweaker.api.recipes.ShapelessRecipe; +import minetweaker.api.recipes.UnknownRecipe; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraft.item.crafting.ShapelessRecipes; +import net.minecraftforge.oredict.ShapedOreRecipe; +import net.minecraftforge.oredict.ShapelessOreRecipe; + +/** + * + * @author Stan + */ +public class RecipeConverter { + private RecipeConverter() { + } + + public static final int TYPE_ADVANCED = 0; + public static final int TYPE_ORE = 1; + public static final int TYPE_BASIC = 2; + + private static int getIngredientType(IIngredient pattern) { + Object internal = pattern.getInternal(); + if (internal == null) { + return TYPE_ADVANCED; + } else if (internal instanceof ItemStack) { + return TYPE_BASIC; + } else { + return TYPE_ORE; + } + } + + private static int getRecipeType(IIngredient[] ingredients) { + int type = TYPE_BASIC; + for (IIngredient ingredient : ingredients) { + type = Math.min(type, getIngredientType(ingredient)); + } + return type; + } + + public static IRecipe convert(ShapelessRecipe recipe) { + IIngredient[] ingredients = recipe.getIngredients(); + int type = getRecipeType(ingredients); + + if (type == TYPE_BASIC) { + ItemStack[] items = new ItemStack[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + items[i] = getItemStack(ingredients[i]); + } + return new ShapelessRecipeBasic(items, recipe); + } else if (type == TYPE_ORE) { + Object[] items = new Object[ingredients.length]; + for (int i = 0; i < ingredients.length; i++) { + items[i] = ingredients[i].getInternal(); + } + return new ShapelessRecipeOre(items, recipe); + } else { + return new ShapelessRecipeAdvanced(recipe); + } + } + + public static IRecipe convert(ShapedRecipe recipe) { + IIngredient[] ingredients = recipe.getIngredients(); + byte[] posx = recipe.getIngredientsX(); + byte[] posy = recipe.getIngredientsY(); + + // determine recipe type + int type = getRecipeType(ingredients); + + // construct recipe + if (type == TYPE_BASIC) { + ItemStack[] basicIngredients = new ItemStack[recipe.getHeight() * recipe.getWidth()]; + for (int i = 0; i < ingredients.length; i++) { + basicIngredients[posx[i] + posy[i] * recipe.getWidth()] = getItemStack(ingredients[i]); + } + + return new ShapedRecipeBasic(basicIngredients, recipe); + } else if (type == TYPE_ORE) { + Object[] converted = new Object[recipe.getHeight() * recipe.getWidth()]; + for (int i = 0; i < ingredients.length; i++) { + converted[posx[i] + posy[i] * recipe.getWidth()] = ingredients[i].getInternal(); + } + + // arguments contents: + // 1) recipe patterns + // 2) characters + ingredients + + int counter = 0; + String[] parts = new String[recipe.getHeight()]; + ArrayList rarguments = new ArrayList(); + for (int i = 0; i < recipe.getHeight(); i++) { + char[] pattern = new char[recipe.getWidth()]; + for (int j = 0; j < recipe.getWidth(); j++) { + int off = i * recipe.getWidth() + j; + if (converted[off] == null) { + pattern[j] = ' '; + } else { + pattern[j] = (char) ('A' + counter); + rarguments.add(pattern[j]); + rarguments.add(converted[off]); + counter++; + } + } + parts[i] = new String(pattern); + } + + rarguments.addAll(0, Arrays.asList(parts)); + + return new ShapedRecipeOre(rarguments.toArray(), recipe); + } else { + return new ShapedRecipeAdvanced(recipe); + } + } + + public static ICraftingRecipe toCraftingRecipe(IRecipe recipe) { + IItemStack output = MineTweakerMC.getIItemStack(recipe.getRecipeOutput()); + + if (recipe instanceof ShapelessRecipes) { + ShapelessRecipes shapeless = (ShapelessRecipes) recipe; + + IIngredient[] ingredients = new IIngredient[shapeless.recipeItems.size()]; + for (int i = 0; i < ingredients.length; i++) { + ingredients[i] = MineTweakerMC.getIIngredient(shapeless.recipeItems.get(i)); + } + + return new ShapelessRecipe(output, ingredients, null); + } else if (recipe instanceof ShapedRecipes) { + ShapedRecipes shaped = (ShapedRecipes) recipe; + + IIngredient[][] ingredients = new IIngredient[shaped.recipeHeight][shaped.recipeWidth]; + for (int i = 0; i < shaped.recipeHeight; i++) { + for (int j = 0; j < shaped.recipeWidth; j++) { + ingredients[i][j] = MineTweakerMC.getIItemStack(shaped.recipeItems[i * shaped.recipeWidth + j]); + } + } + + return new ShapedRecipe(output, ingredients, null, false); + } else if (recipe instanceof ShapedOreRecipe) { + ShapedOreRecipe shaped = (ShapedOreRecipe) recipe; + + int width = (int) Math.sqrt(recipe.getRecipeSize()); + int height = recipe.getRecipeSize() / width; + + IIngredient[][] recipeIngredients = new IIngredient[height][width]; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + recipeIngredients[i][j] = MineTweakerMC.getIIngredient(shaped.getInput()[i * width + j]); + } + } + + return new ShapedRecipe(output, recipeIngredients, null, false); + } else if (recipe instanceof ShapelessOreRecipe) { + ShapelessOreRecipe shapeless = (ShapelessOreRecipe) recipe; + + IIngredient[] ingredients = new IIngredient[shapeless.getRecipeSize()]; + for (int i = 0; i < ingredients.length; i++) { + ingredients[i] = MineTweakerMC.getIIngredient(shapeless.getInput().get(i)); + } + + return new ShapelessRecipe(output, ingredients, null); + } else { + return new UnknownRecipe(output); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeAdvanced.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeAdvanced.java new file mode 100644 index 0000000..f9d83d8 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeAdvanced.java @@ -0,0 +1,52 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import minetweaker.api.recipes.ShapedRecipe; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; + +/** + * TODO: NEI integration for this kind of recipes. + * + * @author Stan + */ +public class ShapedRecipeAdvanced implements IRecipe { + private final ShapedRecipe recipe; + + public ShapedRecipeAdvanced(ShapedRecipe recipe) { + this.recipe = recipe; + } + + @Override + public boolean matches(InventoryCrafting inventory, World world) { + return recipe.matches(MCCraftingInventory.get(inventory)); + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inventory) { + return getItemStack(recipe.getCraftingResult(MCCraftingInventory.get(inventory))).copy(); + } + + @Override + public int getRecipeSize() { + return recipe.getWidth() * recipe.getHeight(); + } + + @Override + public ItemStack getRecipeOutput() { + return getItemStack(recipe.getOutput()); + } + + @Override + public ItemStack[] getRemainingItems(InventoryCrafting p_179532_1_) { + return new ItemStack[]{}; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeBasic.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeBasic.java new file mode 100644 index 0000000..29564d2 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeBasic.java @@ -0,0 +1,44 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import minetweaker.api.item.IItemStack; +import minetweaker.api.recipes.ShapedRecipe; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ShapedRecipes; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class ShapedRecipeBasic extends ShapedRecipes { + private final ShapedRecipe recipe; + + public ShapedRecipeBasic(ItemStack[] basicInputs, ShapedRecipe recipe) { + super(recipe.getWidth(), recipe.getHeight(), basicInputs, getItemStack(recipe.getOutput())); + + this.recipe = recipe; + } + + @Override + public boolean matches(InventoryCrafting inventory, World world) { + return recipe.matches(MCCraftingInventory.get(inventory)); + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inventory) { + IItemStack result = recipe.getCraftingResult(MCCraftingInventory.get(inventory)); + if (result == null) { + return null; + } else { + return getItemStack(result).copy(); + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeOre.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeOre.java new file mode 100644 index 0000000..ec5aaf3 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapedRecipeOre.java @@ -0,0 +1,38 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import minetweaker.api.recipes.ShapedRecipe; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.oredict.ShapedOreRecipe; + +/** + * + * @author Stan + */ +public class ShapedRecipeOre extends ShapedOreRecipe { + private final ShapedRecipe recipe; + + public ShapedRecipeOre(Object[] contents, ShapedRecipe recipe) { + super(getItemStack(recipe.getOutput()), contents); + + this.recipe = recipe; + } + + @Override + public boolean matches(InventoryCrafting inventory, World world) { + return recipe.matches(MCCraftingInventory.get(inventory)); + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inventory) { + return getItemStack(recipe.getCraftingResult(MCCraftingInventory.get(inventory))).copy(); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeAdvanced.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeAdvanced.java new file mode 100644 index 0000000..592daf7 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeAdvanced.java @@ -0,0 +1,51 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import minetweaker.api.recipes.ShapelessRecipe; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.IRecipe; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class ShapelessRecipeAdvanced implements IRecipe { + private final ShapelessRecipe recipe; + + public ShapelessRecipeAdvanced(ShapelessRecipe recipe) { + this.recipe = recipe; + } + + @Override + public boolean matches(InventoryCrafting inventory, World world) { + return recipe.matches(MCCraftingInventory.get(inventory)); + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inventory) { + return getItemStack(recipe.getCraftingResult(MCCraftingInventory.get(inventory))).copy(); + } + + @Override + public int getRecipeSize() { + return recipe.getSize(); + } + + @Override + public ItemStack getRecipeOutput() { + return getItemStack(recipe.getOutput()); + } + + @Override + public ItemStack[] getRemainingItems(InventoryCrafting p_179532_1_) { + return new ItemStack[] {}; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeBasic.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeBasic.java new file mode 100644 index 0000000..ca87458 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeBasic.java @@ -0,0 +1,41 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; + +import java.util.Arrays; + +import minetweaker.api.recipes.ShapelessRecipe; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.ShapelessRecipes; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class ShapelessRecipeBasic extends ShapelessRecipes { + private final ShapelessRecipe recipe; + + public ShapelessRecipeBasic(ItemStack[] ingredients, ShapelessRecipe recipe) { + super(getItemStack(recipe.getOutput()), Arrays.asList(ingredients)); + + this.recipe = recipe; + } + + @Override + public boolean matches(InventoryCrafting inventory, World world) { + return recipe.matches(MCCraftingInventory.get(inventory)); + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inventory) { + return getItemStack(recipe.getCraftingResult(MCCraftingInventory.get(inventory))).copy(); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeOre.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeOre.java new file mode 100644 index 0000000..bf717b0 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/recipes/ShapelessRecipeOre.java @@ -0,0 +1,38 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.recipes; + +import static minetweaker.api.minecraft.MineTweakerMC.getItemStack; +import minetweaker.api.recipes.ShapelessRecipe; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; +import net.minecraftforge.oredict.ShapelessOreRecipe; + +/** + * + * @author Stan + */ +public class ShapelessRecipeOre extends ShapelessOreRecipe { + private final ShapelessRecipe recipe; + + public ShapelessRecipeOre(Object[] ingredients, ShapelessRecipe recipe) { + super(getItemStack(recipe.getOutput()), ingredients); + + this.recipe = recipe; + } + + @Override + public boolean matches(InventoryCrafting inventory, World world) { + return recipe.matches(MCCraftingInventory.get(inventory)); + } + + @Override + public ItemStack getCraftingResult(InventoryCrafting inventory) { + return getItemStack(recipe.getCraftingResult(MCCraftingInventory.get(inventory))).copy(); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/server/MCServer.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/server/MCServer.java new file mode 100644 index 0000000..f1eb471 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/server/MCServer.java @@ -0,0 +1,237 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.server; + +import java.util.Arrays; +import java.util.List; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.player.IPlayer; +import minetweaker.api.server.AbstractServer; +import minetweaker.api.server.ICommandFunction; +import minetweaker.api.server.ICommandTabCompletion; +import minetweaker.api.server.ICommandValidator; +import net.minecraft.command.CommandException; +import net.minecraft.command.CommandHandler; +import net.minecraft.command.ICommand; +import net.minecraft.command.ICommandSender; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.server.MinecraftServer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.server.management.UserListOps; +import net.minecraft.util.BlockPos; + +/** + * + * @author Stan + */ +public class MCServer extends AbstractServer { + private final MinecraftServer server; + + public MCServer(MinecraftServer server) { + this.server = server; + } + + @Override + public void addCommand(String name, String usage, String[] aliases, ICommandFunction function, ICommandValidator validator, ICommandTabCompletion completion) { + ICommand command = new MCCommand(name, usage, aliases, function, validator, completion); + MineTweakerAPI.apply(new AddCommandAction(command)); + } + + @Override + public void removeCommand(String name) { + ICommand command = (ICommand) ((CommandHandler) server.getCommandManager()).getCommands().get(name); + if (command == null) { + MineTweakerAPI.logWarning("No such command: " + name); + } else { + MineTweakerAPI.apply(new RemoveCommandAction(command)); + } + } + + @Override + public boolean isOp(IPlayer player) { + if (player == ServerPlayer.INSTANCE) + return true; + + UserListOps ops = MinecraftServer.getServer().getConfigurationManager().getOppedPlayers(); + if (server.isDedicatedServer()) { + return ops.hasEntries() || ops.getGameProfileFromName(player.getName()) != null; + } else { + return true; + } + } + + private static IPlayer getPlayer(ICommandSender commandSender) { + if (commandSender instanceof EntityPlayer) { + return MineTweakerMC.getIPlayer((EntityPlayer) commandSender); + } else if (commandSender instanceof DedicatedServer) { + return ServerPlayer.INSTANCE; + } else { + System.out.println("Unsupported command sender: " + commandSender); + System.out.println("player name: " + commandSender.getName()); + return null; + } + } + + private static void removeCommand(ICommand command) { + CommandHandler ch = (CommandHandler) MinecraftServer.getServer().getCommandManager(); + ch.getCommands().remove(command.getName()); + + if (command.getAliases() != null) { + for (String alias : (List) command.getAliases()) { + ch.getCommands().remove(alias); + } + } + } + + private class MCCommand implements ICommand { + private final String name; + private final String usage; + private final List aliases; + private final ICommandFunction function; + private final ICommandValidator validator; + private final ICommandTabCompletion completion; + + public MCCommand(String name, String usage, String[] aliases, ICommandFunction function, ICommandValidator validator, ICommandTabCompletion completion) { + this.name = name; + this.usage = usage; + this.aliases = Arrays.asList(aliases); + this.function = function; + this.validator = validator; + this.completion = completion; + } + + @Override + public String getName() { + return name; + } + + @Override + public String getCommandUsage(ICommandSender var1) { + return usage; + } + + @Override + public List getAliases() { + return aliases; + } + + @Override + public boolean canCommandSenderUse(ICommandSender var1) { + if (validator == null) { + return true; + } else { + return validator.canExecute(getPlayer(var1)); + } + } + + + @Override + public boolean isUsernameIndex(String[] var1, int var2) { + return false; + } + + @Override + public int compareTo(Object o) { + return 0; + } + + @Override + public void execute(ICommandSender sender, String[] args) throws CommandException { + function.execute(args, getPlayer(sender)); + } + + @Override + public List addTabCompletionOptions(ICommandSender sender, String[] args, BlockPos pos) { + if (completion != null) { + return Arrays.asList(completion.getTabCompletionOptions(args, getPlayer(sender))); + } else { + return null; + } + } + } + + private class AddCommandAction implements IUndoableAction { + private final ICommand command; + + public AddCommandAction(ICommand command) { + this.command = command; + } + + @Override + public void apply() { + CommandHandler ch = (CommandHandler) MinecraftServer.getServer().getCommandManager(); + ch.registerCommand(command); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + removeCommand(command); + } + + @Override + public String describe() { + return "Adding command " + command.getName(); + } + + @Override + public String describeUndo() { + return "Removing command " + command.getName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private class RemoveCommandAction implements IUndoableAction { + private final ICommand command; + + public RemoveCommandAction(ICommand command) { + this.command = command; + } + + @Override + public void apply() { + removeCommand(command); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + CommandHandler ch = (CommandHandler) MinecraftServer.getServer().getCommandManager(); + ch.registerCommand(command); + } + + @Override + public String describe() { + return "Adding command " + command.getName(); + } + + @Override + public String describeUndo() { + return "Removing command " + command.getName(); + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/server/ServerPlayer.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/server/ServerPlayer.java new file mode 100644 index 0000000..772f8c6 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/server/ServerPlayer.java @@ -0,0 +1,127 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.server; + +import java.awt.Desktop; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.io.IOException; +import java.net.URI; +import java.util.logging.Level; +import java.util.logging.Logger; + +import minetweaker.api.chat.IChatMessage; +import minetweaker.api.data.IData; +import minetweaker.api.item.IItemStack; +import minetweaker.api.player.IPlayer; +import net.minecraft.server.dedicated.DedicatedServer; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +/** + * + * @author Stan + */ +public class ServerPlayer implements IPlayer { + public static final ServerPlayer INSTANCE = new ServerPlayer(); + + private ServerPlayer() { + + } + + @Override + public String getId() { + return "server"; + } + + @Override + public String getName() { + return "Server"; + } + + @Override + public IData getData() { + // TODO: implement + return null; + } + + @Override + public void update(IData data) { + // TODO: implement + } + + @Override + public void sendChat(IChatMessage message) { + DedicatedServer.getServer().addChatMessage((IChatComponent) message.getInternal()); + } + + @Override + public void sendChat(String message) { + DedicatedServer.getServer().addChatMessage(new ChatComponentText(message)); + } + + @Override + public int getHotbarSize() { + return 0; + } + + @Override + public IItemStack getHotbarStack(int i) { + return null; + } + + @Override + public int getInventorySize() { + return 0; + } + + @Override + public IItemStack getInventoryStack(int i) { + return null; + } + + @Override + public IItemStack getCurrentItem() { + return null; + } + + @Override + public boolean isCreative() { + return true; + } + + @Override + public boolean isAdventure() { + return false; + } + + @Override + public void openBrowser(String url) { + if (Desktop.isDesktopSupported()) { + try { + Desktop.getDesktop().browse(URI.create(url)); + } catch (IOException ex) { + Logger.getLogger(ServerPlayer.class.getName()).log(Level.SEVERE, null, ex); + } + } + } + + @Override + public void copyToClipboard(String value) { + if (Desktop.isDesktopSupported()) { + StringSelection stringSelection = new StringSelection(value); + Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); + clipboard.setContents(stringSelection, null); + } + } + + @Override + public void give(IItemStack stack) { + + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerHacks.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerHacks.java new file mode 100644 index 0000000..ff06ea5 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerHacks.java @@ -0,0 +1,291 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.util; + +import java.io.File; +import java.lang.reflect.Constructor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.logging.Level; +import java.util.logging.Logger; + +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; +import net.minecraft.inventory.InventoryCrafting; +import net.minecraft.inventory.SlotCrafting; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.server.MinecraftServer; +import net.minecraft.util.StatCollector; +import net.minecraft.util.StringTranslate; +import net.minecraft.util.WeightedRandom; +import net.minecraftforge.common.ChestGenHooks; +import net.minecraftforge.common.ForgeHooks; +import net.minecraftforge.fml.common.registry.EntityRegistry; +import net.minecraftforge.oredict.OreDictionary; +import net.minecraftforge.oredict.ShapedOreRecipe; + +import com.google.common.collect.BiMap; + +/** + * Common class for all runtime hacks (stuff requiring reflection). It is not + * unexpected to have it break with new minecraft versions and may need regular + * adjustment - as such, those have been collected here. + * + * @author Stan Hebben + */ +public class MineTweakerHacks { + private static final Field NBTTAGLIST_TAGLIST; + private static final Field OREDICTIONARY_IDTOSTACK; + private static final Field OREDICTIONARY_IDTOSTACKUN; + private static final Field MINECRAFTSERVER_ANVILFILE; + private static final Field SHAPEDORERECIPE_WIDTH; + private static final Field INVENTORYCRAFTING_EVENTHANDLER; + private static final Field SLOTCRAFTING_PLAYER; + + private static final Field ENTITYREGISTRY_CLASSREGISTRATIONS; + private static final Field SEEDENTRY_SEED; + private static final Constructor SEEDENTRY_CONSTRUCTOR; + + static { + NBTTAGLIST_TAGLIST = getField(NBTTagList.class, MineTweakerObfuscation.NBTTAGLIST_TAGLIST); + OREDICTIONARY_IDTOSTACK = getField(OreDictionary.class, MineTweakerObfuscation.OREDICTIONARY_IDTOSTACK); + OREDICTIONARY_IDTOSTACKUN = getField(OreDictionary.class, MineTweakerObfuscation.OREDICTIONARY_IDTOSTACKUN); + MINECRAFTSERVER_ANVILFILE = getField(MinecraftServer.class, MineTweakerObfuscation.MINECRAFTSERVER_ANVILFILE); + SHAPEDORERECIPE_WIDTH = getField(ShapedOreRecipe.class, new String[] { "width" }); + INVENTORYCRAFTING_EVENTHANDLER = getField(InventoryCrafting.class, MineTweakerObfuscation.INVENTORYCRAFTING_EVENTHANDLER); + SLOTCRAFTING_PLAYER = getField(SlotCrafting.class, MineTweakerObfuscation.SLOTCRAFTING_PLAYER); + + ENTITYREGISTRY_CLASSREGISTRATIONS = getField(EntityRegistry.class, new String[] { "entityClassRegistrations" }); + + Class forgeSeedEntry = null; + try { + forgeSeedEntry = (Class) Class.forName("net.minecraftforge.common.ForgeHooks$SeedEntry"); + } catch (ClassNotFoundException ex) { + } + + SEEDENTRY_SEED = getField(forgeSeedEntry, "seed"); + + Constructor seedEntryConstructor = null; + + try { + seedEntryConstructor = forgeSeedEntry.getConstructor(ItemStack.class, int.class); + seedEntryConstructor.setAccessible(true); + } catch (NoSuchMethodException ex) { + Logger.getLogger(MineTweakerHacks.class.getName()).log(Level.SEVERE, null, ex); + } catch (SecurityException ex) { + Logger.getLogger(MineTweakerHacks.class.getName()).log(Level.SEVERE, null, ex); + } + + SEEDENTRY_CONSTRUCTOR = seedEntryConstructor; + } + + private MineTweakerHacks() { + } + + public static BiMap, EntityRegistry.EntityRegistration> getEntityClassRegistrations() { + try { + return (BiMap, EntityRegistry.EntityRegistration>) ENTITYREGISTRY_CLASSREGISTRATIONS.get(EntityRegistry.instance()); + } catch (IllegalArgumentException ex) { + return null; + } catch (IllegalAccessException ex) { + return null; + } + } + + public static List getTagList(NBTTagList list) { + if (NBTTAGLIST_TAGLIST == null) { + return null; + } + try { + return (List) NBTTAGLIST_TAGLIST.get(list); + } catch (IllegalArgumentException ex) { + return null; + } catch (IllegalAccessException ex) { + return null; + } + } + + public static List getSeeds() { + return getPrivateStaticObject(ForgeHooks.class, "seedList"); + } + + public static Map getChestLoot() { + return getPrivateStaticObject(ChestGenHooks.class, "chestInfo"); + } + + public static Map getTranslations() { + return getPrivateObject( + getPrivateStaticObject(StatCollector.class, "localizedName", "field_74839_a"), + "languageList", + "field_74816_c"); + } + + public static List> getOreIdStacks() { + try { + return (List>) OREDICTIONARY_IDTOSTACK.get(null); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("ERROR - could not load ore dictionary stacks!"); + return null; + } + } + + public static List> getOreIdStacksUn() { + try { + return (List>) OREDICTIONARY_IDTOSTACKUN.get(null); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("ERROR - could not load ore dictionary stacks!"); + return null; + } + } + + public static File getAnvilFile(MinecraftServer server) { + try { + return (File) MINECRAFTSERVER_ANVILFILE.get(server); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not load anvil file!"); + return null; + } + } + + public static File getWorldDirectory(MinecraftServer server) { + if (server.isDedicatedServer()) { + return server.getFile("world"); + } else { + File worldsDir = getAnvilFile(server); + if (worldsDir == null) + return null; + + return new File(worldsDir, server.getFolderName()); + } + } + + public static int getShapedOreRecipeWidth(ShapedOreRecipe recipe) { + try { + return SHAPEDORERECIPE_WIDTH.getInt(recipe); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not load anvil file!"); + return 3; + } + } + + public static Container getCraftingContainer(InventoryCrafting inventory) { + try { + return (Container) INVENTORYCRAFTING_EVENTHANDLER.get(inventory); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not get inventory eventhandler"); + return null; + } + } + + public static EntityPlayer getCraftingSlotPlayer(SlotCrafting slot) { + try { + return (EntityPlayer) SLOTCRAFTING_PLAYER.get(slot); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not get inventory eventhandler"); + return null; + } + } + + public static StringTranslate getStringTranslateInstance() { + try { + Field field = getField(StringTranslate.class, MineTweakerObfuscation.STRINGTRANSLATE_INSTANCE); + return (StringTranslate) field.get(null); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not get string translator"); + return null; + } + } + + public static ItemStack getSeedEntrySeed(Object entry) { + try { + return (ItemStack) SEEDENTRY_SEED.get(entry); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not get SeedEntry seed"); + return null; + } + } + + public static WeightedRandom.Item constructSeedEntry(WeightedItemStack stack) { + try { + return SEEDENTRY_CONSTRUCTOR.newInstance(MineTweakerMC.getItemStack(stack.getStack()), (int) stack.getChance()); + } catch (InstantiationException ex) { + MineTweakerAPI.logError("could not construct SeedEntry"); + } catch (IllegalAccessException ex) { + MineTweakerAPI.logError("could not construct SeedEntry"); + } catch (IllegalArgumentException ex) { + MineTweakerAPI.logError("could not construct SeedEntry"); + } catch (InvocationTargetException ex) { + MineTweakerAPI.logError("could not construct SeedEntry"); + } + + return null; + } + + public static T getPrivateStaticObject(Class cls, String... names) { + for (String name : names) { + try { + Field field = cls.getDeclaredField(name); + field.setAccessible(true); + return (T) field.get(null); + } catch (NoSuchFieldException ex) { + + } catch (SecurityException ex) { + + } catch (IllegalAccessException ex) { + + } + } + + return null; + } + + public static T getPrivateObject(Object object, String... names) { + Class cls = object.getClass(); + for (String name : names) { + try { + Field field = cls.getDeclaredField(name); + field.setAccessible(true); + return (T) field.get(object); + } catch (NoSuchFieldException ex) { + + } catch (SecurityException ex) { + + } catch (IllegalAccessException ex) { + + } + } + + return null; + } + + // ####################### + // ### Private Methods ### + // ####################### + + private static Field getField(Class cls, String... names) { + for (String name : names) { + try { + Field field = cls.getDeclaredField(name); + field.setAccessible(true); + return field; + } catch (NoSuchFieldException ex) { + } catch (SecurityException ex) { + } + } + + return null; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerObfuscation.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerObfuscation.java new file mode 100644 index 0000000..08d1267 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerObfuscation.java @@ -0,0 +1,25 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.util; + +/** + * + * @author Stanneke + */ +public class MineTweakerObfuscation { + private MineTweakerObfuscation() { + } + + public static final String[] NBTTAGLIST_TAGLIST = { "tagList", "field_74747_a" }; + public static final String[] CRAFTINGMANAGER_RECIPES = { "recipes", "field_77597_b" }; + public static final String[] OREDICTIONARY_IDTOSTACK = { "idToStack" }; + public static final String[] OREDICTIONARY_IDTOSTACKUN = { "idToStackUn" }; + public static final String[] MINECRAFTSERVER_ANVILFILE = { "anvilFile", "field_71308_o" }; + public static final String[] INVENTORYCRAFTING_EVENTHANDLER = { "eventHandler", "field_70465_c" }; + public static final String[] SLOTCRAFTING_PLAYER = { "thePlayer", "field_75238_b" }; + public static final String[] STRINGTRANSLATE_INSTANCE = { "instance", "field_74817_a" }; +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerPlatformUtils.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerPlatformUtils.java new file mode 100644 index 0000000..aa211fb --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/util/MineTweakerPlatformUtils.java @@ -0,0 +1,46 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.util; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraftforge.fml.client.FMLClientHandler; +import net.minecraftforge.fml.common.FMLCommonHandler; +import net.minecraftforge.fml.relauncher.Side; + +/** + * + * @author Stan + */ +public class MineTweakerPlatformUtils { + private MineTweakerPlatformUtils() { + } + + public static Class getLivingEntityClass(String entityClassName) { + try { + Class entityClass = Class.forName(entityClassName); + if (!EntityLivingBase.class.isAssignableFrom(entityClass)) { + throw new RuntimeException("Not an entity class: " + entityClassName); + } + return (Class) entityClass; + } catch (ClassNotFoundException ex) { + throw new RuntimeException("entity class not found: " + entityClassName); + } + } + + public static String getLanguage() { + return FMLCommonHandler.instance().getSide() == Side.SERVER ? null : FMLClientHandler.instance().getCurrentLanguage(); + } + + public static boolean isLanguageActive(String lang) { + String current = getLanguage(); + return current != null && current.equals(lang); + } + + public static boolean isClient() { + return FMLCommonHandler.instance().getSide() == Side.CLIENT; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCLootRegistry.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCLootRegistry.java new file mode 100644 index 0000000..b8fe86b --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCLootRegistry.java @@ -0,0 +1,204 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.vanilla; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.vanilla.ILootRegistry; +import minetweaker.api.vanilla.LootEntry; +import minetweaker.mc18.util.MineTweakerHacks; +import net.minecraft.util.WeightedRandomChestContent; +import net.minecraftforge.common.ChestGenHooks; + +/** + * + * @author Stan + */ +public class MCLootRegistry implements ILootRegistry { + private static final Map LOOT = MineTweakerHacks.getChestLoot(); + + @Override + public void addChestLoot(String type, WeightedItemStack item) { + WeightedRandomChestContent content = new WeightedRandomChestContent( + MineTweakerMC.getItemStack(item.getStack()), + 1, + 1, + (int) item.getChance()); + MineTweakerAPI.apply(new AddLootAction(type, content)); + } + + @Override + public void addChestLoot(String type, WeightedItemStack item, int min, int max) { + WeightedRandomChestContent content = new WeightedRandomChestContent( + MineTweakerMC.getItemStack(item.getStack()), + min, + max, + (int) item.getChance()); + MineTweakerAPI.apply(new AddLootAction(type, content)); + } + + @Override + public void removeChestLoot(String type, IIngredient pattern) { + MineTweakerAPI.apply(new RemoveLootAction(type, pattern)); + } + + @Override + public List getLoot(String type) { + ChestGenHooks recipe = LOOT.get(type); + List contents = MineTweakerHacks.getPrivateObject(recipe, "contents"); + + List results = new ArrayList(); + for (WeightedRandomChestContent content : contents) { + results.add(new LootEntry(new WeightedItemStack( + MineTweakerMC.getIItemStack(content.theItemId), + content.itemWeight), + content.theMinimumChanceToGenerateItem, + content.theMaximumChanceToGenerateItem)); + } + return results; + } + + @Override + public List getLootTypes() { + Set keys = LOOT.keySet(); + List keyList = new ArrayList(); + keyList.addAll(keys); + return keyList; + } + + // ###################### + // ### Action Classes ### + // ###################### + + /** + * Ported from ModTweaker. + * + * @author JoshieJack + */ + private static class AddLootAction implements IUndoableAction { + private final String chest; + private final WeightedRandomChestContent content; + + public AddLootAction(String chest, WeightedRandomChestContent content) { + this.chest = chest; + this.content = content; + } + + @Override + public void apply() { + ChestGenHooks recipe = LOOT.get(chest); + List contents = MineTweakerHacks.getPrivateObject(recipe, "contents"); + + contents.add(content); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + ChestGenHooks recipe = LOOT.get(chest); + List contents = MineTweakerHacks.getPrivateObject(recipe, "contents"); + + contents.remove(content); + } + + public String getRecipeInfo() { + return content.theItemId.getDisplayName(); + } + + @Override + public String describe() { + return "Adding chest loot " + content.theItemId.getDisplayName() + " to loot class " + chest; + } + + @Override + public String describeUndo() { + return "Removing chest loot " + content.theItemId.getDisplayName() + " from loot class " + chest; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + /** + * Ported from ModTweaker. + * + * @author JoshieJack + */ + private static class RemoveLootAction implements IUndoableAction { + private final String chest; + private final IIngredient pattern; + private final List removed; + + public RemoveLootAction(String chest, IIngredient pattern) { + this.chest = chest; + this.pattern = pattern; + removed = new ArrayList(); + } + + @Override + public void apply() { + removed.clear(); + + ChestGenHooks recipe = LOOT.get(chest); + List contents = MineTweakerHacks.getPrivateObject(recipe, "contents"); + + for (WeightedRandomChestContent r : contents) { + if (pattern.matches(MineTweakerMC.getIItemStack(r.theItemId))) { + removed.add(r); + } + } + + for (WeightedRandomChestContent r : removed) { + contents.remove(r); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + ChestGenHooks recipe = LOOT.get(chest); + List contents = MineTweakerHacks.getPrivateObject(recipe, "contents"); + + for (WeightedRandomChestContent entry : removed) { + contents.add(entry); + } + } + + @Override + public String describe() { + return "Removing chest loot " + pattern + " for loot type " + chest; + } + + @Override + public String describeUndo() { + return "Restoring chest loot " + pattern + " for loot type " + chest + " (" + removed.size() + " entries)"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCSeedRegistry.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCSeedRegistry.java new file mode 100644 index 0000000..6f61973 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCSeedRegistry.java @@ -0,0 +1,150 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.vanilla; + +import java.util.ArrayList; +import java.util.List; + +import minetweaker.IUndoableAction; +import minetweaker.MineTweakerAPI; +import minetweaker.api.item.IIngredient; +import minetweaker.api.item.IItemStack; +import minetweaker.api.item.WeightedItemStack; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.vanilla.ISeedRegistry; +import minetweaker.mc18.util.MineTweakerHacks; +import net.minecraft.item.ItemStack; +import net.minecraft.util.WeightedRandom; + +/** + * + * @author Stan + */ +public class MCSeedRegistry implements ISeedRegistry { + private static final List SEEDS = MineTweakerHacks.getSeeds(); + + @Override + public void addSeed(WeightedItemStack item) { + MineTweakerAPI.apply(new AddSeedAction(item)); + } + + @Override + public void removeSeed(IIngredient pattern) { + MineTweakerAPI.apply(new RemoveSeedAction(pattern)); + } + + @Override + public List getSeeds() { + List entries = (List) SEEDS; + + List results = new ArrayList(); + for (WeightedRandom.Item entry : entries) { + results.add(new WeightedItemStack( + MineTweakerMC.getIItemStack(MineTweakerHacks.getSeedEntrySeed(entry)), + entry.itemWeight + )); + } + return results; + } + + // ###################### + // ### Action classes ### + // ###################### + + private static class AddSeedAction implements IUndoableAction { + private final IItemStack item; + private final WeightedRandom.Item entry; + + public AddSeedAction(WeightedItemStack item) { + this.item = item.getStack(); + entry = MineTweakerHacks.constructSeedEntry(item); + } + + @Override + public void apply() { + SEEDS.add(entry); + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + SEEDS.remove(entry); + } + + @Override + public String describe() { + return "Adding seed entry " + item; + } + + @Override + public String describeUndo() { + return "Removing seed entry " + item; + } + + @Override + public Object getOverrideKey() { + return null; + } + } + + private static class RemoveSeedAction implements IUndoableAction { + private final IIngredient pattern; + private final List removed; + + public RemoveSeedAction(IIngredient ingredient) { + this.pattern = ingredient; + removed = new ArrayList(); + } + + @Override + public void apply() { + removed.clear(); + + for (Object entry : SEEDS) { + ItemStack itemStack = MineTweakerHacks.getSeedEntrySeed(entry); + if (pattern.matches(MineTweakerMC.getIItemStack(itemStack))) { + removed.add(entry); + } + } + + for (Object entry : removed) { + SEEDS.remove(entry); + } + } + + @Override + public boolean canUndo() { + return true; + } + + @Override + public void undo() { + for (Object entry : removed) { + SEEDS.add(entry); + } + } + + @Override + public String describe() { + return "Removing seeds " + pattern; + } + + @Override + public String describeUndo() { + return "Restoring seeds " + pattern + " (" + removed.size() + " entries)"; + } + + @Override + public Object getOverrideKey() { + return null; + } + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCVanilla.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCVanilla.java new file mode 100644 index 0000000..0a9007b --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/vanilla/MCVanilla.java @@ -0,0 +1,30 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.vanilla; + +import minetweaker.api.vanilla.ILootRegistry; +import minetweaker.api.vanilla.ISeedRegistry; +import minetweaker.api.vanilla.IVanilla; + +/** + * + * @author Stan + */ +public class MCVanilla implements IVanilla { + private final MCLootRegistry lootRegistry = new MCLootRegistry(); + private final MCSeedRegistry seedRegistry = new MCSeedRegistry(); + + @Override + public ILootRegistry getLoot() { + return lootRegistry; + } + + @Override + public ISeedRegistry getSeeds() { + return seedRegistry; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/world/MCBiome.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/world/MCBiome.java new file mode 100644 index 0000000..e1a85f1 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/world/MCBiome.java @@ -0,0 +1,27 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.world; + +import minetweaker.api.world.IBiome; +import net.minecraft.world.biome.BiomeGenBase; + +/** + * + * @author Stan + */ +public class MCBiome implements IBiome { + private final BiomeGenBase biome; + + public MCBiome(BiomeGenBase biome) { + this.biome = biome; + } + + @Override + public String getName() { + return biome.biomeName; + } +} diff --git a/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/world/MCDimension.java b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/world/MCDimension.java new file mode 100644 index 0000000..e822cbb --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/java/minetweaker/mc18/world/MCDimension.java @@ -0,0 +1,45 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +package minetweaker.mc18.world; + +import minetweaker.api.block.IBlock; +import minetweaker.api.minecraft.MineTweakerMC; +import minetweaker.api.world.IDimension; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +/** + * + * @author Stan + */ +public class MCDimension implements IDimension { + private final World world; + + public MCDimension(World world) { + this.world = world; + } + + @Override + public boolean isDay() { + return world.isDaytime(); + } + + @Override + public int getBrightness(int x, int y, int z) { + return (int) world.getLightBrightness(new BlockPos(x, y, z)); + } + + @Override + public IDimension getDimension() { + return this; + } + + @Override + public IBlock getBlock(int x, int y, int z) { + return MineTweakerMC.getBlock(world, x, y, z); + } +} diff --git a/MineTweaker3-MC18-Main/src/main/resources/assets/minetweaker/logo.png b/MineTweaker3-MC18-Main/src/main/resources/assets/minetweaker/logo.png new file mode 100644 index 0000000..674382e Binary files /dev/null and b/MineTweaker3-MC18-Main/src/main/resources/assets/minetweaker/logo.png differ diff --git a/MineTweaker3-MC18-Main/src/main/resources/mcmod.info b/MineTweaker3-MC18-Main/src/main/resources/mcmod.info new file mode 100644 index 0000000..b4de473 --- /dev/null +++ b/MineTweaker3-MC18-Main/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "MineTweaker3", + "name": "MineTweaker 3", + "version": "${version}", + "mcversion": "${mcversion}", + "description": "Customize your minecraft experience!", + "credits": "Created By Stan Hebben", + "logoFile": "assets/minetweaker/logo.png", + "url": "http://minetweaker3.powerofbytes.com", + "authorList": [ "Stan Hebben" ], + "parent": "", + "screenshots": [], + "dependencies": [] +} +]