diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..fdd4c84 --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# eclipse +bin +*.launch +.settings +.metadata +.classpath +.project + +# gradle +build +.gradle + +# other +eclipse +run + +# Files from Forge MDK +forge*changelog.txt diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..c82238b --- /dev/null +++ b/build.gradle @@ -0,0 +1,128 @@ +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + jcenter() + mavenCentral() + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:3.+' + } +} + +apply plugin: 'net.minecraftforge.gradle' +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +apply plugin: 'eclipse' +apply plugin: 'maven-publish' + +version = '0.1' +group = 'magnileve.chungamod' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'chungamod' + +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. + +minecraft { + // 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 always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + //mappings channel: 'snapshot', version: '20171003-1.12' + mappings channel: 'snapshot', version: '20171003-1.12' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'info' + } + + server { + + // Recommended logging data for a userdev environment + property 'forge.logging.markers', 'SCAN,REGISTRIES,REGISTRYDUMP' + + // Recommended logging level for the console + property 'forge.logging.console.level', 'info' + } + } +} + +configurations { + jarLibs +} + +dependencies { + // Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed + // that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.12.2-14.23.5.2854' + + // 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' + + // These dependencies get remapped to your current MCP mappings + // deobf '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 + jarLibs files('libs\\discord-rpc.jar') + + implementation configurations.jarLibs +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Specification-Title": "examplemod", + "Specification-Vendor": "examplemodsareus", + "Specification-Version": "1", // We are version 1 of ourselves + "Implementation-Title": project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"examplemodsareus", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } + from { + configurations.jarLibs.collect { + it.isDirectory() ? it : zipTree(it) + } + } +} + +// Example configuration to allow publishing using the maven-publish task +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +//publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..7a3265e Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..949819d --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..cccdd3d --- /dev/null +++ b/gradlew @@ -0,0 +1,172 @@ +#!/usr/bin/env sh + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# 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\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS="" + +# 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 +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +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" -a "$nonstop" = "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"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # 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 + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=$(save "$@") + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..f955316 --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,84 @@ +@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 + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@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= + +@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 Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_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=%* + +: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/libs/discord-rpc.jar b/libs/discord-rpc.jar new file mode 100644 index 0000000..ef5c4bb Binary files /dev/null and b/libs/discord-rpc.jar differ diff --git a/src/main/java/magnileve/chungamod/Chungamod.java b/src/main/java/magnileve/chungamod/Chungamod.java new file mode 100644 index 0000000..84a45f3 --- /dev/null +++ b/src/main/java/magnileve/chungamod/Chungamod.java @@ -0,0 +1,44 @@ +package magnileve.chungamod; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.Mod.Instance; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import org.apache.logging.log4j.Logger; + +import magnileve.chungamod.time.TickTimer; + +@Mod(modid = Ref.MODID, name = Ref.NAME, version = Ref.VERSION, acceptedMinecraftVersions = Ref.ACCEPTED_MINECRAFT_VERSIONS) +public class Chungamod { + + private static Minecraft mc; + private static Logger log; + + @Instance + public static Chungamod instance; + + @EventHandler + public void preInit(FMLPreInitializationEvent event) { + mc = Minecraft.getMinecraft(); + log = event.getModLog(); + log.info(Ref.MODID + ":Pre-Initialization"); + Settings.load(log); + Ref.init(mc); + TickTimer.init(log); + Commands.init(mc, log); + } + + @EventHandler + public void init(FMLInitializationEvent event) { + log.info(Ref.MODID + ":Initialization"); + } + + @EventHandler + public void postInit(FMLPostInitializationEvent event) { + log.info(Ref.MODID + ":Post-Initialization"); + Commands.init2(); + } +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/Commands.java b/src/main/java/magnileve/chungamod/Commands.java new file mode 100644 index 0000000..38fb969 --- /dev/null +++ b/src/main/java/magnileve/chungamod/Commands.java @@ -0,0 +1,287 @@ +package magnileve.chungamod; + +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import java.util.Collection; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; + +import magnileve.chungamod.itemstorage.AutoSort; +import magnileve.chungamod.time.ClientTps; +import magnileve.chungamod.time.Activity; +import net.arikia.dev.drpc.DiscordEventHandlers; +import net.arikia.dev.drpc.DiscordRPC; +import net.arikia.dev.drpc.DiscordRichPresence; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.client.Minecraft; +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.world.chunk.Chunk; +import net.minecraftforge.client.event.ClientChatEvent; + +@Mod.EventBusSubscriber(modid=Ref.MODID) +public class Commands { + +private static final long START_TIME = System.currentTimeMillis() / 1000; + +private static Minecraft mc; +private static Logger log; +private static final String HELP_MESSAGE = "Chungamod \\version by Magnileve\nCommands:\n\\prefixcancel - cancel current activities\n\\prefixset - set a setting\n\\prefixset - set a setting of a feature\n\\prefixhelp - sends this message\n\\prefixautosort - automatically sort shulker boxes\n\\prefixblockdata - get block state of selected block\n\\prefixclienttps - measure and periodically send client TPS"; + +protected static void init(Minecraft minecraft, Logger logger) { + mc = minecraft; + log = logger; +} + +public static void init2() { + //initiate DiscordRPC + if((Boolean) Settings.get("discordrpc")) { + discordRPCstart(); + } + java.lang.Runtime.getRuntime().addShutdownHook(new Thread() { + @Override + public void run() { + if((Boolean) Settings.get("discordrpc")) DiscordRPC.discordShutdown(); + } + }); +} + +@SubscribeEvent +@SideOnly(value = Side.CLIENT) +public static void onServerChatEvent(ClientChatEvent event) { + if(event.getMessage().startsWith((String) Settings.get("prefix"))) { + event.setCanceled(true); + log.info("Chungamod command called: " + event.getMessage()); + String[] command = event.getMessage().split(" "); + if (command[0].length() == ((String) Settings.get("prefix")).length()) mc.player.sendMessage(new TextComponentString(HELP_MESSAGE.replaceAll("\\\\prefix", (String) Settings.get("prefix")).replaceFirst("\\\\version", Ref.VERSION))); + else switch (command[0].substring(((String) Settings.get("prefix")).length()).toLowerCase()) { + case "help": + mc.player.sendMessage(new TextComponentString(HELP_MESSAGE.replaceAll("\\n\\\\prefix", "\n" + (String) Settings.get("prefix")).replaceFirst("\\\\version", Ref.VERSION))); + break; + case "set": + if(command.length > 1) { + command[1] = command[1].toLowerCase(); + Object settingValue = Settings.getValue(command[1]); + if(settingValue != null) { + Settings.Type settingValueEnum = null; + try { + settingValueEnum = (Settings.Type) settingValue; + } catch(ClassCastException e) { + + } + if(settingValueEnum == null) { + Object[] featureSettings = (Object[]) settingValue; + if(command.length > 2) { + byte i = 1; + command[2] = command[2].toLowerCase(); + for(String setting:((String) featureSettings[0]).split(" ")) { + if(setting.equals(command[2])) { + switch((Settings.Type) featureSettings[i]) { + case STRING: + if(command.length > 3) { + String newString = Ref.inverseSplit(command, " ").substring(command[0].length() + command[1].length() + 2); + Settings.set(command[1], command[2], newString); + Ref.sendMessage("Set " + command[1] + "." + command[2] + " to " + newString); + } else Ref.sendMessage(Settings.get(command[1], command[2]).toString()); + break; + case BOOLEAN: + if(command.length > 3) { + if(command[3].toLowerCase().equals("true") || command[3].toLowerCase().equals("false")) { + Settings.set(command[1], command[2], Boolean.valueOf(command[3])); + Ref.sendMessage("Set " + command[1] + "." + command[2] + " to " + command[3]); + } Ref.sendMessage("Valid setting values: true, false"); + } else Ref.sendMessage(Settings.get(command[1], command[2]).toString()); + break; + case BLOCKPOS: + try { + BlockPos newPos; + if (command.length > 3) { + newPos = new BlockPos(Integer.valueOf(command[3]), Integer.valueOf(command[4]), Integer.valueOf(command[5])); + } else { + newPos = mc.getRenderViewEntity().rayTrace(4.5D, 1.0F).getBlockPos(); + if(Block.getIdFromBlock(mc.world.getBlockState(newPos).getBlock()) == 0) { + Ref.sendMessage(Settings.get(command[1], command[2]).toString()); + break; + } + } + Settings.set(command[1], command[2], newPos); + Ref.sendMessage("Set " + command[1] + "." + command[2] + " to " + newPos); + } catch (IndexOutOfBoundsException e) { + Ref.sendMessage("Look at a block while setting this value or supply coordinates: " + command[0] + " " + command[1] + " " + command[2] + " "); + } catch (NumberFormatException e) { + Ref.sendMessage("Look at a block while setting this value or supply coordinates: " + command[0] + " " + command[1] + " " + command[2] + " "); + } catch (NullPointerException e) { + Ref.sendMessage("NullPointerException while setting BlockPos"); + log.warn("NullPointerException while setting BlockPos"); + log.catching(Level.WARN, e); + } + break; + case SHORT: + if(command.length == 4) { + try { + Short newNumber = Short.valueOf(command[3]); + if(newNumber < 0) newNumber = 0; + Settings.set(command[1], command[2], newNumber); + Ref.sendMessage("Set " + command[1] + "." + command[2] + " to " + newNumber); + } catch(NumberFormatException e) { + Ref.sendMessage("Enter a number value"); + } + } else Ref.sendMessage(Settings.get(command[1], command[2]).toString()); + break; + case STRING_ONE_WORD: + if(command.length == 4) { + Settings.set(command[1], command[2], command[3]); + Ref.sendMessage("Set " + command[1] + "." + command[2] + " to " + command[3]); + } else if(command.length == 3) Ref.sendMessage(Settings.get(command[1], command[2]).toString()); + else Ref.sendMessage("Value can not contain spaces"); + break; + case OBJECT_ARRAY: + log.error("Enum representing object array in setting values"); + break; + } + i = 0; + break; + } + i++; + } + if(i != 0) { + Ref.sendMessage("Settings for " + command[1] + ": " + ((String) featureSettings[0]).replaceAll(" ", ", ")); + } + } else Ref.sendMessage("Settings for " + command[1] + ": " + ((String) featureSettings[0]).replaceAll(" ", ", ")); + } else { + switch(settingValueEnum) { + case STRING: + if(command.length > 2) { + String newString = Ref.inverseSplit(command, " ").substring(command[0].length() + command[1].length() + 2); + Settings.set(command[1], newString); + Ref.sendMessage("Set " + command[1] + " to " + newString); + } else Ref.sendMessage(Settings.get(command[1]).toString()); + break; + case BOOLEAN: + if(command.length > 2) { + if(command[2].toLowerCase().equals("true") || command[2].toLowerCase().equals("false")) { + Settings.set(command[1], Boolean.valueOf(command[2])); + Ref.sendMessage("Set " + command[1] + " to " + command[2]); + } Ref.sendMessage("Valid setting values: true, false"); + } else Ref.sendMessage(Settings.get(command[1]).toString()); + break; + case BLOCKPOS: + try { + BlockPos newPos; + if (command.length > 2) { + newPos = new BlockPos(Integer.valueOf(command[2]), Integer.valueOf(command[3]), Integer.valueOf(command[4])); + } else { + newPos = mc.getRenderViewEntity().rayTrace(4.5D, 1.0F).getBlockPos(); + if(Block.getIdFromBlock(mc.world.getBlockState(newPos).getBlock()) == 0) { + Ref.sendMessage(Settings.get(command[1]).toString()); + break; + } + } + Settings.set(command[1], newPos); + Ref.sendMessage("Set " + command[1] + " to " + newPos); + } catch (IndexOutOfBoundsException e) { + Ref.sendMessage("Look at a block while setting this value or supply coordinates: " + command[0] + " " + command[1] + " "); + } catch (NumberFormatException e) { + Ref.sendMessage("Look at a block while setting this value or supply coordinates: " + command[0] + " " + command[1] + " "); + } catch (NullPointerException e) { + Ref.sendMessage("NullPointerException while setting BlockPos"); + log.warn("NullPointerException while setting BlockPos"); + log.catching(Level.WARN, e); + } + break; + case SHORT: + if(command.length == 3) { + try { + Short newNumber = Short.valueOf(command[2]); + if(newNumber < 0) newNumber = 0; + Settings.set(command[1], newNumber); + Ref.sendMessage("Set " + command[1] + " to " + newNumber); + } catch(NumberFormatException e) { + Ref.sendMessage("Enter a number value"); + } + } else Ref.sendMessage(Settings.get(command[1]).toString()); + break; + case STRING_ONE_WORD: + if(command.length == 3) { + Settings.set(command[1], command[2]); + Ref.sendMessage("Set " + command[1] + " to " + command[2]); + } else if(command.length == 2) Ref.sendMessage(Settings.get(command[1]).toString()); + else Ref.sendMessage("Value can not contain spaces"); + break; + case OBJECT_ARRAY: + log.error("Enum representing object array in setting values"); + break; + } + } + } + } else Ref.sendMessage("Enter a setting and value following your command"); + case "autosort": + if(Settings.get("autosort", "pos1") != null && Settings.get("autosort", "pos2") != null && Settings.get("autosort", "source") != null) { + Ref.sendMessage("Running AutoSort"); + Ref.runningActivities.add(new AutoSort(mc, (BlockPos) Settings.get("autosort", "pos1"), (BlockPos) Settings.get("autosort", "pos2"), (BlockPos) Settings.get("autosort", "source"), (Short) Settings.get("autosort", "sourceemptytimeout"), (BlockPos) Settings.get("autosort", "overflow"), log)); + } + else Ref.sendMessage("Make sure to set AutoSort settings pos1, pos2, and source before running (use " + (String) Settings.get("prefix") + "set autosort "); + break; + case "cancel": + Ref.sendMessage("Cancelling running activities"); + for(Activity activity:Ref.runningActivities) activity.stop(); + Ref.runningActivities.clear(); + break; + case "clienttps": + Ref.runningActivities.add(new ClientTps()); + break; + case "blockdata": + BlockPos blockPos = mc.getRenderViewEntity().rayTrace(4.5D, 1.0F).getBlockPos(); + for(IProperty property:mc.world.getBlockState(blockPos).getBlock().getBlockState().getProperties()) { + Ref.sendMessage(property.toString()); + Ref.sendMessage(property.getName()); + Ref.sendMessage(property.getClass().toString()); + Ref.sendMessage("property value: " + mc.world.getBlockState(blockPos).getValue(property)); + } + if(Block.getIdFromBlock(mc.world.getBlockState(blockPos).getBlock()) == 68) { + TileEntitySign tileEntity = (TileEntitySign) mc.world.getChunkFromBlockCoords(blockPos).getTileEntity(blockPos, Chunk.EnumCreateEntityType.CHECK); + for(ITextComponent text:tileEntity.signText) Ref.sendMessage("Sign text: " + text); + } + break; + + default: + if((Boolean) Settings.get("debug")) { + switch (command[0].substring(((String) Settings.get("prefix")).length()).toLowerCase()) { + case "cameradirection": + Ref.sendMessage("Camera pitch: " + mc.player.cameraPitch + "\nCamera yaw: " + mc.player.cameraYaw + "\nRotation pitch: " + mc.player.rotationPitch + "\nRotation yaw: " + mc.player.rotationYaw); + break; + case "entitylist": + for(Collection collection:mc.world.getChunkFromBlockCoords(mc.player.getPosition()).getEntityLists()) { + log.debug("\nCollection " + collection.getClass()); + for(Object o:collection) { + log.debug(o.getClass().toString()); + log.debug(o.toString()); + } + } + break; + case "playerpos": + Ref.sendMessage(Ref.playerPos().toString()); + break; + + default: + mc.player.sendMessage(new TextComponentString("Unknown command. Try " + (String) Settings.get("prefix") + "help for a list of commands")); + } + } else mc.player.sendMessage(new TextComponentString("Unknown command. Try " + (String) Settings.get("prefix") + "help for a list of commands")); + } + } +} + +//setup DiscordRPC +private static void discordRPCstart() { + DiscordRPC.discordInitialize("832742372420091964", new DiscordEventHandlers.Builder().build(), true); + DiscordRPC.discordUpdatePresence(new DiscordRichPresence.Builder("Mincerfat client").setBigImage("chungustransparentcroppedlarge", "All hail Big Chungus").setDetails("The funniest").setStartTimestamps(START_TIME).build()); +} + +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/LeaveServerListener.java b/src/main/java/magnileve/chungamod/LeaveServerListener.java new file mode 100644 index 0000000..28b5b71 --- /dev/null +++ b/src/main/java/magnileve/chungamod/LeaveServerListener.java @@ -0,0 +1,18 @@ +package magnileve.chungamod; + +import magnileve.chungamod.time.Activity; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent.ClientDisconnectionFromServerEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid=Ref.MODID) +public class LeaveServerListener { + @SubscribeEvent + @SideOnly(value = Side.CLIENT) + public static void onClientDisconnectEvent(ClientDisconnectionFromServerEvent event) { + for(Activity activity:Ref.runningActivities) activity.stop(); + Ref.runningActivities.clear(); + } +} diff --git a/src/main/java/magnileve/chungamod/Ref.java b/src/main/java/magnileve/chungamod/Ref.java new file mode 100644 index 0000000..c550d30 --- /dev/null +++ b/src/main/java/magnileve/chungamod/Ref.java @@ -0,0 +1,67 @@ +package magnileve.chungamod; + +import java.util.LinkedList; + +import magnileve.chungamod.time.Activity; +import net.minecraft.client.Minecraft; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextComponentString; + +public class Ref { + public static final String MODID = "chungamod"; + public static final String NAME = "Chungamod"; + public static final String VERSION = "0.1"; + public static final String ACCEPTED_MINECRAFT_VERSIONS = "[1.12]"; + private static Minecraft mc; + public static LinkedList runningActivities; + + public static void init(Minecraft minecraft) { + mc = minecraft; + runningActivities = new LinkedList(); + } + + //send message to player + public static void sendMessage(String message) { + mc.player.sendMessage(new TextComponentString("[Chungamod] " + message)); + } + + //inverse of string.split(regex) + public static String inverseSplit(String[] strings, String regex) { + if (strings.length == 0) return ""; + String str = strings[0]; + for (short i = 1; i < strings.length; i++) str = str + regex + strings[i]; + return str; + } + + //copied and pasted from the Mincerfat code becaues it has protected visibility there + public static final Vec3d getVectorForRotation(float pitch, float yaw) { + float f = MathHelper.cos(-yaw * 0.017453292F - (float)Math.PI); + float f1 = MathHelper.sin(-yaw * 0.017453292F - (float)Math.PI); + float f2 = -MathHelper.cos(-pitch * 0.017453292F); + float f3 = MathHelper.sin(-pitch * 0.017453292F); + return new Vec3d((double)(f1 * f2), (double)f3, (double)(f * f2)); + } + + public static BlockPos playerPos() { + return new BlockPos(mc.player.posX, mc.player.posY, mc.player.posZ); + } + + //get yaw from cardinal direction + public static float enumFacingToYaw(EnumFacing facing) { + switch(facing) { + case SOUTH: + return 0F; + case WEST: + return 90F; + case NORTH: + return 180F; + case EAST: + return -90F; + default: + throw new IllegalStateException("Unable to get yaw from vertical direction " + facing); + } + } +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/Settings.java b/src/main/java/magnileve/chungamod/Settings.java new file mode 100644 index 0000000..39623a5 --- /dev/null +++ b/src/main/java/magnileve/chungamod/Settings.java @@ -0,0 +1,191 @@ +package magnileve.chungamod; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.util.HashMap; + +import org.apache.logging.log4j.Logger; + +import net.minecraft.util.math.BlockPos; + +public class Settings { + +private static final HashMap SETTING_VALUES = settingValues(); +private static final HashMap DEFAULT_SETTINGS = defaultSettings(); +private static Logger log; +private static HashMap settings; + +private static final HashMap settingValues() { + HashMap settingValues = new HashMap<>(); + settingValues.put("prefix", Type.STRING_ONE_WORD); + settingValues.put("discordrpc", Type.BOOLEAN); + settingValues.put("debug", Type.BOOLEAN); + Object[] autoSortSettings = {"pos1 pos2 source sourceemptyimeout overflow", Type.BLOCKPOS, Type.BLOCKPOS, Type.BLOCKPOS, Type.SHORT, Type.BLOCKPOS}; + settingValues.put("autosort", autoSortSettings); + return settingValues; +} + +private static final HashMap defaultSettings() { + HashMap defaultSettings = new HashMap<>(); + defaultSettings.put("prefix", ","); + defaultSettings.put("discordrpc", true); + defaultSettings.put("debug", false); + Object[] autoSortSettings = {"pos1 pos2 source sourceemptytimeout overflow", null, null, null, new Short((short) 2), null}; + defaultSettings.put("autosort", autoSortSettings); + return defaultSettings; +} + +public static Object get(String setting) { + Object returnSetting = settings.get(setting); + if(returnSetting instanceof Integer[]) { + Integer[] integersValue = (Integer[]) returnSetting; + BlockPos blockPosValue = new BlockPos(integersValue[0], integersValue[1], integersValue[2]); + returnSetting = (Object) blockPosValue; + } + return returnSetting; +} + +public static Object get(String feature, String setting) { + Object returnSetting; + try { + Object[] featureSettings = (Object[]) settings.get(feature); + String[] settingNames = ((String) (featureSettings[0])).split(" "); + byte i = 0; + while(!settingNames[i].equalsIgnoreCase(setting)) i++; + returnSetting = featureSettings[i + 1]; + } catch(Exception e) { + log.error("Settings corrupted for " + feature); + settings.put(feature, DEFAULT_SETTINGS.get(feature)); + Object[] featureSettings = (Object[]) settings.get(feature); + String[] settingNames = ((String) (featureSettings[0])).split(" "); + byte i = 0; + while(!settingNames[i].equalsIgnoreCase(setting)) i++; + returnSetting = featureSettings[i + 1]; + } + if(returnSetting instanceof Integer[]) { + Integer[] integersValue = (Integer[]) returnSetting; + BlockPos blockPosValue = new BlockPos(integersValue[0], integersValue[1], integersValue[2]); + returnSetting = (Object) blockPosValue; + } + return returnSetting; +} + +public static void set(String setting, Object value) { + if(value instanceof BlockPos) { + BlockPos blockPosValue = (BlockPos) value; + Integer[] integersValue = {blockPosValue.getX(), blockPosValue.getY(), blockPosValue.getZ()}; + value = (Object) integersValue; + } + settings.put(setting, value); + save(settings); +} + +public static void set(String feature, String setting, Object value) { + if(value instanceof BlockPos) { + BlockPos blockPosValue = (BlockPos) value; + Integer[] integersValue = {blockPosValue.getX(), blockPosValue.getY(), blockPosValue.getZ()}; + value = (Object) integersValue; + } + try { + Object[] featureSettings = (Object[]) settings.get(feature); + String[] settingNames = ((String) (featureSettings[0])).split(" "); + byte i = 0; + while(!settingNames[i].equalsIgnoreCase(setting)) i++; + featureSettings[i + 1] = value; + settings.put(feature, featureSettings); + } catch(Exception e) { + log.error("Settings corrupted for " + feature); + settings.put(feature, DEFAULT_SETTINGS.get(feature)); + Object[] featureSettings = (Object[]) settings.get(feature); + String[] settingNames = ((String) (featureSettings[0])).split(" "); + byte i = 0; + while(!settingNames[i].equalsIgnoreCase(setting)) i++; + featureSettings[i + 1] = value; + settings.put(feature, featureSettings); + } + save(settings); +} + +public static Object getValue(String setting) { + return SETTING_VALUES.get(setting); +} + +public static Class getValue(String feature, String setting) { + Object[] featureSettings = (Object[]) SETTING_VALUES.get(feature); + String[] settingNames = ((String) (featureSettings[0])).split(" "); + byte i = 0; + while(!settingNames[i].equalsIgnoreCase(setting)) i++; + return (Class) featureSettings[i + 1]; +} + +@SuppressWarnings("unchecked") +protected static void load(Logger logger) { + log = logger; + HashMap loadedSettings; + Object getSettingsResult = null; + HashMap getSettings; + FileInputStream fileIn = null; + try { + fileIn = new FileInputStream(".\\chungamod\\settings.ser"); + } catch (IOException e) { + log.info("Settings file not found"); + getSettings = DEFAULT_SETTINGS; + try { + new FileOutputStream(".\\chungamod\\settings.ser").close(); + } catch (IOException e1) { + File file = new File(".\\chungamod"); + file.mkdir(); + } + save(getSettings); + getSettingsResult = getSettings; + } + if(fileIn != null) { + try { + ObjectInputStream in = new ObjectInputStream(fileIn); + getSettings = (HashMap) in.readObject(); + in.close(); + fileIn.close(); + getSettingsResult = getSettings; + log.debug("Settings loaded"); + } catch (Exception e) { + getSettingsResult = e; + } + } + if(getSettingsResult instanceof HashMap) loadedSettings = (HashMap) getSettingsResult; + else { + try { + Exception e = (Exception) getSettingsResult; + log.error("Error loading settings"); + e.printStackTrace(); + } catch(Exception e) { + log.error("Settings file corrupted"); + e.printStackTrace(); + } + loadedSettings = DEFAULT_SETTINGS; + save(loadedSettings); + } + settings = loadedSettings; +} + +private static void save(HashMap settings) { + try { + FileOutputStream fileOut = new FileOutputStream(".\\chungamod\\settings.ser"); + ObjectOutputStream out = new ObjectOutputStream(fileOut); + out.writeObject(settings); + out.close(); + fileOut.close(); + log.debug("Settings saved"); + } catch (IOException e) { + e.printStackTrace(); + } +} + +public static enum Type { + OBJECT_ARRAY, STRING, BOOLEAN, BLOCKPOS, SHORT, STRING_ONE_WORD +} + +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/itemstorage/AutoSort.java b/src/main/java/magnileve/chungamod/itemstorage/AutoSort.java new file mode 100644 index 0000000..a9e7795 --- /dev/null +++ b/src/main/java/magnileve/chungamod/itemstorage/AutoSort.java @@ -0,0 +1,405 @@ +package magnileve.chungamod.itemstorage; + +import java.util.LinkedList; + +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.Logger; + +import magnileve.chungamod.Ref; +import magnileve.chungamod.time.Activity; +import magnileve.chungamod.time.TickListener; +import magnileve.chungamod.time.TickTimer; +import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetHandlerPlayClient; +import net.minecraft.inventory.ClickType; +import net.minecraft.inventory.Slot; +import net.minecraft.item.Item; +import net.minecraft.network.play.client.CPacketClickWindow; +import net.minecraft.network.play.client.CPacketPlayer; +import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock; +import net.minecraft.tileentity.TileEntitySign; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.world.chunk.Chunk; + +public class AutoSort implements TickListener, Activity { + +private Minecraft mc; +private Logger log; +private NetHandlerPlayClient connection; +private LinkedList sortLocations; +private Status status; +private BlockPos source; +private BlockPos overflow; +private BlockPos destination; +private StorageUnit unit; +private int nextTick; +private short sourceEmptyTimeout; +private byte slot; +private byte moveSlot; +private byte inventorySpace; +private EnumFacing sourceFacing; +private EnumFacing overflowFacing; +private EnumFacing destinationOffset; +private boolean sourceDoubleChest; +private boolean overflowDoubleChest; +private boolean goToOverflow; + +public AutoSort(Minecraft minecraft, BlockPos pos1, BlockPos pos2, BlockPos shulkerSource, short sourceEmptyTimeout, BlockPos shulkerOverflow, Logger logger) { + mc = minecraft; + connection = mc.player.connection; + log = logger; + source = shulkerSource; + this.sourceEmptyTimeout = sourceEmptyTimeout; + overflow = shulkerOverflow; + if(source.getDistance((int) mc.player.posX, (int) mc.player.posY, (int) mc.player.posZ) > 250 || + (overflow == null ? false : overflow.getDistance((int) mc.player.posX, (int) mc.player.posY, (int) mc.player.posZ) > 250) || + pos1.getDistance((int) mc.player.posX, (int) mc.player.posY, (int) mc.player.posZ) > 250 || + pos2.getDistance((int) mc.player.posX, (int) mc.player.posY, (int) mc.player.posZ) > 250) { + Ref.sendMessage("AutoSort error: Chests too far away"); + Ref.runningActivities.remove(this); + return; + } + sortLocations = new LinkedList<>(); + goToOverflow = false; + log.info("[AutoSort] Running AutoSort"); + for(IProperty property:mc.world.getBlockState(source).getBlock().getBlockState().getProperties()) if(property.getName().equals("facing")) { + sourceFacing = (EnumFacing) mc.world.getBlockState(source).getValue(property); + sourceDoubleChest = (isChest(Block.getIdFromBlock(mc.world.getBlockState(source.offset(sourceFacing.rotateY())).getBlock())) || + isChest(Block.getIdFromBlock(mc.world.getBlockState(source.offset(sourceFacing.rotateYCCW())).getBlock()))); + break; + } + if(overflow != null) for(IProperty property:mc.world.getBlockState(overflow).getBlock().getBlockState().getProperties()) if(property.getName().equals("facing")) { + overflowFacing = (EnumFacing) mc.world.getBlockState(overflow).getValue(property); + overflowDoubleChest = (isChest(Block.getIdFromBlock(mc.world.getBlockState(overflow.offset(overflowFacing.rotateY())).getBlock())) || + isChest(Block.getIdFromBlock(mc.world.getBlockState(overflow.offset(overflowFacing.rotateYCCW())).getBlock()))); + break; + } + int minX = Math.min(pos1.getX(), pos2.getX()); + int minY = Math.min(pos1.getY(), pos2.getY()); + int minZ = Math.min(pos1.getZ(), pos2.getZ()); + int maxX = Math.max(pos1.getX(), pos2.getX()); + int maxY = Math.max(pos1.getY(), pos2.getY()); + int maxZ = Math.max(pos1.getZ(), pos2.getZ()); + for(int x = minX; x <= maxX; x++) for(int y = minY; y <= maxY; y++) for(int z = minZ; z <= maxZ; z++) { + if(Block.getIdFromBlock(mc.world.getBlockState(new BlockPos(x, y, z)).getBlock()) == 68) { + BlockPos blockPos = new BlockPos(x, y, z); + for(IProperty property:mc.world.getBlockState(blockPos).getBlock().getBlockState().getProperties()) if(property.getName().equals("facing")) { + String shulkerName = ""; + for(ITextComponent line:((TileEntitySign) mc.world.getChunkFromBlockCoords(blockPos).getTileEntity(blockPos, Chunk.EnumCreateEntityType.CHECK)).signText) if(!line.getFormattedText().isEmpty()) { + char[] lineChars = line.getFormattedText().toCharArray(); + String actualLine = ""; + for(char character:lineChars) { + if(character == '§') break; + actualLine += character; + } + shulkerName += " " + actualLine; + } + if(!shulkerName.isEmpty()) { + shulkerName = shulkerName.substring(1); + EnumFacing facing = (EnumFacing) mc.world.getBlockState(blockPos).getValue(property); + blockPos = blockPos.offset(facing, -1); + int blockID = Block.getIdFromBlock(mc.world.getBlockState(blockPos).getBlock()); + if(isChest(blockID)) { + while(Block.getIdFromBlock(mc.world.getBlockState(blockPos).getBlock()) == blockID) blockPos = blockPos.down(); + blockPos = blockPos.up(); + EnumFacing doubleChestFacing = null; + if(Block.getIdFromBlock(mc.world.getBlockState(blockPos.offset(facing.rotateY())).getBlock()) == blockID) doubleChestFacing = facing.rotateY(); + else if(Block.getIdFromBlock(mc.world.getBlockState(blockPos.offset(facing.rotateYCCW())).getBlock()) == blockID) doubleChestFacing = facing.rotateYCCW(); + else if(Block.getIdFromBlock(mc.world.getBlockState(blockPos.offset(facing.getOpposite())).getBlock()) == blockID) doubleChestFacing = facing.getOpposite(); + byte height = 0; + while(Block.getIdFromBlock(mc.world.getBlockState(blockPos.up(height)).getBlock()) == blockID && + (doubleChestFacing == null ? true : (Block.getIdFromBlock(mc.world.getBlockState(blockPos.up(height).offset(doubleChestFacing)).getBlock())) == blockID) && height < 6) height++; + sortLocations.add(new StorageUnit(blockPos, shulkerName, height, facing, doubleChestFacing != null)); + log.debug("[AutoSort] Adding storage location of \"" + shulkerName + "\" with height " + height + " at " + blockPos); + for(char character:shulkerName.toCharArray()) log.debug(character); + } + break; + } + } + } + } + for(byte i = 9; i < 45; i++) { + Slot thisSlot = mc.player.openContainer.getSlot(i); + if(thisSlot.getHasStack()) { + int itemID = Item.getIdFromItem(thisSlot.getStack().getItem()); + if(itemID > 218 && itemID < 235 && overflow != null) inventorySpace++; + } else inventorySpace++; + } + slot = 8; + status = Status.SEARCHING_STORAGE; + TickTimer.addListener(this); + nextTick(1); +} + +@Override +public void onTick(int tick) { +if(tick == nextTick) { + try { + switch(status) { + case GOING_TO_STORAGE: + case GOING_TO_SOURCE: + case GOING_TO_OVERFLOW: + double distance = new BlockPos(mc.player.posX, mc.player.posY, mc.player.posZ).getDistance(destination.offset(destinationOffset).getX(), destination.getY(), destination.offset(destinationOffset).getZ()); + if(distance == 0D) { + mc.player.sendChatMessage("#cancel"); + + //open chest + double dx = destination.getX() - mc.player.posX + 0.5; + double dy = destination.getY() - mc.player.posY + 0.5 - mc.player.eyeHeight; + if(status == Status.GOING_TO_STORAGE) { + dy += unit.getFillHeight(); + if(Block.getIdFromBlock(mc.world.getBlockState(destination.up(unit.getFillHeight()).offset(unit.getFacing())).getBlock()) == 68) { + if(unit.getFillHeight() == 0) dy += 0.375; + else if(unit.getFillHeight() == 1 || unit.getFillHeight() == 2) dy -= 0.375; + else if(unit.getFillHeight() == 3) dy -= 0.3125; + } + } + double dz = destination.getZ() - mc.player.posZ + 0.5; + log.debug("Start chest coords: " + (dx + mc.player.posX) + ", " + (dy + mc.player.posY) + ", " + (dz + mc.player.posZ)); + + double yawToPlayer = -Math.atan2(dx, dz) + Math.PI; + double edgeOfBlockRadius = Math.min(Math.abs(1 / Math.cos(yawToPlayer)), Math.abs(1 / Math.sin(yawToPlayer))) / 2; + dx += -Math.sin(yawToPlayer) * edgeOfBlockRadius; + dz += Math.cos(yawToPlayer) * edgeOfBlockRadius; + log.debug("Shifted chest coords: " + (dx + mc.player.posX) + ", " + (dy + mc.player.posY) + ", " + (dz + mc.player.posZ)); + + double r = Math.sqrt(dx * dx + dy * dy + dz * dz); + double yaw = -Math.atan2(dx, dz) / Math.PI * 180; + if(yaw < 0) yaw = 360 + yaw; + double pitch = -Math.asin(dy / r) / Math.PI * 180; + mc.player.connection.sendPacket(new CPacketPlayer.Rotation((float) yaw, (float) pitch, mc.player.onGround)); + + Vec3d vec3d = mc.player.getPositionEyes(1.0F); + Vec3d vec3d1 = Ref.getVectorForRotation((float) pitch, (float) yaw); + Vec3d vec3d2 = vec3d.addVector(vec3d1.x * 4.5D, vec3d1.y * 4.5D, vec3d1.z * 4.5D); + RayTraceResult rayTrace = mc.world.rayTraceBlocks(vec3d, vec3d2, false, false, true); + + BlockPos pos1 = rayTrace.getBlockPos(); + Vec3d vec1 = rayTrace.hitVec; + float f = (float)(vec1.x - (double)pos1.getX()); + float f1 = (float)(vec1.y - (double)pos1.getY()); + float f2 = (float)(vec1.z - (double)pos1.getZ()); + connection.sendPacket(new CPacketPlayerTryUseItemOnBlock(pos1, rayTrace.sideHit, EnumHand.MAIN_HAND, f, f1, f2)); + + if(status == Status.GOING_TO_STORAGE) status = Status.WAITING_ON_STORAGE; + else if(status == Status.GOING_TO_SOURCE) status = Status.WAITING_ON_SOURCE; + else status = Status.WAITING_ON_OVERFLOW; + nextTick(1); + } else nextTick((int) (distance * 5)); + break; + case WAITING_ON_SOURCE: + if(mc.player.openContainer.windowId == 0) { + nextTick(1); + break; + } else { + slot = -1; + moveSlot = 0; + status = Status.TAKING_SHULKERS; + log.debug("[AutoSort] Taking shulkers"); + } + case TAKING_SHULKERS: + if(slot == (sourceDoubleChest ? 54 : 27)) { + if(moveSlot == 0) { + status = Status.SOURCE_EMPTY_TIMEOUT; + if(sourceEmptyTimeout != 0) { + nextTick(sourceEmptyTimeout * 40); + break; + } + } else { + //connection.sendPacket(new CPacketCloseWindow(mc.player.openContainer.windowId)); + mc.player.closeScreen(); + slot = 8; + status = Status.SEARCHING_STORAGE; + } + } else { + for(slot++; slot < (sourceDoubleChest ? 54 : 27); slot++) { + Slot thisSlot = mc.player.openContainer.getSlot(slot); + if(thisSlot.getHasStack()) { + int itemID = Item.getIdFromItem(thisSlot.getStack().getItem()); + if(itemID > 218 && itemID < 235) { + connection.sendPacket(new CPacketClickWindow(mc.player.openContainer.windowId, slot, 0, ClickType.QUICK_MOVE, thisSlot.getStack(), mc.player.openContainer.getNextTransactionID(mc.player.inventory))); + moveSlot++; + if(moveSlot == inventorySpace) slot = (byte) (sourceDoubleChest ? 54 : 27); + break; + } + } + } + } + nextTick(2); + break; + case SEARCHING_STORAGE: + if(mc.player.openContainer.windowId == 0) { + for(slot++; slot < 45; slot++) { + Slot thisSlot = mc.player.openContainer.getSlot(slot); + if(thisSlot.getHasStack()) { + int itemID = Item.getIdFromItem(thisSlot.getStack().getItem()); + if(itemID > 218 && itemID < 235) { + for(StorageUnit unit:sortLocations) { + if((unit.getName()).equals(thisSlot.getStack().getDisplayName())) { + log.debug("[AutoSort] Going to storage for: " + thisSlot.getStack().getDisplayName()); + this.unit = unit; + status = Status.GOING_TO_STORAGE; + break; + } + } + if(status == Status.GOING_TO_STORAGE) break; + else goToOverflow = true; + } + } + } + if(status == Status.GOING_TO_STORAGE) { + destination = unit.getBlockPos(); + destinationOffset = unit.getFacing(); + } else { + if(goToOverflow && overflow != null) { + status = Status.GOING_TO_OVERFLOW; + log.debug("[AutoSort] Going to overflow"); + destination = overflow; + destinationOffset = overflowFacing; + goToOverflow = false; + } else { + status = Status.GOING_TO_SOURCE; + log.debug("[AutoSort] Going to source"); + destination = source; + destinationOffset = sourceFacing; + } + } + mc.player.sendChatMessage("#goto ~" + (destination.offset(destinationOffset).getX() - (int) Math.floor(mc.player.posX)) + " ~" + (destination.getY() - (int) Math.floor(mc.player.posY)) + " ~" + (destination.offset(destinationOffset).getZ() - (int) Math.floor(mc.player.posZ))); + } + nextTick(1); + break; + case WAITING_ON_STORAGE: + if(mc.player.openContainer.windowId == 0) { + nextTick(1); + break; + } else { + if(mc.player.openContainer.getSlot(unit.doubleChest() ? 53 : 26).getHasStack()) { + mc.player.closeScreen(); + log.debug("[AutoSort] Chest full"); + if(unit.nextUp()) { + status = Status.GOING_TO_STORAGE; + } else { + sortLocations.remove(unit); + if(sortLocations.size() == 0) { + Ref.sendMessage("[AutoSort] Storage full"); + stop(); + Ref.runningActivities.remove(this); + break; + } + status = Status.SEARCHING_STORAGE; + } + nextTick(1); + break; + } else { + log.debug("Slot: " + slot + (unit.doubleChest() ? 44 : 17)); + moveSlot = (byte) (slot + (unit.doubleChest() ? 44 : 17)); + status = Status.PUTTING_SHULKERS; + log.debug("Putting shulkers: " + unit.getName()); + } + } + case PUTTING_SHULKERS: + for(moveSlot++; moveSlot < (unit.doubleChest() ? 90 : 63); moveSlot++) { + Slot thisSlot = mc.player.openContainer.getSlot(moveSlot); + if(thisSlot.getHasStack()) { + int itemID = Item.getIdFromItem(thisSlot.getStack().getItem()); + log.debug("MoveSlot: " + moveSlot); + log.debug(thisSlot.getStack().getDisplayName() + unit.getName()); + log.debug(thisSlot.getStack().getDisplayName().equals(unit.getName())); + if(itemID > 218 && itemID < 235 && thisSlot.getStack().getDisplayName().equals(unit.getName())) { + connection.sendPacket(new CPacketClickWindow(mc.player.openContainer.windowId, moveSlot, 0, ClickType.QUICK_MOVE, thisSlot.getStack(), mc.player.openContainer.getNextTransactionID(mc.player.inventory))); + break; + } + } + } + if(moveSlot == (unit.doubleChest() ? 90 : 63)) { + mc.player.closeScreen(); + status = Status.SEARCHING_STORAGE; + } else if(mc.player.openContainer.getSlot(unit.doubleChest() ? 53 : 26).getHasStack()) status = Status.WAITING_ON_STORAGE; + nextTick(2); + break; + case WAITING_ON_OVERFLOW: + if(mc.player.openContainer.windowId == 0) { + nextTick(1); + break; + } else { + slot = (byte) (overflowDoubleChest ? 53 : 26); + status = Status.DUMPING_SHULKERS; + log.debug("[AutoSort] Dumping shulkers"); + } + case DUMPING_SHULKERS: + for(slot++; slot < (overflowDoubleChest ? 90 : 63); slot++) { + Slot thisSlot = mc.player.openContainer.getSlot(slot); + if(thisSlot.getHasStack()) { + int itemID = Item.getIdFromItem(thisSlot.getStack().getItem()); + if(itemID > 218 && itemID < 235) { + connection.sendPacket(new CPacketClickWindow(mc.player.openContainer.windowId, slot, 0, ClickType.QUICK_MOVE, thisSlot.getStack(), mc.player.openContainer.getNextTransactionID(mc.player.inventory))); + break; + } + } + } + if(slot == (overflowDoubleChest ? 90 : 63)) { + mc.player.closeScreen(); + slot = 8; + status = Status.SEARCHING_STORAGE; + } else if(mc.player.openContainer.getSlot(overflowDoubleChest ? 53 : 26).getHasStack()) { + Ref.sendMessage("[AutoSort] Overflow chest full"); + stop(); + Ref.runningActivities.remove(this); + break; + } + nextTick(2); + break; + case SOURCE_EMPTY_TIMEOUT: + Slot thisSlot = mc.player.openContainer.getSlot(0); + if(thisSlot.getHasStack()) { + int itemID = Item.getIdFromItem(thisSlot.getStack().getItem()); + if(itemID > 218 && itemID < 235) { + slot = -1; + moveSlot = 0; + status = Status.TAKING_SHULKERS; + break; + } + } + mc.player.closeScreen(); + Ref.sendMessage("[AutoSort] Finished sorting"); + stop(); + Ref.runningActivities.remove(this); + break; + } + } catch(Exception e) { + Ref.sendMessage("Exception in AutoSort: " + e.getClass().getName() + (e.getMessage() == null ? "" : ": " + e.getMessage())); + log.catching(Level.ERROR, e); + stop(); + Ref.runningActivities.remove(this); + } +} +} + +@Override +public void stop() { + log.info("[AutoSort] Stopping AutoSort"); + if(status.equals(Status.GOING_TO_SOURCE) || status.equals(Status.GOING_TO_STORAGE)) mc.player.sendChatMessage("#cancel"); + TickTimer.removeListener(this); +} + +private enum Status { + GOING_TO_SOURCE, WAITING_ON_SOURCE, TAKING_SHULKERS, SEARCHING_STORAGE, GOING_TO_STORAGE, WAITING_ON_STORAGE, PUTTING_SHULKERS, GOING_TO_OVERFLOW, WAITING_ON_OVERFLOW, DUMPING_SHULKERS, SOURCE_EMPTY_TIMEOUT +} + +private void nextTick(int tick) { + nextTick = TickTimer.current() + tick; + TickTimer.add(tick); +} + +private boolean isChest(int blockID) { + return (blockID == 54 || blockID == 146); +} + +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/itemstorage/StorageUnit.java b/src/main/java/magnileve/chungamod/itemstorage/StorageUnit.java new file mode 100644 index 0000000..44e62c8 --- /dev/null +++ b/src/main/java/magnileve/chungamod/itemstorage/StorageUnit.java @@ -0,0 +1,49 @@ +package magnileve.chungamod.itemstorage; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; + +public class StorageUnit { + +private BlockPos location; +private String shulkerName; +private byte height; +private byte fillHeight; +private EnumFacing facing; +private boolean doubleChest; + +protected StorageUnit(BlockPos location, String shulkerName, byte height, EnumFacing facing, boolean doubleChest) { + this.location = location; + this.shulkerName = shulkerName; + this.height = height; + fillHeight = 0; + this.facing = facing; + this.doubleChest = doubleChest; +} + +protected String getName() { + return shulkerName; +} + +protected BlockPos getBlockPos() { + return location; +} + +protected byte getFillHeight() { + return fillHeight; +} + +protected boolean nextUp() { + fillHeight++; + return fillHeight < height; +} + +protected EnumFacing getFacing() { + return facing; +} + +protected boolean doubleChest() { + return doubleChest; +} + +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/time/Activity.java b/src/main/java/magnileve/chungamod/time/Activity.java new file mode 100644 index 0000000..a6e68f8 --- /dev/null +++ b/src/main/java/magnileve/chungamod/time/Activity.java @@ -0,0 +1,5 @@ +package magnileve.chungamod.time; + +public interface Activity { + public void stop(); +} diff --git a/src/main/java/magnileve/chungamod/time/ClientTps.java b/src/main/java/magnileve/chungamod/time/ClientTps.java new file mode 100644 index 0000000..2e0a597 --- /dev/null +++ b/src/main/java/magnileve/chungamod/time/ClientTps.java @@ -0,0 +1,31 @@ +package magnileve.chungamod.time; + +import magnileve.chungamod.Ref; + +public class ClientTps implements TickListener, Activity { + + private byte tickCount; + private long time; + + public ClientTps() { + tickCount = 0; + time = System.currentTimeMillis(); + TickTimer.addListener(this); + TickTimer.add(1); + } + @Override + public void stop() { + TickTimer.removeListener(this); + Ref.runningActivities.remove(this); + } + + @Override + public void onTick(int tick) { + tickCount++; + if(tickCount == 0) { + Ref.sendMessage("Current Client TPS: " + (1 / (((double) (System.currentTimeMillis() - time)) / 256000))); + time = System.currentTimeMillis(); + } + TickTimer.add(1); + } +} diff --git a/src/main/java/magnileve/chungamod/time/TickListener.java b/src/main/java/magnileve/chungamod/time/TickListener.java new file mode 100644 index 0000000..0edf6eb --- /dev/null +++ b/src/main/java/magnileve/chungamod/time/TickListener.java @@ -0,0 +1,5 @@ +package magnileve.chungamod.time; + +public interface TickListener { + public void onTick(int tick); +} \ No newline at end of file diff --git a/src/main/java/magnileve/chungamod/time/TickTimer.java b/src/main/java/magnileve/chungamod/time/TickTimer.java new file mode 100644 index 0000000..ac69ce6 --- /dev/null +++ b/src/main/java/magnileve/chungamod/time/TickTimer.java @@ -0,0 +1,73 @@ +package magnileve.chungamod.time; + +import java.util.LinkedList; + +import org.apache.logging.log4j.Logger; + +import magnileve.chungamod.Ref; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +@Mod.EventBusSubscriber(modid=Ref.MODID) +public class TickTimer { + +private static int tick; +private static LinkedList listenTicks; +private static LinkedList listeners; +private static Logger log; + +public static void init(Logger logger) { + tick = 0; + listenTicks = new LinkedList(); + listeners = new LinkedList(); + log = logger; +} + +@SubscribeEvent +@SideOnly(value = Side.CLIENT) +public static void onTick(ClientTickEvent event) { + tick++; + if(!listenTicks.isEmpty() && listenTicks.peekFirst() == tick) { + listenTicks.remove(); + for(TickListener listener:listeners) listener.onTick(tick); + } +} + +public static void add(int futureTicks) { + if (futureTicks > 0) { + futureTicks += tick; + int i = 0; + if(listenTicks.isEmpty()) listenTicks.add(i, futureTicks); + else for(int tickCount:listenTicks) { + if(tickCount > tick) { + listenTicks.add(i, futureTicks); + break; + } + if(tickCount == tick) break; + i++; + } + } else { + log.fatal("Trying to add a tick in the past to the tick listener"); + throw new RuntimeException("Trying to add a tick in the past to the tick listener"); + } +} + +public static void addListener(TickListener listener) { + listeners.add(listener); +} + +public static void removeListener(TickListener listener) { + for(TickListener recordedListener:listeners) if(recordedListener == listener) { + listeners.remove(listener); + break; + } +} + +public static int current() { + return tick; +} + +} \ No newline at end of file diff --git a/src/main/java/mcmod.info b/src/main/java/mcmod.info new file mode 100644 index 0000000..04a7238 --- /dev/null +++ b/src/main/java/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "chungamod", + "name": "Chungamod", + "description": "The funniest Mincerfat client", + "version": "Testing", + "mcversion": "1.12.2", + "url": "", + "updateUrl": "", + "authorList": ["Magnileve"], + "credits": "Big Chungus, the almighty Wabbit", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +] \ No newline at end of file diff --git a/src/main/java/pack.mcmeta b/src/main/java/pack.mcmeta new file mode 100644 index 0000000..4018267 --- /dev/null +++ b/src/main/java/pack.mcmeta @@ -0,0 +1,7 @@ +{ + "pack": { + "description": "examplemod resources", + "pack_format": 3, + "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)." + } +} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..04a7238 --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "chungamod", + "name": "Chungamod", + "description": "The funniest Mincerfat client", + "version": "Testing", + "mcversion": "1.12.2", + "url": "", + "updateUrl": "", + "authorList": ["Magnileve"], + "credits": "Big Chungus, the almighty Wabbit", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +] \ No newline at end of file diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..4018267 --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,7 @@ +{ + "pack": { + "description": "examplemod resources", + "pack_format": 3, + "_comment": "A pack_format of 3 should be used starting with Minecraft 1.11. All resources, including language files, should be lowercase (eg: en_us.lang). A pack_format of 2 will load your mod resources with LegacyV2Adapter, which requires language files to have uppercase letters (eg: en_US.lang)." + } +}