diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f8a3cd828 --- /dev/null +++ b/.gitignore @@ -0,0 +1,42 @@ +## Based on GitHub's Eclipse .gitignore + +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 \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 000000000..21d4f1bda --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 simibubi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/build.gradle b/build.gradle new file mode 100644 index 000000000..af8cd416c --- /dev/null +++ b/build.gradle @@ -0,0 +1,149 @@ +buildscript { + repositories { + maven { url = 'https://files.minecraftforge.net/maven' } + jcenter() + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true + } +} +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.0.1' +group = 'com.simibubi.create' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'create' + +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: '20190621-1.14.2' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + // accessTransformer = file('build/resources/main/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', 'debug' + + mods { + create { + source sourceSets.main + } + } + } + + server { + 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', 'debug' + + mods { + create { + source sourceSets.main + } + } + } + + data { + 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', 'debug' + + args '--mod', 'create', '--all', '--output', file('src/generated/resources/') + + mods { + create { + source sourceSets.main + } + } + } + } +} + +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.14.3-27.0.43' + + // 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 + +} + +// Example for how to get properties into the manifest for reading by the runtime.. +jar { + manifest { + attributes([ + "Specification-Title": "create", + "Specification-Vendor": "simibubi", + "Specification-Version": "1", // We are version 1 of ourselves + "Implementation-Title": project.name, + "Implementation-Version": "${version}", + "Implementation-Vendor" :"simibubi", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } +} + +// Example configuration to allow publishing using the maven-publish task +// we define a custom artifact that is sourced from the reobfJar output task +// and then declare that to be published +// Note you'll need to add a repository here +def reobfFile = file("$buildDir/reobfJar/output.jar") +def reobfArtifact = artifacts.add('default', reobfFile) { + type 'jar' + builtBy 'reobfJar' +} +publishing { + publications { + mavenJava(MavenPublication) { + artifact reobfArtifact + } + } + repositories { + maven { + url "file:///${project.projectDir}/mcmodsrepo" + } + } +} \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 000000000..7a3265ee9 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 000000000..949819d28 --- /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 000000000..cccdd3d51 --- /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 000000000..f9553162f --- /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/src/main/java/com/simibubi/create/AllBlocks.java b/src/main/java/com/simibubi/create/AllBlocks.java new file mode 100644 index 000000000..86754b354 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllBlocks.java @@ -0,0 +1,51 @@ +package com.simibubi.create; + +import com.simibubi.create.block.IJustForRendering; +import com.simibubi.create.block.symmetry.BlockSymmetryCrossPlane; +import com.simibubi.create.block.symmetry.BlockSymmetryPlane; +import com.simibubi.create.block.symmetry.BlockSymmetryTriplePlane; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.item.BlockItem; +import net.minecraft.item.Item; +import net.minecraftforge.registries.IForgeRegistry; + +public enum AllBlocks { + + SYMMETRY_PLANE(new BlockSymmetryPlane()), + SYMMETRY_CROSSPLANE(new BlockSymmetryCrossPlane()), + SYMMETRY_TRIPLEPLANE(new BlockSymmetryTriplePlane()); + + public Block block; + + private AllBlocks(Block block) { + this.block = block; + this.block.setRegistryName(Create.ID, this.name().toLowerCase()); + } + + public static void registerBlocks(IForgeRegistry registry) { + for (AllBlocks block : values()) { + registry.register(block.block); + } + } + + public static void registerItemBlocks(IForgeRegistry registry) { + for (AllBlocks block : values()) { + if (block.get() instanceof IJustForRendering) + continue; + + registry.register(new BlockItem(block.get(), AllItems.standardProperties()) + .setRegistryName(block.get().getRegistryName())); + } + } + + public Block get() { + return block; + } + + public boolean typeOf(BlockState state) { + return state.getBlock() == block; + } + +} diff --git a/src/main/java/com/simibubi/create/AllItems.java b/src/main/java/com/simibubi/create/AllItems.java new file mode 100644 index 000000000..ddca40375 --- /dev/null +++ b/src/main/java/com/simibubi/create/AllItems.java @@ -0,0 +1,42 @@ +package com.simibubi.create; + +import com.simibubi.create.item.ItemWandSymmetry; + +import net.minecraft.item.Item; +import net.minecraft.item.Item.Properties; +import net.minecraft.item.ItemStack; +import net.minecraftforge.registries.IForgeRegistry; + +public enum AllItems { + + SYMMETRY_WAND(new ItemWandSymmetry(standardProperties())); + + public Item item; + + private AllItems(Item item) { + this.item = item; + this.item.setRegistryName(Create.ID, this.name().toLowerCase()); + } + + public static Properties standardProperties() { + return new Properties().group(Create.creativeTab); + } + + public static void registerItems(IForgeRegistry iForgeRegistry) { + for (AllItems item : values()) { + iForgeRegistry.register(item.get()); + } + } + + public Item get() { + return item; + } + + public boolean typeOf(ItemStack stack) { + return stack.getItem() == item; + } + + public static void initColorHandlers() { + } + +} diff --git a/src/main/java/com/simibubi/create/Create.java b/src/main/java/com/simibubi/create/Create.java new file mode 100644 index 000000000..efdbe56e3 --- /dev/null +++ b/src/main/java/com/simibubi/create/Create.java @@ -0,0 +1,62 @@ +package com.simibubi.create; + +import org.apache.logging.log4j.Logger; + +import com.simibubi.create.networking.Packets; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.item.ItemGroup; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; + +@EventBusSubscriber(bus = Bus.FORGE) +@Mod(Create.ID) +public class Create { + + public static final String ID = "create"; + public static final String NAME = "Create"; + public static final String VERSION = "0.0.1"; + + public static Logger logger; + + public static ItemGroup creativeTab = new CreateItemGroup(); + + public Create() { + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); + modEventBus.addListener(this::clientInit); + modEventBus.addListener(this::init); + } + + private void clientInit(FMLClientSetupEvent event) { + AllItems.initColorHandlers(); + +// ScrollFixer.init(); + } + + private void init(final FMLCommonSetupEvent event) { + Packets.registerPackets(); + } + + @EventBusSubscriber(bus = Bus.MOD) + public static class RegistryListener { + + @SubscribeEvent + public static void registerItems(RegistryEvent.Register event) { + AllItems.registerItems(event.getRegistry()); + AllBlocks.registerItemBlocks(event.getRegistry()); + } + + @SubscribeEvent + public static void registerBlocks(RegistryEvent.Register event) { + AllBlocks.registerBlocks(event.getRegistry()); + } + } +} diff --git a/src/main/java/com/simibubi/create/CreateItemGroup.java b/src/main/java/com/simibubi/create/CreateItemGroup.java new file mode 100644 index 000000000..381e5ff6c --- /dev/null +++ b/src/main/java/com/simibubi/create/CreateItemGroup.java @@ -0,0 +1,16 @@ +package com.simibubi.create; + +import net.minecraft.item.ItemGroup; +import net.minecraft.item.ItemStack; + +public final class CreateItemGroup extends ItemGroup { + + public CreateItemGroup() { + super(getGroupCountSafe(), Create.ID); + } + + @Override + public ItemStack createIcon() { + return new ItemStack(AllItems.SYMMETRY_WAND.get()); + } +} diff --git a/src/main/java/com/simibubi/create/ScrollFixer.java b/src/main/java/com/simibubi/create/ScrollFixer.java new file mode 100644 index 000000000..d896a94c3 --- /dev/null +++ b/src/main/java/com/simibubi/create/ScrollFixer.java @@ -0,0 +1,50 @@ +package com.simibubi.create; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +import org.lwjgl.glfw.GLFW; +import org.lwjgl.glfw.GLFWScrollCallback; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.MouseHelper; + +public class ScrollFixer { + + private static List> listeners; + + public static void init() { + listeners = new ArrayList<>(); + Method method; + try { + MouseHelper mouseHelper = Minecraft.getInstance().mouseHelper; + method = mouseHelper.getClass().getDeclaredMethod("scrollCallback", Long.TYPE, + Double.TYPE, Double.TYPE); + method.setAccessible(true); + GLFW.glfwSetScrollCallback(Minecraft.getInstance().mainWindow.getHandle(), new GLFWScrollCallback() { + @Override + public void invoke(long win, double dx, double dy) { + for (Predicate consumer : listeners) { + if (consumer.test(dy)) + return; + } + try { + method.invoke(mouseHelper, win, dx, dy); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + e.printStackTrace(); + } + } + }); + } catch (NoSuchMethodException | SecurityException e1) { + e1.printStackTrace(); + } + } + + public static void addMouseWheelListener(Predicate callback) { + listeners.add(callback); + } + +} diff --git a/src/main/java/com/simibubi/create/block/IJustForRendering.java b/src/main/java/com/simibubi/create/block/IJustForRendering.java new file mode 100644 index 000000000..580ab5fde --- /dev/null +++ b/src/main/java/com/simibubi/create/block/IJustForRendering.java @@ -0,0 +1,5 @@ +package com.simibubi.create.block; + +public interface IJustForRendering { + +} diff --git a/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetry.java b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetry.java new file mode 100644 index 000000000..880782ad6 --- /dev/null +++ b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetry.java @@ -0,0 +1,13 @@ +package com.simibubi.create.block.symmetry; + +import com.simibubi.create.block.IJustForRendering; + +import net.minecraft.block.Block; + +public class BlockSymmetry extends Block implements IJustForRendering { + + public BlockSymmetry(Properties properties) { + super(properties); + } + +} diff --git a/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryCrossPlane.java b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryCrossPlane.java new file mode 100644 index 000000000..31e471585 --- /dev/null +++ b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryCrossPlane.java @@ -0,0 +1,27 @@ +package com.simibubi.create.block.symmetry; + +import com.simibubi.create.item.symmetry.SymmetryCrossPlane; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.material.Material; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.StateContainer.Builder; + +public class BlockSymmetryCrossPlane extends BlockSymmetry { + + public static final EnumProperty align = EnumProperty.create("align", + SymmetryCrossPlane.Align.class); + + public BlockSymmetryCrossPlane() { + super(Properties.create(Material.AIR)); + this.setDefaultState(getDefaultState().with(align, SymmetryCrossPlane.Align.Y)); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(align); + super.fillStateContainer(builder); + } + +} diff --git a/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryPlane.java b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryPlane.java new file mode 100644 index 000000000..3c0fe2f42 --- /dev/null +++ b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryPlane.java @@ -0,0 +1,26 @@ +package com.simibubi.create.block.symmetry; + +import com.simibubi.create.item.symmetry.SymmetryPlane; + +import net.minecraft.block.Block; +import net.minecraft.block.BlockState; +import net.minecraft.block.material.Material; +import net.minecraft.state.EnumProperty; +import net.minecraft.state.StateContainer.Builder; + +public class BlockSymmetryPlane extends BlockSymmetry { + + public static final EnumProperty align = EnumProperty.create("align", SymmetryPlane.Align.class); + + public BlockSymmetryPlane() { + super(Properties.create(Material.AIR)); + this.setDefaultState(getDefaultState().with(align, SymmetryPlane.Align.XY)); + } + + @Override + protected void fillStateContainer(Builder builder) { + builder.add(align); + super.fillStateContainer(builder); + } + +} diff --git a/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryTriplePlane.java b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryTriplePlane.java new file mode 100644 index 000000000..e63f32f7e --- /dev/null +++ b/src/main/java/com/simibubi/create/block/symmetry/BlockSymmetryTriplePlane.java @@ -0,0 +1,12 @@ +package com.simibubi.create.block.symmetry; + +import net.minecraft.block.material.Material; + +public class BlockSymmetryTriplePlane extends BlockSymmetry { + + public BlockSymmetryTriplePlane() { + super(Properties.create(Material.AIR)); + } + + +} diff --git a/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java b/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java new file mode 100644 index 000000000..5f01b4b92 --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/AbstractSimiScreen.java @@ -0,0 +1,101 @@ +package com.simibubi.create.gui; + +import java.util.ArrayList; +import java.util.List; + +import com.simibubi.create.gui.widgets.AbstractSimiWidget; + +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.gui.widget.Widget; +import net.minecraft.util.text.StringTextComponent; + +public abstract class AbstractSimiScreen extends Screen { + + protected int sWidth, sHeight; + protected int topLeftX, topLeftY; + protected List widgets; + + protected AbstractSimiScreen() { + super(new StringTextComponent("")); + widgets = new ArrayList<>(); + } + + protected void setWindowSize(int width, int height) { + sWidth = width; + sHeight = height; + topLeftX = (this.width - sWidth) / 2; + topLeftY = (this.height - sHeight) / 2; + } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) { + renderBackground(); + renderWindow(mouseX, mouseY, partialTicks); + for (Widget widget : widgets) + widget.render(mouseX, mouseY, partialTicks); + renderWindowForeground(mouseX, mouseY, partialTicks); + for (Widget widget : widgets) + widget.renderToolTip(mouseX, mouseY); + } + + @Override + public boolean mouseClicked(double x, double y, int button) { + boolean result = false; + for (Widget widget : widgets) { + if (widget.mouseClicked(x, y, button)) + result = true; + } + return result; + } + + @Override + public boolean keyPressed(int code, int p_keyPressed_2_, int p_keyPressed_3_) { + for (Widget widget : widgets) { + if (widget.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_)) + return true; + } + return super.keyPressed(code, p_keyPressed_2_, p_keyPressed_3_); + } + + @Override + public boolean charTyped(char character, int code) { + for (Widget widget : widgets) { + if (widget.charTyped(character, code)) + return true; + } + return super.charTyped(character, code); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + for (Widget widget : widgets) { + if (widget.mouseScrolled(mouseX, mouseY, delta)) + return true; + } + return super.mouseScrolled(mouseX, mouseY, delta); + } + + @Override + public boolean shouldCloseOnEsc() { + return true; + } + + @Override + public boolean isPauseScreen() { + return false; + } + + protected abstract void renderWindow(int mouseX, int mouseY, float partialTicks); + + protected void renderWindowForeground(int mouseX, int mouseY, float partialTicks) { + for (Widget widget : widgets) { + if (!widget.isHovered()) + continue; + + if (widget instanceof AbstractSimiWidget && !((AbstractSimiWidget) widget).getToolTip().isEmpty()) { + renderTooltip(((AbstractSimiWidget) widget).getToolTip(), mouseX, mouseY); + } + } + } + +} diff --git a/src/main/java/com/simibubi/create/gui/GuiOpener.java b/src/main/java/com/simibubi/create/gui/GuiOpener.java new file mode 100644 index 000000000..74112956f --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/GuiOpener.java @@ -0,0 +1,26 @@ +package com.simibubi.create.gui; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; + +@EventBusSubscriber +public class GuiOpener { + + private static Screen openedGuiNextTick; + + @SubscribeEvent + public static void onClientTick(ClientTickEvent event) { + if (openedGuiNextTick != null) { + Minecraft.getInstance().displayGuiScreen(openedGuiNextTick); + openedGuiNextTick = null; + } + } + + public static void open(Screen gui) { + openedGuiNextTick = gui; + } + +} diff --git a/src/main/java/com/simibubi/create/gui/GuiResources.java b/src/main/java/com/simibubi/create/gui/GuiResources.java new file mode 100644 index 000000000..8941318cc --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/GuiResources.java @@ -0,0 +1,89 @@ +package com.simibubi.create.gui; + +import com.simibubi.create.Create; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.AbstractGui; +import net.minecraft.util.ResourceLocation; + +public enum GuiResources { + + // Inventories + PLAYER_INVENTORY("player_inventory.png", 176, 108), + COMPOSER("composer.png", 256, 58), + PALETTES("palette_picker.png", 256, 236), + EXPORTER("design_exporter.png", 200, 111), + THEME_EDITOR("theme_editor.png", 200, 187), + WAND_SYMMETRY("wand_symmetry.png", 207, 58), + + // Widgets + PALETTE_BUTTON("palette_picker.png", 0, 236, 20, 20), + TEXT_INPUT("widgets.png", 0, 28, 194, 47), + BUTTON("widgets.png", 18, 18), + BUTTON_HOVER("widgets.png", 18, 0, 18, 18), + BUTTON_DOWN("widgets.png", 36, 0, 18, 18), + INDICATOR("widgets.png", 0, 18, 18, 5), + INDICATOR_WHITE("widgets.png", 18, 18, 18, 5), + INDICATOR_GREEN("widgets.png", 0, 23, 18, 5), + INDICATOR_YELLOW("widgets.png", 18, 23, 18, 5), + INDICATOR_RED("widgets.png", 36, 23, 18, 5), + GRAY("background.png", 0, 0, 16, 16), + + SCROLLBAR_AXIS("widgets.png", 224, 0, 32, 256), + SCROLLBAR_CAP("widgets.png", 0, 87, 40, 6), + SCROLLBAR_INDICATOR("widgets.png", 0, 75, 40, 12), + SCROLLBAR_BACKGROUND("widgets.png", 0, 93, 40, 16), + + // Icons + ICON_NONE("icons.png", 16, 16, 16, 16), + ICON_ADD("icons.png", 16, 16), + ICON_TRASH("icons.png", 16, 0, 16, 16), + ICON_3x3("icons.png", 32, 0, 16, 16), + ICON_TARGET("icons.png", 48, 0, 16, 16), + ICON_CONFIRM("icons.png", 0, 16, 16, 16), + + ICON_NORMAL_ROOF("icons.png", 32, 16, 16, 16), + ICON_FLAT_ROOF("icons.png", 48, 16, 16, 16), + ICON_NO_ROOF("icons.png", 0, 32, 16, 16), + + ICON_TOWER_NO_ROOF("icons.png", 16, 32, 16, 16), + ICON_TOWER_ROOF("icons.png", 32, 32, 16, 16), + ICON_TOWER_FLAT_ROOF("icons.png", 48, 32, 16, 16), + + ICON_LAYER_REGULAR("icons.png", 0, 48, 16, 16), + ICON_LAYER_OPEN("icons.png", 16, 48, 16, 16), + ICON_LAYER_FOUNDATION("icons.png", 32, 48, 16, 16), + ICON_LAYER_SPECIAL("icons.png", 48, 48, 16, 16), + + ICON_TOOL_RESHAPE("icons.png", 0, 64, 16, 16), + ICON_TOOL_ROOM("icons.png", 16, 64, 16, 16), + ICON_TOOL_TOWER("icons.png", 32, 64, 16, 16), + ICON_TOOL_STACK("icons.png", 48, 64, 16, 16), + + ICON_TOOL_HEIGHT("icons.png", 0, 80, 16, 16), + ICON_TOOL_REROLL("icons.png", 16, 80, 16, 16), + ICON_TOOL_REROLL_TARGET("icons.png", 32, 80, 16, 16), + ICON_TOOL_PALETTE("icons.png", 48, 80, 16, 16); + + public static final int FONT_COLOR = 0x575F7A; + + public final ResourceLocation location; + public int width, height; + public int startX, startY; + + private GuiResources(String location, int width, int height) { + this(location, 0, 0, width, height); + } + + private GuiResources(String location, int startX, int startY, int width, int height) { + this.location = new ResourceLocation(Create.ID, "textures/gui/" + location); + this.width = width; this.height = height; + this.startX = startX; this.startY = startY; + } + + public void draw(AbstractGui screen, int i, int j) { + Minecraft.getInstance().getTextureManager().bindTexture(location); + screen.blit(i, j, startX, startY, width, height); + } + +} diff --git a/src/main/java/com/simibubi/create/gui/GuiWandSymmetry.java b/src/main/java/com/simibubi/create/gui/GuiWandSymmetry.java new file mode 100644 index 000000000..bf16d9d89 --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/GuiWandSymmetry.java @@ -0,0 +1,178 @@ +package com.simibubi.create.gui; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.gui.widgets.DynamicLabel; +import com.simibubi.create.gui.widgets.OptionScrollArea; +import com.simibubi.create.gui.widgets.ScrollArea; +import com.simibubi.create.item.ItemWandSymmetry; +import com.simibubi.create.item.symmetry.SymmetryCrossPlane; +import com.simibubi.create.item.symmetry.SymmetryElement; +import com.simibubi.create.item.symmetry.SymmetryEmptySlot; +import com.simibubi.create.item.symmetry.SymmetryPlane; +import com.simibubi.create.item.symmetry.SymmetryTriplePlane; +import com.simibubi.create.networking.PacketNbt; +import com.simibubi.create.networking.Packets; + +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.RenderHelper; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.texture.AtlasTexture; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.client.model.data.EmptyModelData; +import net.minecraftforge.fml.network.PacketDistributor; + +public class GuiWandSymmetry extends AbstractSimiScreen { + + private ScrollArea areaType; + private DynamicLabel labelType; + private ScrollArea areaAlign; + private DynamicLabel labelAlign; + + private SymmetryElement currentElement; + private float animationProgress; + private ItemStack wand; + + public GuiWandSymmetry(ItemStack wand) { + super(); + + currentElement = ItemWandSymmetry.getMirror(wand); + if (currentElement instanceof SymmetryEmptySlot) { + currentElement = new SymmetryPlane(Vec3d.ZERO); + } + this.wand = wand; + animationProgress = 0; + } + + @Override + public void init() { + super.init(); + this.setWindowSize(GuiResources.WAND_SYMMETRY.width + 50, GuiResources.WAND_SYMMETRY.height + 50); + + labelType = new DynamicLabel(topLeftX + 122, topLeftY + 15, "").colored(0xFFFFFFFF).withShadow(); + labelAlign = new DynamicLabel(topLeftX + 122, topLeftY + 35, "").colored(0xFFFFFFFF).withShadow(); + + int state = currentElement instanceof SymmetryTriplePlane ? 2 + : currentElement instanceof SymmetryCrossPlane ? 1 : 0; + areaType = new OptionScrollArea(topLeftX + 119, topLeftY + 12, 70, 14) + .forOptions(SymmetryElement.TOOLTIP_ELEMENTS).titled("Type of Mirror").writingTo(labelType) + .setState(state); + + areaType.calling(position -> { + switch (position) { + case 0: + currentElement = new SymmetryPlane(currentElement.getPosition()); + break; + case 1: + currentElement = new SymmetryCrossPlane(currentElement.getPosition()); + break; + case 2: + currentElement = new SymmetryTriplePlane(currentElement.getPosition()); + break; + default: + break; + } + initAlign(currentElement); + }); + + widgets.clear(); + + initAlign(currentElement); + + widgets.add(labelAlign); + widgets.add(areaType); + widgets.add(labelType); + + } + + private void initAlign(SymmetryElement element) { + if (areaAlign != null) { + widgets.remove(areaAlign); + } + + areaAlign = new OptionScrollArea(topLeftX + 119, topLeftY + 32, 70, 14).forOptions(element.getAlignToolTips()) + .titled("Direction").writingTo(labelAlign).setState(element.getOrientationIndex()) + .calling(element::setOrientation); + + widgets.add(areaAlign); + } + + @Override + public void tick() { + super.tick(); + animationProgress++; + } + + @Override + protected void renderWindow(int mouseX, int mouseY, float partialTicks) { + GuiResources.WAND_SYMMETRY.draw(this, topLeftX, topLeftY); + + int x = topLeftX + 63; + int y = topLeftY + 15; + + font.drawString("Symmetry", x, y, GuiResources.FONT_COLOR); + font.drawString("Direction", x, y + 20, GuiResources.FONT_COLOR); + + minecraft.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE); + GlStateManager.enableBlend(); + + renderBlock(); + renderBlock(); + + GlStateManager.pushLightingAttributes(); + GlStateManager.pushMatrix(); + + RenderHelper.enableStandardItemLighting(); + GlStateManager.enableBlend(); + GlStateManager.enableRescaleNormal(); + GlStateManager.enableAlphaTest(); + GlStateManager.alphaFunc(516, 0.1F); + GlStateManager.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + + GlStateManager.translated((this.width - this.sWidth) / 2 + 250, 250, 100); + GlStateManager.rotatef(-30, .4f, 0, -.2f); + GlStateManager.rotatef(90 + 0.2f * animationProgress, 0, 1, 0); + GlStateManager.scaled(100, -100, 100); + itemRenderer.renderItem(wand, itemRenderer.getModelWithOverrides(wand)); + + GlStateManager.disableAlphaTest(); + GlStateManager.disableRescaleNormal(); + GlStateManager.disableLighting(); + + GlStateManager.popMatrix(); + GlStateManager.popAttributes(); + } + + protected void renderBlock() { + GlStateManager.pushMatrix(); + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + GlStateManager.translated(topLeftX + 15, topLeftY - 117, 20); + GlStateManager.rotatef(-22.5f, .3f, 1f, 0f); + GlStateManager.scaled(32, -32, 32); + minecraft.getBlockRendererDispatcher().renderBlock(currentElement.getModel(), new BlockPos(0, -5, 0), + minecraft.world, buffer, minecraft.world.rand, EmptyModelData.INSTANCE); + + Tessellator.getInstance().draw(); + GlStateManager.popMatrix(); + } + + @Override + public void removed() { + ItemStack heldItemMainhand = minecraft.player.getHeldItemMainhand(); + CompoundNBT compound = heldItemMainhand.getTag(); + compound.put(ItemWandSymmetry.$SYMMETRY, currentElement.writeToNbt()); + heldItemMainhand.setTag(compound); + Packets.channel.send(PacketDistributor.SERVER.noArg(), new PacketNbt(heldItemMainhand)); + minecraft.player.setHeldItem(Hand.MAIN_HAND, heldItemMainhand); + super.removed(); + } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/AbstractSimiWidget.java b/src/main/java/com/simibubi/create/gui/widgets/AbstractSimiWidget.java new file mode 100644 index 000000000..48888dd2d --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/widgets/AbstractSimiWidget.java @@ -0,0 +1,25 @@ +package com.simibubi.create.gui.widgets; + +import java.util.LinkedList; +import java.util.List; + +import net.minecraft.client.gui.widget.Widget; + +public abstract class AbstractSimiWidget extends Widget { + + protected List toolTip; + + public AbstractSimiWidget(int xIn, int yIn, int widthIn, int heightIn) { + super(xIn, yIn, widthIn, heightIn, ""); + toolTip = new LinkedList<>(); + } + + public List getToolTip() { + return toolTip; + } + + @Override + public void renderButton(int p_renderButton_1_, int p_renderButton_2_, float p_renderButton_3_) { + } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/DynamicLabel.java b/src/main/java/com/simibubi/create/gui/widgets/DynamicLabel.java new file mode 100644 index 000000000..d6bacabaa --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/widgets/DynamicLabel.java @@ -0,0 +1,42 @@ +package com.simibubi.create.gui.widgets; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; + +public class DynamicLabel extends AbstractSimiWidget { + + public String text; + protected boolean hasShadow; + protected int color; + protected FontRenderer font; + + public DynamicLabel(int x, int y, String text) { + super(x, y, Minecraft.getInstance().fontRenderer.getStringWidth(text), 10); + font = Minecraft.getInstance().fontRenderer; + this.text = "Label"; + color = 0xFFFFFF; + hasShadow = false; + } + + public DynamicLabel colored(int color) { + this.color = color; + return this; + } + + public DynamicLabel withShadow() { + this.hasShadow = true; + return this; + } + + @Override + public void render(int mouseX, int mouseY, float partialTicks) { + if (!visible) + return; + + if (hasShadow) + font.drawStringWithShadow(text, x, y, color); + else + font.drawString(text, x, y, color); + } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/GuiIndicator.java b/src/main/java/com/simibubi/create/gui/widgets/GuiIndicator.java new file mode 100644 index 000000000..26d44d516 --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/widgets/GuiIndicator.java @@ -0,0 +1,35 @@ +package com.simibubi.create.gui.widgets; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.gui.GuiResources; + +public class GuiIndicator extends AbstractSimiWidget { + + public enum State { + OFF, ON, + RED, YELLOW, GREEN; + } + + public State state; + + public GuiIndicator(int x, int y, String tooltip) { + super(x, y, GuiResources.INDICATOR.width, GuiResources.INDICATOR.height); + this.toolTip = ImmutableList.of(tooltip); + this.state = State.OFF; + } + + @Override + public void render(int mouseX, int mouseY, float partialTicks ) { + GuiResources toDraw; + switch(state) { + case ON: toDraw = GuiResources.INDICATOR_WHITE; break; + case OFF: toDraw = GuiResources.INDICATOR; break; + case RED: toDraw = GuiResources.INDICATOR_RED; break; + case YELLOW: toDraw = GuiResources.INDICATOR_YELLOW; break; + case GREEN: toDraw = GuiResources.INDICATOR_GREEN; break; + default: toDraw = GuiResources.INDICATOR; break; + } + toDraw.draw(this, x, y); + } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/OptionScrollArea.java b/src/main/java/com/simibubi/create/gui/widgets/OptionScrollArea.java new file mode 100644 index 000000000..210376ade --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/widgets/OptionScrollArea.java @@ -0,0 +1,47 @@ +package com.simibubi.create.gui.widgets; + +import java.util.ArrayList; +import java.util.List; + +import net.minecraft.util.text.TextFormatting; + +public class OptionScrollArea extends ScrollArea { + + protected List options; + + public OptionScrollArea(int xIn, int yIn, int widthIn, int heightIn) { + super(xIn, yIn, widthIn, heightIn); + options = new ArrayList<>(); + } + + public ScrollArea forOptions(List options) { + this.options = options; + this.max = options.size(); + updateTooltip(); + return this; + } + + @Override + protected void writeToLabel() { + displayLabel.text = options.get(state); + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + return super.mouseScrolled(mouseX, mouseY, -delta); + } + + @Override + protected void updateTooltip() { + super.updateTooltip(); + for (int i = min; i < max; i++) { + StringBuilder result = new StringBuilder(); + if (i == state) + result.append(TextFormatting.WHITE).append("-> ").append(options.get(i)); + else + result.append(TextFormatting.GRAY).append("> ").append(options.get(i)); + toolTip.add(result.toString()); + } + } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java b/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java new file mode 100644 index 000000000..fed9acd9c --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/widgets/ScrollArea.java @@ -0,0 +1,239 @@ +package com.simibubi.create.gui.widgets; + +import java.util.function.Consumer; + +import com.simibubi.create.utility.Keyboard; + +import net.minecraft.util.text.TextFormatting; + +public class ScrollArea extends AbstractSimiWidget { + + protected Consumer onScroll; + protected int state; + protected String title = "Choose an option"; + protected DynamicLabel displayLabel; + + protected int min, max; + + public ScrollArea(int xIn, int yIn, int widthIn, int heightIn) { + super(xIn, yIn, widthIn, heightIn); + state = 0; + min = 0; + max = 1; + } + + public ScrollArea withRange(int min, int max) { + this.min = min; + this.max = max; + return this; + } + + public ScrollArea calling(Consumer onScroll) { + this.onScroll = onScroll; + return this; + } + + public ScrollArea titled(String title) { + this.title = title; + updateTooltip(); + return this; + } + + public ScrollArea writingTo(DynamicLabel label) { + this.displayLabel = label; + writeToLabel(); + return this; + } + + public int getState() { + return state; + } + + public ScrollArea setState(int state) { + this.state = state; + clampState(); + updateTooltip(); + if (displayLabel != null) + writeToLabel(); + return this; + } + + @Override + public boolean mouseScrolled(double mouseX, double mouseY, double delta) { + if (!isHovered) + return false; + + int priorState = state; + int step = (int) Math.signum(delta) * (Keyboard.isKeyDown(Keyboard.LSHIFT) ? 5 : 1); + + state += step; + clampState(); + + if (priorState != state) + onChanged(); + + return priorState != state; + } + + protected void clampState() { + if (state >= max) + state = max - 1; + if (state < min) + state = min; + } + + protected void onChanged() { + if (displayLabel != null) + writeToLabel(); + if (onScroll != null) + onScroll.accept(state); + updateTooltip(); + } + + protected void writeToLabel() { + displayLabel.text = "" + state; + } + + protected void updateTooltip() { + toolTip.clear(); + toolTip.add(TextFormatting.BLUE + title); + } + +// public interface IScrollAction { +// public void onScroll(int position); +// } +// +// public interface ICancelableScrollAction extends IScrollAction { +// public void onScroll(int position); +// +// public boolean canScroll(int position); +// } +// +// private int x, y, width, height; +// private IScrollAction action; +// public boolean enabled; +// private Optional> tooltipContent; +// private int min, max; +// private boolean limitless; +// private boolean numeric; +// +// public ScrollArea(List options, IScrollAction action) { +// this(0, options.size(), action); +// this.tooltipContent = Optional.of(options); +// updateTooltip(); +// } +// +// public ScrollArea(int min, int max, IScrollAction action) { +// this(action); +// this.limitless = false; +// this.min = min; +// this.max = max; +// } +// +// public ScrollArea(IScrollAction action) { +// this.enabled = true; +// this.action = action; +// this.tooltipContent = Optional.absent(); +// this.limitless = true; +// this.numeric = false; +// } +// +// public void setBounds(int x, int y, int width, int height) { +// this.x = x; +// this.y = y; +// this.width = width; +// this.height = height; +// } +// +// public void setState(int state) { +// currentState = state; +// updateTooltip(); +// } +// +// public int getState() { +// return currentState; +// } +// +// public boolean isHovered(double x, double y) { +// return (x > this.x && x < this.x + this.width && y > this.y && y < this.y + this.height); +// } +// +// public void tryScroll(double mouseX, double mouseY, int amount) { +// if (enabled && isHovered(mouseX, mouseY)) { +// scroll(numeric? -amount : amount); +// } +// } +// +// public void setNumeric(boolean numeric) { +// this.numeric = numeric; +// } +// +// private void scroll(int amount) { +// if (enabled) { +// +// if (limitless) { +// if (!(action instanceof ICancelableScrollAction) +// || ((ICancelableScrollAction) action).canScroll(amount)) +// action.onScroll(amount); +// return; +// } +// +// if (!(action instanceof ICancelableScrollAction) +// || ((ICancelableScrollAction) action).canScroll(currentState + amount)) { +// currentState += amount; +// if (currentState < min) +// currentState = min; +// if (currentState >= max) +// currentState = max - 1; +// updateTooltip(); +// action.onScroll(currentState); +// } +// } +// } +// +// public void draw(Screen screen, int mouseX, int mouseY) { +// GlStateManager.pushLightingAttributes(); +// if (enabled && isHovered(mouseX, mouseY)) { +// GlStateManager.pushMatrix(); +// GlStateManager.translated(mouseX, mouseY,0); +// if (tooltipContent.isPresent()) +// screen.renderTooltip(getToolTip(), 0, 0); +// else +// screen.renderTooltip(TextFormatting.BLUE + title, 0, 0); +// GlStateManager.popMatrix(); +// } +// +// GlStateManager.popAttributes(); +// } +// +// public List getToolTip() { +// return tooltip; +// } +// +// public void setTitle(String title) { +// this.title = title; +// updateTooltip(); +// } +// +// private void updateTooltip() { +// tooltip = new LinkedList<>(); +// tooltip.add(TextFormatting.BLUE + title); +// +// if (tooltipContent.isPresent()) { +// for (int i = min; i < max; i++) { +// StringBuilder result = new StringBuilder(); +// if (i == currentState) +// result.append(TextFormatting.WHITE).append("-> ").append(tooltipContent.get().get(i)); +// else +// result.append(TextFormatting.GRAY).append("> ").append(tooltipContent.get().get(i)); +// tooltip.add(result.toString()); +// } +// +// } +// } +// +// public boolean isNumeric() { +// return numeric; +// } + +} diff --git a/src/main/java/com/simibubi/create/gui/widgets/SimiButton.java b/src/main/java/com/simibubi/create/gui/widgets/SimiButton.java new file mode 100644 index 000000000..33de77bd4 --- /dev/null +++ b/src/main/java/com/simibubi/create/gui/widgets/SimiButton.java @@ -0,0 +1,57 @@ +package com.simibubi.create.gui.widgets; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.gui.GuiResources; + +import net.minecraft.client.Minecraft; +import net.minecraft.util.ResourceLocation; + +public class SimiButton extends AbstractSimiWidget { + + private GuiResources icon; + protected boolean pressed; + + public SimiButton(int x, int y, GuiResources icon) { + super(x, y, 16, 16); + this.icon = icon; + } + + @Override + public void renderButton(int mouseX, int mouseY, float partialTicks) { + if (this.visible) { + ResourceLocation buttonTextures = GuiResources.BUTTON.location; + ResourceLocation iconTexture = icon.location; + this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; + + GuiResources button = + (pressed) ? button = GuiResources.BUTTON_DOWN : + (isHovered) ? GuiResources.BUTTON_HOVER : + GuiResources.BUTTON; + + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + Minecraft.getInstance().getTextureManager().bindTexture(buttonTextures); + blit(x, y, button.startX, button.startY, button.width, button.height); + Minecraft.getInstance().getTextureManager().bindTexture(iconTexture); + blit(x +1, y +1, icon.startX, icon.startY, icon.width, icon.height); + } + } + + + @Override + public void onClick(double p_onClick_1_, double p_onClick_3_) { + super.onClick(p_onClick_1_, p_onClick_3_); + this.pressed = true; + } + + @Override + public void onRelease(double p_onRelease_1_, double p_onRelease_3_) { + super.onRelease(p_onRelease_1_, p_onRelease_3_); + this.pressed = false; + } + + public void setToolTip(String text) { + toolTip.clear(); + toolTip.add(text); + } + +} diff --git a/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java b/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java new file mode 100644 index 000000000..70332bc05 --- /dev/null +++ b/src/main/java/com/simibubi/create/item/ItemWandSymmetry.java @@ -0,0 +1,191 @@ +package com.simibubi.create.item; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.simibubi.create.gui.GuiOpener; +import com.simibubi.create.gui.GuiWandSymmetry; +import com.simibubi.create.item.symmetry.SymmetryCrossPlane; +import com.simibubi.create.item.symmetry.SymmetryElement; +import com.simibubi.create.item.symmetry.SymmetryEmptySlot; +import com.simibubi.create.item.symmetry.SymmetryPlane; +import com.simibubi.create.networking.PacketSymmetryEffect; +import com.simibubi.create.networking.Packets; + +import net.minecraft.block.BlockState; +import net.minecraft.block.Blocks; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUseContext; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Direction; +import net.minecraft.util.Hand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.shapes.ISelectionContext; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.network.PacketDistributor; + +public class ItemWandSymmetry extends Item { + + public static final String $SYMMETRY = "symmetry"; + private static final String $ENABLE = "enable"; + + public ItemWandSymmetry(Properties properties) { + super(properties.maxStackSize(1)); + } + + @Override + public ActionResultType onItemUse(ItemUseContext context) { + PlayerEntity player = context.getPlayer(); + BlockPos pos = context.getPos(); + player.getCooldownTracker().setCooldown(this, 5); + + if (context.getWorld().isRemote || context.getHand() != Hand.MAIN_HAND) + return ActionResultType.SUCCESS; + + ItemStack wand = player.getHeldItem(context.getHand()); + checkNBT(wand); + CompoundNBT compound = wand.getTag().getCompound($SYMMETRY); + pos = pos.offset(context.getFace()); + SymmetryElement previousElement = SymmetryElement.fromNBT(compound); + + if (player.isSneaking()) { + if (!(previousElement instanceof SymmetryEmptySlot)) + wand.getTag().putBoolean($ENABLE, !isEnabled(wand)); + return ActionResultType.SUCCESS; + } + + wand.getTag().putBoolean($ENABLE, true); + Vec3d pos3d = new Vec3d(pos.getX(), pos.getY(), pos.getZ()); + SymmetryElement newElement = new SymmetryPlane(pos3d); + + if (previousElement instanceof SymmetryEmptySlot) { + newElement.setOrientation((player.getHorizontalFacing() == Direction.NORTH + || player.getHorizontalFacing() == Direction.SOUTH) ? SymmetryPlane.Align.XY.ordinal() + : SymmetryPlane.Align.YZ.ordinal()); + newElement.enable = true; + player.sendStatusMessage(new StringTextComponent(TextFormatting.GREEN + "New Plane created"), true); + wand.getTag().putBoolean($ENABLE, true); + + } else { + previousElement.setPosition(pos3d); + + if (previousElement instanceof SymmetryPlane) { + previousElement.setOrientation((player.getHorizontalFacing() == Direction.NORTH + || player.getHorizontalFacing() == Direction.SOUTH) ? SymmetryPlane.Align.XY.ordinal() + : SymmetryPlane.Align.YZ.ordinal()); + } + + if (previousElement instanceof SymmetryCrossPlane) { + float rotation = player.getRotationYawHead(); + float abs = Math.abs(rotation % 90); + boolean diagonal = abs > 22 && abs < 45 + 22; + previousElement.setOrientation( + diagonal ? SymmetryCrossPlane.Align.D.ordinal() : SymmetryCrossPlane.Align.Y.ordinal()); + } + + newElement = previousElement; + } + + compound = newElement.writeToNbt(); + wand.getTag().put($SYMMETRY, compound); + + player.setHeldItem(context.getHand(), wand); + return ActionResultType.SUCCESS; + } + + @Override + public ActionResult onItemRightClick(World worldIn, PlayerEntity playerIn, Hand handIn) { + if (worldIn.isRemote) { + GuiOpener.open(new GuiWandSymmetry(playerIn.getHeldItem(handIn))); + playerIn.getCooldownTracker().setCooldown(this, 5); + } + return super.onItemRightClick(worldIn, playerIn, handIn); + } + + private static void checkNBT(ItemStack wand) { + if (!wand.hasTag() || !wand.getTag().contains($SYMMETRY)) { + wand.setTag(new CompoundNBT()); + wand.getTag().put($SYMMETRY, new SymmetryEmptySlot(new Vec3d(0, 0, 0)).writeToNbt()); + wand.getTag().putBoolean($ENABLE, false); + } + } + + public static boolean isEnabled(ItemStack stack) { + checkNBT(stack); + return stack.getTag().getBoolean($ENABLE); + } + + public static SymmetryElement getMirror(ItemStack stack) { + checkNBT(stack); + return SymmetryElement.fromNBT((CompoundNBT) stack.getTag().getCompound($SYMMETRY)); + } + + public static void apply(World world, ItemStack wand, PlayerEntity player, BlockPos pos, BlockState block) { + checkNBT(wand); + if (!isEnabled(wand)) + return; + + Map blockSet = new HashMap<>(); + blockSet.put(pos, block); + SymmetryElement symmetry = SymmetryElement + .fromNBT((CompoundNBT) wand.getTag().getCompound($SYMMETRY)); + + Vec3d mirrorPos = symmetry.getPosition(); + if (mirrorPos.distanceTo(new Vec3d(pos)) > 50) + return; + + symmetry.process(blockSet); + + BlockPos to = new BlockPos(mirrorPos); + List targets = new ArrayList<>(); + + targets.add(pos); + for (BlockPos position : blockSet.keySet()) { + if (world.func_217350_a(block, position, ISelectionContext.forEntity(player))) { + world.setBlockState(position, blockSet.get(position)); + targets.add(position); + } + } + + Packets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), new PacketSymmetryEffect(to, targets)); + } + + public static void remove(World world, ItemStack wand, PlayerEntity player, BlockPos pos) { + BlockState air = Blocks.AIR.getDefaultState(); + checkNBT(wand); + if (!isEnabled(wand)) + return; + + Map blockSet = new HashMap<>(); + blockSet.put(pos, air); + SymmetryElement symmetry = SymmetryElement + .fromNBT((CompoundNBT) wand.getTag().getCompound($SYMMETRY)); + + Vec3d mirrorPos = symmetry.getPosition(); + if (mirrorPos.distanceTo(new Vec3d(pos)) > 50) + return; + + symmetry.process(blockSet); + + BlockPos to = new BlockPos(mirrorPos); + List targets = new ArrayList<>(); + + targets.add(pos); + for (BlockPos position : blockSet.keySet()) { + targets.add(position); + world.setBlockState(position, air); + } + + Packets.channel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> player), new PacketSymmetryEffect(to, targets)); + } + +} diff --git a/src/main/java/com/simibubi/create/item/SymmetryHandler.java b/src/main/java/com/simibubi/create/item/SymmetryHandler.java new file mode 100644 index 000000000..ae9d13064 --- /dev/null +++ b/src/main/java/com/simibubi/create/item/SymmetryHandler.java @@ -0,0 +1,177 @@ +package com.simibubi.create.item; + +import java.util.Random; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.platform.GlStateManager; +import com.simibubi.create.AllItems; +import com.simibubi.create.item.symmetry.SymmetryElement; +import com.simibubi.create.item.symmetry.SymmetryEmptySlot; +import com.simibubi.create.utility.TessellatorHelper; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.player.ClientPlayerEntity; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.particles.ParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraftforge.client.event.RenderWorldLastEvent; +import net.minecraftforge.client.model.data.EmptyModelData; +import net.minecraftforge.event.world.BlockEvent.BreakEvent; +import net.minecraftforge.event.world.BlockEvent.EntityPlaceEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber; +import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus; +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent; + +@EventBusSubscriber(bus = Bus.FORGE) +public class SymmetryHandler { + + private static int tickCounter = 0; + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onBlockPlaced(EntityPlaceEvent event) { + if (event.getWorld().isRemote()) + return; + if (!(event.getEntity() instanceof PlayerEntity)) + return; + + PlayerEntity player = (PlayerEntity) event.getEntity(); + PlayerInventory inv = player.inventory; + for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { + if (!inv.getStackInSlot(i).isEmpty() && inv.getStackInSlot(i).getItem() == AllItems.SYMMETRY_WAND.get()) { + ItemWandSymmetry.apply(player.world, inv.getStackInSlot(i), player, event.getPos(), + event.getPlacedBlock()); + } + } + } + + @SubscribeEvent(priority = EventPriority.LOWEST) + public static void onBlockDestroyed(BreakEvent event) { + if (event.getWorld().isRemote()) + return; + + PlayerEntity player = event.getPlayer(); + PlayerInventory inv = player.inventory; + for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { + if (!inv.getStackInSlot(i).isEmpty() && AllItems.SYMMETRY_WAND.typeOf(inv.getStackInSlot(i))) { + ItemWandSymmetry.remove(player.world, inv.getStackInSlot(i), player, event.getPos()); + } + } + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void render(RenderWorldLastEvent event) { + Minecraft mc = Minecraft.getInstance(); + ClientPlayerEntity player = mc.player; + + GL11.glEnable(GL11.GL_BLEND); + + for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { + ItemStack stackInSlot = player.inventory.getStackInSlot(i); + if (stackInSlot != null && AllItems.SYMMETRY_WAND.typeOf(stackInSlot) + && ItemWandSymmetry.isEnabled(stackInSlot)) { + SymmetryElement mirror = ItemWandSymmetry.getMirror(stackInSlot); + if (mirror instanceof SymmetryEmptySlot) + continue; + + TessellatorHelper.prepareForDrawing(); + BlockPos pos = new BlockPos(mirror.getPosition()); + + float yShift = 0; + double speed = 1 / 16d; + yShift = MathHelper.sin((float) ((tickCounter + event.getPartialTicks()) * speed)) / 5f; + + BufferBuilder buffer = Tessellator.getInstance().getBuffer(); + buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.BLOCK); + GlStateManager.pushMatrix(); + GlStateManager.translated(0, yShift + .2f, 0); + mc.getBlockRendererDispatcher().renderBlock(mirror.getModel(), pos, player.world, buffer, player.world.getRandom(), + EmptyModelData.INSTANCE); + Tessellator.getInstance().draw(); + GlStateManager.popMatrix(); + TessellatorHelper.cleanUpAfterDrawing(); + + } + } + + GL11.glDisable(GL11.GL_BLEND); + } + + @OnlyIn(Dist.CLIENT) + @SubscribeEvent + public static void onClientTick(ClientTickEvent event) { + Minecraft mc = Minecraft.getInstance(); + ClientPlayerEntity player = mc.player; + + if (mc.world == null) + return; + if (mc.isGamePaused()) + return; + + tickCounter++; + + if (tickCounter % 10 == 0) { + for (int i = 0; i < PlayerInventory.getHotbarSize(); i++) { + ItemStack stackInSlot = player.inventory.getStackInSlot(i); + + if (stackInSlot != null && AllItems.SYMMETRY_WAND.typeOf(stackInSlot) + && ItemWandSymmetry.isEnabled(stackInSlot)) { + + SymmetryElement mirror = ItemWandSymmetry.getMirror(stackInSlot); + if (mirror instanceof SymmetryEmptySlot) + continue; + + Random r = new Random(); + double offsetX = (r.nextDouble() - 0.5) * 0.3; + double offsetZ = (r.nextDouble() - 0.5) * 0.3; + + Vec3d pos = mirror.getPosition().add(0.5 + offsetX, 1 / 4d, 0.5 + offsetZ); + Vec3d speed = new Vec3d(0, r.nextDouble() * 1 / 8f, 0); + mc.world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, speed.z); + } + } + } + + } + + public static void drawEffect(BlockPos from, BlockPos to) { + double density = 0.3f; + Vec3d start = new Vec3d(from).add(0.5, 0.5, 0.5); + Vec3d end = new Vec3d(to).add(0.5, 0.5, 0.5); + Vec3d diff = end.subtract(start); + + Vec3d step = diff.normalize().scale(density); + int steps = (int) (diff.length() / step.length()); + + Random r = new Random(); + for (int i = 5; i < steps - 1; i++) { + Vec3d pos = start.add(step.scale(i)); + Vec3d speed = new Vec3d(0, r.nextDouble() * -40f, 0); + Minecraft.getInstance().world.addParticle(ParticleTypes.WITCH, pos.x, pos.y, pos.z, speed.x, + speed.y, speed.z); + } + + Vec3d speed = new Vec3d(0, r.nextDouble() * 1 / 32f, 0); + Vec3d pos = start.add(step.scale(5)); + Minecraft.getInstance().world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, + speed.z); + + speed = new Vec3d(0, r.nextDouble() * 1 / 32f, 0); + pos = start.add(step.scale(steps)); + Minecraft.getInstance().world.addParticle(ParticleTypes.END_ROD, pos.x, pos.y, pos.z, speed.x, speed.y, + speed.z); + } + +} diff --git a/src/main/java/com/simibubi/create/item/symmetry/SymmetryCrossPlane.java b/src/main/java/com/simibubi/create/item/symmetry/SymmetryCrossPlane.java new file mode 100644 index 000000000..e1579bc6a --- /dev/null +++ b/src/main/java/com/simibubi/create/item/symmetry/SymmetryCrossPlane.java @@ -0,0 +1,96 @@ +package com.simibubi.create.item.symmetry; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.block.symmetry.BlockSymmetryCrossPlane; + +import net.minecraft.block.BlockState; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class SymmetryCrossPlane extends SymmetryElement { + + public static enum Align implements IStringSerializable { + Y("y"), D("d"); + + private final String name; + + private Align(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + } + + public SymmetryCrossPlane(Vec3d pos) { + super(pos); + orientation = Align.Y; + } + + @Override + protected void setOrientation() { + if (orientationIndex < 0) + orientationIndex += Align.values().length; + if (orientationIndex >= Align.values().length) + orientationIndex -= Align.values().length; + orientation = Align.values()[orientationIndex]; + } + + @Override + public void setOrientation(int index) { + this.orientation = Align.values()[index]; + orientationIndex = index; + } + + @Override + public Map process(BlockPos position, BlockState block) { + Map result = new HashMap<>(); + + switch ((Align) orientation) { + case D: + result.put(flipD1(position), flipD1(block)); + result.put(flipD2(position), flipD2(block)); + result.put(flipD1(flipD2(position)), flipD1(flipD2(block))); + break; + case Y: + result.put(flipX(position), flipX(block)); + result.put(flipZ(position), flipZ(block)); + result.put(flipX(flipZ(position)), flipX(flipZ(block))); + break; + default: + break; + } + + return result; + } + + @Override + public String typeName() { + return CROSS_PLANE; + } + + @Override + public BlockState getModel() { + return AllBlocks.SYMMETRY_CROSSPLANE.block.getDefaultState().with(BlockSymmetryCrossPlane.align, + (Align) orientation); + } + + @Override + public List getAlignToolTips() { + return ImmutableList.of("Orthogonal", "Diagonal"); + } + +} diff --git a/src/main/java/com/simibubi/create/item/symmetry/SymmetryElement.java b/src/main/java/com/simibubi/create/item/symmetry/SymmetryElement.java new file mode 100644 index 000000000..9da5f2859 --- /dev/null +++ b/src/main/java/com/simibubi/create/item/symmetry/SymmetryElement.java @@ -0,0 +1,255 @@ +package com.simibubi.create.item.symmetry; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; + +import net.minecraft.block.BlockState; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.nbt.FloatNBT; +import net.minecraft.nbt.ListNBT; +import net.minecraft.state.DirectionProperty; +import net.minecraft.state.IProperty; +import net.minecraft.state.properties.BlockStateProperties; +import net.minecraft.util.Direction; +import net.minecraft.util.Direction.Axis; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.Mirror; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public abstract class SymmetryElement { + + public static final String EMPTY = "empty"; + public static final String PLANE = "plane"; + public static final String CROSS_PLANE = "cross_plane"; + public static final String TRIPLE_PLANE = "triple_plane"; + + public static final List TOOLTIP_ELEMENTS = ImmutableList.of("Mirror once", "Rectanglar", "Octagonal"); + + protected Vec3d position; + protected IStringSerializable orientation; + protected int orientationIndex; + public boolean enable; + + public SymmetryElement(Vec3d pos) { + position = pos; + enable = true; + orientationIndex = 0; + } + + public IStringSerializable getOrientation() { + return orientation; + } + + public Vec3d getPosition() { + return position; + } + + public int getOrientationIndex() { + return orientationIndex; + } + + public void rotate(boolean forward) { + orientationIndex += forward ? 1 : -1; + setOrientation(); + } + + public void process(Map blocks) { + Map result = new HashMap<>(); + for (BlockPos pos : blocks.keySet()) { + result.putAll(process(pos, blocks.get(pos))); + } + blocks.putAll(result); + } + + public abstract Map process(BlockPos position, BlockState block); + + protected abstract void setOrientation(); + + public abstract void setOrientation(int index); + + public abstract String typeName(); + + public abstract BlockState getModel(); + + private static final String $ORIENTATION = "direction"; + private static final String $POSITION = "pos"; + private static final String $TYPE = "type"; + private static final String $ENABLE = "enable"; + + public CompoundNBT writeToNbt() { + CompoundNBT nbt = new CompoundNBT(); + nbt.putInt($ORIENTATION, orientationIndex); + + ListNBT floatList = new ListNBT(); + floatList.add(new FloatNBT((float) position.x)); + floatList.add(new FloatNBT((float) position.y)); + floatList.add(new FloatNBT((float) position.z)); + nbt.put($POSITION, floatList); + nbt.putString($TYPE, typeName()); + nbt.putBoolean($ENABLE, enable); + + return nbt; + } + + public static SymmetryElement fromNBT(CompoundNBT nbt) { + ListNBT floatList = nbt.getList($POSITION, 5); + Vec3d pos = new Vec3d(floatList.getFloat(0), floatList.getFloat(1), floatList.getFloat(2)); + SymmetryElement element; + + switch (nbt.getString($TYPE)) { + case PLANE: + element = new SymmetryPlane(pos); + break; + case CROSS_PLANE: + element = new SymmetryCrossPlane(pos); + break; + case TRIPLE_PLANE: + element = new SymmetryTriplePlane(pos); + break; + default: + element = new SymmetryEmptySlot(pos); + break; + } + + element.setOrientation(nbt.getInt($ORIENTATION)); + element.enable = nbt.getBoolean($ENABLE); + + return element; + } + + protected Vec3d getDiff(BlockPos position) { + return this.position.scale(-1).add(position.getX(), position.getY(), position.getZ()); + } + + protected BlockPos getIDiff(BlockPos position) { + Vec3d diff = getDiff(position); + return new BlockPos((int) diff.x, (int) diff.y, (int) diff.z); + } + + protected BlockState flipX(BlockState in) { + return in.mirror(Mirror.FRONT_BACK); + } + + protected BlockState flipY(BlockState in) { + for (IProperty property : in.getProperties()) { + + if (property == BlockStateProperties.HALF) + return in.cycle(property); + // Directional Blocks + if (property instanceof DirectionProperty) { + if (in.get(property) == Direction.DOWN) { + return in.with((DirectionProperty) property, Direction.UP); + } else if (in.get(property) == Direction.UP) { + return in.with((DirectionProperty) property, Direction.DOWN); + } + } + } + return in; + } + + protected BlockState flipZ(BlockState in) { + return in.mirror(Mirror.LEFT_RIGHT); + } + + protected BlockState flipD1(BlockState in) { + for (IProperty property : in.getProperties()) { + + if (property == BlockStateProperties.AXIS || property == BlockStateProperties.HORIZONTAL_AXIS) { + Axis axis = ((Axis) in.get(property)); + if (axis.isVertical()) + return in; + Axis value = axis == Axis.X ? Axis.Z : Axis.X; + if (property == BlockStateProperties.AXIS) + return in.with(BlockStateProperties.AXIS, value); + return in.with(BlockStateProperties.HORIZONTAL_AXIS, value); + } + + if (property instanceof DirectionProperty) { + switch ((Direction) in.get(property)) { + case EAST: + return in.with((DirectionProperty) property, Direction.NORTH); + case NORTH: + return in.with((DirectionProperty) property, Direction.EAST); + case SOUTH: + return in.with((DirectionProperty) property, Direction.WEST); + case WEST: + return in.with((DirectionProperty) property, Direction.SOUTH); + default: + break; + } + } + + } + return in; + } + + protected BlockState flipD2(BlockState in) { + for (IProperty property : in.getProperties()) { + + if (property == BlockStateProperties.AXIS || property == BlockStateProperties.HORIZONTAL_AXIS) { + Axis axis = ((Axis) in.get(property)); + if (axis.isVertical()) + return in; + Axis value = axis == Axis.X ? Axis.Z : Axis.X; + if (property == BlockStateProperties.AXIS) + return in.with(BlockStateProperties.AXIS, value); + return in.with(BlockStateProperties.HORIZONTAL_AXIS, value); + } + + if (property instanceof DirectionProperty) { + switch ((Direction) in.get(property)) { + case EAST: + return in.with((DirectionProperty) property, Direction.SOUTH); + case NORTH: + return in.with((DirectionProperty) property, Direction.WEST); + case SOUTH: + return in.with((DirectionProperty) property, Direction.EAST); + case WEST: + return in.with((DirectionProperty) property, Direction.NORTH); + default: + break; + } + } + + } + return in; + } + + protected BlockPos flipX(BlockPos position) { + BlockPos diff = getIDiff(position); + return new BlockPos(position.getX() - 2 * diff.getX(), position.getY(), position.getZ()); + } + + protected BlockPos flipY(BlockPos position) { + BlockPos diff = getIDiff(position); + return new BlockPos(position.getX(), position.getY() - 2 * diff.getY(), position.getZ()); + } + + protected BlockPos flipZ(BlockPos position) { + BlockPos diff = getIDiff(position); + return new BlockPos(position.getX(), position.getY(), position.getZ() - 2 * diff.getZ()); + } + + protected BlockPos flipD2(BlockPos position) { + BlockPos diff = getIDiff(position); + return new BlockPos(position.getX() - diff.getX() + diff.getZ(), position.getY(), + position.getZ() - diff.getZ() + diff.getX()); + } + + protected BlockPos flipD1(BlockPos position) { + BlockPos diff = getIDiff(position); + return new BlockPos(position.getX() - diff.getX() - diff.getZ(), position.getY(), + position.getZ() - diff.getZ() - diff.getX()); + } + + public void setPosition(Vec3d pos3d) { + this.position = pos3d; + } + + public abstract List getAlignToolTips(); + +} diff --git a/src/main/java/com/simibubi/create/item/symmetry/SymmetryEmptySlot.java b/src/main/java/com/simibubi/create/item/symmetry/SymmetryEmptySlot.java new file mode 100644 index 000000000..6e3de73cb --- /dev/null +++ b/src/main/java/com/simibubi/create/item/symmetry/SymmetryEmptySlot.java @@ -0,0 +1,60 @@ +package com.simibubi.create.item.symmetry; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; + +import net.minecraft.block.BlockState; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class SymmetryEmptySlot extends SymmetryElement { + + public static enum Align implements IStringSerializable { + None("none"); + + private final String name; + private Align(String name) { this.name = name; } + @Override public String getName() { return name; } + @Override public String toString() { return name; } + } + + public SymmetryEmptySlot(Vec3d pos) { + super(pos); + orientation = Align.None; + } + + @Override + protected void setOrientation() { + } + + @Override + public void setOrientation(int index) { + this.orientation = Align.values()[index]; + orientationIndex = index; + } + + @Override + public Map process(BlockPos position, BlockState block) { + return new HashMap<>(); + } + + @Override + public String typeName() { + return EMPTY; + } + + @Override + public BlockState getModel() { + return null; + } + + @Override + public List getAlignToolTips() { + return ImmutableList.of(); + } + +} diff --git a/src/main/java/com/simibubi/create/item/symmetry/SymmetryPlane.java b/src/main/java/com/simibubi/create/item/symmetry/SymmetryPlane.java new file mode 100644 index 000000000..cae0b3a64 --- /dev/null +++ b/src/main/java/com/simibubi/create/item/symmetry/SymmetryPlane.java @@ -0,0 +1,91 @@ +package com.simibubi.create.item.symmetry; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; +import com.simibubi.create.block.symmetry.BlockSymmetryPlane; + +import net.minecraft.block.BlockState; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class SymmetryPlane extends SymmetryElement { + + public static enum Align implements IStringSerializable { + XY("xy"), YZ("yz"); + + private final String name; + + private Align(String name) { + this.name = name; + } + + @Override + public String getName() { + return name; + } + + @Override + public String toString() { + return name; + } + } + + public SymmetryPlane(Vec3d pos) { + super(pos); + orientation = Align.XY; + } + + @Override + protected void setOrientation() { + if (orientationIndex < 0) + orientationIndex += Align.values().length; + if (orientationIndex >= Align.values().length) + orientationIndex -= Align.values().length; + orientation = Align.values()[orientationIndex]; + } + + @Override + public void setOrientation(int index) { + this.orientation = Align.values()[index]; + orientationIndex = index; + } + + @Override + public Map process(BlockPos position, BlockState block) { + Map result = new HashMap<>(); + switch ((Align) orientation) { + + case XY: + result.put(flipZ(position), flipZ(block)); + break; + case YZ: + result.put(flipX(position), flipX(block)); + break; + default: + break; + + } + return result; + } + + @Override + public String typeName() { + return PLANE; + } + + @Override + public BlockState getModel() { + return AllBlocks.SYMMETRY_PLANE.block.getDefaultState().with(BlockSymmetryPlane.align, (Align) orientation); + } + + @Override + public List getAlignToolTips() { + return ImmutableList.of("Mirror Z", "Mirror X"); + } + +} diff --git a/src/main/java/com/simibubi/create/item/symmetry/SymmetryTriplePlane.java b/src/main/java/com/simibubi/create/item/symmetry/SymmetryTriplePlane.java new file mode 100644 index 000000000..b651d2030 --- /dev/null +++ b/src/main/java/com/simibubi/create/item/symmetry/SymmetryTriplePlane.java @@ -0,0 +1,66 @@ +package com.simibubi.create.item.symmetry; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import com.google.common.collect.ImmutableList; +import com.simibubi.create.AllBlocks; + +import net.minecraft.block.BlockState; +import net.minecraft.util.IStringSerializable; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class SymmetryTriplePlane extends SymmetryElement { + + public SymmetryTriplePlane(Vec3d pos) { + super(pos); + orientationIndex = 0; + } + + @Override + public Map process(BlockPos position, BlockState block) { + Map result = new HashMap<>(); + + result.put(flipX(position), flipX(block)); + result.put(flipZ(position), flipZ(block)); + result.put(flipX(flipZ(position)), flipX(flipZ(block))); + + result.put(flipD1(position), flipD1(block)); + result.put(flipD1(flipX(position)), flipD1(flipX(block))); + result.put(flipD1(flipZ(position)), flipD1(flipZ(block))); + result.put(flipD1(flipX(flipZ(position))), flipD1(flipX(flipZ(block)))); + + return result; + } + + @Override + public String typeName() { + return TRIPLE_PLANE; + } + + @Override + public BlockState getModel() { + return AllBlocks.SYMMETRY_TRIPLEPLANE.block.getDefaultState(); + } + + @Override + protected void setOrientation() { + } + + @Override + public void setOrientation(int index) { + } + + @Override + public IStringSerializable getOrientation() { + return SymmetryCrossPlane.Align.Y; + } + + @Override + public List getAlignToolTips() { + return ImmutableList.of("Horizontal"); + } + +} diff --git a/src/main/java/com/simibubi/create/networking/PacketNbt.java b/src/main/java/com/simibubi/create/networking/PacketNbt.java new file mode 100644 index 000000000..1b90cc077 --- /dev/null +++ b/src/main/java/com/simibubi/create/networking/PacketNbt.java @@ -0,0 +1,36 @@ +package com.simibubi.create.networking; + +import java.util.function.Supplier; + +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class PacketNbt { + + public ItemStack stack; + + public PacketNbt(ItemStack stack) { + this.stack = stack; + } + + public PacketNbt(PacketBuffer buffer) { + stack = buffer.readItemStack(); + } + + public void toBytes(PacketBuffer buffer) { + buffer.writeItemStack(stack); + } + + public void handle(Supplier context) { + context.get().enqueueWork(() -> { + ServerPlayerEntity player = context.get().getSender(); + ItemStack heldItem = player.getHeldItemMainhand(); + if (heldItem.getItem() == stack.getItem()) { + heldItem.setTag(stack.getTag()); + } + }); + } + +} diff --git a/src/main/java/com/simibubi/create/networking/PacketSymmetryEffect.java b/src/main/java/com/simibubi/create/networking/PacketSymmetryEffect.java new file mode 100644 index 000000000..9f75e432d --- /dev/null +++ b/src/main/java/com/simibubi/create/networking/PacketSymmetryEffect.java @@ -0,0 +1,50 @@ +package com.simibubi.create.networking; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Supplier; + +import com.simibubi.create.item.SymmetryHandler; + +import net.minecraft.client.Minecraft; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraftforge.fml.network.NetworkEvent.Context; + +public class PacketSymmetryEffect { + + private BlockPos mirror; + private List positions; + + public PacketSymmetryEffect(BlockPos mirror, List positions) { + this.mirror = mirror; + this.positions = positions; + } + + public PacketSymmetryEffect(PacketBuffer buffer) { + mirror = buffer.readBlockPos(); + int amt = buffer.readInt(); + positions = new ArrayList<>(amt); + for (int i = 0; i < amt; i++) { + positions.add(buffer.readBlockPos()); + } + } + + public void toBytes(PacketBuffer buffer) { + buffer.writeBlockPos(mirror); + buffer.writeInt(positions.size()); + for (BlockPos blockPos : positions) { + buffer.writeBlockPos(blockPos); + } + } + + public void handle(Supplier context) { + if (Minecraft.getInstance().player.getPositionVector().distanceTo(new Vec3d(mirror)) > 100) + return; + + for (BlockPos to : positions) + SymmetryHandler.drawEffect(mirror, to); + } + +} diff --git a/src/main/java/com/simibubi/create/networking/Packets.java b/src/main/java/com/simibubi/create/networking/Packets.java new file mode 100644 index 000000000..7ca507cf5 --- /dev/null +++ b/src/main/java/com/simibubi/create/networking/Packets.java @@ -0,0 +1,23 @@ +package com.simibubi.create.networking; + +import com.simibubi.create.Create; + +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.fml.network.NetworkRegistry; +import net.minecraftforge.fml.network.simple.SimpleChannel; + +public class Packets { + + public static final SimpleChannel channel = NetworkRegistry.newSimpleChannel( + new ResourceLocation(Create.ID, "simple_channel"), () -> "1", v -> v.equals("1"), v -> v.equals("1")); + + public static void registerPackets() { + int i = 0; + + channel.registerMessage(i++, PacketNbt.class, PacketNbt::toBytes, PacketNbt::new, + PacketNbt::handle); + channel.registerMessage(i++, PacketSymmetryEffect.class, PacketSymmetryEffect::toBytes, PacketSymmetryEffect::new, + PacketSymmetryEffect::handle); + } + +} diff --git a/src/main/java/com/simibubi/create/utility/Keyboard.java b/src/main/java/com/simibubi/create/utility/Keyboard.java new file mode 100644 index 000000000..088e26633 --- /dev/null +++ b/src/main/java/com/simibubi/create/utility/Keyboard.java @@ -0,0 +1,30 @@ +package com.simibubi.create.utility; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.util.InputMappings; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +@OnlyIn(Dist.CLIENT) +public class Keyboard { + + public static final int PRESS = 1; + public static final int HOLD = 2; + public static final int RELEASE = 0; + + public static final int LSHIFT = 340; + public static final int LALT = 342; + public static final int RETURN = 257; + + public static final int DOWN = 264; + public static final int LEFT = 263; + public static final int RIGHT = 262; + public static final int UP = 265; + + public static final int G = 71; + + public static boolean isKeyDown(int key) { + return InputMappings.isKeyDown(Minecraft.getInstance().mainWindow.getHandle(), key); + } + +} diff --git a/src/main/java/com/simibubi/create/utility/TessellatorHelper.java b/src/main/java/com/simibubi/create/utility/TessellatorHelper.java new file mode 100644 index 000000000..22d3e53bd --- /dev/null +++ b/src/main/java/com/simibubi/create/utility/TessellatorHelper.java @@ -0,0 +1,216 @@ +package com.simibubi.create.utility; + +import org.lwjgl.opengl.GL11; + +import com.mojang.blaze3d.platform.GlStateManager; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ActiveRenderInfo; +import net.minecraft.client.renderer.BufferBuilder; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +public class TessellatorHelper { + + public static final float fontScale = 1/512f; + + public static void prepareForDrawing() { + Minecraft mc = Minecraft.getInstance(); + GlStateManager.pushMatrix(); + GlStateManager.pushLightingAttributes(); + GlStateManager.enableBlend(); + GlStateManager.enableAlphaTest(); + GlStateManager.color4f(1, 1, 1, 1); + + ActiveRenderInfo renderInfo = mc.gameRenderer.getActiveRenderInfo(); + Vec3d view = renderInfo.getProjectedView(); + GlStateManager.translated(-view.x, -view.y, -view.z); + } + + public static void begin() { + Tessellator.getInstance().getBuffer().begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX); + } + + public static void draw() { + Tessellator.getInstance().draw(); + } + + public static void cleanUpAfterDrawing() { + GlStateManager.disableAlphaTest(); + GlStateManager.disableBlend(); + GlStateManager.popAttributes(); + GlStateManager.popMatrix(); + } + + public static void drawString(String str, float x, float y, float z, boolean scalesUp, boolean hasDepth) { + Minecraft mc = Minecraft.getInstance(); + float pitch = mc.getRenderManager().playerViewX; + float yaw = mc.getRenderManager().playerViewY; + boolean isThirdPersonFrontal = mc.gameSettings.thirdPersonView == 2; + + GlStateManager.pushMatrix(); + GlStateManager.pushLightingAttributes(); + GlStateManager.translatef(x, y, z); + GlStateManager.normal3f(0.0F, 1.0F, 0.0F); + GlStateManager.rotatef(-yaw, 0.0F, 1.0F, 0.0F); + GlStateManager.rotatef((float) (isThirdPersonFrontal ? -1 : 1) * pitch, 1.0F, 0.0F, 0.0F); + GlStateManager.scalef(-0.025F, -0.025F, 0.025F); + GlStateManager.disableLighting(); + if (!hasDepth) { + GlStateManager.depthMask(false); + GlStateManager.disableDepthTest(); + } + + GlStateManager.enableBlend(); + GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ONE, + GlStateManager.DestFactor.ZERO); + int i = mc.fontRenderer.getStringWidth(str) / 2; + GlStateManager.disableTexture(); + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder bufferbuilder = tessellator.getBuffer(); + bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR); + bufferbuilder.pos((double) (-i - 3), (double) (-3), 0.0D).color(1F, 1F, 1F, .5F).endVertex(); + bufferbuilder.pos((double) (-i - 3), (double) (10), 0.0D).color(1F, 1F, 1F, .5F).endVertex(); + bufferbuilder.pos((double) (i + 3), (double) (10), 0.0D).color(1F, 1F, 1F, .5F).endVertex(); + bufferbuilder.pos((double) (i + 3), (double) (-3), 0.0D).color(1F, 1F, 1F, .5F).endVertex(); + + if (scalesUp) { + double distance = mc.player.getEyePosition(mc.getRenderPartialTicks()).squareDistanceTo(x, y, z); + double scale = distance * fontScale; + GlStateManager.scaled(2 + scale, 2 + scale, 2 + scale); + } + tessellator.draw(); + GlStateManager.enableTexture(); + if (hasDepth) { + GlStateManager.translatef(0, 0, -0.125f); + } + + mc.fontRenderer.drawString(str, -mc.fontRenderer.getStringWidth(str) / 2, 0, 0); + GlStateManager.enableDepthTest(); + + GlStateManager.color4f(1.0F, 1.0F, 1.0F, 1.0F); + GlStateManager.depthMask(true); + GlStateManager.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.SRC_ALPHA, + GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); + GlStateManager.popMatrix(); + GlStateManager.popAttributes(); + } + + public static void cube(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale, + boolean scaleVertical, boolean doubleFaces) { + TessellatorHelper.walls(bufferBuilder, pos, size, scale, scaleVertical, doubleFaces); + int w = size.getX(); + int h = size.getY(); + int l = size.getZ(); + + if (doubleFaces) { + TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false); + TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false); + } else { + TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, 0, l), scale, true, scaleVertical, false, false); + TessellatorHelper.face(bufferBuilder, pos.east(w).up(h), new BlockPos(-w, 0, l), scale, true, scaleVertical, false, false); + } + } + + public static void walls(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double scale, + boolean scaleVertical, boolean doubleFaces) { + int w = size.getX(); + int h = size.getY(); + int l = size.getZ(); + + if (doubleFaces) { + TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false); + TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false); + TessellatorHelper.doubleFace(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false); + TessellatorHelper.doubleFace(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false); + } else { + TessellatorHelper.face(bufferBuilder, pos, new BlockPos(w, h, 0), scale, true, scaleVertical, false, false); + TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(0, h, -l), scale, true, scaleVertical, false, false); + TessellatorHelper.face(bufferBuilder, pos.east(w).south(l), new BlockPos(-w, h, 0), scale, true, scaleVertical, false, false); + TessellatorHelper.face(bufferBuilder, pos, new BlockPos(0, h, l), scale, true, scaleVertical, false, false); + } + } + + public static void doubleFace(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, + boolean stretch, boolean shiftVertical, boolean mirrorTexture) { + TessellatorHelper.face(bufferBuilder, pos, size, shift, stretch, shiftVertical, false, mirrorTexture); + TessellatorHelper.face(bufferBuilder, pos.add(size.getX(), 0, (size.getY() == 0) ? 0 : size.getZ()), + new BlockPos(-size.getX(), size.getY(), (size.getY() == 0) ? size.getZ() : -size.getZ()), -shift, + stretch, shiftVertical, true, mirrorTexture); + } + + public static void face(BufferBuilder bufferBuilder, BlockPos pos, BlockPos size, double shift, boolean stretch, + boolean shiftVertical, boolean shiftBackwards, boolean mirrorTexture) { + int w = size.getX(); + int h = size.getY(); + int l = size.getZ(); + if (shiftBackwards) + shift = -shift; + + if (w == 0) { // YZ plane -> H has to be positive + + double xs = (l < 0) ? shift : -shift; + if (shiftBackwards) + xs = -xs; + double ys1 = shiftVertical ? shift : 0; + double zs1 = l < 0 ? -shift : shift; + if (!stretch && (l > 0 ^ mirrorTexture)) + zs1 = -zs1; + double ys2 = stretch ? -ys1 : ys1; + double zs2 = stretch ? -zs1 : zs1; + double u1 = (mirrorTexture) ? l : 0; + double u2 = (mirrorTexture) ? 0 : l; + + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs1), pos.south(l), u2, h); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys1, zs1), pos.south(l).up(h), u2, 0); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys1, zs2), pos.up(h), u1, 0); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs, ys2, zs2), pos, u1, h); + + } else if (h == 0) { // XZ plane -> L has to be positive + + double ys = w < 0 ? shift : -shift; + if (shiftBackwards) + ys = -ys; + double xs1 = w < 0 ? -shift : shift; + double zs1 = shift; + double xs2 = stretch ? -xs1 : xs1; + double zs2 = stretch ? -zs1 : zs1; + double u1 = (mirrorTexture) ? w : 0; + double u2 = (mirrorTexture) ? 0 : w; + + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs1), pos.south(l), u1, l); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys, zs2), pos, u1, 0); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs2), pos.east(w), u2, 0); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys, zs1), pos.east(w).south(l), u2, l); + + } else if (l == 0) { // XY plane -> H has to be positive + + double zs = w < 0 ? shift : -shift; + if (shiftBackwards) + zs = -zs; + double ys1 = shiftVertical ? shift : 0; + double xs1 = w < 0 ? -shift : shift; + if (!stretch && (w > 0 ^ mirrorTexture)) + xs1 = -xs1; + double ys2 = stretch ? -ys1 : ys1; + double xs2 = stretch ? -xs1 : xs1; + double u1 = (mirrorTexture) ? w : 0; + double u2 = (mirrorTexture) ? 0 : w; + + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys2, zs), pos, u1, h); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs2, ys1, zs), pos.up(h), u1, 0); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys1, zs), pos.east(w).up(h), u2, 0); + TessellatorHelper.posTexShift(bufferBuilder, new Vec3d(xs1, ys2, zs), pos.east(w), u2, h); + + } + } + + private static void posTexShift(BufferBuilder bufferBuilder, Vec3d shift, BlockPos pos, double u, double v) { + bufferBuilder.pos(shift.x + pos.getX(), shift.y + pos.getY(), shift.z + pos.getZ()).tex(u, v).endVertex(); + } + +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml new file mode 100644 index 000000000..24fd5fc78 --- /dev/null +++ b/src/main/resources/META-INF/mods.toml @@ -0,0 +1,56 @@ +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="[26,)" #mandatory (26 is current forge version) +# A URL to refer people to when problems occur with this mod +#issueTrackerURL=""#optional +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="create" #mandatory +# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it +version="${file.jarVersion}" #mandatory + # A display name for the mod +displayName="Create" #mandatory +# A URL to query for updates for this mod. See the JSON update specification +#updateJSONURL=""#optional +# A URL for the "homepage" for this mod, displayed in the mod UI +displayURL="http://example.com/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +logoFile="examplemod.png" #optional +# A text field displayed in the mod UI +credits="Thanks for this example mod goes to Java" #optional +# A text field displayed in the mod UI +authors="simibubi" #optional +# The description text for the mod (multi line!) (#mandatory) +description=''' +This is a long form description of the mod. You can write whatever you want here + +Have some lorem ipsum. + +Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis lacinia magna. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Sed sagittis luctus odio eu tempus. Interdum et malesuada fames ac ante ipsum primis in faucibus. Pellentesque volutpat ligula eget lacus auctor sagittis. In hac habitasse platea dictumst. Nunc gravida elit vitae sem vehicula efficitur. Donec mattis ipsum et arcu lobortis, eleifend sagittis sem rutrum. Cras pharetra quam eget posuere fermentum. Sed id tincidunt justo. Lorem ipsum dolor sit amet, consectetur adipiscing elit. +''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.examplemod]] #optional + # the modid of the dependency + modId="forge" #mandatory + # Does this dependency have to exist - if not, ordering below must be specified + mandatory=true #mandatory + # The version range of the dependency + versionRange="[27,)" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory + ordering="NONE" + # Side this dependency is applied on - BOTH, CLIENT or SERVER + side="BOTH" +# Here's another dependency +[[dependencies.examplemod]] + modId="minecraft" + mandatory=true + versionRange="[1.14.3]" + ordering="NONE" + side="BOTH" \ No newline at end of file diff --git a/src/main/resources/assets/create/blockstates/symmetry_crossplane.json b/src/main/resources/assets/create/blockstates/symmetry_crossplane.json new file mode 100644 index 000000000..9e96d8f55 --- /dev/null +++ b/src/main/resources/assets/create/blockstates/symmetry_crossplane.json @@ -0,0 +1,7 @@ +{ + "forgemarker": 1, + "variants": { + "align=y": { "model": "create:block/symmetry_crossplane"}, + "align=d": { "model": "create:block/symmetry_crossplane_diagonal"} + } +} diff --git a/src/main/resources/assets/create/blockstates/symmetry_plane.json b/src/main/resources/assets/create/blockstates/symmetry_plane.json new file mode 100644 index 000000000..48859198d --- /dev/null +++ b/src/main/resources/assets/create/blockstates/symmetry_plane.json @@ -0,0 +1,7 @@ +{ + "forgemarker": 1, + "variants": { + "align=xy": { "model": "create:block/symmetry_plane" }, + "align=yz": { "model": "create:block/symmetry_plane", "y": 90 } + } +} diff --git a/src/main/resources/assets/create/blockstates/symmetry_tripleplane.json b/src/main/resources/assets/create/blockstates/symmetry_tripleplane.json new file mode 100644 index 000000000..2574d1eaf --- /dev/null +++ b/src/main/resources/assets/create/blockstates/symmetry_tripleplane.json @@ -0,0 +1,6 @@ +{ + "forgemarker": 1, + "variants": { + "": { "model": "create:block/symmetry_tripleplane" } + } +} diff --git a/src/main/resources/assets/create/lang/en_us.json b/src/main/resources/assets/create/lang/en_us.json new file mode 100644 index 000000000..248e40894 --- /dev/null +++ b/src/main/resources/assets/create/lang/en_us.json @@ -0,0 +1,4 @@ +{ + "item.create.symmetry_wand": "Staff of Symmetry", + "itemGroup.create": "Create" +} diff --git a/src/main/resources/assets/create/models/block/symmetry_crossplane.json b/src/main/resources/assets/create/models/block/symmetry_crossplane.json new file mode 100644 index 000000000..4e221b354 --- /dev/null +++ b/src/main/resources/assets/create/models/block/symmetry_crossplane.json @@ -0,0 +1,144 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", + "textures": { + "0": "block/white_stained_glass", + "1": "block/obsidian", + "2": "block/blue_terracotta" + }, + "elements": [ + { + "name": "Mirror", + "from": [ 4.0, 1.0, 7.500000007450581 ], + "to": [ 7.0, 12.0, 8.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 7.0, 15.0 ] } + } + }, + { + "name": "rod_left_bottom", + "from": [ 1.2000000029802322, 3.0, 7.0 ], + "to": [ 3.2000000029802322, 4.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left_top", + "from": [ 1.2000000029802322, 12.0, 7.0 ], + "to": [ 3.2000000029802322, 13.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left", + "from": [ 2.0, 4.0, 7.499999992549419 ], + "to": [ 3.0, 12.0, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -22.5 }, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 0.0, 4.0, 8.0 ] }, + "south": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 1.0, 6.0, 9.0 ] } + } + }, + { + "name": "rod_right_bottom", + "from": [ 12.799999997019768, 3.0, 7.0 ], + "to": [ 14.799999997019768, 4.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_right", + "from": [ 13.0, 4.0, 7.499999992549419 ], + "to": [ 14.0, 12.0, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -22.5 }, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 2.0, 4.0, 10.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 3.0, 4.0, 11.0 ] }, + "south": { "texture": "#2", "uv": [ 4.0, 3.0, 5.0, 11.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 0.0, 6.0, 8.0 ] } + } + }, + { + "name": "rod_right_top", + "from": [ 12.799999997019768, 12.0, 7.0 ], + "to": [ 14.799999997019768, 13.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "CrossMirror", + "from": [ 7.499999992549419, 4.0, 9.50000000745058 ], + "to": [ 8.49999999254942, 15.0, 12.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 6.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 1.0, 12.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 3.0, 3.0, 4.0, 6.0 ] }, + "down": { "texture": "#0", "uv": [ 5.0, 9.0, 6.0, 12.0 ] } + } + }, + { + "name": "Mirror II", + "from": [ 9.0, 3.0, 7.500000007450581 ], + "to": [ 12.0, 14.0, 8.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 7.0, 15.0 ] } + } + }, + { + "name": "CrossMirror II", + "from": [ 7.499999992549419, 2.0, 3.5000000074505806 ], + "to": [ 8.49999999254942, 13.0, 6.500000007450581 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 6.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 14.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 2.0, 12.0, 13.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 6.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 8.0, 5.0, 11.0 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/symmetry_crossplane_diagonal.json b/src/main/resources/assets/create/models/block/symmetry_crossplane_diagonal.json new file mode 100644 index 000000000..431ff819b --- /dev/null +++ b/src/main/resources/assets/create/models/block/symmetry_crossplane_diagonal.json @@ -0,0 +1,148 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", + "textures": { + "0": "block/white_stained_glass", + "1": "block/obsidian", + "2": "block/blue_terracotta" + }, + "elements": [ + { + "name": "Mirror", + "from": [ 4.0, 1.0, 7.500000007450581 ], + "to": [ 7.0, 12.0, 8.50000000745058 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 7.0, 15.0 ] } + } + }, + { + "name": "rod_left_bottom", + "from": [ 1.2000000029802322, 3.0, 7.0 ], + "to": [ 3.2000000029802322, 4.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left_top", + "from": [ 1.2000000029802322, 12.0, 7.0 ], + "to": [ 3.2000000029802322, 13.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left", + "from": [ 2.0, 4.0, 7.499999992549419 ], + "to": [ 3.0, 12.0, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 22.5 }, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 0.0, 4.0, 8.0 ] }, + "south": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 1.0, 6.0, 9.0 ] } + } + }, + { + "name": "rod_right_bottom", + "from": [ 12.799999997019768, 3.0, 7.0 ], + "to": [ 14.799999997019768, 4.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_right", + "from": [ 13.0, 4.0, 7.499999992549419 ], + "to": [ 14.0, 12.0, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 22.5 }, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 2.0, 4.0, 10.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 3.0, 4.0, 11.0 ] }, + "south": { "texture": "#2", "uv": [ 4.0, 3.0, 5.0, 11.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 0.0, 6.0, 8.0 ] } + } + }, + { + "name": "rod_right_top", + "from": [ 12.799999997019768, 12.0, 7.0 ], + "to": [ 14.799999997019768, 13.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 22.5 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "CrossMirror", + "from": [ 7.499999992549419, 4.0, 9.50000000745058 ], + "to": [ 8.49999999254942, 15.0, 12.50000000745058 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 6.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 1.0, 12.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 3.0, 3.0, 4.0, 6.0 ] }, + "down": { "texture": "#0", "uv": [ 5.0, 9.0, 6.0, 12.0 ] } + } + }, + { + "name": "Mirror II", + "from": [ 9.0, 3.0, 7.500000007450581 ], + "to": [ 12.0, 14.0, 8.50000000745058 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 7.0, 15.0 ] } + } + }, + { + "name": "CrossMirror II", + "from": [ 7.499999992549419, 2.0, 3.5000000074505806 ], + "to": [ 8.49999999254942, 13.0, 6.500000007450581 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 6.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 14.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 2.0, 12.0, 13.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 6.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 8.0, 5.0, 11.0 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/symmetry_plane.json b/src/main/resources/assets/create/models/block/symmetry_plane.json new file mode 100644 index 000000000..6b4c451ce --- /dev/null +++ b/src/main/resources/assets/create/models/block/symmetry_plane.json @@ -0,0 +1,99 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", + "textures": { + "0": "block/white_stained_glass", + "1": "block/obsidian", + "2": "block/blue_terracotta" + }, + "elements": [ + { + "name": "Mirror", + "from": [ 4.0, 1.0, 7.500000007450581 ], + "to": [ 12.0, 15.0, 8.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 12.0, 15.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 15.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 12.0, 15.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 15.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 12.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 12.0, 15.0 ] } + } + }, + { + "name": "rod_left_bottom", + "from": [ 1.2000000029802322, 3.0, 7.0 ], + "to": [ 3.2000000029802322, 4.0, 9.0 ], + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left_top", + "from": [ 1.2000000029802322, 12.0, 7.0 ], + "to": [ 3.2000000029802322, 13.0, 9.0 ], + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left", + "from": [ 2.0, 4.0, 7.499999992549419 ], + "to": [ 3.0, 12.0, 8.49999999254942 ], + "shade": false, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 0.0, 4.0, 8.0 ] }, + "south": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 1.0, 6.0, 9.0 ] } + } + }, + { + "name": "rod_right_bottom", + "from": [ 12.799999997019768, 3.0, 7.0 ], + "to": [ 14.799999997019768, 4.0, 9.0 ], + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_right", + "from": [ 13.0, 4.0, 7.499999992549419 ], + "to": [ 14.0, 12.0, 8.49999999254942 ], + "shade": false, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 2.0, 4.0, 10.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 3.0, 4.0, 11.0 ] }, + "south": { "texture": "#2", "uv": [ 4.0, 3.0, 5.0, 11.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 0.0, 6.0, 8.0 ] } + } + }, + { + "name": "rod_right_top", + "from": [ 12.799999997019768, 12.0, 7.0 ], + "to": [ 14.799999997019768, 13.0, 9.0 ], + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/block/symmetry_tripleplane.json b/src/main/resources/assets/create/models/block/symmetry_tripleplane.json new file mode 100644 index 000000000..e29c91958 --- /dev/null +++ b/src/main/resources/assets/create/models/block/symmetry_tripleplane.json @@ -0,0 +1,172 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", + "textures": { + "0": "block/white_stained_glass", + "1": "block/obsidian", + "2": "block/blue_terracotta" + }, + "elements": [ + { + "name": "Mirror", + "from": [ 6.499999992549419, 1.0, 10.50000000745058 ], + "to": [ 9.49999999254942, 12.0, 11.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 7.0, 15.0 ] } + } + }, + { + "name": "rod_left_bottom", + "from": [ 1.2000000029802322, 3.0, 7.0 ], + "to": [ 3.2000000029802322, 4.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left_top", + "from": [ 1.2000000029802322, 12.0, 7.0 ], + "to": [ 3.2000000029802322, 13.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_left", + "from": [ 2.0, 4.0, 7.499999992549419 ], + "to": [ 3.0, 12.0, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 0.0, 4.0, 8.0 ] }, + "south": { "texture": "#2", "uv": [ 3.0, 1.0, 4.0, 9.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 1.0, 6.0, 9.0 ] } + } + }, + { + "name": "rod_right_bottom", + "from": [ 12.799999997019768, 3.0, 7.0 ], + "to": [ 14.799999997019768, 4.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "rod_right", + "from": [ 13.0, 4.0, 7.499999992549419 ], + "to": [ 14.0, 12.0, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#2", "uv": [ 3.0, 2.0, 4.0, 10.0 ] }, + "east": { "texture": "#2", "uv": [ 3.0, 3.0, 4.0, 11.0 ] }, + "south": { "texture": "#2", "uv": [ 4.0, 3.0, 5.0, 11.0 ] }, + "west": { "texture": "#2", "uv": [ 5.0, 0.0, 6.0, 8.0 ] } + } + }, + { + "name": "rod_right_top", + "from": [ 12.799999997019768, 12.0, 7.0 ], + "to": [ 14.799999997019768, 13.0, 9.0 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "east": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "south": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "west": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 1.0 ] }, + "up": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] }, + "down": { "texture": "#1", "uv": [ 0.0, 0.0, 2.0, 2.0 ] } + } + }, + { + "name": "CrossMirror", + "from": [ 4.499999977648258, 2.0, 6.500000007450581 ], + "to": [ 5.499999977648258, 13.0, 9.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 6.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 1.0, 12.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 3.0, 3.0, 4.0, 6.0 ] }, + "down": { "texture": "#0", "uv": [ 5.0, 9.0, 6.0, 12.0 ] } + } + }, + { + "name": "Mirror II", + "from": [ 6.499999992549419, 3.0, 4.500000007450581 ], + "to": [ 9.49999999254942, 14.0, 5.500000007450581 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 4.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 12.0, 1.0, 13.0, 12.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 1.0, 7.0, 2.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 14.0, 7.0, 15.0 ] } + } + }, + { + "name": "CrossMirror II", + "from": [ 10.50000000745058, 4.0, 6.500000007450581 ], + "to": [ 11.50000000745058, 15.0, 9.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 6.0, 12.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 14.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 2.0, 12.0, 13.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 6.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 8.0, 5.0, 11.0 ] } + } + }, + { + "name": "Cube", + "from": [ 7.499999992549419, 6.0, -0.4999999925494194 ], + "to": [ 8.49999999254942, 10.0, 3.5000000074505806 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 5.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 7.0, 5.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 7.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 2.0, 13.0, 6.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 7.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 8.0, 5.0, 12.0 ] } + } + }, + { + "name": "Cube", + "from": [ 7.499999992549419, 6.0, 12.50000000745058 ], + "to": [ 8.49999999254942, 10.0, 16.50000000745058 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": -45.0 }, + "faces": { + "north": { "texture": "#0", "uv": [ 4.0, 1.0, 5.0, 5.0 ] }, + "east": { "texture": "#0", "uv": [ 3.0, 1.0, 7.0, 5.0 ] }, + "south": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 7.0 ] }, + "west": { "texture": "#0", "uv": [ 9.0, 2.0, 13.0, 6.0 ] }, + "up": { "texture": "#0", "uv": [ 4.0, 3.0, 5.0, 7.0 ] }, + "down": { "texture": "#0", "uv": [ 4.0, 8.0, 5.0, 12.0 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/models/item/symmetry_wand.json b/src/main/resources/assets/create/models/item/symmetry_wand.json new file mode 100644 index 000000000..24cb1cb33 --- /dev/null +++ b/src/main/resources/assets/create/models/item/symmetry_wand.json @@ -0,0 +1,253 @@ +{ + "__comment": "Model generated using MrCrayfish's Model Creator (http://mrcrayfish.com/modelcreator/)", +"ambientocclusion": true, + "display": { + "firstperson_righthand": { + "rotation": [ 15, 0, 0 ], + "translation": [ 0, 0, -2], + "scale":[ 0.6, 0.6, 0.6 ] + }, + "thirdperson_righthand": { + "rotation": [ 15, 0, 0 ], + "translation": [ -1, 1, 1], + "scale":[ 0.5, 0.5, 0.5 ] + }, + "gui": { + "rotation": [ 40, 135, 32 ], + "translation": [ -1.2, -1, 3], + "scale":[ 0.8, 0.8, 0.8 ] + }, + "ground": { + "rotation": [ 0, 0, 0 ], + "translation": [ 0, 4.2, 0], + "scale":[ 0.4, 0.4, 0.4 ] + }, + "fixed": { + "rotation": [ 0, 90, 0 ], + "translation": [ -2, -1, 0 ], + "scale": [ 1, 1, 1 ] + } + }, + "textures": { + "0": "block/obsidian", + "1": "block/purple_concrete_powder", + "2": "block/dark_oak_log", + "3": "block/white_stained_glass", + "4": "block/purple_stained_glass", + "5": "block/white_concrete" + }, + "elements": [ + { + "name": "Grip Core", + "from": [ 6.500000007450581, -5.0, 6.500000007450581 ], + "to": [ 9.50000000745058, 6.0, 9.50000000745058 ], + "faces": { + "north": { "texture": "#0", "uv": [ 5.0, 1.0, 8.0, 12.0 ] }, + "east": { "texture": "#0", "uv": [ 2.0, 3.0, 5.0, 14.0 ] }, + "south": { "texture": "#0", "uv": [ 10.0, 1.0, 13.0, 12.0 ] }, + "west": { "texture": "#0", "uv": [ 7.0, 1.0, 10.0, 12.0 ] }, + "up": { "texture": "#-1", "uv": [ 0.0, 0.0, 3.0, 3.0 ] }, + "down": { "texture": "#0", "uv": [ 5.0, 6.0, 8.0, 9.0 ] } + } + }, + { + "name": "Rod Bottom Core", + "from": [ 6.500000007450581, 8.000000014901161, 6.500000007450581 ], + "to": [ 9.50000000745058, 17.00000001490116, 9.50000000745058 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#1", "uv": [ 5.0, 7.0, 8.0, 16.0 ] }, + "east": { "texture": "#1", "uv": [ 7.0, 7.0, 10.0, 16.0 ] }, + "south": { "texture": "#1", "uv": [ 1.0, 7.0, 4.0, 16.0 ] }, + "west": { "texture": "#1", "uv": [ 3.0, 7.0, 6.0, 16.0 ] }, + "up": { "texture": "#1", "uv": [ 12.0, 1.0, 15.0, 4.0 ] }, + "down": { "texture": "#2", "uv": [ 8.0, 10.0, 11.0, 13.0 ] } + } + }, + { + "name": "Grip Cap", + "from": [ 5.999999985098839, 6.0, 6.0 ], + "to": [ 9.999999985098839, 7.0, 10.0 ], + "faces": { + "north": { "texture": "#2", "uv": [ 2.0, 0.0, 6.0, 1.0 ] }, + "east": { "texture": "#2", "uv": [ 0.0, 0.0, 4.0, 1.0 ] }, + "south": { "texture": "#2", "uv": [ 0.0, 0.0, 4.0, 1.0 ] }, + "west": { "texture": "#2", "uv": [ 0.0, 1.0, 4.0, 2.0 ] }, + "up": { "texture": "#2", "uv": [ 10.0, 15.0, 14.0, 11.0 ] }, + "down": { "texture": "#2", "uv": [ 5.0, 3.0, 9.0, 7.0 ] } + } + }, + { + "name": "Rod Core", + "from": [ 7.0, 18.00000001490116, 7.0 ], + "to": [ 9.0, 26.00000001490116, 9.0 ], + "faces": { + "north": { "texture": "#5", "uv": [ 2.0, 2.0, 4.0, 10.0 ] }, + "east": { "texture": "#5", "uv": [ 4.0, 2.0, 6.0, 10.0 ] }, + "south": { "texture": "#5", "uv": [ 4.0, 2.0, 6.0, 10.0 ] }, + "west": { "texture": "#5", "uv": [ 8.0, 2.0, 10.0, 10.0 ] }, + "up": { "texture": "#5", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "down": { "texture": "#5", "uv": [ 2.0, 2.0, 4.0, 4.0 ] } + } + }, + { + "name": "Rod Top Core", + "from": [ 6.500000007450581, 27.00000001490116, 6.500000007450581 ], + "to": [ 9.50000000745058, 30.00000001490116, 9.50000000745058 ], + "rotation": { "origin": [ 8.0, 8.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#1", "uv": [ 1.0, 4.0, 4.0, 7.0 ] }, + "east": { "texture": "#1", "uv": [ 1.0, 4.0, 4.0, 7.0 ] }, + "south": { "texture": "#1", "uv": [ 1.0, 4.0, 4.0, 7.0 ] }, + "west": { "texture": "#1", "uv": [ 1.0, 4.0, 4.0, 7.0 ] }, + "up": { "texture": "#1", "uv": [ 12.0, 1.0, 15.0, 4.0 ] }, + "down": { "texture": "#1", "uv": [ 12.0, 1.0, 15.0, 4.0 ] } + } + }, + { + "name": "Cap", + "from": [ 5.999999985098839, 31.0, 6.0 ], + "to": [ 9.999999985098839, 32.0, 10.0 ], + "faces": { + "north": { "texture": "#2", "uv": [ 0.0, 0.0, 4.0, 1.0 ] }, + "east": { "texture": "#2", "uv": [ 0.0, 0.0, 4.0, 1.0 ] }, + "south": { "texture": "#2", "uv": [ 0.0, 0.0, 4.0, 1.0 ] }, + "west": { "texture": "#2", "uv": [ 0.0, 0.0, 4.0, 1.0 ] }, + "up": { "texture": "#2", "uv": [ 7.0, 10.0, 11.0, 14.0 ] }, + "down": { "texture": "#2", "uv": [ 7.0, 10.0, 11.0, 14.0 ] } + } + }, + { + "name": "Grip Deco", + "from": [ 6.3000000193715096, 4.0, 6.3000000193715096 ], + "to": [ 9.700000025331974, 5.0, 9.700000025331974 ], + "faces": { + "north": { "texture": "#2", "uv": [ 2.0, 7.0, 5.4000000059604645, 8.0 ] }, + "east": { "texture": "#2", "uv": [ 4.0, 7.0, 7.4000000059604645, 8.0 ] }, + "south": { "texture": "#2", "uv": [ 6.0, 7.0, 9.400000005960464, 8.0 ] }, + "west": { "texture": "#2", "uv": [ 7.0, 7.0, 10.400000005960464, 8.0 ] } + } + }, + { + "name": "Rod Bottom Cap", + "from": [ 6.000000014901161, 16.0, 6.000000014901161 ], + "to": [ 10.000000014901161, 18.0, 10.000000014901161 ], + "rotation": { "origin": [ 8.0, 6.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] }, + "east": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] }, + "south": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] }, + "west": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] } + } + }, + { + "name": "Rod Top Cap", + "from": [ 6.000000014901161, 26.0, 6.000000014901161 ], + "to": [ 10.000000014901161, 28.0, 10.000000014901161 ], + "rotation": { "origin": [ 8.0, 6.0, 8.0 ], "axis": "y", "angle": 45.0 }, + "faces": { + "north": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] }, + "east": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] }, + "south": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] }, + "west": { "texture": "#4", "uv": [ 2.0, 2.0, 6.0, 4.0 ] } + } + }, + { + "name": "Square North", + "from": [ 7.499999992549419, 21.0, 3.0 ], + "to": [ 8.49999999254942, 23.0, 5.0 ], + "shade": false, + "rotation": { "origin": [ 9.0, 22.0, 5.0 ], "axis": "x", "angle": 45.0 }, + "faces": { + "north": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "east": { "texture": "#3", "uv": [ 6.0, 6.0, 8.0, 8.0 ] }, + "south": { "texture": "#3", "uv": [ 8.0, 6.0, 9.0, 8.0 ] }, + "west": { "texture": "#3", "uv": [ 11.0, 9.0, 13.0, 11.0 ] }, + "up": { "texture": "#3", "uv": [ 9.0, 5.0, 6.0, 8.0 ] }, + "down": { "texture": "#3", "uv": [ 5.0, 7.0, 6.0, 9.0 ] } + } + }, + { + "name": "Square South", + "from": [ 7.499999992549419, 22.0, 10.0 ], + "to": [ 8.49999999254942, 24.0, 12.0 ], + "shade": false, + "rotation": { "origin": [ 13.0, 22.0, 11.0 ], "axis": "x", "angle": 45.0 }, + "faces": { + "north": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "east": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "south": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "west": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "up": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "down": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] } + } + }, + { + "name": "Rod Bottom Deco 1", + "from": [ 7.499999992549419, 9.0, 5.500000007450581 ], + "to": [ 8.49999999254942, 10.0, 10.50000000745058 ], + "faces": { + "north": { "texture": "#2", "uv": [ 0.0, 0.0, 1.0, 1.0 ] }, + "east": { "texture": "#2", "uv": [ 0.0, 0.0, 5.0, 1.0 ] }, + "south": { "texture": "#2", "uv": [ 0.0, 0.0, 1.0, 1.0 ] }, + "west": { "texture": "#2", "uv": [ 0.0, 0.0, 5.0, 1.0 ] }, + "up": { "texture": "#2", "uv": [ 0.0, 0.0, 1.0, 5.0 ] }, + "down": { "texture": "#2", "uv": [ 0.0, 0.0, 1.0, 5.0 ] } + } + }, + { + "name": "Rod Bottom Deco 2", + "from": [ 5.499999992549419, 9.0, 7.500000007450581 ], + "to": [ 10.49999999254942, 10.0, 8.50000000745058 ], + "faces": { + "north": { "texture": "#2", "uv": [ 0.0, 0.0, 5.0, 1.0 ] }, + "east": { "texture": "#2", "uv": [ 0.0, 0.0, 1.0, 1.0 ] }, + "south": { "texture": "#2", "uv": [ 0.0, 0.0, 5.0, 1.0 ] }, + "west": { "texture": "#2", "uv": [ 0.0, 0.0, 1.0, 1.0 ] }, + "up": { "texture": "#2", "uv": [ 0.0, 0.0, 5.0, 1.0 ] }, + "down": { "texture": "#2", "uv": [ 0.0, 0.0, 5.0, 1.0 ] } + } + }, + { + "name": "Square West", + "from": [ 11.49999999254942, 22.49999999254942, 7.499999992549419 ], + "to": [ 13.49999999254942, 24.49999999254942, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 13.0, 22.0, 11.0 ], "axis": "z", "angle": 45.0 }, + "faces": { + "north": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "east": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "south": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "west": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "up": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 3.0 ] }, + "down": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 3.0 ] } + } + }, + { + "name": "Square East", + "from": [ 6.499999992549419, 27.49999999254942, 7.499999992549419 ], + "to": [ 8.49999999254942, 29.49999999254942, 8.49999999254942 ], + "shade": false, + "rotation": { "origin": [ 13.0, 22.0, 11.0 ], "axis": "z", "angle": 45.0 }, + "faces": { + "north": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "east": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "south": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 4.0 ] }, + "west": { "texture": "#3", "uv": [ 2.0, 2.0, 3.0, 4.0 ] }, + "up": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 3.0 ] }, + "down": { "texture": "#3", "uv": [ 2.0, 2.0, 4.0, 3.0 ] } + } + }, + { + "name": "Cube", + "from": [ 6.3000000193715096, -4.0, 6.3000000193715096 ], + "to": [ 9.700000025331974, -3.0, 9.700000025331974 ], + "faces": { + "north": { "texture": "#2", "uv": [ 5.0, 15.0, 8.400000005960464, 16.0 ] }, + "east": { "texture": "#2", "uv": [ 8.0, 15.0, 11.400000005960464, 16.0 ] }, + "south": { "texture": "#2", "uv": [ 8.0, 15.0, 11.400000005960464, 16.0 ] }, + "west": { "texture": "#2", "uv": [ 7.0, 15.0, 3.4000000059604645, 16.0 ] } + } + } + ] +} \ No newline at end of file diff --git a/src/main/resources/assets/create/textures/block/marker/exporter.png b/src/main/resources/assets/create/textures/block/marker/exporter.png new file mode 100644 index 000000000..89cf7a311 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/exporter.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/heavy.png b/src/main/resources/assets/create/textures/block/marker/heavy.png new file mode 100644 index 000000000..cf1f76289 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/heavy.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/inner.png b/src/main/resources/assets/create/textures/block/marker/inner.png new file mode 100644 index 000000000..ae1426441 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/inner.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/inner_selected.png b/src/main/resources/assets/create/textures/block/marker/inner_selected.png new file mode 100644 index 000000000..ef26fa1e4 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/inner_selected.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/inner_super_selected.png b/src/main/resources/assets/create/textures/block/marker/inner_super_selected.png new file mode 100644 index 000000000..d7ee1d757 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/inner_super_selected.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/inner_transparent.png b/src/main/resources/assets/create/textures/block/marker/inner_transparent.png new file mode 100644 index 000000000..5d52d49a3 Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/inner_transparent.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/light.png b/src/main/resources/assets/create/textures/block/marker/light.png new file mode 100644 index 000000000..4f2f340ce Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/light.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/select.png b/src/main/resources/assets/create/textures/block/marker/select.png new file mode 100644 index 000000000..eadf5cecb Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/select.png differ diff --git a/src/main/resources/assets/create/textures/block/marker/trim.png b/src/main/resources/assets/create/textures/block/marker/trim.png new file mode 100644 index 000000000..5f98a6f0a Binary files /dev/null and b/src/main/resources/assets/create/textures/block/marker/trim.png differ diff --git a/src/main/resources/assets/create/textures/gui/background.png b/src/main/resources/assets/create/textures/gui/background.png new file mode 100644 index 000000000..de5cde99c Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/background.png differ diff --git a/src/main/resources/assets/create/textures/gui/icons.png b/src/main/resources/assets/create/textures/gui/icons.png new file mode 100644 index 000000000..fd368353e Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/icons.png differ diff --git a/src/main/resources/assets/create/textures/gui/player_inventory.png b/src/main/resources/assets/create/textures/gui/player_inventory.png new file mode 100644 index 000000000..0ab18ce97 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/player_inventory.png differ diff --git a/src/main/resources/assets/create/textures/gui/wand_symmetry.png b/src/main/resources/assets/create/textures/gui/wand_symmetry.png new file mode 100644 index 000000000..fb8b7e3e5 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/wand_symmetry.png differ diff --git a/src/main/resources/assets/create/textures/gui/widgets.png b/src/main/resources/assets/create/textures/gui/widgets.png new file mode 100644 index 000000000..0c7695db7 Binary files /dev/null and b/src/main/resources/assets/create/textures/gui/widgets.png differ diff --git a/src/main/resources/assets/create/textures/item/blueprint_empty.png b/src/main/resources/assets/create/textures/item/blueprint_empty.png new file mode 100644 index 000000000..105eeaae3 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/blueprint_empty.png differ diff --git a/src/main/resources/assets/create/textures/item/blueprint_filled.png b/src/main/resources/assets/create/textures/item/blueprint_filled.png new file mode 100644 index 000000000..982788716 Binary files /dev/null and b/src/main/resources/assets/create/textures/item/blueprint_filled.png differ diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 000000000..867ef98d9 --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "create resources", + "pack_format": 4 + } +}