commit f8f76e8f249fecd748ea5f4aaa3cd2949e3c8a7d Author: Christian Knaapen Date: Sat Sep 15 11:21:21 2018 +0200 Mirror, array and quickreplace. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d341f1c --- /dev/null +++ b/.gitignore @@ -0,0 +1,43 @@ +## Based on GitHub's Eclipse .gitignore + +classes/ +run/ +.gradle/ +build/ +gradle-app.setting + +## IntelliJ IDEA + +.idea/ +*.iml +*.iws +*.ipr + +## Eclipse + +eclipse/ +*.pydevproject +.project +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.classpath +.settings/ +.loadpath + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# CDT-specific +.cproject + +# PDT-specific +.buildpath diff --git a/Logo.png b/Logo.png new file mode 100644 index 0000000..e167aa9 Binary files /dev/null and b/Logo.png differ diff --git a/Logo.xcf b/Logo.xcf new file mode 100644 index 0000000..12a229d Binary files /dev/null and b/Logo.xcf differ diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..bc2df1b --- /dev/null +++ b/build.gradle @@ -0,0 +1,77 @@ +buildscript { + repositories { + jcenter() + maven { url = "http://files.minecraftforge.net/maven" } + } + dependencies { + classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' + } +} +apply plugin: 'net.minecraftforge.gradle.forge' +//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. + + +version = "0.1.1" +group = "nl.requios.effortlessbuilding" // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = "effortlessbuilding" + +sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. +compileJava { + sourceCompatibility = targetCompatibility = '1.8' +} + +minecraft { + version = "1.12.2-14.23.4.2705" + 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 always work. + // simply re-run your setup task after changing the mappings to update your workspace. + mappings = "snapshot_20171003" + // 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 except the mcmod.info + from(sourceSets.main.resources.srcDirs) { + exclude 'mcmod.info' + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..30d399d 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..e18cba7 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Sep 14 12:28:28 PDT 2015 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-bin.zip diff --git a/gradlew b/gradlew new file mode 100644 index 0000000..91a7e26 --- /dev/null +++ b/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/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..8a0b282 --- /dev/null +++ b/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/src/main/java/nl/requios/effortlessbuilding/Array.java b/src/main/java/nl/requios/effortlessbuilding/Array.java new file mode 100644 index 0000000..d5dc1a4 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/Array.java @@ -0,0 +1,82 @@ +package nl.requios.effortlessbuilding; + +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; +import net.minecraftforge.common.util.BlockSnapshot; +import net.minecraftforge.event.world.BlockEvent; + +public class Array { + //TODO config file + public static final int MAX_COUNT = 100; + + public static class ArraySettings{ + public boolean enabled = false; + public BlockPos offset = BlockPos.ORIGIN; + public int count = 5; + + public ArraySettings(){ + } + + public ArraySettings(boolean enabled, BlockPos offset, int count) { + this.enabled = enabled; + this.offset = offset; + this.count = count; + } + } + + //Called from EventHandler + public static void onBlockPlaced(BlockEvent.PlaceEvent event) { + if (event.getWorld().isRemote) return; + + //find arraysettings for the player that placed the block + ArraySettings a = BuildSettingsManager.getBuildSettings(event.getPlayer()).getArraySettings(); + if (a == null || !a.enabled) return; + + if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return; + + BlockPos pos = event.getPos(); + Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ()); + for (int i = 0; i < a.count; i++) { + pos = pos.add(offset); + if (event.getWorld().isBlockLoaded(pos, true)) { + event.getWorld().setBlockState(pos, event.getPlacedBlock()); + + //Mirror synergy + BlockSnapshot blockSnapshot = new BlockSnapshot(event.getWorld(), pos, event.getPlacedBlock()); + BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, event.getPlacedBlock(), event.getPlayer(), EnumHand.MAIN_HAND); + Mirror.onBlockPlaced(placeEvent); + } + } + } + + //Called from EventHandler + public static void onBlockBroken(BlockEvent.BreakEvent event) { + if (event.getWorld().isRemote) return; + + //find arraysettings for the player that placed the block + ArraySettings a = BuildSettingsManager.getBuildSettings(event.getPlayer()).getArraySettings(); + if (a == null || !a.enabled) return; + + if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return; + + BlockPos pos = event.getPos(); + Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ()); + for (int i = 0; i < a.count; i++) { + pos = pos.add(offset); + if (event.getWorld().isBlockLoaded(pos, false)) { + event.getWorld().setBlockToAir(pos); + + //Mirror synergy + BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(event.getWorld(), pos, event.getState(), event.getPlayer()); + Mirror.onBlockBroken(breakEvent); + } + } + } + +// @SubscribeEvent +// @SideOnly(Side.CLIENT) +// public static void onRender(RenderWorldLastEvent event) { +// +// } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/BuildSettingsManager.java b/src/main/java/nl/requios/effortlessbuilding/BuildSettingsManager.java new file mode 100644 index 0000000..8b4dbcb --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/BuildSettingsManager.java @@ -0,0 +1,102 @@ +package nl.requios.effortlessbuilding; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.PlayerEvent; +import nl.requios.effortlessbuilding.capability.BuildModifierCapability; +import nl.requios.effortlessbuilding.network.BuildSettingsMessage; + +@Mod.EventBusSubscriber +public class BuildSettingsManager { + + public static BuildSettings getBuildSettings(EntityPlayer player){ + if (player.hasCapability(BuildModifierCapability.buildModifier, null)) { + BuildModifierCapability.IBuildModifier capability = player.getCapability(BuildModifierCapability.buildModifier, null); + return capability.getBuildModifierData(); + } + EffortlessBuilding.log("buildsettings is null"); + return null; + } + + public static void setBuildSettings(EntityPlayer player, BuildSettings buildSettings) { + if (player == null) { + EffortlessBuilding.log("cannot set buildsettings, player is null"); + return; + } + if (player.hasCapability(BuildModifierCapability.buildModifier, null)) { + BuildModifierCapability.IBuildModifier capability = player.getCapability(BuildModifierCapability.buildModifier, null); + capability.setBuildModifierData(buildSettings); + } else { + EffortlessBuilding.log(player, "Saving buildsettings failed."); + } + } + + public static class BuildSettings { + private Mirror.MirrorSettings mirrorSettings; + private Array.ArraySettings arraySettings; + private boolean quickReplace = false; + + public BuildSettings() { + mirrorSettings = new Mirror.MirrorSettings(); + arraySettings = new Array.ArraySettings(); + } + + public BuildSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings, boolean quickReplace) { + this.mirrorSettings = mirrorSettings; + this.arraySettings = arraySettings; + this.quickReplace = quickReplace; + } + + public Mirror.MirrorSettings getMirrorSettings() { + return mirrorSettings; + } + + public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) { + this.mirrorSettings = mirrorSettings; + } + + public Array.ArraySettings getArraySettings() { + return arraySettings; + } + + public void setArraySettings(Array.ArraySettings arraySettings) { + this.arraySettings = arraySettings; + } + + public boolean doQuickReplace() { + return quickReplace; + } + + public void setQuickReplace(boolean quickReplace) { + this.quickReplace = quickReplace; + } + } + + @SubscribeEvent + public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { + EntityPlayer player = event.player; + handleNewPlayer(player); + } + + @SubscribeEvent + public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { + EntityPlayer player = event.player; + handleNewPlayer(player); + } + + private static void handleNewPlayer(EntityPlayer player){ + if (getBuildSettings(player) == null) { + setBuildSettings(player, new BuildSettings()); + } + + //Only on server + if (!player.world.isRemote) { + //Send to client + BuildSettingsMessage msg = new BuildSettingsMessage(getBuildSettings(player)); + EffortlessBuilding.packetHandler.sendTo(msg, (EntityPlayerMP) player); + } + } +} + diff --git a/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java new file mode 100644 index 0000000..baa2732 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/EffortlessBuilding.java @@ -0,0 +1,106 @@ +package nl.requios.effortlessbuilding; + +import net.minecraft.block.Block; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.util.text.TextComponentString; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.network.NetworkRegistry; +import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper; +import net.minecraftforge.fml.relauncher.Side; +import nl.requios.effortlessbuilding.capability.*; +import nl.requios.effortlessbuilding.inventory.RandomizerGuiHandler; +import nl.requios.effortlessbuilding.item.ItemRandomizerBag; +import nl.requios.effortlessbuilding.network.BuildSettingsMessage; +import nl.requios.effortlessbuilding.network.QuickReplaceMessage; +import nl.requios.effortlessbuilding.proxy.IProxy; +import org.apache.logging.log4j.Logger; + +@Mod(modid = EffortlessBuilding.MODID, name = EffortlessBuilding.NAME, version = EffortlessBuilding.VERSION) +@Mod.EventBusSubscriber +public class EffortlessBuilding +{ + public static final String MODID = "effortlessbuilding"; + public static final String NAME = "Effortless Building"; + public static final String VERSION = "0.1.2"; + + @Mod.Instance(EffortlessBuilding.MODID) + public static EffortlessBuilding instance; + + public static Logger logger; + + @SidedProxy( + clientSide="nl.requios.effortlessbuilding.proxy.ClientProxy", + serverSide="nl.requios.effortlessbuilding.proxy.ServerProxy" + ) + public static IProxy proxy; + + public static final SimpleNetworkWrapper packetHandler = NetworkRegistry.INSTANCE.newSimpleChannel(EffortlessBuilding.MODID); + + public static final Block[] BLOCKS = { + }; + + public static final Item[] ITEMS = { + new ItemRandomizerBag() + }; + + public static final int RANDOMIZER_BAG_GUI = 0; + + @EventHandler + // preInit "Run before anything else. Read your config, create blocks, items, etc, and register them with the GameRegistry." + public void preInit(FMLPreInitializationEvent event) + { + logger = event.getModLog(); + + CapabilityManager.INSTANCE.register(BuildModifierCapability.IBuildModifier.class, new BuildModifierCapability.Storage(), BuildModifierCapability.BuildModifier.class); + + EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.SERVER); + EffortlessBuilding.packetHandler.registerMessage(BuildSettingsMessage.MessageHandler.class, BuildSettingsMessage.class, 0, Side.CLIENT); + + EffortlessBuilding.packetHandler.registerMessage(QuickReplaceMessage.MessageHandler.class, QuickReplaceMessage.class, 1, Side.SERVER); + EffortlessBuilding.packetHandler.registerMessage(QuickReplaceMessage.MessageHandler.class, QuickReplaceMessage.class, 1, Side.CLIENT); + + proxy.preInit(event); + } + + @EventHandler + // Do your mod setup. Build whatever data structures you care about. + // Register network handlers + public void init(FMLInitializationEvent event) + { + NetworkRegistry.INSTANCE.registerGuiHandler(EffortlessBuilding.instance, new RandomizerGuiHandler()); + proxy.init(event); + } + + @EventHandler + // postInit "Handle interaction with other mods, complete your setup based on this." + public void postInit(FMLPostInitializationEvent event) + { + proxy.postInit(event); + } + + @EventHandler + public void serverStarting(FMLServerStartingEvent event) + { + proxy.serverStarting(event); + } + + public static void log(String msg){ + logger.info(msg); + } + + public static void log(EntityPlayer player, String msg){ + log(player, msg, false); + } + + public static void log(EntityPlayer player, String msg, boolean actionBar){ + player.sendStatusMessage(new TextComponentString(msg), actionBar); + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/EventHandler.java b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java new file mode 100644 index 0000000..aaadd48 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/EventHandler.java @@ -0,0 +1,59 @@ +package nl.requios.effortlessbuilding; + +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemBlock; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import nl.requios.effortlessbuilding.capability.BuildModifierCapability; + +@Mod.EventBusSubscriber +public class EventHandler +{ + @SubscribeEvent + public static void registerBlocks(RegistryEvent.Register event) + { + event.getRegistry().registerAll(EffortlessBuilding.BLOCKS); + } + + @SubscribeEvent + public static void registerItems(RegistryEvent.Register event) + { + event.getRegistry().registerAll(EffortlessBuilding.ITEMS); + + for (Block block : EffortlessBuilding.BLOCKS) + { + event.getRegistry().register(new ItemBlock(block).setRegistryName(block.getRegistryName())); + } + } + + @SubscribeEvent + public static void attachCapabilities(AttachCapabilitiesEvent event) { + if (event.getObject() instanceof EntityPlayer) { + event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "BuildModifier"), new BuildModifierCapability.Provider()); + } + } + + + @SubscribeEvent + public static void onBlockPlaced(BlockEvent.PlaceEvent event) { + QuickReplace.onBlockPlaced(event); + if (event.isCanceled()) return; + Array.onBlockPlaced(event); + Mirror.onBlockPlaced(event); + } + + + @SubscribeEvent + public static void onBlockBroken(BlockEvent.BreakEvent event) { + Array.onBlockBroken(event); + Mirror.onBlockBroken(event); + } + +} diff --git a/src/main/java/nl/requios/effortlessbuilding/Mirror.java b/src/main/java/nl/requios/effortlessbuilding/Mirror.java new file mode 100644 index 0000000..5a4b939 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/Mirror.java @@ -0,0 +1,401 @@ +package nl.requios.effortlessbuilding; + +import net.minecraft.block.BlockDirectional; +import net.minecraft.block.BlockDispenser; +import net.minecraft.block.BlockStairs; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.event.world.BlockEvent; +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 org.lwjgl.opengl.GL11; +import org.lwjgl.util.Color; + +@Mod.EventBusSubscriber +public class Mirror { + + //TODO config file + public static final int MAX_RADIUS = 200; + + private static final Color colorX = new Color(255, 72, 52); + private static final Color colorY = new Color(67, 204, 51); + private static final Color colorZ = new Color(52, 247, 255); + private static final int lineAlpha = 200; + private static final int planeAlpha = 75; + private static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting + + + public static class MirrorSettings { + public boolean enabled = false; + public Vec3d position = new Vec3d(0.5, 64.5, 0.5); + public boolean mirrorX = true, mirrorY = false, mirrorZ = false; + public int radius = 20; + public boolean drawLines = true, drawPlanes = false; + + public MirrorSettings() { + } + + public MirrorSettings(boolean mirrorEnabled, Vec3d position, boolean mirrorX, boolean mirrorY, boolean mirrorZ, int radius, boolean drawLines, boolean drawPlanes) { + this.enabled = mirrorEnabled; + this.position = position; + this.mirrorX = mirrorX; + this.mirrorY = mirrorY; + this.mirrorZ = mirrorZ; + this.radius = radius; + this.drawLines = drawLines; + this.drawPlanes = drawPlanes; + } + } + + //Called from EventHandler + public static void onBlockPlaced(BlockEvent.PlaceEvent event) { + if (event.getWorld().isRemote) return; + + //find mirrorsettings for the player that placed the block + MirrorSettings m = BuildSettingsManager.getBuildSettings(event.getPlayer()).getMirrorSettings(); + if (m == null) return; + + if (!m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return; + + //if within mirror distance, mirror + BlockPos oldBlockPos = event.getPos(); + + if (oldBlockPos.getX() + 0.5 < m.position.x - m.radius || oldBlockPos.getX() + 0.5 > m.position.x + m.radius || + oldBlockPos.getY() + 0.5 < m.position.y - m.radius || oldBlockPos.getY() + 0.5 > m.position.y + m.radius || + oldBlockPos.getZ() + 0.5 < m.position.z - m.radius || oldBlockPos.getZ() + 0.5 > m.position.z+ m.radius) + return; + + if (m.mirrorX) { + placeMirrorX(event.getWorld(), m, oldBlockPos, event.getPlacedBlock()); + } + + if (m.mirrorY) { + placeMirrorY(event.getWorld(), m, oldBlockPos, event.getPlacedBlock()); + } + + if (m.mirrorZ) { + placeMirrorZ(event.getWorld(), m, oldBlockPos, event.getPlacedBlock()); + } + } + + private static void placeMirrorX(World world, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState) { + //find mirror position + double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5); + BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ()); + IBlockState newBlockState = oldBlockState; + //place block + if (world.isBlockLoaded(newBlockPos, true)) { + newBlockState = oldBlockState.withMirror(net.minecraft.util.Mirror.FRONT_BACK); + + world.setBlockState(newBlockPos, newBlockState); + } + if (m.mirrorY) placeMirrorY(world, m, newBlockPos, newBlockState); + if (m.mirrorZ) placeMirrorZ(world, m, newBlockPos, newBlockState); + } + + private static void placeMirrorY(World world, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState) { + //find mirror position + double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5); + BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ()); + IBlockState newBlockState = oldBlockState; + //place block + if (world.isBlockLoaded(newBlockPos, true)) { + newBlockState = getVerticalMirror(oldBlockState); + + world.setBlockState(newBlockPos, newBlockState); + } + if (m.mirrorZ) placeMirrorZ(world, m, newBlockPos, newBlockState); + } + + private static void placeMirrorZ(World world, MirrorSettings m, BlockPos oldBlockPos, IBlockState oldBlockState) { + //find mirror position + double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); + BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z); + IBlockState newBlockState = oldBlockState; + //place block + if (world.isBlockLoaded(newBlockPos, true)) { + newBlockState = oldBlockState.withMirror(net.minecraft.util.Mirror.LEFT_RIGHT); + + world.setBlockState(newBlockPos, newBlockState); + } + } + + private static IBlockState getVerticalMirror(IBlockState blockState) { + //Stairs + if (blockState.getBlock() instanceof BlockStairs) { + if (blockState.getValue(BlockStairs.HALF) == BlockStairs.EnumHalf.BOTTOM) { + return blockState.withProperty(BlockStairs.HALF, BlockStairs.EnumHalf.TOP); + } else { + return blockState.withProperty(BlockStairs.HALF, BlockStairs.EnumHalf.BOTTOM); + } + } + + //Buttons, endrod, observer, piston + if (blockState.getBlock() instanceof BlockDirectional) { + if (blockState.getValue(BlockDirectional.FACING) == EnumFacing.DOWN) { + return blockState.withProperty(BlockDirectional.FACING, EnumFacing.UP); + } else if (blockState.getValue(BlockDirectional.FACING) == EnumFacing.UP) { + return blockState.withProperty(BlockDirectional.FACING, EnumFacing.DOWN); + } + } + + //Dispenser, dropper + if (blockState.getBlock() instanceof BlockDispenser) { + if (blockState.getValue(BlockDispenser.FACING) == EnumFacing.DOWN) { + return blockState.withProperty(BlockDispenser.FACING, EnumFacing.UP); + } else if (blockState.getValue(BlockDispenser.FACING) == EnumFacing.UP) { + return blockState.withProperty(BlockDispenser.FACING, EnumFacing.DOWN); + } + } + + return blockState; + } + + //Called from EventHandler + public static void onBlockBroken(BlockEvent.BreakEvent event) { + if (event.getWorld().isRemote) return; + + //find mirrorsettings for the player that broke the block + MirrorSettings m = BuildSettingsManager.getBuildSettings(event.getPlayer()).getMirrorSettings(); + if (m == null) return; + + if (!m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return; + + //if within mirror distance, break mirror block + BlockPos oldBlockPos = event.getPos(); + + if (oldBlockPos.getX() + 0.5 < m.position.x - m.radius || oldBlockPos.getX() + 0.5 > m.position.x + m.radius || + oldBlockPos.getY() + 0.5 < m.position.y - m.radius || oldBlockPos.getY() + 0.5 > m.position.y + m.radius || + oldBlockPos.getZ() + 0.5 < m.position.z - m.radius || oldBlockPos.getZ() + 0.5 > m.position.z+ m.radius) + return; + + if (m.mirrorX) { + breakMirrorX(event, m, oldBlockPos); + } + + if (m.mirrorY) { + breakMirrorY(event, m, oldBlockPos); + } + + if (m.mirrorZ) { + breakMirrorZ(event, m, oldBlockPos); + } + } + + private static void breakMirrorX(BlockEvent.BreakEvent event, MirrorSettings m, BlockPos oldBlockPos) { + //find mirror position + double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5); + BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ()); + //break block + if (event.getWorld().isBlockLoaded(newBlockPos, true)) { + event.getWorld().setBlockToAir(newBlockPos); + } + if (m.mirrorY) breakMirrorY(event, m, newBlockPos); + if (m.mirrorZ) breakMirrorZ(event, m, newBlockPos); + } + + private static void breakMirrorY(BlockEvent.BreakEvent event, MirrorSettings m, BlockPos oldBlockPos) { + //find mirror position + double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5); + BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ()); + //place block + if (event.getWorld().isBlockLoaded(newBlockPos, true)) { + event.getWorld().setBlockToAir(newBlockPos); + } + if (m.mirrorZ) breakMirrorZ(event, m, newBlockPos); + } + + private static void breakMirrorZ(BlockEvent.BreakEvent event, MirrorSettings m, BlockPos oldBlockPos) { + //find mirror position + double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); + BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z); + //place block + if (event.getWorld().isBlockLoaded(newBlockPos, true)) { + event.getWorld().setBlockToAir(newBlockPos); + } + } + + @SubscribeEvent + @SideOnly(Side.CLIENT) + public static void onRender(RenderWorldLastEvent event) { + EntityPlayerSP player = Minecraft.getMinecraft().player; + BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); + if (buildSettings == null) return; + MirrorSettings m = buildSettings.getMirrorSettings(); + + if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return; + + Vec3d playerPos = new Vec3d(player.posX, player.posY, player.posZ); + Vec3d pos = m.position.add(epsilon); + int radius = m.radius; + + if (m.mirrorX) { + Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius); + Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius); + + drawMirrorPlane(playerPos, posA, posB, colorX, m.drawLines, m.drawPlanes); + } + if (m.mirrorY) { + Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius); + Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius); + + drawMirrorPlaneY(playerPos, posA, posB, colorY, m.drawLines, m.drawPlanes); + } + if (m.mirrorZ) { + Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z); + Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z); + + drawMirrorPlane(playerPos, posA, posB, colorZ, m.drawLines, m.drawPlanes); + } + + //Draw axis coordinated colors if two or more axes are enabled + //(If only one is enabled the lines are that planes color) + if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) { + drawMirrorLines(playerPos, m); + } + } + + @SideOnly(Side.CLIENT) + public static void drawMirrorPlane(Vec3d playerPos, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) { + + GL11.glPushAttrib(GL11.GL_ENABLE_BIT); + GL11.glPushMatrix(); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_TEXTURE_2D); + + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z); + + GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha); + GL11.glLineWidth(2); + GL11.glDepthMask(false); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + if (drawPlanes) { + bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posA.x, posB.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posB.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + + tessellator.draw(); + } + + if (drawLines) { + Vec3d middle = posA.add(posB).scale(0.5); + bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(posA.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(posB.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(middle.x, posA.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(middle.x, posB.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + + tessellator.draw(); + } + + GL11.glDepthMask(true); + GL11.glPopMatrix(); + GL11.glPopAttrib(); + } + + @SideOnly(Side.CLIENT) + public static void drawMirrorPlaneY(Vec3d playerPos, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) { + + GL11.glPushAttrib(GL11.GL_ENABLE_BIT); + GL11.glPushMatrix(); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_TEXTURE_2D); + + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z); + + GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()); + GL11.glLineWidth(2); + GL11.glDepthMask(false); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + if (drawPlanes) { + bufferBuilder.begin(GL11.GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(posA.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posA.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posA.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + bufferBuilder.pos(posB.x, posA.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); + + tessellator.draw(); + } + + if (drawLines) { + Vec3d middle = posA.add(posB).scale(0.5); + bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(middle.x, middle.y, posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(middle.x, middle.y, posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(posA.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(posB.x, middle.y, middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); + + tessellator.draw(); + } + + GL11.glDepthMask(true); + GL11.glPopMatrix(); + GL11.glPopAttrib(); + } + + @SideOnly(Side.CLIENT) + public static void drawMirrorLines(Vec3d playerPos, MirrorSettings m) { + + Vec3d pos = m.position.add(epsilon); + + GL11.glPushAttrib(GL11.GL_ENABLE_BIT); + GL11.glPushMatrix(); + GL11.glDisable(GL11.GL_CULL_FACE); + GL11.glDisable(GL11.GL_LIGHTING); + GL11.glDisable(GL11.GL_TEXTURE_2D); + + GL11.glEnable(GL11.GL_BLEND); + GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + GL11.glTranslated(-playerPos.x, -playerPos.y, -playerPos.z); + + GL11.glColor4d(100, 100, 100, 255); + GL11.glLineWidth(2); + GL11.glDepthMask(false); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferBuilder = tessellator.getBuffer(); + + bufferBuilder.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION_COLOR); + + bufferBuilder.pos(pos.x - m.radius, pos.y, pos.z).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x + m.radius, pos.y, pos.z).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y - m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y + m.radius, pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y, pos.z - m.radius).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); + bufferBuilder.pos(pos.x, pos.y, pos.z + m.radius).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); + + tessellator.draw(); + + GL11.glDepthMask(true); + GL11.glPopMatrix(); + GL11.glPopAttrib(); + } + + +} diff --git a/src/main/java/nl/requios/effortlessbuilding/QuickReplace.java b/src/main/java/nl/requios/effortlessbuilding/QuickReplace.java new file mode 100644 index 0000000..023b1d6 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/QuickReplace.java @@ -0,0 +1,61 @@ +package nl.requios.effortlessbuilding; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.common.util.BlockSnapshot; +import net.minecraftforge.event.world.BlockEvent; +import nl.requios.effortlessbuilding.network.QuickReplaceMessage; + +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.UUID; + +public class QuickReplace { + //Dilemma in getting blockstate from event to when message is received: + // 1) send via client. Then hacking makes it possible to place any block. + // 2) save serverside. Messages may not be received chronologically so data could get switched. + //Solution for now: save blockstate per player. Messages from 1 player will rarely come unchronologically + //and players will rarely switch between blocks that quickly. + + private static Dictionary blockStates = new Hashtable<>(); + + public static void onBlockPlaced(BlockEvent.PlaceEvent event) { + if (event.getWorld().isRemote) return; + //Only serverside + + BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(event.getPlayer()); + if (!buildSettings.doQuickReplace()) return; + + //TODO base on player facing instead, no more messages (or break block clientside) + + blockStates.put(event.getPlayer().getUniqueID(), event.getPlacedBlock()); + + //RayTraceResult result = event.getWorld().rayTraceBlocks(event.getPlayer().getPositionEyes(1f), event.getPlayer().getLookVec()); + EffortlessBuilding.packetHandler.sendTo(new QuickReplaceMessage(), (EntityPlayerMP) event.getPlayer()); + + event.setCanceled(true); + } + + public static void onMessageReceived(EntityPlayer player, QuickReplaceMessage message) { + BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); + if (!buildSettings.doQuickReplace()) return; + + //TODO check for bedrock, end portal etc in survival + + if (!message.isBlockHit() || message.getBlockPos() == null) return; + + BlockPos placedAgainstBlockPos = message.getBlockPos(); + //placedAgainstBlockPos = placedAgainstBlockPos.down(); + IBlockState blockState = blockStates.get(player.getUniqueID()); + player.world.setBlockState(placedAgainstBlockPos, blockState); + + //Mirror and Array synergy + BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, placedAgainstBlockPos, blockState); + BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, EnumHand.MAIN_HAND); + Array.onBlockPlaced(placeEvent); + Mirror.onBlockPlaced(placeEvent); + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/capability/BuildModifierCapability.java b/src/main/java/nl/requios/effortlessbuilding/capability/BuildModifierCapability.java new file mode 100644 index 0000000..f1b8a3a --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/capability/BuildModifierCapability.java @@ -0,0 +1,138 @@ +package nl.requios.effortlessbuilding.capability; + +import net.minecraft.nbt.NBTBase; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityInject; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import nl.requios.effortlessbuilding.Array; +import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings; +import nl.requios.effortlessbuilding.Mirror; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +@Mod.EventBusSubscriber +public class BuildModifierCapability { + + @CapabilityInject(IBuildModifier.class) + public final static Capability buildModifier = null; + + public interface IBuildModifier { + BuildSettings getBuildModifierData(); + + void setBuildModifierData(BuildSettings buildSettings); + } + + public static class BuildModifier implements IBuildModifier { + private BuildSettings buildSettings; + + @Override + public BuildSettings getBuildModifierData() { + return buildSettings; + } + + @Override + public void setBuildModifierData(BuildSettings buildSettings) { + this.buildSettings = buildSettings; + } + } + + public static class Storage implements Capability.IStorage { + @Override + public NBTBase writeNBT(Capability capability, IBuildModifier instance, EnumFacing side) { + NBTTagCompound compound = new NBTTagCompound(); + BuildSettings buildSettings = instance.getBuildModifierData(); + + //MIRROR + Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); + compound.setBoolean("mirrorEnabled", m.enabled); + compound.setDouble("mirrorPosX", m.position.x); + compound.setDouble("mirrorPosY", m.position.y); + compound.setDouble("mirrorPosZ", m.position.z); + compound.setBoolean("mirrorX", m.mirrorX); + compound.setBoolean("mirrorY", m.mirrorY); + compound.setBoolean("mirrorZ", m.mirrorZ); + compound.setInteger("mirrorRadius", m.radius); + compound.setBoolean("mirrorDrawLines", m.drawLines); + compound.setBoolean("mirrorDrawPlanes", m.drawPlanes); + + //ARRAY + Array.ArraySettings a = buildSettings.getArraySettings(); + compound.setBoolean("arrayEnabled", a.enabled); + compound.setInteger("arrayOffsetX", a.offset.getX()); + compound.setInteger("arrayOffsetY", a.offset.getY()); + compound.setInteger("arrayOffsetZ", a.offset.getZ()); + compound.setInteger("arrayCount", a.count); + + //compound.setBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace + return compound; + } + + @Override + public void readNBT(Capability capability, IBuildModifier instance, EnumFacing side, NBTBase nbt) { + NBTTagCompound compound = (NBTTagCompound) nbt; + + //MIRROR + boolean mirrorEnabled = compound.getBoolean("mirrorEnabled"); + Vec3d mirrorPosition = new Vec3d(compound.getDouble("mirrorPosX"), compound.getDouble("mirrorPosY"), compound.getDouble("mirrorPosZ")); + boolean mirrorX = compound.getBoolean("mirrorX"); + boolean mirrorY = compound.getBoolean("mirrorY"); + boolean mirrorZ = compound.getBoolean("mirrorZ"); + int mirrorRadius = compound.getInteger("mirrorRadius"); + boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines"); + boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes"); + Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes); + + //ARRAY + boolean arrayEnabled = compound.getBoolean("arrayEnabled"); + BlockPos arrayOffset = new BlockPos(compound.getInteger("arrayOffsetX"), compound.getInteger("arrayOffsetY"), compound.getInteger("arrayOffsetZ")); + int arrayCount = compound.getInteger("arrayCount"); + Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); + + //boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace + + BuildSettings buildSettings = new BuildSettings(mirrorSettings, arraySettings, false); + instance.setBuildModifierData(buildSettings); + } + } + + public static class Provider implements ICapabilitySerializable { + IBuildModifier inst = buildModifier.getDefaultInstance(); + + @Override + public boolean hasCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { + return capability == buildModifier; + } + + @Override + public T getCapability(@Nonnull Capability capability, @Nullable EnumFacing facing) { + if (capability == buildModifier) return buildModifier.cast(inst); + return null; + } + + @Override + public NBTBase serializeNBT() { + return buildModifier.getStorage().writeNBT(buildModifier, inst, null); + } + + @Override + public void deserializeNBT(NBTBase nbt) { + buildModifier.getStorage().readNBT(buildModifier, inst, null, nbt); + } + } + + // Allows for the capability to persist after death. + @SubscribeEvent + public static void clonePlayer(PlayerEvent.Clone event) { + IBuildModifier original = event.getOriginal().getCapability(buildModifier, null); + IBuildModifier clone = event.getEntity().getCapability(buildModifier, null); + clone.setBuildModifierData(original.getBuildModifierData()); + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/gui/SettingsGui.java b/src/main/java/nl/requios/effortlessbuilding/gui/SettingsGui.java new file mode 100644 index 0000000..13766c5 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/gui/SettingsGui.java @@ -0,0 +1,314 @@ +package nl.requios.effortlessbuilding.gui; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.client.config.GuiCheckBox; +import nl.requios.effortlessbuilding.Array; +import nl.requios.effortlessbuilding.BuildSettingsManager; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.Mirror; +import nl.requios.effortlessbuilding.network.BuildSettingsMessage; +import nl.requios.effortlessbuilding.proxy.ClientProxy; +import org.lwjgl.input.Keyboard; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class SettingsGui extends GuiScreen { + + protected List textFieldList = new ArrayList<>(); + + protected List mirrorButtonList = new ArrayList<>(); + protected List mirrorTextFieldList = new ArrayList<>(); + protected List arrayTextFieldList = new ArrayList<>(); + + private GuiTextField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius; + private GuiCheckBox buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ; + private GuiButton buttonDrawPlanes, buttonDrawLines; + private boolean drawPlanes, drawLines; + private GuiButton buttonCurrentPosition, buttonClose; + + private GuiCheckBox buttonArrayEnabled; + private GuiTextField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount; + + private int left, right, top, bottom; + + @Override + //Create buttons and labels and add them to buttonList/labelList + public void initGui() { + int id = 0; + left = width / 2 - 140; + right = width / 2 + 140; + top = height / 2 - 100; + bottom = height / 2 + 100; + + //MIRROR + int y = top - 2; + buttonMirrorEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false); + buttonList.add(buttonMirrorEnabled); + + y = top + 18; + textMirrorPosX = new GuiTextField(id++, fontRenderer, left + 70, y, 50, 18); + textMirrorPosX.setText("0.5"); + mirrorTextFieldList.add(textMirrorPosX); + + textMirrorPosY = new GuiTextField(id++, fontRenderer, left + 140, y, 50, 18); + textMirrorPosY.setText("64.5"); + mirrorTextFieldList.add(textMirrorPosY); + + textMirrorPosZ = new GuiTextField(id++, fontRenderer, left + 210, y, 50, 18); + textMirrorPosZ.setText("0.5"); + mirrorTextFieldList.add(textMirrorPosZ); + + y = top + 50; + buttonMirrorX = new GuiCheckBox(id++, left + 60, y, " X", true); + mirrorButtonList.add(buttonMirrorX); + + buttonMirrorY = new GuiCheckBox(id++, left + 100, y, " Y", false); + mirrorButtonList.add(buttonMirrorY); + + buttonMirrorZ = new GuiCheckBox(id++, left + 140, y, " Z", false); + mirrorButtonList.add(buttonMirrorZ); + + y = top + 47; + textMirrorRadius = new GuiTextField(id++, fontRenderer, left + 220, y, 60, 18); + textMirrorRadius.setText("50"); + mirrorTextFieldList.add(textMirrorRadius); + + y = top + 72; + buttonCurrentPosition = new GuiButton(id++, left + 5, y, 110, 20, "Set to current pos"); + mirrorButtonList.add(buttonCurrentPosition); + + buttonDrawLines = new GuiButton(id++, left + 127, y, 70, 20, "Show lines"); + mirrorButtonList.add(buttonDrawLines); + + buttonDrawPlanes = new GuiButton(id++, left + 209, y, 75, 20, "Show area"); + mirrorButtonList.add(buttonDrawPlanes); + + //ARRAY + y = top + 100; + buttonArrayEnabled = new GuiCheckBox(id++, left - 15 + 8, y, "", false); + buttonList.add(buttonArrayEnabled); + + y = top + 120; + textArrayOffsetX = new GuiTextField(id++, fontRenderer, left + 70, y, 50, 18); + textArrayOffsetX.setText("0"); + arrayTextFieldList.add(textArrayOffsetX); + + textArrayOffsetY = new GuiTextField(id++, fontRenderer, left + 140, y, 50, 18); + textArrayOffsetY.setText("0"); + arrayTextFieldList.add(textArrayOffsetY); + + textArrayOffsetZ = new GuiTextField(id++, fontRenderer, left + 210, y, 50, 18); + textArrayOffsetZ.setText("0"); + arrayTextFieldList.add(textArrayOffsetZ); + + y = top + 150; + textArrayCount = new GuiTextField(id++, fontRenderer, left + 55, y, 50, 18); + textArrayCount.setText("5"); + arrayTextFieldList.add(textArrayCount); + + //CLOSE + y = height - 40; + buttonClose = new GuiButton(id++, width / 2 - 100, y, "Close"); + buttonList.add(buttonClose); + + BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); + if (buildSettings != null) { + //MIRROR + Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); + buttonMirrorEnabled.setIsChecked(m.enabled); + textMirrorPosX.setText(String.valueOf(m.position.x)); + textMirrorPosY.setText(String.valueOf(m.position.y)); + textMirrorPosZ.setText(String.valueOf(m.position.z)); + buttonMirrorX.setIsChecked(m.mirrorX); + buttonMirrorY.setIsChecked(m.mirrorY); + buttonMirrorZ.setIsChecked(m.mirrorZ); + textMirrorRadius.setText(String.valueOf(m.radius)); + drawLines = m.drawLines; + drawPlanes = m.drawPlanes; + buttonDrawLines.displayString = drawLines ? "Hide lines" : "Show lines"; + buttonDrawPlanes.displayString = drawPlanes ? "Hide area" : "Show area"; + + //ARRAY + Array.ArraySettings a = buildSettings.getArraySettings(); + buttonArrayEnabled.setIsChecked(a.enabled); + textArrayOffsetX.setText(String.valueOf(a.offset.getX())); + textArrayOffsetY.setText(String.valueOf(a.offset.getY())); + textArrayOffsetZ.setText(String.valueOf(a.offset.getZ())); + textArrayCount.setText(String.valueOf(a.count)); + } + + buttonList.addAll(mirrorButtonList); + textFieldList.addAll(mirrorTextFieldList); + textFieldList.addAll(arrayTextFieldList); + } + + @Override + //Process general logic, i.e. hide buttons + public void updateScreen() { + textFieldList.forEach(GuiTextField::updateCursorCounter); + } + + @Override + //Set colors using GL11, use the fontRendererObj field to display text + //Use drawTexturedModalRect() to transfers areas of a texture resource to the screen + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + this.drawDefaultBackground(); + + int y = top; + int offset = 8; + + buttonMirrorEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks); + if (buttonMirrorEnabled.isChecked()) { + fontRenderer.drawString("Mirror enabled", left + offset, y, 0xFFFFFF, true); + + y = top + 18 + 5; + fontRenderer.drawString("Position", left + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("X", left + 50 + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("Y", left + 120 + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("Z", left + 190 + offset, y, 0xFFFFFF, true); + + y = top + 52; + fontRenderer.drawString("Direction", left + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("Size", left + 190, y, 0xFFFFFF, true); + + mirrorButtonList.forEach(button -> button.drawButton(this.mc, mouseX, mouseY, partialTicks)); + mirrorTextFieldList.forEach(textField -> textField.drawTextBox()); + } else { + fontRenderer.drawString("Mirror disabled", left + offset, y, 0x999999, true); + } + + y = top + 100 + 2; + buttonArrayEnabled.drawButton(this.mc, mouseX, mouseY, partialTicks); + if (buttonArrayEnabled.isChecked()) { + fontRenderer.drawString("Array enabled", left + offset, y, 0xFFFFFF, true); + + y = top + 120 + 5; + fontRenderer.drawString("Offset", left + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("X", left + 50 + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("Y", left + 120 + offset, y, 0xFFFFFF, true); + fontRenderer.drawString("Z", left + 190 + offset, y, 0xFFFFFF, true); + + y = top + 150 + 5; + fontRenderer.drawString("Count", left + offset, y, 0xFFFFFF, true); + + arrayTextFieldList.forEach(textField -> textField.drawTextBox()); + } else { + fontRenderer.drawString("Array disabled", left + offset, y, 0x999999, true); + } + + buttonClose.drawButton(this.mc, mouseX, mouseY, partialTicks); + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + super.keyTyped(typedChar, keyCode); + if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK || keyCode == Keyboard.KEY_DELETE) { + for (GuiTextField textField : textFieldList) { + if (textField.isFocused()) { + textField.textboxKeyTyped(typedChar, keyCode); + } + } + } + if (keyCode == ClientProxy.keyBindings[0].getKeyCode()) { + Minecraft.getMinecraft().player.closeScreen(); + } + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + textFieldList.forEach(textField -> textField.mouseClicked(mouseX, mouseY, mouseButton)); + } + + @Override + protected void actionPerformed(GuiButton button) throws IOException { + //check what button and action type (left/right click) + if (button == buttonClose) { + mc.player.closeScreen(); + } + if (button == buttonCurrentPosition) { + Vec3d pos = new Vec3d(Math.floor(mc.player.posX) + 0.5, Math.floor(mc.player.posY) + 0.5, Math.floor(mc.player.posZ) + 0.5); + textMirrorPosX.setText(String.valueOf(pos.x)); + textMirrorPosY.setText(String.valueOf(pos.y)); + textMirrorPosZ.setText(String.valueOf(pos.z)); + } + if (button == buttonDrawLines) { + drawLines = !drawLines; + buttonDrawLines.displayString = drawLines ? "Hide lines" : "Show lines"; + } + if (button == buttonDrawPlanes) { + drawPlanes = !drawPlanes; + buttonDrawPlanes.displayString = drawPlanes ? "Hide area" : "Show area"; + } + } + + @Override + public void onGuiClosed() { + //save everything + + //MIRROR + boolean mirrorEnabled = buttonMirrorEnabled.isChecked(); + + Vec3d mirrorPos = new Vec3d(0.5, 64.5, 0.5); + try { + mirrorPos = new Vec3d(Double.parseDouble(textMirrorPosX.getText()), Double.parseDouble(textMirrorPosY.getText()), Double.parseDouble(textMirrorPosZ.getText())); + } catch (NumberFormatException | NullPointerException ex) { + EffortlessBuilding.log(Minecraft.getMinecraft().player, "Mirror position not valid.", true); + EffortlessBuilding.log("Mirror position not valid. Resetting to default."); + } + + boolean mirrorX = buttonMirrorX.isChecked(); + boolean mirrorY = buttonMirrorY.isChecked(); + boolean mirrorZ = buttonMirrorZ.isChecked(); + + int mirrorRadius = 50; + try { + mirrorRadius = Math.min(Integer.parseInt(textMirrorRadius.getText()), Mirror.MAX_RADIUS); + } catch (NumberFormatException | NullPointerException ex) { + EffortlessBuilding.log(Minecraft.getMinecraft().player, "Mirror radius not valid.", true); + EffortlessBuilding.log("Mirror radius not valid. Resetting to default."); + } + mirrorRadius = Math.max(1, mirrorRadius); + mirrorRadius = Math.min(Mirror.MAX_RADIUS, mirrorRadius); + + Mirror.MirrorSettings m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes); + + //ARRAY + boolean arrayEnabled = buttonArrayEnabled.isChecked(); + BlockPos arrayOffset = new BlockPos(0, 0, 0); + try { + arrayOffset = new BlockPos(Integer.parseInt(textArrayOffsetX.getText()), Integer.parseInt(textArrayOffsetY.getText()), Integer.parseInt(textArrayOffsetZ.getText())); + } catch (NumberFormatException | NullPointerException ex) { + EffortlessBuilding.log(Minecraft.getMinecraft().player, "Array offset not valid.", true); + EffortlessBuilding.log("Array offset not valid. Resetting to default."); + } + + int arrayCount = 5; + try { + arrayCount = Integer.parseInt(textArrayCount.getText()); + } catch (NumberFormatException | NullPointerException ex) { + EffortlessBuilding.log(Minecraft.getMinecraft().player, "Array count not valid.", true); + EffortlessBuilding.log("Array count not valid. Resetting to default."); + } + arrayCount = Math.max(1, arrayCount); + arrayCount = Math.min(Array.MAX_COUNT, arrayCount); + + Array.ArraySettings a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); + + BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(mc.player); + if (buildSettings == null) buildSettings = new BuildSettingsManager.BuildSettings(); + buildSettings.setMirrorSettings(m); + buildSettings.setArraySettings(a); + BuildSettingsManager.setBuildSettings(mc.player, buildSettings); + + //Send to server + EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagContainer.java b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagContainer.java new file mode 100644 index 0000000..dcf6235 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagContainer.java @@ -0,0 +1,11 @@ +package nl.requios.effortlessbuilding.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.Container; + +public class RandomizerBagContainer extends Container { + @Override + public boolean canInteractWith(EntityPlayer playerIn) { + return false; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagGuiContainer.java b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagGuiContainer.java new file mode 100644 index 0000000..0ee87a5 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagGuiContainer.java @@ -0,0 +1,15 @@ +package nl.requios.effortlessbuilding.inventory; + +import net.minecraft.client.gui.inventory.GuiContainer; +import net.minecraft.inventory.Container; + +public class RandomizerBagGuiContainer extends GuiContainer { + public RandomizerBagGuiContainer(Container inventorySlotsIn) { + super(inventorySlotsIn); + } + + @Override + protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { + + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagInventory.java b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagInventory.java new file mode 100644 index 0000000..052559b --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerBagInventory.java @@ -0,0 +1,144 @@ +package nl.requios.effortlessbuilding.inventory; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraftforge.items.IItemHandler; + +import javax.annotation.Nonnull; + +public class RandomizerBagInventory implements IItemHandler { + + //Reference to NBT data + private final ItemStack invItem; + + public static final int INV_SIZE = 5; + + private ItemStack[] inventory = new ItemStack[INV_SIZE]; + + public RandomizerBagInventory(ItemStack invItem) { + this.invItem = invItem; + + if (!invItem.hasTagCompound()) { + invItem.setTagCompound(new NBTTagCompound()); + } + + readFromNBT(invItem.getTagCompound()); + } + + @Override + public int getSlots() { + return INV_SIZE; + } + + @Nonnull + @Override + public ItemStack getStackInSlot(int slot) { + return inventory[slot]; + } + + @Nonnull + @Override + public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { + ItemStack slotStack = getStackInSlot(slot); + if (slotStack.getCount() == 0) { + setInventorySlotContents(slot, stack); + return null; + } + if (getSlotLimit(slot) - slotStack.getCount() < stack.getCount()) { + //Not enough place remaining, split stack + slotStack.setCount(getSlotLimit(slot)); + onInventoryChanged(); + stack.copy().shrink(getSlotLimit(slot) - slotStack.getCount()); + //TODO make proper + return stack; + } else { + slotStack.grow(stack.getCount()); + onInventoryChanged(); + return null; + } + } + + @Nonnull + @Override + public ItemStack extractItem(int slot, int amount, boolean simulate) { + ItemStack stack = getStackInSlot(slot); + if (stack == null) return stack; + + if (stack.getCount() > amount) { + stack = stack.splitStack(amount); + onInventoryChanged(); + } else { + setInventorySlotContents(slot, null); + } + return stack; + } + + @Override + public int getSlotLimit(int slot) { + return 64; + } + + public void onInventoryChanged() { + for (int i = 0; i < getSlotLimit(0); ++i) { + if (getStackInSlot(i) != null && getStackInSlot(i).getCount() == 0) { + inventory[i] = null; + } + } + + writeToNBT(invItem.getTagCompound()); + } + + public void setInventorySlotContents(int slot, ItemStack stack) { + inventory[slot] = stack; + + if (stack != null && stack.getCount() > getSlotLimit(slot)) { + stack.setCount(getSlotLimit(slot)); + } + + // Don't forget this line or your inventory will not be saved! + onInventoryChanged(); + } + + public void readFromNBT(NBTTagCompound compound) { + // Gets the custom taglist we wrote to this compound, if any + // 1.7.2+ change to compound.getTagList("ItemInventory", Constants.NBT.TAG_COMPOUND); + NBTTagList items = compound.getTagList("ItemInventory", 0); + + for (int i = 0; i < items.tagCount(); ++i) { + // 1.7.2+ change to items.getCompoundTagAt(i) + NBTTagCompound item = items.getCompoundTagAt(i); + int slot = item.getInteger("Slot"); + + // Just double-checking that the saved slot index is within our inventory array bounds + if (slot >= 0 && slot < getSlots()) { + inventory[slot] = new ItemStack(item); + } + } + } + + /** + * A custom method to write our inventory to an ItemStack's NBT compound + */ + public void writeToNBT(NBTTagCompound tagcompound) { + // Create a new NBT Tag List to store itemstacks as NBT Tags + NBTTagList items = new NBTTagList(); + + for (int i = 0; i < getSlots(); ++i) { + // Only write stacks that contain items + if (getStackInSlot(i) != null) { + // Make a new NBT Tag Compound to write the itemstack and slot index to + NBTTagCompound item = new NBTTagCompound(); + item.setInteger("Slot", i); + // Writes the itemstack in slot(i) to the Tag Compound we just made + getStackInSlot(i).writeToNBT(item); + + // add the tag compound to our tag list + items.appendTag(item); + } + } + // Add the TagList to the ItemStack's Tag Compound with the name "ItemInventory" + tagcompound.setTag("ItemInventory", items); + } + +} diff --git a/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerGuiHandler.java b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerGuiHandler.java new file mode 100644 index 0000000..7a2aec6 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/inventory/RandomizerGuiHandler.java @@ -0,0 +1,32 @@ +package nl.requios.effortlessbuilding.inventory; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.network.IGuiHandler; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.inventory.RandomizerBagContainer; + +import javax.annotation.Nullable; + +public class RandomizerGuiHandler implements IGuiHandler { + @Nullable + @Override + public Object getServerGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { + if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) { + // Use the player's held item to create the inventory + return new RandomizerBagContainer(); + } + return null; + } + + @Nullable + @Override + public Object getClientGuiElement(int ID, EntityPlayer player, World world, int x, int y, int z) { + if (ID == EffortlessBuilding.RANDOMIZER_BAG_GUI) { + // We have to cast the new container as our custom class + // and pass in currently held item for the inventory + return new RandomizerBagGuiContainer(new RandomizerBagContainer()); + } + return null; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java b/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java new file mode 100644 index 0000000..c8e180d --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/item/ItemRandomizerBag.java @@ -0,0 +1,56 @@ +package nl.requios.effortlessbuilding.item; + +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import nl.requios.effortlessbuilding.EffortlessBuilding; + +public class ItemRandomizerBag extends Item { + + public ItemRandomizerBag(){ + this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag"); + this.setUnlocalizedName(this.getRegistryName().toString()); + + this.maxStackSize = 1; + this.setCreativeTab(CreativeTabs.DECORATIONS); + } + + @Override + public EnumActionResult onItemUse(EntityPlayer player, World worldIn, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + + if (worldIn.isRemote) return EnumActionResult.PASS; + EffortlessBuilding.log(player, "onItemUse"); + + if (player.isSneaking()){ + //Open inventory + player.openGui(EffortlessBuilding.instance, EffortlessBuilding.RANDOMIZER_BAG_GUI, worldIn, 0, 0, 0); + } else { + //Place block + + } + return EnumActionResult.PASS; + } + + @Override + public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { + if (worldIn.isRemote) return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + EffortlessBuilding.log(playerIn, "onItemRightClick"); + + //Open inventory + playerIn.openGui(EffortlessBuilding.instance, EffortlessBuilding.RANDOMIZER_BAG_GUI, worldIn, 0, 0, 0); + + return new ActionResult<>(EnumActionResult.PASS, playerIn.getHeldItem(handIn)); + } + + @Override + public int getMaxItemUseDuration(ItemStack stack) { + return 1; + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/network/BuildSettingsMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/BuildSettingsMessage.java new file mode 100644 index 0000000..1e30464 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/network/BuildSettingsMessage.java @@ -0,0 +1,110 @@ +package nl.requios.effortlessbuilding.network; + +import io.netty.buffer.ByteBuf; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.util.IThreadListener; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import nl.requios.effortlessbuilding.Array; +import nl.requios.effortlessbuilding.BuildSettingsManager; +import nl.requios.effortlessbuilding.BuildSettingsManager.BuildSettings; +import nl.requios.effortlessbuilding.Mirror; + +public class BuildSettingsMessage implements IMessage { + + private BuildSettings buildSettings; + + public BuildSettingsMessage() { + } + + public BuildSettingsMessage(BuildSettings buildSettings) { + this.buildSettings = buildSettings; + } + + @Override + public void toBytes(ByteBuf buf) { + //MIRROR + Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); + buf.writeBoolean(m.enabled); + buf.writeDouble(m.position.x); + buf.writeDouble(m.position.y); + buf.writeDouble(m.position.z); + buf.writeBoolean(m.mirrorX); + buf.writeBoolean(m.mirrorY); + buf.writeBoolean(m.mirrorZ); + buf.writeInt(m.radius); + buf.writeBoolean(m.drawLines); + buf.writeBoolean(m.drawPlanes); + + //ARRAY + Array.ArraySettings a = buildSettings.getArraySettings(); + buf.writeBoolean(a.enabled); + buf.writeInt(a.offset.getX()); + buf.writeInt(a.offset.getY()); + buf.writeInt(a.offset.getZ()); + buf.writeInt(a.count); + + buf.writeBoolean(buildSettings.doQuickReplace()); + } + + @Override + public void fromBytes(ByteBuf buf) { + //MIRROR + boolean mirrorEnabled = buf.readBoolean(); + Vec3d mirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); + boolean mirrorX = buf.readBoolean(); + boolean mirrorY = buf.readBoolean(); + boolean mirrorZ = buf.readBoolean(); + int mirrorRadius = buf.readInt(); + boolean mirrorDrawLines = buf.readBoolean(); + boolean mirrorDrawPlanes = buf.readBoolean(); + Mirror.MirrorSettings m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes); + + //ARRAY + boolean arrayEnabled = buf.readBoolean(); + BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); + int arrayCount = buf.readInt(); + Array.ArraySettings a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); + + boolean quickReplace = buf.readBoolean(); + buildSettings = new BuildSettings(m, a, quickReplace); + } + + // The params of the IMessageHandler are + public static class MessageHandler implements IMessageHandler { + // Do note that the default constructor is required, but implicitly defined in this case + + @Override + public IMessage onMessage(BuildSettingsMessage message, MessageContext ctx) { + //EffortlessBuilding.log("message received on " + ctx.side + " side"); + + // This is the player the packet was sent to the server from + EntityPlayer player = (ctx.side.isClient() ? Minecraft.getMinecraft().player : ctx.getServerHandler().player); + // The value that was sent + BuildSettings buildSettings = message.buildSettings; + Mirror.MirrorSettings m = buildSettings.getMirrorSettings(); + Array.ArraySettings a = buildSettings.getArraySettings(); + + // Sanitize + m.radius = Math.min(m.radius, Mirror.MAX_RADIUS); + m.radius = Math.max(1, m.radius); + + a.count = Math.min(a.count, Array.MAX_COUNT); + a.count = Math.max(0, a.count); + + // Execute the action on the main server thread by adding it as a scheduled task + IThreadListener threadListener = (ctx.side.isClient() ? Minecraft.getMinecraft() : ((EntityPlayerMP) player).getServerWorld()); + threadListener.addScheduledTask(() -> { + EntityPlayer p = (ctx.side.isClient() ? Minecraft.getMinecraft().player : ctx.getServerHandler().player); + BuildSettingsManager.setBuildSettings(p, buildSettings); + }); + // No response packet + return null; + } + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/network/QuickReplaceMessage.java b/src/main/java/nl/requios/effortlessbuilding/network/QuickReplaceMessage.java new file mode 100644 index 0000000..5a54c34 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/network/QuickReplaceMessage.java @@ -0,0 +1,88 @@ +package nl.requios.effortlessbuilding.network; + +import io.netty.buffer.ByteBuf; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; +import net.minecraftforge.fml.common.network.simpleimpl.IMessage; +import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import net.minecraftforge.fml.relauncher.Side; +import nl.requios.effortlessbuilding.QuickReplace; +import nl.requios.effortlessbuilding.proxy.ClientProxy; + +public class QuickReplaceMessage implements IMessage { + + private boolean blockHit; + private BlockPos blockPos; + private EnumFacing sideHit; + + public QuickReplaceMessage() { + this.blockHit = false; + this.blockPos = BlockPos.ORIGIN; + this.sideHit = EnumFacing.UP; + } + + public QuickReplaceMessage(RayTraceResult result) { + this.blockHit = result.typeOfHit == RayTraceResult.Type.BLOCK; + this.blockPos = result.getBlockPos(); + this.sideHit = result.sideHit; + } + + public boolean isBlockHit() { + return blockHit; + } + + public BlockPos getBlockPos() { + return blockPos; + } + + public EnumFacing getSideHit() { + return sideHit; + } + + @Override + public void toBytes(ByteBuf buf) { + buf.writeBoolean(blockHit); + buf.writeInt(blockPos.getX()); + buf.writeInt(blockPos.getY()); + buf.writeInt(blockPos.getZ()); + buf.writeInt(sideHit.getIndex()); + } + + @Override + public void fromBytes(ByteBuf buf) { + blockHit = buf.readBoolean(); + blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); + sideHit = EnumFacing.getFront(buf.readInt()); + } + + // The params of the IMessageHandler are + public static class MessageHandler implements IMessageHandler { + // Do note that the default constructor is required, but implicitly defined in this case + + @Override + public IMessage onMessage(QuickReplaceMessage message, MessageContext ctx) { + //EffortlessBuilding.log("message received on " + ctx.side + " side"); + + if (ctx.side == Side.CLIENT){ + //Received clientside + //Send back your info + return new QuickReplaceMessage(ClientProxy.previousLookAt); + + //TODO break block then return +// Minecraft.getMinecraft().addScheduledTask(() -> { +// EffortlessBuilding.packetHandler.sendToServer(new QuickReplaceMessage(Minecraft.getMinecraft().objectMouseOver)); +// }); + + } else { + //Received serverside + ctx.getServerHandler().player.getServerWorld().addScheduledTask(() -> { + QuickReplace.onMessageReceived(ctx.getServerHandler().player, message); + }); + } + // No response packet + return null; + } + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java new file mode 100644 index 0000000..64620f6 --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/proxy/ClientProxy.java @@ -0,0 +1,130 @@ +package nl.requios.effortlessbuilding.proxy; + +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.Item; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.*; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.InputEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; +import net.minecraftforge.fml.relauncher.Side; +import nl.requios.effortlessbuilding.BuildSettingsManager; +import nl.requios.effortlessbuilding.EffortlessBuilding; +import nl.requios.effortlessbuilding.gui.SettingsGui; +import nl.requios.effortlessbuilding.network.BuildSettingsMessage; +import org.lwjgl.input.Keyboard; + +@Mod.EventBusSubscriber(Side.CLIENT) +public class ClientProxy implements IProxy { + public static KeyBinding[] keyBindings; + public static RayTraceResult previousLookAt; + public static RayTraceResult currentLookAt; + + @Override + public void preInit(FMLPreInitializationEvent event) { + } + + @Override + public void init(FMLInitializationEvent event) { + // register key bindings + keyBindings = new KeyBinding[2]; + + // instantiate the key bindings + keyBindings[0] = new KeyBinding("key.hud.desc", Keyboard.KEY_NUMPAD0, "key.effortlessbuilding.category"); + keyBindings[1] = new KeyBinding("key.replace.desc", Keyboard.KEY_NUMPAD1, "key.effortlessbuilding.category"); + + // register all the key bindings + for (int i = 0; i < keyBindings.length; ++i) { + ClientRegistry.registerKeyBinding(keyBindings[i]); + } + } + + @Override + public void postInit(FMLPostInitializationEvent event) { + + } + + @Override + public EntityPlayer getPlayerEntityFromContext(MessageContext ctx) { + return (ctx.side.isClient() ? Minecraft.getMinecraft().player : EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx)); + } + + @Override + public void serverStarting(FMLServerStartingEvent event) { + // This will never get called on client side + } + + @SubscribeEvent + public static void registerModels(ModelRegistryEvent event) { + for (Block block : EffortlessBuilding.BLOCKS) { + ModelLoader.setCustomModelResourceLocation(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory")); + } + + for (Item item : EffortlessBuilding.ITEMS) { + ModelLoader.setCustomModelResourceLocation(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory")); + } + } + + @SubscribeEvent(priority = EventPriority.NORMAL, receiveCanceled = true) + public static void onKeyPress(InputEvent.KeyInputEvent event) { + // check each enumerated key binding type for pressed and take appropriate action + EntityPlayerSP player = Minecraft.getMinecraft().player; + if (keyBindings[0].isPressed()) { + // do stuff for this key binding here + // remember you may need to send packet to server + if (Minecraft.getMinecraft().currentScreen == null) { + Minecraft.getMinecraft().displayGuiScreen(new SettingsGui()); + } else { + player.closeScreen(); + } + } + if (keyBindings[1].isPressed()) { + // do stuff for this key binding here + // remember you may need to send packet to server + BuildSettingsManager.BuildSettings buildSettings = BuildSettingsManager.getBuildSettings(player); + buildSettings.setQuickReplace(!buildSettings.doQuickReplace()); + EffortlessBuilding.log(player, "Set "+ TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (buildSettings.doQuickReplace() ? "on" : "off")); + EffortlessBuilding.packetHandler.sendToServer(new BuildSettingsMessage(buildSettings)); + } + } + + @SubscribeEvent + public static void onClientTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.START) return; + + RayTraceResult objectMouseOver = Minecraft.getMinecraft().objectMouseOver; + if (objectMouseOver == null) return; + + if (currentLookAt == null) { + currentLookAt = objectMouseOver; + previousLookAt = objectMouseOver; + return; + } + + if (objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) { + if (currentLookAt.typeOfHit != RayTraceResult.Type.BLOCK) { + currentLookAt = objectMouseOver; + previousLookAt = objectMouseOver; + } else { + if (currentLookAt.getBlockPos() != objectMouseOver.getBlockPos()){ + previousLookAt = currentLookAt; + currentLookAt = objectMouseOver; + } + } + } + + + } +} diff --git a/src/main/java/nl/requios/effortlessbuilding/proxy/IProxy.java b/src/main/java/nl/requios/effortlessbuilding/proxy/IProxy.java new file mode 100644 index 0000000..a6b0bcd --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/proxy/IProxy.java @@ -0,0 +1,40 @@ +package nl.requios.effortlessbuilding.proxy; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public interface IProxy +{ + /** + * Register entities and networking. + */ + void preInit(FMLPreInitializationEvent event); + + /** + * Register event listeners, recipes and advancements. + */ + void init(FMLInitializationEvent event); + + /** + * For doing inter-mod stuff like checking which mods are loaded or if you want a complete view of things across + * mods like having a list of all registered items to aid random item generation. + */ + void postInit(FMLPostInitializationEvent event); + + /** + * Server commands should be registered here. + */ + void serverStarting(FMLServerStartingEvent event); + + /** + * Returns a side-appropriate EntityPlayer for use during message handling. + * + * @param parContext the context + * @return the player entity from context + */ + EntityPlayer getPlayerEntityFromContext(MessageContext parContext); +} diff --git a/src/main/java/nl/requios/effortlessbuilding/proxy/ServerProxy.java b/src/main/java/nl/requios/effortlessbuilding/proxy/ServerProxy.java new file mode 100644 index 0000000..e15559d --- /dev/null +++ b/src/main/java/nl/requios/effortlessbuilding/proxy/ServerProxy.java @@ -0,0 +1,38 @@ +package nl.requios.effortlessbuilding.proxy; + +import net.minecraft.entity.player.EntityPlayer; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.event.FMLServerStartingEvent; +import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; + +public class ServerProxy implements IProxy +{ + @Override + public void preInit(FMLPreInitializationEvent event) + { + } + + @Override + public void init(FMLInitializationEvent event) + { + } + + @Override + public void postInit(FMLPostInitializationEvent event) + { + } + + @Override + public void serverStarting(FMLServerStartingEvent event) + { + //event.registerServerCommand(new CommandStructureCapture()); + } + + @Override + public EntityPlayer getPlayerEntityFromContext(MessageContext ctx) + { + return ctx.getServerHandler().player; + } +} diff --git a/src/main/resources/assets/effortlessbuilding/lang/en_us.lang b/src/main/resources/assets/effortlessbuilding/lang/en_us.lang new file mode 100644 index 0000000..df377b5 --- /dev/null +++ b/src/main/resources/assets/effortlessbuilding/lang/en_us.lang @@ -0,0 +1,5 @@ +key.effortlessbuilding.category=Effortless Building +key.hud.desc=Open Settings +key.replace.desc=Switch Replace Mode + +item.effortlessbuilding:randomizer_bag.name=Randomizer Bag \ No newline at end of file diff --git a/src/main/resources/assets/effortlessbuilding/models/item/randomizer_bag.json b/src/main/resources/assets/effortlessbuilding/models/item/randomizer_bag.json new file mode 100644 index 0000000..5f74c2e --- /dev/null +++ b/src/main/resources/assets/effortlessbuilding/models/item/randomizer_bag.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { + "layer0": "items/fireball" + } +} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..2fd7eef --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ +{ + "modid": "effortlessbuilding", + "name": "Effortless Building", + "description": "Makes building easier by providing tools like mirrors, arrays, quickreplace and a block randomizer.", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "https://requios.nl/", + "updateUrl": "", + "authorList": ["Requios"], + "credits": "", + "logoFile": "", + "screenshots": [], + "dependencies": [] +} +] 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)." + } +}