45 Commits

Author SHA1 Message Date
Christian
ee235d0689 Bumped version number 2023-01-28 22:40:52 +01:00
Christian
84d3c34d66 Disabled capability logs. Using build mode enum name to get icon. 2023-01-28 22:07:59 +01:00
Christian Knaapen
ea59fef099 Changed reach upgrade recipes. Made radial menu smaller.
Cleaned up radial menu code.
Added russian language.
Tweaked cube icon.
2023-01-14 15:35:43 +01:00
Christian Knaapen
5e6c42d372 Fixed disassembling blocks with the Create Wrench duplicating the item when a build mode other than Normal is used. Disabled break outlines in survival, because breaking multiple blocks in survival is deprecated. 2022-10-25 21:52:14 +02:00
Christian Knaapen
14460c2c01 Fixed keybindings not being registered. 2022-10-24 21:01:19 +02:00
Christian Knaapen
3b31a74780 Merge branch 'master' into 1.19 2022-07-30 10:48:08 +02:00
manapart
911d4b5605 Merged in 1.19 (pull request #4)
1.19

Approved-by: Requios
2022-07-30 08:46:57 +00:00
Christian Knaapen
13ee819439 Merge branch '1.18' 2022-07-30 10:02:13 +02:00
ManApart
319fedc2dd seemingly working with forge .99 2022-07-16 16:14:40 -04:00
ManApart
c7e6230424 seems to be working fine 2022-07-10 08:19:33 -04:00
ManApart
e7ef54bd80 starting game 2022-07-10 08:10:57 -04:00
ManApart
d5af0b097e compiling 2022-07-10 08:05:19 -04:00
ManApart
63b95df0ff upgrade translatable component 2022-07-10 07:59:17 -04:00
ManApart
b3730896e5 upgrade text component 2022-07-10 07:55:10 -04:00
ManApart
675a4930af initial gradle changes 2022-07-10 07:45:49 -04:00
Christian Knaapen
6e22577d61 Updated to work with 1.18.2. 2022-03-19 22:26:59 +01:00
Christian Knaapen
6e7aab673f Fixed crash when previewing lanterns using mirror or radial mirror (blockstate nullpointer). 2022-03-19 21:49:37 +01:00
Christian Knaapen
ad2e81c54e Added build mode categories with colored lines. Hiding pyramid/cone/dome buttons for now. Changed icon of normal mode and renamed to disable. 2022-02-13 16:23:22 +01:00
Christian Knaapen
780d5cc972 Removed reach command and functionality to break multiple blocks in survival. 2022-02-13 01:11:02 +01:00
Christian Knaapen
a1d30fd752 Added descriptions to radial menu. Added pyramid, cone and dome buttons, icons and placeholder classes. Fixed leftclicking to cancel in survival. 2022-02-12 20:55:29 +01:00
Christian Knaapen
96ffc5c1a5 Fixed multiplayer: cache in Mode/ModifierSettingsManager does not work on server, so it's removed. Also changed some packets to use separate classes for clientside handling, as recommended by the Forge Community Wiki. 2022-01-16 15:55:44 +01:00
Christian Knaapen
5ca826362b Update to 1.18 2022-01-03 13:47:18 +01:00
Christian Knaapen
9ae02b16de Tweaks and cleanup 2021-12-05 17:53:47 +01:00
Christian Knaapen
80e355a806 Revamped the radial menu. Removed some old code. 2021-12-05 14:30:57 +01:00
Christian Knaapen
700a3062f7 Hotfix: Fixed crash when rendering overlay: Invalid shaders/core/dissolve.json: Couldn't compile fragment program. 2021-11-02 01:40:17 +01:00
Christian Knaapen
f45d3ffad7 Added golden and diamond randomizer bags (with container, screen, icon and recipe). Updated recipes for reach upgrades. 2021-10-31 16:52:08 +01:00
Christian Knaapen
c8cfa515d0 Fixed icons in radial menu. Cleaned up radial menu code a bit. 2021-10-30 21:34:53 +02:00
Christian Knaapen
6760388bc7 Fixed block preview shader dissolve effect. Fixed reach upgrade item icons. 2021-10-30 20:00:47 +02:00
Christian Knaapen
80c475ff54 Fixed block preview shader being glitchy. Now shows block without effects. 2021-10-30 16:32:23 +02:00
Christian Knaapen
5b8fafd9f7 Fixed randomizer bag inventory not opening. 2021-10-16 13:24:33 +02:00
Christian Knaapen
43d0a02faf Moved dissolve shader to Minecraft's new custom shader rendertype. 2021-09-26 19:38:02 +02:00
Christian Knaapen
4b1997e44f [TASK] Fixed rendering modifier lines and areas. Rendering block previews no longer crashes (renders black). 2021-09-26 12:48:36 +02:00
Christian Knaapen
3930844208 Fixed capabilities and setup events. 2021-09-12 16:58:09 +02:00
Christian Knaapen
d9df8b0d0e Fixed remaining compiler errors. Using deferred registries now, and cleaned up mods.toml file. 2021-09-12 13:54:25 +02:00
Christian Knaapen
178a4ca4e1 Fixed 200+ compiler errors. 23 left. 2021-09-01 17:37:09 +02:00
Christian Knaapen
2297c38574 WIP Update to 1.17 2021-09-01 14:51:44 +02:00
Christian Knaapen
72d1085a54 Updated mapping to 1.16.5 official names. 2021-09-01 14:13:08 +02:00
Christian Knaapen
47f38d0a58 Bumped version number 2021-05-20 21:11:38 +02:00
Alexei Robyn
54d9c3a92f Merged in fakeplayer-fix-1.16 (pull request #3)
Fix FakePlayer-related crashes

Approved-by: Requios
2021-05-20 18:16:16 +00:00
Alexei Robyn
f77a937c6c Fix FakePlayer-related crashes 2021-05-20 14:14:58 +10:00
Christian Knaapen
b41f102f0c Using deferred registry for Randomizer Bag container, which fixes startup crash in 1.16.4 and 1.16.5. 2021-02-03 20:50:09 +01:00
grimm auld
f2fee42c58 Merged in 1.16 (pull request #2)
1.16

Approved-by: Requios
2021-02-02 20:28:16 +00:00
grimmauld
d63786f6e2 merge version bump 2021-02-02 12:52:18 +01:00
grimmauld
5fe5978777 Fix some stuff 2021-01-29 23:43:12 +01:00
grimmauld
7b5f055d22 Get stuff running on 1.16.3 2021-01-29 23:12:11 +01:00
124 changed files with 9004 additions and 8436 deletions

5
.gitattributes vendored Normal file
View File

@@ -0,0 +1,5 @@
# Disable autocrlf on generated files, they always generate with LF
# Add any extra files or paths here to make git stop saying they
# are changed when only line endings change.
src/generated/**/.cache/cache text eol=lf
src/generated/**/*.json text eol=lf

1
.gitignore vendored
View File

@@ -20,6 +20,7 @@ build
# other # other
eclipse eclipse
run run
logs/*
# Files from Forge MDK # Files from Forge MDK
forge*changelog.txt forge*changelog.txt

View File

@@ -1,34 +1,26 @@
buildscript { plugins {
repositories { id 'eclipse'
maven { url = 'https://files.minecraftforge.net/maven' } id 'maven-publish'
jcenter() id 'net.minecraftforge.gradle' version '5.1.+'
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 = '1.15.2-2.21' version = '1.19-2.40'
group = 'nl.requios.effortlessbuilding' // http://maven.apache.org/guides/mini/guide-naming-conventions.html group = 'nl.requios.effortlessbuilding'
archivesBaseName = 'effortlessbuilding' archivesBaseName = 'effortlessbuilding'
sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. // Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17.
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
minecraft { minecraft {
// The mappings can be changed at any time, and must be in the following format. // The mappings can be changed at any time, and must be in the following format.
// snapshot_YYYYMMDD Snapshot are built nightly. // snapshot_YYYYMMDD Snapshot are built nightly.
// stable_# Stables are built at the discretion of the MCP team. // stable_# Stables are built at the discretion of the MCP team.
// Use non-default mappings at your own risk. they may not always work. // 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. // Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: 'snapshot', version: '20200514-1.15.1' mappings channel: 'official', version: '1.19.2'
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations. // Default run configurations.
// These can be tweaked, removed, or duplicated as needed. // These can be tweaked, removed, or duplicated as needed.
@@ -42,6 +34,9 @@ minecraft {
// Recommended logging level for the console // Recommended logging level for the console
property 'forge.logging.console.level', 'debug' property 'forge.logging.console.level', 'debug'
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', 'effortlessbuilding'
mods { mods {
effortlessbuilding { effortlessbuilding {
source sourceSets.main source sourceSets.main
@@ -52,12 +47,31 @@ minecraft {
server { server {
workingDirectory project.file('run') workingDirectory project.file('run')
// Recommended logging data for a userdev environment (SCAN,REGISTRIES,REGISTRYDUMP)
property 'forge.logging.markers', 'REGISTRIES' property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug' property 'forge.logging.console.level', 'debug'
property 'forge.enabledGameTestNamespaces', 'effortlessbuilding'
mods {
effortlessbuilding {
source sourceSets.main
}
}
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
property 'forge.enabledGameTestNamespaces', 'effortlessbuilding'
mods { mods {
effortlessbuilding { effortlessbuilding {
source sourceSets.main source sourceSets.main
@@ -66,15 +80,14 @@ minecraft {
} }
data { data {
workingDirectory project.file('run') workingDirectory project.file('run')
// Recommended logging data for a userdev environment (SCAN,REGISTRIES,REGISTRYDUMP)
property 'forge.logging.markers', 'REGISTRIES' property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug' property 'forge.logging.console.level', 'debug'
args '--mod', 'effortlessbuilding', '--all', '--output', file('src/generated/resources/') // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'effortlessbuilding', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
mods { mods {
effortlessbuilding { effortlessbuilding {
@@ -85,30 +98,36 @@ minecraft {
} }
} }
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
repositories {
// Put repositories for dependencies here
// ForgeGradle automatically adds the Forge maven and Maven Central for you
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so:
// flatDir {
// dir 'libs'
// }
}
dependencies { dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it. // The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.15.2-31.2.0' minecraft 'net.minecraftforge:forge:1.19.2-43.1.47'
// You may put jars on which you depend on in ./libs or you may define them like so.. // Real mod deobf dependency examples - these get remapped to your current mappings
// compile "some.group:artifact:version:classifier" // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency
// compile "some.group:artifact:version" // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency
// implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency
// Real examples // Examples using mod jars from ./libs
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}")
// 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... // For more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.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.. // Example for how to get properties into the manifest for reading by the runtime..
@@ -119,18 +138,18 @@ jar {
"Specification-Vendor": "requios", "Specification-Vendor": "requios",
"Specification-Version": "1", // We are version 1 of ourselves "Specification-Version": "1", // We are version 1 of ourselves
"Implementation-Title": project.name, "Implementation-Title": project.name,
"Implementation-Version": "${version}", "Implementation-Version": project.jar.archiveVersion,
"Implementation-Vendor" :"requios", "Implementation-Vendor" :"requios",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
]) ])
} }
} }
// Example configuration to allow publishing using the maven-publish task // Example configuration to allow publishing using the maven-publish plugin
// This is the preferred method to reobfuscate your jar file // This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar') jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing // However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
//publish.dependsOn('reobfJar') // publish.dependsOn('reobfJar')
publishing { publishing {
publications { publications {
@@ -140,7 +159,11 @@ publishing {
} }
repositories { repositories {
maven { maven {
url "file:///${project.projectDir}/mcmodsrepo" url "file://${project.projectDir}/mcmodsrepo"
} }
} }
} }
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}

Binary file not shown.

View File

@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-bin.zip

286
gradlew vendored
View File

@@ -1,78 +1,129 @@
#!/usr/bin/env sh #!/bin/sh
#
# Copyright <20> 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
############################################################################## ##############################################################################
## #
## Gradle start up script for UN*X # Gradle start up script for POSIX generated by Gradle.
## #
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions <20>$var<61>, <20>${var}<7D>, <20>${var:-default}<7D>, <20>${var+SET}<7D>,
# <20>${var#prefix}<7D>, <20>${var%suffix}<7D>, and <20>$( cmd )<29>;
# * compound commands having a testable exit status, especially <20>case<73>;
# * various built-in commands including <20>command<6E>, <20>set<65>, and <20>ulimit<69>.
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
############################################################################## ##############################################################################
# Attempt to set APP_HOME # Attempt to set APP_HOME
# Resolve links: $0 may be a link # Resolve links: $0 may be a link
PRG="$0" app_path=$0
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do # Need this for daisy-chained symlinks.
ls=`ls -ld "$PRG"` while
link=`expr "$ls" : '.*-> \(.*\)$'` APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
if expr "$link" : '/.*' > /dev/null; then [ -h "$app_path" ]
PRG="$link" do
else ls=$( ls -ld "$app_path" )
PRG=`dirname "$PRG"`"/$link" link=${ls#*' -> '}
fi case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle" APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` APP_BASE_NAME=${0##*/}
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS="" DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD=maximum
warn () { warn () {
echo "$*" echo "$*"
} } >&2
die () { die () {
echo echo
echo "$*" echo "$*"
echo echo
exit 1 exit 1
} } >&2
# OS specific support (must be 'true' or 'false'). # OS specific support (must be 'true' or 'false').
cygwin=false cygwin=false
msys=false msys=false
darwin=false darwin=false
nonstop=false nonstop=false
case "`uname`" in case "$( uname )" in #(
CYGWIN* ) CYGWIN* ) cygwin=true ;; #(
cygwin=true Darwin* ) darwin=true ;; #(
;; MSYS* | MINGW* ) msys=true ;; #(
Darwin* ) NONSTOP* ) nonstop=true ;;
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables # IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java" JAVACMD=$JAVA_HOME/jre/sh/java
else else
JAVACMD="$JAVA_HOME/bin/java" JAVACMD=$JAVA_HOME/bin/java
fi fi
if [ ! -x "$JAVACMD" ] ; then if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -81,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation." location of your Java installation."
fi fi
else else
JAVACMD="java" 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. 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 Please set the JAVA_HOME variable in your environment to match the
@@ -89,84 +140,95 @@ location of your Java installation."
fi fi
# Increase the maximum file descriptors if we can. # Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
MAX_FD_LIMIT=`ulimit -H -n` case $MAX_FD in #(
if [ $? -eq 0 ] ; then max*)
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then MAX_FD=$( ulimit -H -n ) ||
MAX_FD="$MAX_FD_LIMIT" warn "Could not query maximum file descriptor limit"
fi esac
ulimit -n $MAX_FD case $MAX_FD in #(
if [ $? -ne 0 ] ; then '' | soft) :;; #(
warn "Could not set maximum file descriptor limit: $MAX_FD" *)
fi ulimit -n "$MAX_FD" ||
else warn "Could not set maximum file descriptor limit to $MAX_FD"
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 esac
fi fi
# Escape application args # Collect all arguments for the java command, stacking in reverse order:
save () { # * args from the command line
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done # * the main class name
echo " " # * -classpath
} # * -D...appname settings
APP_ARGS=$(save "$@") # * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules # For Cygwin or MSYS, switch paths to Windows format before running java
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong JAVACMD=$( cygpath --unix "$JAVACMD" )
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")" # Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi fi
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@" exec "$JAVACMD" "$@"

43
gradlew.bat vendored
View File

@@ -1,3 +1,19 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS= set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@@ -35,7 +54,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto execute
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@@ -45,28 +64,14 @@ echo location of your Java installation.
goto fail 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 :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @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% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

6
settings.gradle Normal file
View File

@@ -0,0 +1,6 @@
pluginManagement {
repositories {
gradlePluginPortal()
maven { url = 'https://maven.minecraftforge.net/' }
}
}

View File

@@ -4,131 +4,111 @@ import net.minecraftforge.common.ForgeConfigSpec;
public class BuildConfig { public class BuildConfig {
private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder(); private static final ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
public static final Reach reach = new Reach(builder); public static final Reach reach = new Reach(builder);
public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder); public static final SurvivalBalancers survivalBalancers = new SurvivalBalancers(builder);
public static final Visuals visuals = new Visuals(builder); public static final Visuals visuals = new Visuals(builder);
public static final ForgeConfigSpec spec = builder.build(); public static final ForgeConfigSpec spec = builder.build();
public static class Reach { public static class Reach {
public final ForgeConfigSpec.ConfigValue<Boolean> enableReachUpgrades; public final ForgeConfigSpec.ConfigValue<Boolean> enableReachUpgrades;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachCreative; public final ForgeConfigSpec.ConfigValue<Integer> maxReachCreative;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel0; public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel0;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel1; public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel1;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel2; public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel2;
public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel3; public final ForgeConfigSpec.ConfigValue<Integer> maxReachLevel3;
public Reach(ForgeConfigSpec.Builder builder) { public Reach(ForgeConfigSpec.Builder builder) {
builder.push("Reach"); builder.push("Reach");
enableReachUpgrades = builder enableReachUpgrades = builder
.comment("Reach: how far away the player can place blocks using mirror/array etc.", .comment("Reach: how far away the player can place blocks using mirror/array etc.",
"Enable the crafting of reach upgrades to increase reach.", "Enable the crafting of reach upgrades to increase reach.",
"If disabled, reach is set to level 3 for survival players.") "If disabled, reach is set to level 3 for survival players.")
.define("enableReachUpgrades", true); .define("enableReachUpgrades", true);
maxReachCreative = builder maxReachCreative = builder
.comment("Maximum reach in creative", .comment("Maximum reach in creative",
"Keep in mind that chunks need to be loaded to be able to place blocks inside.") "Keep in mind that chunks need to be loaded to be able to place blocks inside.")
.define("maxReachCreative", 200); .define("maxReachCreative", 200);
maxReachLevel0 = builder maxReachLevel0 = builder
.comment("Maximum reach in survival without upgrades", .comment("Maximum reach in survival without upgrades",
"Reach upgrades are craftable consumables that permanently increase reach.", "Reach upgrades are craftable consumables that permanently increase reach.",
"Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.") "Set to 0 to disable Effortless Building until the player has consumed a reach upgrade.")
.define("maxReachLevel0", 20); .define("maxReachLevel0", 20);
maxReachLevel1 = builder maxReachLevel1 = builder
.comment("Maximum reach in survival with one upgrade") .comment("Maximum reach in survival with one upgrade")
.define("maxReachLevel1", 50); .define("maxReachLevel1", 50);
maxReachLevel2 = builder maxReachLevel2 = builder
.comment("Maximum reach in survival with two upgrades") .comment("Maximum reach in survival with two upgrades")
.define("maxReachLevel2", 100); .define("maxReachLevel2", 100);
maxReachLevel3 = builder maxReachLevel3 = builder
.comment("Maximum reach in survival with three upgrades") .comment("Maximum reach in survival with three upgrades")
.define("maxReachLevel3", 200); .define("maxReachLevel3", 200);
builder.pop(); builder.pop();
} }
} }
public static class SurvivalBalancers { public static class SurvivalBalancers {
public final ForgeConfigSpec.ConfigValue<Boolean> breakFar; public final ForgeConfigSpec.ConfigValue<Integer> quickReplaceMiningLevel;
public final ForgeConfigSpec.ConfigValue<Boolean> increasedMiningTime; public final ForgeConfigSpec.ConfigValue<Integer> undoStackSize;
public final ForgeConfigSpec.ConfigValue<Integer> miningTimePercentage;
public final ForgeConfigSpec.ConfigValue<Integer> quickReplaceMiningLevel;
public final ForgeConfigSpec.ConfigValue<Integer> undoStackSize;
public SurvivalBalancers(ForgeConfigSpec.Builder builder) { public SurvivalBalancers(ForgeConfigSpec.Builder builder) {
builder.push("SurvivalBalancers"); builder.push("SurvivalBalancers");
breakFar = builder quickReplaceMiningLevel = builder
.comment("Allows a survival player to break blocks that are far away, in addition to placing blocks.", .comment("Determines what blocks can be replaced in survival.",
"Note: this allows insta-breaking of blocks in survival.") "-1: only blocks that can be harvested by hand (default)",
.define("breakFar", false); "0: blocks that can be harvested with wooden or gold tools",
"1: blocks that can be harvested with stone tools",
"2: blocks that can be harvested with iron tools",
"3: blocks that can be harvested with diamond tools",
"4: blocks that can be harvested with netherite tools")
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
increasedMiningTime = builder undoStackSize = builder
.comment("Increases the time to mine a block when breaking multiple at once.", .comment("How many placements are remembered for the undo functionality.")
"Mining time depends on how many blocks, what type of blocks, and the percentage below.", .worldRestart()
"Example: breaking 1 dirt + 1 obsidian takes the time of breaking 1 dirt + 1 obsidian.") .define("undoStackSize", 10);
.define("increasedMiningTime", true);
miningTimePercentage = builder builder.pop();
.comment("How much the mining time of each additional block counts towards an increased mining time.", }
"A percentage between 0% and 100%, where 0% is the same as disabling it,", }
"and 100% takes as much time as breaking each block individually.",
"The block in front of you always counts as 100%.")
.defineInRange("miningTimePercentage", 50, 0, 200);
quickReplaceMiningLevel = builder public static class Visuals {
.comment("Determines what blocks can be replaced in survival.", public final ForgeConfigSpec.ConfigValue<Boolean> alwaysShowBlockPreview;
"-1: only blocks that can be harvested by hand (default)", public final ForgeConfigSpec.ConfigValue<Double> dissolveTimeMultiplier;
"0: blocks that can be harvested with wooden or gold tools", public final ForgeConfigSpec.ConfigValue<Integer> shaderThreshold;
"1: blocks that can be harvested with stone tools", public final ForgeConfigSpec.ConfigValue<Boolean> useShaders;
"2: blocks that can be harvested with iron tools",
"3: blocks that can be harvested with diamond tools")
.defineInRange("quickReplaceMiningLevel", -1, -1, 3);
undoStackSize = builder public Visuals(ForgeConfigSpec.Builder builder) {
.comment("How many placements are remembered for the undo functionality.") builder.push("Visuals");
.worldRestart()
.define("undoStackSize", 10);
builder.pop(); alwaysShowBlockPreview = builder
} .comment("Show a block preview if you have a block in hand even in the 'Normal' build mode")
} .define("alwaysShowBlockPreview", false);
public static class Visuals { dissolveTimeMultiplier = builder
public final ForgeConfigSpec.ConfigValue<Boolean> alwaysShowBlockPreview; .comment("How long the dissolve effect takes when placing blocks.",
public final ForgeConfigSpec.ConfigValue<Double> dissolveTimeMultiplier; "Default between 30 and 60 ticks, you can multiply that here.",
public final ForgeConfigSpec.ConfigValue<Integer> shaderTreshold; "Recommended values:",
public final ForgeConfigSpec.ConfigValue<Boolean> useShaders; "Snappy: 0.7",
"Relaxing: 1.5")
.define("dissolveTimeMultiplier", 1.0);
public Visuals(ForgeConfigSpec.Builder builder) { shaderThreshold = builder
builder.push("Visuals"); .comment("Switch to using the simple performance shader when placing more than this many blocks.")
.define("shaderTreshold", 1500);
alwaysShowBlockPreview = builder useShaders = builder
.comment("Show a block preview if you have a block in hand even in the 'Normal' build mode") .comment("Use fancy shaders while placing blocks")
.define("alwaysShowBlockPreview", false); .define("useShaders", true);
dissolveTimeMultiplier = builder builder.pop();
.comment("How long the dissolve effect takes when placing blocks.", }
"Default between 30 and 60 ticks, you can multiply that here.", }
"Recommended values:",
"Snappy: 0.7",
"Relaxing: 1.5")
.define("dissolveTimeMultiplier", 1.0);
shaderTreshold = builder
.comment("Switch to using the simple performance shader when placing more than this many blocks.")
.define("shaderTreshold", 1500);
useShaders = builder
.comment("Use fancy shaders while placing blocks")
.define("useShaders", true);
builder.pop();
}
}
} }

View File

@@ -1,37 +1,30 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.block.Block; import net.minecraft.network.chat.Component;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.inventory.container.Container; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.inventory.container.ContainerType; import net.minecraft.world.inventory.MenuType;
import net.minecraft.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import net.minecraft.util.registry.Registry;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.crafting.CraftingHelper;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor; import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ExtensionPoint;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.event.lifecycle.InterModEnqueueEvent;
import net.minecraftforge.fml.event.lifecycle.InterModProcessEvent;
import net.minecraftforge.fml.event.server.FMLServerStartingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.network.IContainerFactory;
import net.minecraftforge.registries.RegistryObject;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.command.CommandReach;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagContainer;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer; import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.*;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade1;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade2;
import nl.requios.effortlessbuilding.item.ItemReachUpgrade3;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import nl.requios.effortlessbuilding.proxy.IProxy; import nl.requios.effortlessbuilding.proxy.IProxy;
@@ -39,119 +32,82 @@ import nl.requios.effortlessbuilding.proxy.ServerProxy;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(EffortlessBuilding.MODID) @Mod(EffortlessBuilding.MODID)
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD) public class EffortlessBuilding {
public class EffortlessBuilding
{
public static final String MODID = "effortlessbuilding";
public static final String NAME = "Effortless Building";
public static final String VERSION = "1.15.2-2.21";
public static EffortlessBuilding instance; public static final String MODID = "effortlessbuilding";
public static final Logger logger = LogManager.getLogger();
public static final Logger logger = LogManager.getLogger(); public static EffortlessBuilding instance;
public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new);
public static IProxy proxy = DistExecutor.runForDist(() -> ClientProxy::new, () -> ServerProxy::new); //Registration
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, MODID);
private static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.MENU_TYPES, EffortlessBuilding.MODID);
public static final ItemRandomizerBag ITEM_RANDOMIZER_BAG = new ItemRandomizerBag(); public static final RegistryObject<Item> RANDOMIZER_BAG_ITEM = ITEMS.register("randomizer_bag", RandomizerBagItem::new);
public static final ItemReachUpgrade1 ITEM_REACH_UPGRADE_1 = new ItemReachUpgrade1(); public static final RegistryObject<Item> GOLDEN_RANDOMIZER_BAG_ITEM = ITEMS.register("golden_randomizer_bag", GoldenRandomizerBagItem::new);
public static final ItemReachUpgrade2 ITEM_REACH_UPGRADE_2 = new ItemReachUpgrade2(); public static final RegistryObject<Item> DIAMOND_RANDOMIZER_BAG_ITEM = ITEMS.register("diamond_randomizer_bag", DiamondRandomizerBagItem::new);
public static final ItemReachUpgrade3 ITEM_REACH_UPGRADE_3 = new ItemReachUpgrade3(); public static final RegistryObject<Item> REACH_UPGRADE_1_ITEM = ITEMS.register("reach_upgrade1", ReachUpgrade1Item::new);
public static final RegistryObject<Item> REACH_UPGRADE_2_ITEM = ITEMS.register("reach_upgrade2", ReachUpgrade2Item::new);
public static final RegistryObject<Item> REACH_UPGRADE_3_ITEM = ITEMS.register("reach_upgrade3", ReachUpgrade3Item::new);
public static final Block[] BLOCKS = { public static final RegistryObject<MenuType<RandomizerBagContainer>> RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("randomizer_bag", () -> registerContainer(RandomizerBagContainer::new));
}; public static final RegistryObject<MenuType<GoldenRandomizerBagContainer>> GOLDEN_RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("golden_randomizer_bag", () -> registerContainer(GoldenRandomizerBagContainer::new));
public static final RegistryObject<MenuType<DiamondRandomizerBagContainer>> DIAMOND_RANDOMIZER_BAG_CONTAINER = CONTAINERS.register("diamond_randomizer_bag", () -> registerContainer(DiamondRandomizerBagContainer::new));
public static final Item[] ITEMS = { public EffortlessBuilding() {
ITEM_RANDOMIZER_BAG, instance = this;
ITEM_REACH_UPGRADE_1,
ITEM_REACH_UPGRADE_2,
ITEM_REACH_UPGRADE_3
};
public static final ContainerType<RandomizerBagContainer> RANDOMIZER_BAG_CONTAINER = register("randomizer_bag", RandomizerBagContainer::new); // Register ourselves for server and other game events we are interested in
public static final ResourceLocation RANDOMIZER_BAG_GUI = new ResourceLocation(EffortlessBuilding.MODID, "randomizer_bag"); FMLJavaModLoadingContext.get().getModEventBus().register(this);
public EffortlessBuilding() { ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
instance = this; CONTAINERS.register(FMLJavaModLoadingContext.get().getModEventBus());
// Register the setup method for modloading //Register config
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::setup); ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, BuildConfig.spec);
// Register the enqueueIMC method for modloading }
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::enqueueIMC);
// Register the processIMC method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::processIMC);
// Register the clientSetup method for modloading
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
//Register config public static <T extends AbstractContainerMenu> MenuType<T> registerContainer(IContainerFactory<T> fact){
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, BuildConfig.spec); MenuType<T> type = new MenuType<T>(fact);
return type;
}
// Register ourselves for server and other game events we are interested in @SubscribeEvent
MinecraftForge.EVENT_BUS.register(this); public void setup(final FMLCommonSetupEvent event) {
} PacketHandler.register();
@SubscribeEvent proxy.setup(event);
public void setup(final FMLCommonSetupEvent event)
{
CapabilityManager.INSTANCE.register(ModifierCapabilityManager.IModifierCapability.class, new ModifierCapabilityManager.Storage(), ModifierCapabilityManager.ModifierCapability::new);
CapabilityManager.INSTANCE.register(ModeCapabilityManager.IModeCapability.class, new ModeCapabilityManager.Storage(), ModeCapabilityManager.ModeCapability::new);
PacketHandler.register(); CompatHelper.setup();
}
//TODO 1.13 config @SubscribeEvent
// ConfigManager.sync(MODID, Config.Type.INSTANCE); public void clientSetup(final FMLClientSetupEvent event) {
proxy.clientSetup(event);
}
proxy.setup(event); @SubscribeEvent
public void registerCapabilities(RegisterCapabilitiesEvent event){
event.register(ModifierCapabilityManager.IModifierCapability.class);
event.register(ModeCapabilityManager.IModeCapability.class);
}
CompatHelper.setup(); public static void log(String msg) {
} logger.info(msg);
}
@SubscribeEvent public static void log(Player player, String msg) {
public void clientSetup(final FMLClientSetupEvent event) { log(player, msg, false);
}
proxy.clientSetup(event); public static void log(Player player, String msg, boolean actionBar) {
} player.displayClientMessage(Component.literal(msg), actionBar);
}
@SubscribeEvent //Log with translation supported, call either on client or server (which then sends a message)
public void enqueueIMC(final InterModEnqueueEvent event) { public static void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
proxy.logTranslate(player, prefix, translationKey, suffix, actionBar);
// some example code to dispatch IMC to another mod }
// InterModComms.sendTo("examplemod", "helloworld", () -> { logger.info("Hello world from the MDK"); return "Hello world";});
}
@SubscribeEvent
public void processIMC(final InterModProcessEvent event) {
// some example code to receive and process InterModComms from other mods
// logger.info("Got IMC {}", event.getIMCStream().
// map(m->m.getMessageSupplier().get()).
// collect(Collectors.toList()));
}
@SubscribeEvent
public void onServerStarting(FMLServerStartingEvent event) {
CommandReach.register(event.getCommandDispatcher());
}
private static <T extends Container> ContainerType<T> register(String key, ContainerType.IFactory<T> factory) {
return Registry.register(Registry.MENU, key, new ContainerType<>(factory));
}
public static void log(String msg){
logger.info(msg);
}
public static void log(PlayerEntity player, String msg){
log(player, msg, false);
}
public static void log(PlayerEntity player, String msg, boolean actionBar){
player.sendStatusMessage(new StringTextComponent(msg), actionBar);
}
//Log with translation supported, call either on client or server (which then sends a message)
public static void logTranslate(PlayerEntity player, String prefix, String translationKey, String suffix, boolean actionBar){
proxy.logTranslate(player, prefix, translationKey, suffix, actionBar);
}
} }

View File

@@ -1,209 +1,175 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.block.BlockState; import net.minecraft.world.InteractionHand;
import net.minecraft.block.Blocks; import net.minecraft.world.item.BlockItem;
import net.minecraft.entity.Entity; import net.minecraft.world.item.ItemStack;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.level.block.Blocks;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.world.entity.Entity;
import net.minecraft.util.ResourceLocation; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.World; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.common.util.FakePlayer;
import net.minecraftforge.event.AttachCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.network.AddUndoMessage; import nl.requios.effortlessbuilding.network.AddUndoMessage;
import nl.requios.effortlessbuilding.network.ClearUndoMessage; import nl.requios.effortlessbuilding.network.ClearUndoMessage;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.RequestLookAtMessage; import nl.requios.effortlessbuilding.network.RequestLookAtMessage;
import java.util.List; @Mod.EventBusSubscriber(modid = EffortlessBuilding.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class EventHandler {
@Mod.EventBusSubscriber @SubscribeEvent
public class EventHandler public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) {
{ if (event.getObject() instanceof FakePlayer) return;
if (event.getObject() instanceof Player) {
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider());
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_mode"), new ModeCapabilityManager.Provider());
}
}
@SubscribeEvent @SubscribeEvent
public static void attachCapabilities(AttachCapabilitiesEvent<Entity> event) { public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) {
if (event.getObject() instanceof PlayerEntity) { if (event.getLevel().isClientSide()) return;
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_modifier"), new ModifierCapabilityManager.Provider());
event.addCapability(new ResourceLocation(EffortlessBuilding.MODID, "build_mode"), new ModeCapabilityManager.Provider());
}
}
//TODO 1.13 config if (!(event.getEntity() instanceof Player)) return;
// @SubscribeEvent
// public static void onConfigChangedEvent(ConfigChangedEvent.OnConfigChangedEvent event)
// {
// if (event.getModID().equals(EffortlessBuilding.MODID))
// {
// ConfigManager.sync(EffortlessBuilding.MODID, Config.Type.INSTANCE);
// }
// }
// @SubscribeEvent if (event.getEntity() instanceof FakePlayer) return;
// public static void onServerTick(TickEvent.ServerTickEvent event) {
//
// }
@SubscribeEvent //Cancel event if necessary
//Only called serverside (except with lilypads...) ServerPlayer player = ((ServerPlayer) event.getEntity());
public static void onBlockPlaced(BlockEvent.EntityPlaceEvent event) { BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (event.getWorld().isRemote()) return; ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (!(event.getEntity() instanceof PlayerEntity)) return; if (buildMode != BuildModes.BuildModeEnum.NORMAL) {
//Cancel event if necessary //Only cancel if itemblock in hand
ServerPlayerEntity player = ((ServerPlayerEntity) event.getEntity()); //Fixed issue with e.g. Create Wrench shift-rightclick disassembling being cancelled.
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode(); ItemStack currentItemStack = player.getItemInHand(InteractionHand.MAIN_HAND);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); if (currentItemStack.getItem() instanceof BlockItem ||
(CompatHelper.isItemBlockProxy(currentItemStack) && !player.isShiftKeyDown())) {
event.setCanceled(true);
}
if (buildMode != BuildModes.BuildModeEnum.NORMAL) { } else if (modifierSettings.doQuickReplace()) {
event.setCanceled(true); //Cancel event and send message if QuickReplace
} else if (modifierSettings.doQuickReplace()) { event.setCanceled(true);
//Cancel event and send message if QuickReplace PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(true));
event.setCanceled(true); PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(true)); } else {
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState())); //NORMAL mode, let vanilla handle block placing
} else { //But modifiers should still work
//NORMAL mode, let vanilla handle block placing
//But modifiers should still work
//Send message to client, which sends message back with raytrace info //Send message to client, which sends message back with raytrace info
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(false)); PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new RequestLookAtMessage(false));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState())); PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new AddUndoMessage(event.getPos(), event.getBlockSnapshot().getReplacedBlock(), event.getState()));
} }
// Stat<ResourceLocation> blocksPlacedStat = StatList.CUSTOM.get(new ResourceLocation(EffortlessBuilding.MODID, "blocks_placed")); // Stat<ResourceLocation> blocksPlacedStat = StatList.CUSTOM.get(new ResourceLocation(EffortlessBuilding.MODID, "blocks_placed"));
// player.getStats().increment(player, blocksPlacedStat, 1); // player.getStats().increment(player, blocksPlacedStat, 1);
// //
// System.out.println(player.getStats().getValue(blocksPlacedStat)); // System.out.println(player.getStats().getValue(blocksPlacedStat));
} }
@SubscribeEvent @SubscribeEvent
public static void onBlockBroken(BlockEvent.BreakEvent event) { public static void onBlockBroken(BlockEvent.BreakEvent event) {
if (event.getWorld().isRemote()) return; if (event.getLevel().isClientSide()) return;
//Cancel event if necessary if (event.getPlayer() instanceof FakePlayer) return;
//If cant break far then dont cancel event ever
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode();
if (buildMode != BuildModes.BuildModeEnum.NORMAL && ReachHelper.canBreakFar(event.getPlayer())) {
event.setCanceled(true);
} else {
//NORMAL mode, let vanilla handle block breaking
//But modifiers and QuickReplace should still work
//Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work
BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false);
//Add to undo stack in client //Cancel event if necessary
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) event.getPlayer()), new AddUndoMessage(event.getPos(), event.getState(), Blocks.AIR.getDefaultState())); //If cant break far then dont cancel event ever
} BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(event.getPlayer()).getBuildMode();
} if (buildMode != BuildModes.BuildModeEnum.NORMAL && ReachHelper.canBreakFar(event.getPlayer())) {
event.setCanceled(true);
} else {
//NORMAL mode, let vanilla handle block breaking
//But modifiers and QuickReplace should still work
//Dont break the original block yourself, otherwise Tinkers Hammer and Veinminer won't work
BuildModes.onBlockBroken(event.getPlayer(), event.getPos(), false);
@SubscribeEvent //Add to undo stack in client
public static void breakSpeed(PlayerEvent.BreakSpeed event) { if (event.getPlayer() instanceof ServerPlayer && event.getState() != null && event.getPos() != null) {
//Disable if config says so PacketDistributor.PacketTarget packetTarget = PacketDistributor.PLAYER.with(() -> (ServerPlayer) event.getPlayer());
if (!BuildConfig.survivalBalancers.increasedMiningTime.get()) return; if (packetTarget != null)
PacketHandler.INSTANCE.send(packetTarget, new AddUndoMessage(event.getPos(), event.getState(), Blocks.AIR.defaultBlockState()));
}
}
}
PlayerEntity player = event.getPlayer(); @SubscribeEvent
World world = player.world; public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) {
BlockPos pos = event.getPos(); if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed())); @SubscribeEvent
public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) {
if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity();
if (player.getCommandSenderWorld().isClientSide) return;
float originalBlockHardness = event.getState().getBlockHardness(world, pos); UndoRedo.clear(player);
if (originalBlockHardness < 0) return; //Dont break bedrock PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new ClearUndoMessage());
float totalBlockHardness = 0; }
//get coordinates
List<BlockPos> coordinates = BuildModifiers.findCoordinates(player, pos);
for (int i = 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i);
//get existing blockstates at those coordinates
BlockState blockState = world.getBlockState(coordinate);
//add hardness for each blockstate, if can break
if (SurvivalHelper.canBreak(world, player, coordinate))
totalBlockHardness += blockState.getBlockHardness(world, coordinate);
}
//Grabbing percentage from config @SubscribeEvent
float percentage = (float) BuildConfig.survivalBalancers.miningTimePercentage.get() / 100; public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
totalBlockHardness *= percentage; if (event.getEntity() instanceof FakePlayer) return;
totalBlockHardness += originalBlockHardness; Player player = event.getEntity();
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
}
float newSpeed = event.getOriginalSpeed() / totalBlockHardness * originalBlockHardness; @SubscribeEvent
if (Float.isNaN(newSpeed) || newSpeed == 0f) newSpeed = 1f; public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) {
event.setNewSpeed(newSpeed); if (event.getEntity() instanceof FakePlayer) return;
Player player = event.getEntity();
if (player.getCommandSenderWorld().isClientSide) return;
//EffortlessBuilding.log(player, String.valueOf(event.getNewSpeed())); //Set build mode to normal
} ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
modeSettings.setBuildMode(BuildModes.BuildModeEnum.NORMAL);
ModeSettingsManager.setModeSettings(player, modeSettings);
@SubscribeEvent //Disable modifiers
public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
PlayerEntity player = event.getPlayer(); modifierSettings.getMirrorSettings().enabled = false;
ModifierSettingsManager.handleNewPlayer(player); modifierSettings.getRadialMirrorSettings().enabled = false;
ModeSettingsManager.handleNewPlayer(player); modifierSettings.getArraySettings().enabled = false;
} ModifierSettingsManager.setModifierSettings(player, modifierSettings);
@SubscribeEvent ModifierSettingsManager.handleNewPlayer(player);
public static void onPlayerLoggedOut(PlayerEvent.PlayerLoggedOutEvent event) { ModeSettingsManager.handleNewPlayer(player);
PlayerEntity player = event.getPlayer();
if (player.getEntityWorld().isRemote) return;
UndoRedo.clear(player); UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new ClearUndoMessage()); PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new ClearUndoMessage());
} }
@SubscribeEvent @SubscribeEvent
public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { public static void onPlayerClone(PlayerEvent.Clone event) {
PlayerEntity player = event.getPlayer(); if (event.getEntity() instanceof FakePlayer) return;
ModifierSettingsManager.handleNewPlayer(player); //Attach capabilities on death, otherwise crash
ModeSettingsManager.handleNewPlayer(player); Player oldPlayer = event.getOriginal();
} oldPlayer.revive();
@SubscribeEvent Player newPlayer = event.getEntity();
public static void onPlayerChangedDimension(PlayerEvent.PlayerChangedDimensionEvent event) { ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
PlayerEntity player = event.getPlayer(); ModeSettingsManager.setModeSettings(newPlayer, ModeSettingsManager.getModeSettings(oldPlayer));
if (player.getEntityWorld().isRemote) return; }
//Set build mode to normal
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
modeSettings.setBuildMode(BuildModes.BuildModeEnum.NORMAL);
ModeSettingsManager.setModeSettings(player, modeSettings);
//Disable modifiers
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.getMirrorSettings().enabled = false;
modifierSettings.getRadialMirrorSettings().enabled = false;
modifierSettings.getArraySettings().enabled = false;
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
ModifierSettingsManager.handleNewPlayer(player);
ModeSettingsManager.handleNewPlayer(player);
UndoRedo.clear(player);
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new ClearUndoMessage());
}
@SubscribeEvent
public static void onPlayerClone(PlayerEvent.Clone event) {
//Attach capabilities on death, otherwise crash
PlayerEntity oldPlayer = event.getOriginal();
oldPlayer.revive();
PlayerEntity newPlayer = event.getPlayer();
ModifierSettingsManager.setModifierSettings(newPlayer, ModifierSettingsManager.getModifierSettings(oldPlayer));
ModeSettingsManager.setModeSettings(newPlayer, ModeSettingsManager.getModeSettings(oldPlayer));
}
} }

View File

@@ -1,48 +1,51 @@
package nl.requios.effortlessbuilding; package nl.requios.effortlessbuilding;
import net.minecraft.client.Minecraft; import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.renderer.texture.AtlasTexture; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.KeyMapping;
import net.minecraft.util.ResourceLocation; import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
import net.minecraftforge.client.event.RegisterShadersEvent;
import net.minecraftforge.client.settings.KeyConflictContext;
import net.minecraftforge.client.settings.KeyModifier;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.render.BuildRenderTypes;
import org.lwjgl.glfw.GLFW;
import java.util.HashMap; import java.io.IOException;
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD, value = {Dist.CLIENT}) @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD, value = {Dist.CLIENT})
public class ModClientEventHandler { public class ModClientEventHandler {
private static final HashMap<BuildModes.BuildModeEnum, ResourceLocation> buildModeIcons = new HashMap<>(); @SubscribeEvent
private static final HashMap<ModeOptions.ActionEnum, ResourceLocation> modeOptionIcons = new HashMap<>(); public static void registerKeyMappings(RegisterKeyMappingsEvent event) {
EffortlessBuilding.log("Registering KeyMappings!");
@SubscribeEvent // register key bindings
public static void onTextureStitch(final TextureStitchEvent.Pre event) { ClientProxy.keyBindings = new KeyMapping[6];
EffortlessBuilding.log("Stitching textures");
//register icon textures
for (final BuildModes.BuildModeEnum mode : BuildModes.BuildModeEnum.values())
{
final ResourceLocation spriteLocation = new ResourceLocation(EffortlessBuilding.MODID, "icons/" + mode.name().toLowerCase());
event.addSprite(spriteLocation);
buildModeIcons.put(mode, spriteLocation);
}
for (final ModeOptions.ActionEnum action : ModeOptions.ActionEnum.values()) // instantiate the key bindings
{ ClientProxy.keyBindings[0] = new KeyMapping("key.effortlessbuilding.hud.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category");
final ResourceLocation spriteLocation = new ResourceLocation(EffortlessBuilding.MODID, "icons/" + action.name().toLowerCase()); ClientProxy.keyBindings[1] = new KeyMapping("key.effortlessbuilding.replace.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_KP_SUBTRACT, 0), "key.effortlessbuilding.category");
event.addSprite(spriteLocation); ClientProxy.keyBindings[2] = new KeyMapping("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category");
modeOptionIcons.put(action, spriteLocation); ClientProxy.keyBindings[3] = new KeyMapping("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category");
} ClientProxy.keyBindings[4] = new KeyMapping("key.effortlessbuilding.redo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputConstants.getKey(GLFW.GLFW_KEY_Y, 0), "key.effortlessbuilding.category");
} ClientProxy.keyBindings[5] = new KeyMapping("key.effortlessbuilding.altplacement.desc", KeyConflictContext.IN_GAME, InputConstants.getKey(GLFW.GLFW_KEY_LEFT_CONTROL, 0), "key.effortlessbuilding.category");
public static TextureAtlasSprite getBuildModeIcon(BuildModes.BuildModeEnum mode) { for (KeyMapping keyBinding : ClientProxy.keyBindings) {
return Minecraft.getInstance().getModelManager().getAtlasTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE).getSprite(buildModeIcons.get(mode)); event.register(keyBinding);
} }
}
public static TextureAtlasSprite getModeOptionIcon(ModeOptions.ActionEnum action) { @SubscribeEvent
return Minecraft.getInstance().getModelManager().getAtlasTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE).getSprite(modeOptionIcons.get(action)); public static void registerShaders(RegisterShadersEvent event) throws IOException {
} event.registerShader(new ShaderInstance(event.getResourceManager(),
new ResourceLocation(EffortlessBuilding.MODID, "dissolve"),
DefaultVertexFormat.BLOCK),
shaderInstance -> BuildRenderTypes.dissolveShaderInstance = shaderInstance);
}
} }

View File

@@ -1,45 +0,0 @@
package nl.requios.effortlessbuilding;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import java.util.HashMap;
// You can use EventBusSubscriber to automatically subscribe events on the contained class (this is subscribing to the MOD
// Event bus for receiving Registry Events)
@Mod.EventBusSubscriber(bus=Mod.EventBusSubscriber.Bus.MOD)
public class ModEventHandler {
@SubscribeEvent
public static void registerBlocks(RegistryEvent.Register<Block> event) {
event.getRegistry().registerAll(EffortlessBuilding.BLOCKS);
}
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event) {
event.getRegistry().registerAll(EffortlessBuilding.ITEMS);
for (Block block : EffortlessBuilding.BLOCKS)
{
event.getRegistry().register(new BlockItem(block, new Item.Properties()).setRegistryName(block.getRegistryName()));
}
}
// @SubscribeEvent
// public static void registerContainerTypes(RegistryEvent.Register<ContainerType<?>> event) {
// event.getRegistry().register()
// }
}

View File

@@ -1,39 +1,39 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import java.util.Dictionary; import java.util.Dictionary;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.UUID; import java.util.UUID;
public abstract class BaseBuildMode implements IBuildMode { public abstract class BaseBuildMode implements IBuildMode {
//In singleplayer client and server variables are shared //In singleplayer client and server variables are shared
//Split everything that needs separate values and may not be called twice in one click //Split everything that needs separate values and may not be called twice in one click
protected Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>(); protected Dictionary<UUID, Integer> rightClickClientTable = new Hashtable<>();
protected Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>(); protected Dictionary<UUID, Integer> rightClickServerTable = new Hashtable<>();
protected Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>(); protected Dictionary<UUID, BlockPos> firstPosTable = new Hashtable<>();
protected Dictionary<UUID, Direction> sideHitTable = new Hashtable<>(); protected Dictionary<UUID, Direction> sideHitTable = new Hashtable<>();
protected Dictionary<UUID, Vec3d> hitVecTable = new Hashtable<>(); protected Dictionary<UUID, Vec3> hitVecTable = new Hashtable<>();
@Override @Override
public void initialize(PlayerEntity player) { public void initialize(Player player) {
rightClickClientTable.put(player.getUniqueID(), 0); rightClickClientTable.put(player.getUUID(), 0);
rightClickServerTable.put(player.getUniqueID(), 0); rightClickServerTable.put(player.getUUID(), 0);
firstPosTable.put(player.getUniqueID(), BlockPos.ZERO); firstPosTable.put(player.getUUID(), BlockPos.ZERO);
sideHitTable.put(player.getUniqueID(), Direction.UP); sideHitTable.put(player.getUUID(), Direction.UP);
hitVecTable.put(player.getUniqueID(), Vec3d.ZERO); hitVecTable.put(player.getUUID(), Vec3.ZERO);
} }
@Override @Override
public Direction getSideHit(PlayerEntity player) { public Direction getSideHit(Player player) {
return sideHitTable.get(player.getUniqueID()); return sideHitTable.get(player.getUUID());
} }
@Override @Override
public Vec3d getHitVec(PlayerEntity player) { public Vec3 getHitVec(Player player) {
return hitVecTable.get(player.getUniqueID()); return hitVecTable.get(player.getUUID());
} }
} }

View File

@@ -1,11 +1,12 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import com.mojang.math.Vector4f;
import net.minecraft.util.Direction; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.Direction;
import net.minecraft.util.math.RayTraceContext; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.level.ClipContext;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.buildmodes.*; import nl.requios.effortlessbuilding.buildmode.buildmodes.*;
import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers; import nl.requios.effortlessbuilding.buildmodifier.BuildModifiers;
@@ -20,252 +21,282 @@ import java.util.Dictionary;
import java.util.Hashtable; import java.util.Hashtable;
import java.util.List; import java.util.List;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*; import static nl.requios.effortlessbuilding.buildmode.ModeOptions.OptionEnum;
public class BuildModes { public class BuildModes {
//Static variables are shared between client and server in singleplayer //Static variables are shared between client and server in singleplayer
//We need them separate //We need them separate
public static Dictionary<PlayerEntity, Boolean> currentlyBreakingClient = new Hashtable<>(); public static Dictionary<Player, Boolean> currentlyBreakingClient = new Hashtable<>();
public static Dictionary<PlayerEntity, Boolean> currentlyBreakingServer = new Hashtable<>(); public static Dictionary<Player, Boolean> currentlyBreakingServer = new Hashtable<>();
public enum BuildModeEnum { //Uses a network message to get the previous raytraceresult from the player
NORMAL("effortlessbuilding.mode.normal", new Normal()), //The server could keep track of all raytraceresults but this might lag with many players
NORMAL_PLUS("effortlessbuilding.mode.normal_plus", new NormalPlus(), OptionEnum.BUILD_SPEED), //Raytraceresult is needed for sideHit and hitVec
LINE("effortlessbuilding.mode.line", new Line() /*, OptionEnum.THICKNESS*/), public static void onBlockPlacedMessage(Player player, BlockPlacedMessage message) {
WALL("effortlessbuilding.mode.wall", new Wall(), OptionEnum.FILL),
FLOOR("effortlessbuilding.mode.floor", new Floor(), OptionEnum.FILL),
DIAGONAL_LINE("effortlessbuilding.mode.diagonal_line", new DiagonalLine() /*, OptionEnum.THICKNESS*/),
DIAGONAL_WALL("effortlessbuilding.mode.diagonal_wall", new DiagonalWall() /*, OptionEnum.FILL*/),
SLOPE_FLOOR("effortlessbuilding.mode.slope_floor", new SlopeFloor(), OptionEnum.RAISED_EDGE),
CIRCLE("effortlessbuilding.mode.circle", new Circle(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CYLINDER("effortlessbuilding.mode.cylinder", new Cylinder(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
SPHERE("effortlessbuilding.mode.sphere", new Sphere(), OptionEnum.CIRCLE_START, OptionEnum.FILL),
CUBE("effortlessbuilding.mode.cube", new Cube(), OptionEnum.CUBE_FILL);
public String name; //Check if not in the middle of breaking
public IBuildMode instance; Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
public OptionEnum[] options; if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) {
//Cancel breaking
initializeMode(player);
return;
}
BuildModeEnum(String name, IBuildMode instance, OptionEnum... options) { ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
this.name = name; ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
this.instance = instance; BuildModeEnum buildMode = modeSettings.getBuildMode();
this.options = options;
}
}
//Uses a network message to get the previous raytraceresult from the player BlockPos startPos = null;
//The server could keep track of all raytraceresults but this might lag with many players
//Raytraceresult is needed for sideHit and hitVec
public static void onBlockPlacedMessage(PlayerEntity player, BlockPlacedMessage message) {
//Check if not in the middle of breaking if (message.isBlockHit() && message.getBlockPos() != null) {
Dictionary<PlayerEntity, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; startPos = message.getBlockPos();
if (currentlyBreaking.get(player) != null && currentlyBreaking.get(player)) {
//Cancel breaking
initializeMode(player);
return;
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); //Offset in direction of sidehit if not quickreplace and not replaceable
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable();
BuildModeEnum buildMode = modeSettings.getBuildMode(); boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, message.getSideHit());
if (!modifierSettings.doQuickReplace() && !replaceable && !becomesDoubleSlab) {
startPos = startPos.relative(message.getSideHit());
}
BlockPos startPos = null; //Get under tall grass and other replaceable blocks
if (modifierSettings.doQuickReplace() && replaceable) {
startPos = startPos.below();
}
if (message.isBlockHit() && message.getBlockPos() != null) { //Check if player reach does not exceed startpos
startPos = message.getBlockPos(); int maxReach = ReachHelper.getMaxReach(player);
if (buildMode != BuildModeEnum.NORMAL && player.blockPosition().distSqr(startPos) > maxReach * maxReach) {
EffortlessBuilding.log(player, "Placement exceeds your reach.");
return;
}
}
//Offset in direction of sidehit if not quickreplace and not replaceable //Even when no starting block is found, call buildmode instance
//TODO 1.13 replaceable //We might want to place things in the air
boolean replaceable = player.world.getBlockState(startPos).getMaterial().isReplaceable(); List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace());
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, message.getSideHit());
if (!modifierSettings.doQuickReplace() && !replaceable && !becomesDoubleSlab) {
startPos = startPos.offset(message.getSideHit());
}
//Get under tall grass and other replaceable blocks if (coordinates.isEmpty()) {
if (modifierSettings.doQuickReplace() && replaceable) { currentlyBreaking.put(player, false);
startPos = startPos.down(); return;
} }
//Check if player reach does not exceed startpos //Limit number of blocks you can place
int maxReach = ReachHelper.getMaxReach(player); int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (buildMode != BuildModeEnum.NORMAL && player.getPosition().distanceSq(startPos) > maxReach * maxReach) { if (coordinates.size() > limit) {
EffortlessBuilding.log(player, "Placement exceeds your reach."); coordinates = coordinates.subList(0, limit);
return; }
}
}
//Even when no starting block is found, call buildmode instance Direction sideHit = buildMode.instance.getSideHit(player);
//We might want to place things in the air if (sideHit == null) sideHit = message.getSideHit();
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, message.getSideHit(), message.getHitVec(), modifierSettings.doQuickReplace());
if (coordinates.isEmpty()) { Vec3 hitVec = buildMode.instance.getHitVec(player);
currentlyBreaking.put(player, false); if (hitVec == null) hitVec = message.getHitVec();
return;
}
//Limit number of blocks you can place BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec, message.getPlaceStartPos());
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (coordinates.size() > limit) {
coordinates = coordinates.subList(0, limit);
}
Direction sideHit = buildMode.instance.getSideHit(player); //Only works when finishing a buildmode is equal to placing some blocks
if (sideHit == null) sideHit = message.getSideHit(); //No intermediate blocks allowed
currentlyBreaking.remove(player);
}
Vec3d hitVec = buildMode.instance.getHitVec(player); //Use a network message to break blocks in the distance using clientside mouse input
if (hitVec == null) hitVec = message.getHitVec(); public static void onBlockBrokenMessage(Player player, BlockBrokenMessage message) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null;
onBlockBroken(player, startPos, true);
}
BuildModifiers.onBlockPlaced(player, coordinates, sideHit, hitVec, message.getPlaceStartPos()); public static void onBlockBroken(Player player, BlockPos startPos, boolean breakStartPos) {
//Only works when finishing a buildmode is equal to placing some blocks //Check if not in the middle of placing
//No intermediate blocks allowed Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player); if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) {
//Cancel placing
initializeMode(player);
return;
}
} if (!ReachHelper.canBreakFar(player)) return;
//Use a network message to break blocks in the distance using clientside mouse input //If first click
public static void onBlockBrokenMessage(PlayerEntity player, BlockBrokenMessage message) { if (currentlyBreaking.get(player) == null) {
BlockPos startPos = message.isBlockHit() ? message.getBlockPos() : null; //If startpos is null, dont do anything
onBlockBroken(player, startPos, true); if (startPos == null) return;
} }
public static void onBlockBroken(PlayerEntity player, BlockPos startPos, boolean breakStartPos) { ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Check if not in the middle of placing //Get coordinates
Dictionary<PlayerEntity, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; BuildModeEnum buildMode = modeSettings.getBuildMode();
if (currentlyBreaking.get(player) != null && !currentlyBreaking.get(player)) { List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, Direction.UP, Vec3.ZERO, true);
//Cancel placing
initializeMode(player);
return;
}
//If first click if (coordinates.isEmpty()) {
if (currentlyBreaking.get(player) == null) { currentlyBreaking.put(player, true);
//If startpos is null, dont do anything return;
if (startPos == null) return; }
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); //Let buildmodifiers break blocks
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); BuildModifiers.onBlockBroken(player, coordinates, breakStartPos);
//Get coordinates //Only works when finishing a buildmode is equal to breaking some blocks
BuildModeEnum buildMode = modeSettings.getBuildMode(); //No intermediate blocks allowed
List<BlockPos> coordinates = buildMode.instance.onRightClick(player, startPos, Direction.UP, Vec3d.ZERO, true); currentlyBreaking.remove(player);
}
if (coordinates.isEmpty()) { public static List<BlockPos> findCoordinates(Player player, BlockPos startPos, boolean skipRaytrace) {
currentlyBreaking.put(player, true); List<BlockPos> coordinates = new ArrayList<>();
return;
}
//Let buildmodifiers break blocks ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
BuildModifiers.onBlockBroken(player, coordinates, breakStartPos); coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace));
//Only works when finishing a buildmode is equal to breaking some blocks return coordinates;
//No intermediate blocks allowed }
currentlyBreaking.remove(player);
}
public static List<BlockPos> findCoordinates(PlayerEntity player, BlockPos startPos, boolean skipRaytrace) { public static void initializeMode(Player player) {
List<BlockPos> coordinates = new ArrayList<>(); //Resetting mode, so not placing or breaking
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
currentlyBreaking.remove(player);
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player);
coordinates.addAll(modeSettings.getBuildMode().instance.findCoordinates(player, startPos, skipRaytrace)); }
return coordinates; public static boolean isCurrentlyPlacing(Player player) {
} Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null && !currentlyBreaking.get(player);
}
public static void initializeMode(PlayerEntity player) { public static boolean isCurrentlyBreaking(Player player) {
//Resetting mode, so not placing or breaking Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
Dictionary<PlayerEntity, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; return currentlyBreaking.get(player) != null && currentlyBreaking.get(player);
currentlyBreaking.remove(player); }
ModeSettingsManager.getModeSettings(player).getBuildMode().instance.initialize(player); //Either placing or breaking
} public static boolean isActive(Player player) {
Dictionary<Player, Boolean> currentlyBreaking = player.level.isClientSide ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null;
}
public static boolean isCurrentlyPlacing(PlayerEntity player) { //Find coordinates on a line bound by a plane
Dictionary<PlayerEntity, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; public static Vec3 findXBound(double x, Vec3 start, Vec3 look) {
return currentlyBreaking.get(player) != null && !currentlyBreaking.get(player); //then y and z are
} double y = (x - start.x) / look.x * look.y + start.y;
double z = (x - start.x) / look.x * look.z + start.z;
public static boolean isCurrentlyBreaking(PlayerEntity player) { return new Vec3(x, y, z);
Dictionary<PlayerEntity, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer; }
return currentlyBreaking.get(player) != null && currentlyBreaking.get(player);
}
//Either placing or breaking
public static boolean isActive(PlayerEntity player) {
Dictionary<PlayerEntity, Boolean> currentlyBreaking = player.world.isRemote ? currentlyBreakingClient : currentlyBreakingServer;
return currentlyBreaking.get(player) != null;
}
//-- Common build mode functionality --// //-- Common build mode functionality --//
//Find coordinates on a line bound by a plane public static Vec3 findYBound(double y, Vec3 start, Vec3 look) {
public static Vec3d findXBound(double x, Vec3d start, Vec3d look) { //then x and z are
//then y and z are double x = (y - start.y) / look.y * look.x + start.x;
double y = (x - start.x) / look.x * look.y + start.y; double z = (y - start.y) / look.y * look.z + start.z;
double z = (x - start.x) / look.x * look.z + start.z;
return new Vec3d(x, y, z); return new Vec3(x, y, z);
} }
public static Vec3d findYBound(double y, Vec3d start, Vec3d look) { public static Vec3 findZBound(double z, Vec3 start, Vec3 look) {
//then x and z are //then x and y are
double x = (y - start.y) / look.y * look.x + start.x; double x = (z - start.z) / look.z * look.x + start.x;
double z = (y - start.y) / look.y * look.z + start.z; double y = (z - start.z) / look.z * look.y + start.y;
return new Vec3d(x, y, z); return new Vec3(x, y, z);
} }
public static Vec3d findZBound(double z, Vec3d start, Vec3d look) { //Use this instead of player.getLookVec() in any buildmodes code
//then x and y are public static Vec3 getPlayerLookVec(Player player) {
double x = (z - start.z) / look.z * look.x + start.x; Vec3 lookVec = player.getLookAngle();
double y = (z - start.z) / look.z * look.y + start.y; double x = lookVec.x;
double y = lookVec.y;
double z = lookVec.z;
return new Vec3d(x, y, z); //Further calculations (findXBound etc) don't like any component being 0 or 1 (e.g. dividing by 0)
} //isCriteriaValid below will take up to 2 minutes to raytrace blocks towards infinity if that is the case
//So make sure they are close to but never exactly 0 or 1
if (Math.abs(x) < 0.0001) x = 0.0001;
if (Math.abs(x - 1.0) < 0.0001) x = 0.9999;
if (Math.abs(x + 1.0) < 0.0001) x = -0.9999;
//Use this instead of player.getLookVec() in any buildmodes code if (Math.abs(y) < 0.0001) y = 0.0001;
public static Vec3d getPlayerLookVec(PlayerEntity player){ if (Math.abs(y - 1.0) < 0.0001) y = 0.9999;
Vec3d lookVec = player.getLookVec(); if (Math.abs(y + 1.0) < 0.0001) y = -0.9999;
double x = lookVec.x;
double y = lookVec.y;
double z = lookVec.z;
//Further calculations (findXBound etc) don't like any component being 0 or 1 (e.g. dividing by 0) if (Math.abs(z) < 0.0001) z = 0.0001;
//isCriteriaValid below will take up to 2 minutes to raytrace blocks towards infinity if that is the case if (Math.abs(z - 1.0) < 0.0001) z = 0.9999;
//So make sure they are close to but never exactly 0 or 1 if (Math.abs(z + 1.0) < 0.0001) z = -0.9999;
if (Math.abs(x) < 0.0001) x = 0.0001;
if (Math.abs(x - 1.0) < 0.0001) x = 0.9999;
if (Math.abs(x + 1.0) < 0.0001) x = -0.9999;
if (Math.abs(y) < 0.0001) y = 0.0001; return new Vec3(x, y, z);
if (Math.abs(y - 1.0) < 0.0001) y = 0.9999; }
if (Math.abs(y + 1.0) < 0.0001) y = -0.9999;
if (Math.abs(z) < 0.0001) z = 0.0001; public static boolean isCriteriaValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace, Vec3 lineBound, Vec3 planeBound, double distToPlayerSq) {
if (Math.abs(z - 1.0) < 0.0001) z = 0.9999; boolean intersects = false;
if (Math.abs(z + 1.0) < 0.0001) z = -0.9999; if (!skipRaytrace) {
//collision within a 1 block radius to selected is fine
ClipContext rayTraceContext = new ClipContext(start, lineBound, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player);
HitResult rayTraceResult = player.level.clip(rayTraceContext);
intersects = rayTraceResult != null && rayTraceResult.getType() == HitResult.Type.BLOCK &&
planeBound.subtract(rayTraceResult.getLocation()).lengthSqr() > 4;
}
return new Vec3d(x, y, z); return planeBound.subtract(start).dot(look) > 0 &&
} distToPlayerSq > 2 && distToPlayerSq < reach * reach &&
!intersects;
}
public static boolean isCriteriaValid(Vec3d start, Vec3d look, int reach, PlayerEntity player, boolean skipRaytrace, Vec3d lineBound, Vec3d planeBound, double distToPlayerSq) { public enum BuildModeEnum {
boolean intersects = false; NORMAL("normal", new Normal(), BuildModeCategoryEnum.BASIC),
if (!skipRaytrace) { NORMAL_PLUS("normal_plus", new NormalPlus(), BuildModeCategoryEnum.BASIC, OptionEnum.BUILD_SPEED),
//collision within a 1 block radius to selected is fine LINE("line", new Line(), BuildModeCategoryEnum.BASIC /*, OptionEnum.THICKNESS*/),
RayTraceContext rayTraceContext = new RayTraceContext(start, lineBound, RayTraceContext.BlockMode.COLLIDER, RayTraceContext.FluidMode.NONE, player); WALL("wall", new Wall(), BuildModeCategoryEnum.BASIC, OptionEnum.FILL),
RayTraceResult rayTraceResult = player.world.rayTraceBlocks(rayTraceContext); FLOOR("floor", new Floor(), BuildModeCategoryEnum.BASIC, OptionEnum.FILL),
intersects = rayTraceResult != null && rayTraceResult.getType() == RayTraceResult.Type.BLOCK && CUBE("cube", new Cube(), BuildModeCategoryEnum.BASIC, OptionEnum.CUBE_FILL),
planeBound.subtract(rayTraceResult.getHitVec()).lengthSquared() > 4; DIAGONAL_LINE("diagonal_line", new DiagonalLine(), BuildModeCategoryEnum.DIAGONAL /*, OptionEnum.THICKNESS*/),
} DIAGONAL_WALL("diagonal_wall", new DiagonalWall(), BuildModeCategoryEnum.DIAGONAL /*, OptionEnum.FILL*/),
SLOPE_FLOOR("slope_floor", new SlopeFloor(), BuildModeCategoryEnum.DIAGONAL, OptionEnum.RAISED_EDGE),
CIRCLE("circle", new Circle(), BuildModeCategoryEnum.CIRCULAR, OptionEnum.CIRCLE_START, OptionEnum.FILL),
CYLINDER("cylinder", new Cylinder(), BuildModeCategoryEnum.CIRCULAR, OptionEnum.CIRCLE_START, OptionEnum.FILL),
SPHERE("sphere", new Sphere(), BuildModeCategoryEnum.CIRCULAR, OptionEnum.CIRCLE_START, OptionEnum.FILL);
// PYRAMID("pyramid", new Pyramid(), BuildModeCategoryEnum.ROOF),
// CONE("cone", new Cone(), BuildModeCategoryEnum.ROOF),
// DOME("dome", new Dome(), BuildModeCategoryEnum.ROOF);
return planeBound.subtract(start).dotProduct(look) > 0 && private final String name;
distToPlayerSq > 2 && distToPlayerSq < reach * reach && public final IBuildMode instance;
!intersects; public final BuildModeCategoryEnum category;
} public final OptionEnum[] options;
BuildModeEnum(String name, IBuildMode instance, BuildModeCategoryEnum category, OptionEnum... options) {
this.name = name;
this.instance = instance;
this.category = category;
this.options = options;
}
public String getName() {
return name;
}
public String getNameKey() {
return "effortlessbuilding.mode." + name;
}
public String getDescriptionKey() {
return "effortlessbuilding.modedescription." + name;
}
}
public enum BuildModeCategoryEnum {
BASIC(new Vector4f(0f, .5f, 1f, .8f)),
DIAGONAL(new Vector4f(0.56f, 0.28f, 0.87f, .8f)),
CIRCULAR(new Vector4f(0.29f, 0.76f, 0.3f, 1f)),
ROOF(new Vector4f(0.83f, 0.87f, 0.23f, .8f));
public final Vector4f color;
BuildModeCategoryEnum(Vector4f color) {
this.color = color;
}
}
} }

View File

@@ -1,25 +1,25 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import java.util.List; import java.util.List;
public interface IBuildMode { public interface IBuildMode {
//Fired when a player selects a buildmode and when it needs to initializeMode //Fired when a player selects a buildmode and when it needs to initializeMode
void initialize(PlayerEntity player); void initialize(Player player);
//Fired when a block would be placed //Fired when a block would be placed
//Return a list of coordinates where you want to place blocks //Return a list of coordinates where you want to place blocks
List<BlockPos> onRightClick(PlayerEntity player, BlockPos blockPos, Direction sideHit, Vec3d hitVec, boolean skipRaytrace); List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace);
//Fired continuously for visualization purposes //Fired continuously for visualization purposes
List<BlockPos> findCoordinates(PlayerEntity player, BlockPos blockPos, boolean skipRaytrace); List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace);
Direction getSideHit(PlayerEntity player); Direction getSideHit(Player player);
Vec3d getHitVec(PlayerEntity player); Vec3 getHitVec(Player player);
} }

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.text.TextFormatting; import net.minecraft.ChatFormatting;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
@@ -9,183 +9,183 @@ import nl.requios.effortlessbuilding.proxy.ClientProxy;
public class ModeOptions { public class ModeOptions {
public enum ActionEnum { private static ActionEnum buildSpeed = ActionEnum.NORMAL_SPEED;
UNDO("effortlessbuilding.action.undo"), private static ActionEnum fill = ActionEnum.FULL;
REDO("effortlessbuilding.action.redo"), private static ActionEnum cubeFill = ActionEnum.CUBE_FULL;
REPLACE("effortlessbuilding.action.replace"), private static ActionEnum raisedEdge = ActionEnum.SHORT_EDGE;
OPEN_MODIFIER_SETTINGS("effortlessbuilding.action.open_modifier_settings"), private static ActionEnum lineThickness = ActionEnum.THICKNESS_1;
OPEN_PLAYER_SETTINGS("effortlessbuilding.action.open_player_settings"), private static ActionEnum circleStart = ActionEnum.CIRCLE_START_CORNER;
NORMAL_SPEED("effortlessbuilding.action.normal_speed"), public static ActionEnum getOptionSetting(OptionEnum option) {
FAST_SPEED("effortlessbuilding.action.fast_speed"), switch (option) {
case BUILD_SPEED:
return getBuildSpeed();
case FILL:
return getFill();
case CUBE_FILL:
return getCubeFill();
case RAISED_EDGE:
return getRaisedEdge();
case LINE_THICKNESS:
return getLineThickness();
case CIRCLE_START:
return getCircleStart();
default:
return null;
}
}
FULL("effortlessbuilding.action.full"), public static ActionEnum getBuildSpeed() {
HOLLOW("effortlessbuilding.action.hollow"), return buildSpeed;
}
CUBE_FULL("effortlessbuilding.action.full"), public static ActionEnum getFill() {
CUBE_HOLLOW("effortlessbuilding.action.hollow"), return fill;
CUBE_SKELETON("effortlessbuilding.action.skeleton"), }
SHORT_EDGE("effortlessbuilding.action.short_edge"), public static ActionEnum getCubeFill() {
LONG_EDGE("effortlessbuilding.action.long_edge"), return cubeFill;
}
THICKNESS_1("effortlessbuilding.action.thickness_1"), public static ActionEnum getRaisedEdge() {
THICKNESS_3("effortlessbuilding.action.thickness_3"), return raisedEdge;
THICKNESS_5("effortlessbuilding.action.thickness_5"), }
CIRCLE_START_CORNER("effortlessbuilding.action.start_corner"), public static ActionEnum getLineThickness() {
CIRCLE_START_CENTER("effortlessbuilding.action.start_center"); return lineThickness;
}
public String name; public static ActionEnum getCircleStart() {
return circleStart;
}
ActionEnum(String name) { //Called on both client and server
this.name = name; public static void performAction(Player player, ActionEnum action) {
} if (action == null) return;
}
public enum OptionEnum { switch (action) {
BUILD_SPEED("effortlessbuilding.action.build_speed", ActionEnum.NORMAL_SPEED, ActionEnum.FAST_SPEED), case UNDO:
FILL("effortlessbuilding.action.filling", ActionEnum.FULL, ActionEnum.HOLLOW), UndoRedo.undo(player);
CUBE_FILL("effortlessbuilding.action.filling", ActionEnum.CUBE_FULL, ActionEnum.CUBE_HOLLOW, ActionEnum.CUBE_SKELETON), break;
RAISED_EDGE("effortlessbuilding.action.raised_edge", ActionEnum.SHORT_EDGE, ActionEnum.LONG_EDGE), case REDO:
LINE_THICKNESS("effortlessbuilding.action.thickness", ActionEnum.THICKNESS_1, ActionEnum.THICKNESS_3, ActionEnum.THICKNESS_5), UndoRedo.redo(player);
CIRCLE_START("effortlessbuilding.action.circle_start", ActionEnum.CIRCLE_START_CORNER, ActionEnum.CIRCLE_START_CENTER); break;
case REPLACE:
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + ChatFormatting.GOLD + "Quick Replace " + ChatFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"), true);
break;
case OPEN_MODIFIER_SETTINGS:
if (player.level.isClientSide)
ClientProxy.openModifierSettings();
break;
case OPEN_PLAYER_SETTINGS:
if (player.level.isClientSide)
ClientProxy.openPlayerSettings();
break;
public String name; case NORMAL_SPEED:
public ActionEnum[] actions; buildSpeed = ActionEnum.NORMAL_SPEED;
break;
case FAST_SPEED:
buildSpeed = ActionEnum.FAST_SPEED;
break;
case FULL:
fill = ActionEnum.FULL;
break;
case HOLLOW:
fill = ActionEnum.HOLLOW;
break;
case CUBE_FULL:
cubeFill = ActionEnum.CUBE_FULL;
break;
case CUBE_HOLLOW:
cubeFill = ActionEnum.CUBE_HOLLOW;
break;
case CUBE_SKELETON:
cubeFill = ActionEnum.CUBE_SKELETON;
break;
case SHORT_EDGE:
raisedEdge = ActionEnum.SHORT_EDGE;
break;
case LONG_EDGE:
raisedEdge = ActionEnum.LONG_EDGE;
break;
case THICKNESS_1:
lineThickness = ActionEnum.THICKNESS_1;
break;
case THICKNESS_3:
lineThickness = ActionEnum.THICKNESS_3;
break;
case THICKNESS_5:
lineThickness = ActionEnum.THICKNESS_5;
break;
case CIRCLE_START_CENTER:
circleStart = ActionEnum.CIRCLE_START_CENTER;
break;
case CIRCLE_START_CORNER:
circleStart = ActionEnum.CIRCLE_START_CORNER;
break;
}
OptionEnum(String name, ActionEnum... actions){ if (player.level.isClientSide &&
this.name = name; action != ActionEnum.REPLACE &&
this.actions = actions; action != ActionEnum.OPEN_MODIFIER_SETTINGS &&
} action != ActionEnum.OPEN_PLAYER_SETTINGS) {
}
private static ActionEnum buildSpeed = ActionEnum.NORMAL_SPEED; EffortlessBuilding.logTranslate(player, "", action.name, "", true);
private static ActionEnum fill = ActionEnum.FULL; }
private static ActionEnum cubeFill = ActionEnum.CUBE_FULL; }
private static ActionEnum raisedEdge = ActionEnum.SHORT_EDGE;
private static ActionEnum lineThickness = ActionEnum.THICKNESS_1;
private static ActionEnum circleStart = ActionEnum.CIRCLE_START_CORNER;
public static ActionEnum getOptionSetting(OptionEnum option) { public enum ActionEnum {
switch (option) { UNDO("effortlessbuilding.action.undo"),
case BUILD_SPEED: REDO("effortlessbuilding.action.redo"),
return getBuildSpeed(); REPLACE("effortlessbuilding.action.replace"),
case FILL: OPEN_MODIFIER_SETTINGS("effortlessbuilding.action.open_modifier_settings"),
return getFill(); OPEN_PLAYER_SETTINGS("effortlessbuilding.action.open_player_settings"),
case CUBE_FILL:
return getCubeFill();
case RAISED_EDGE:
return getRaisedEdge();
case LINE_THICKNESS:
return getLineThickness();
case CIRCLE_START:
return getCircleStart();
default:
return null;
}
}
public static ActionEnum getBuildSpeed() { NORMAL_SPEED("effortlessbuilding.action.normal_speed"),
return buildSpeed; FAST_SPEED("effortlessbuilding.action.fast_speed"),
}
public static ActionEnum getFill() { FULL("effortlessbuilding.action.full"),
return fill; HOLLOW("effortlessbuilding.action.hollow"),
}
public static ActionEnum getCubeFill() { CUBE_FULL("effortlessbuilding.action.full"),
return cubeFill; CUBE_HOLLOW("effortlessbuilding.action.hollow"),
} CUBE_SKELETON("effortlessbuilding.action.skeleton"),
public static ActionEnum getRaisedEdge() { SHORT_EDGE("effortlessbuilding.action.short_edge"),
return raisedEdge; LONG_EDGE("effortlessbuilding.action.long_edge"),
}
public static ActionEnum getLineThickness() { THICKNESS_1("effortlessbuilding.action.thickness_1"),
return lineThickness; THICKNESS_3("effortlessbuilding.action.thickness_3"),
} THICKNESS_5("effortlessbuilding.action.thickness_5"),
public static ActionEnum getCircleStart() { CIRCLE_START_CORNER("effortlessbuilding.action.start_corner"),
return circleStart; CIRCLE_START_CENTER("effortlessbuilding.action.start_center");
}
//Called on both client and server public String name;
public static void performAction(PlayerEntity player, ActionEnum action) {
if (action == null) return;
switch (action) { ActionEnum(String name) {
case UNDO: this.name = name;
UndoRedo.undo(player); }
break; }
case REDO:
UndoRedo.redo(player);
break;
case REPLACE:
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"), true);
break;
case OPEN_MODIFIER_SETTINGS:
if (player.world.isRemote)
ClientProxy.openModifierSettings();
break;
case OPEN_PLAYER_SETTINGS:
if (player.world.isRemote)
ClientProxy.openPlayerSettings();
break;
case NORMAL_SPEED: public enum OptionEnum {
buildSpeed = ActionEnum.NORMAL_SPEED; BUILD_SPEED("effortlessbuilding.action.build_speed", ActionEnum.NORMAL_SPEED, ActionEnum.FAST_SPEED),
break; FILL("effortlessbuilding.action.filling", ActionEnum.FULL, ActionEnum.HOLLOW),
case FAST_SPEED: CUBE_FILL("effortlessbuilding.action.filling", ActionEnum.CUBE_FULL, ActionEnum.CUBE_HOLLOW, ActionEnum.CUBE_SKELETON),
buildSpeed = ActionEnum.FAST_SPEED; RAISED_EDGE("effortlessbuilding.action.raised_edge", ActionEnum.SHORT_EDGE, ActionEnum.LONG_EDGE),
break; LINE_THICKNESS("effortlessbuilding.action.thickness", ActionEnum.THICKNESS_1, ActionEnum.THICKNESS_3, ActionEnum.THICKNESS_5),
case FULL: CIRCLE_START("effortlessbuilding.action.circle_start", ActionEnum.CIRCLE_START_CORNER, ActionEnum.CIRCLE_START_CENTER);
fill = ActionEnum.FULL;
break;
case HOLLOW:
fill = ActionEnum.HOLLOW;
break;
case CUBE_FULL:
cubeFill = ActionEnum.CUBE_FULL;
break;
case CUBE_HOLLOW:
cubeFill = ActionEnum.CUBE_HOLLOW;
break;
case CUBE_SKELETON:
cubeFill = ActionEnum.CUBE_SKELETON;
break;
case SHORT_EDGE:
raisedEdge = ActionEnum.SHORT_EDGE;
break;
case LONG_EDGE:
raisedEdge = ActionEnum.LONG_EDGE;
break;
case THICKNESS_1:
lineThickness = ActionEnum.THICKNESS_1;
break;
case THICKNESS_3:
lineThickness = ActionEnum.THICKNESS_3;
break;
case THICKNESS_5:
lineThickness = ActionEnum.THICKNESS_5;
break;
case CIRCLE_START_CENTER:
circleStart = ActionEnum.CIRCLE_START_CENTER;
break;
case CIRCLE_START_CORNER:
circleStart = ActionEnum.CIRCLE_START_CORNER;
break;
}
if (player.world.isRemote && public String name;
action != ActionEnum.REPLACE && public ActionEnum[] actions;
action != ActionEnum.OPEN_MODIFIER_SETTINGS &&
action != ActionEnum.OPEN_PLAYER_SETTINGS) {
EffortlessBuilding.logTranslate(player, "", action.name, "", true); OptionEnum(String name, ActionEnum... actions) {
} this.name = name;
} this.actions = actions;
}
}
} }

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModeCapabilityManager; import nl.requios.effortlessbuilding.capability.ModeCapabilityManager;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -16,83 +16,82 @@ import javax.annotation.Nonnull;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class ModeSettingsManager { public class ModeSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability //Retrieves the buildsettings of a player through the modeCapability capability
//Never returns null //Never returns null
@Nonnull @Nonnull
public static ModeSettings getModeSettings(PlayerEntity player) { public static ModeSettings getModeSettings(Player player) {
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability = LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.modeCapability, null); player.getCapability(ModeCapabilityManager.MODE_CAPABILITY, null);
if (modeCapability.isPresent()) { if (modeCapability.isPresent()) {
ModeCapabilityManager.IModeCapability capability = modeCapability.orElse(null); ModeCapabilityManager.IModeCapability capability = modeCapability.orElse(null);
if (capability.getModeData() == null) { if (capability.getModeData() == null){
capability.setModeData(new ModeSettings()); capability.setModeData(new ModeSettings());
} }
return capability.getModeData(); return capability.getModeData();
} }
//Player does not have modeCapability capability // EffortlessBuilding.logger.warn("Player does not have modeCapability: " + player);
//Return dummy settings //Return dummy settings
return new ModeSettings(); return new ModeSettings();
// throw new IllegalArgumentException("Player does not have modeCapability capability"); }
}
public static void setModeSettings(PlayerEntity player, ModeSettings modeSettings) { public static void setModeSettings(Player player, ModeSettings modeSettings) {
if (player == null) { if (player == null) {
EffortlessBuilding.log("Cannot set buildmode settings, player is null"); EffortlessBuilding.log("Cannot set buildmode settings, player is null");
return; return;
} }
LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability = LazyOptional<ModeCapabilityManager.IModeCapability> modeCapability =
player.getCapability(ModeCapabilityManager.modeCapability, null); player.getCapability(ModeCapabilityManager.MODE_CAPABILITY, null);
modeCapability.ifPresent((capability) -> { modeCapability.ifPresent((capability) -> {
capability.setModeData(modeSettings); capability.setModeData(modeSettings);
BuildModes.initializeMode(player); BuildModes.initializeMode(player);
}); });
if (!modeCapability.isPresent()) { if (!modeCapability.isPresent()) {
EffortlessBuilding.log(player, "Saving buildmode settings failed."); EffortlessBuilding.log(player, "Saving buildmode settings failed.");
} }
} }
public static String sanitize(ModeSettings modeSettings, PlayerEntity player) { public static String sanitize(ModeSettings modeSettings, Player player) {
int maxReach = ReachHelper.getMaxReach(player); int maxReach = ReachHelper.getMaxReach(player);
String error = ""; String error = "";
//TODO sanitize //TODO sanitize
return error; return error;
} }
public static class ModeSettings { public static void handleNewPlayer(Player player) {
private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.NORMAL; //Makes sure player has mode settings (if it doesnt it will create it)
getModeSettings(player);
public ModeSettings() { //Only on server
} if (!player.level.isClientSide) {
//Send to client
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player));
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), msg);
}
}
public ModeSettings(BuildModes.BuildModeEnum buildMode) { public static class ModeSettings {
this.buildMode = buildMode; private BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.NORMAL;
}
public BuildModes.BuildModeEnum getBuildMode() { public ModeSettings() {
return this.buildMode; }
}
public void setBuildMode(BuildModes.BuildModeEnum buildMode) { public ModeSettings(BuildModes.BuildModeEnum buildMode) {
this.buildMode = buildMode; this.buildMode = buildMode;
} }
}
public static void handleNewPlayer(PlayerEntity player){ public BuildModes.BuildModeEnum getBuildMode() {
//Makes sure player has mode settings (if it doesnt it will create it) return this.buildMode;
getModeSettings(player); }
//Only on server public void setBuildMode(BuildModes.BuildModeEnum buildMode) {
if (!player.world.isRemote) { this.buildMode = buildMode;
//Send to client }
ModeSettingsMessage msg = new ModeSettingsMessage(getModeSettings(player)); }
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), msg);
}
}
} }

View File

@@ -1,213 +1,213 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*; import java.util.*;
public abstract class ThreeClicksBuildMode extends BaseBuildMode { public abstract class ThreeClicksBuildMode extends BaseBuildMode {
protected Dictionary<UUID, BlockPos> secondPosTable = new Hashtable<>(); protected Dictionary<UUID, BlockPos> secondPosTable = new Hashtable<>();
static class HeightCriteria { //Finds height after floor has been chosen in buildmodes with 3 clicks
Vec3d planeBound; public static BlockPos findHeight(Player player, BlockPos secondPos, boolean skipRaytrace) {
Vec3d lineBound; Vec3 look = BuildModes.getPlayerLookVec(player);
double distToLineSq; Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
double distToPlayerSq;
HeightCriteria(Vec3d planeBound, BlockPos secondPos, Vec3d start) { List<HeightCriteria> criteriaList = new ArrayList<>(3);
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, secondPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
//Make it from a plane into a line, on y axis only //X
private Vec3d toLongestLine(Vec3d boundVec, BlockPos secondPos) { Vec3 xBound = BuildModes.findXBound(secondPos.getX(), start, look);
BlockPos bound = new BlockPos(boundVec); criteriaList.add(new HeightCriteria(xBound, secondPos, start));
return new Vec3d(secondPos.getX(), bound.getY(), secondPos.getZ());
}
//check if its not behind the player and its not too close and not too far //Z
//also check if raytrace from player to block does not intersect blocks Vec3 zBound = BuildModes.findZBound(secondPos.getZ(), start, look);
public boolean isValid(Vec3d start, Vec3d look, int reach, PlayerEntity player, boolean skipRaytrace) { criteriaList.add(new HeightCriteria(zBound, secondPos, start));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq); //Remove invalid criteria
} int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
} criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
@Override //If none are valid, return empty list of blocks
public void initialize(PlayerEntity player) { if (criteriaList.isEmpty()) return null;
super.initialize(player);
secondPosTable.put(player.getUniqueID(), BlockPos.ZERO);
}
@Override //If only 1 is valid, choose that one
public List<BlockPos> onRightClick(PlayerEntity player, BlockPos blockPos, Direction sideHit, Vec3d hitVec, boolean skipRaytrace) { HeightCriteria selected = criteriaList.get(0);
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; //If multiple are valid, choose based on criteria
int rightClickNr = rightClickTable.get(player.getUniqueID()); if (criteriaList.size() > 1) {
rightClickNr++; //Select the one that is closest (from wall position to its line counterpart)
rightClickTable.put(player.getUniqueID(), rightClickNr); for (int i = 1; i < criteriaList.size(); i++) {
HeightCriteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
}
return new BlockPos(selected.lineBound);
}
if (rightClickNr == 1) { @Override
//If clicking in air, reset and try again public void initialize(Player player) {
if (blockPos == null) { super.initialize(player);
rightClickTable.put(player.getUniqueID(), 0); secondPosTable.put(player.getUUID(), BlockPos.ZERO);
return list; }
}
//First click, remember starting position @Override
firstPosTable.put(player.getUniqueID(), blockPos); public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
sideHitTable.put(player.getUniqueID(), sideHit); List<BlockPos> list = new ArrayList<>();
hitVecTable.put(player.getUniqueID(), hitVec);
//Keep list empty, dont place any blocks yet
} else if (rightClickNr == 2) {
//Second click, find other floor point
BlockPos firstPos = firstPosTable.get(player.getUniqueID());
BlockPos secondPos = findSecondPos(player, firstPos, true);
if (secondPos == null) { Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
rightClickTable.put(player.getUniqueID(), 1); int rightClickNr = rightClickTable.get(player.getUUID());
return list; rightClickNr++;
} rightClickTable.put(player.getUUID(), rightClickNr);
secondPosTable.put(player.getUniqueID(), secondPos); if (rightClickNr == 1) {
//If clicking in air, reset and try again
if (blockPos == null) {
rightClickTable.put(player.getUUID(), 0);
return list;
}
} else { //First click, remember starting position
//Third click, place diagonal wall with height firstPosTable.put(player.getUUID(), blockPos);
list = findCoordinates(player, blockPos, skipRaytrace); sideHitTable.put(player.getUUID(), sideHit);
rightClickTable.put(player.getUniqueID(), 0); hitVecTable.put(player.getUUID(), hitVec);
} //Keep list empty, dont place any blocks yet
} else if (rightClickNr == 2) {
//Second click, find other floor point
BlockPos firstPos = firstPosTable.get(player.getUUID());
BlockPos secondPos = findSecondPos(player, firstPos, true);
return list; if (secondPos == null) {
} rightClickTable.put(player.getUUID(), 1);
return list;
}
@Override secondPosTable.put(player.getUUID(), secondPos);
public List<BlockPos> findCoordinates(PlayerEntity player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID());
if (rightClickNr == 0) { } else {
if (blockPos != null) //Third click, place diagonal wall with height
list.add(blockPos); list = findCoordinates(player, blockPos, skipRaytrace);
} else if (rightClickNr == 1) { rightClickTable.put(player.getUUID(), 0);
BlockPos firstPos = firstPosTable.get(player.getUniqueID()); }
BlockPos secondPos = findSecondPos(player, firstPos, true); return list;
if (secondPos == null) return list; }
//Limit amount of blocks you can place per row @Override
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUUID());
int x1 = firstPos.getX(), x2 = secondPos.getX(); if (rightClickNr == 0) {
int y1 = firstPos.getY(), y2 = secondPos.getY(); if (blockPos != null)
int z1 = firstPos.getZ(), z2 = secondPos.getZ(); list.add(blockPos);
} else if (rightClickNr == 1) {
BlockPos firstPos = firstPosTable.get(player.getUUID());
//limit axis BlockPos secondPos = findSecondPos(player, firstPos, true);
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; if (secondPos == null) return list;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//Add diagonal line from first to second //Limit amount of blocks you can place per row
list.addAll(getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2)); int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
} else { int x1 = firstPos.getX(), x2 = secondPos.getX();
BlockPos firstPos = firstPosTable.get(player.getUniqueID()); int y1 = firstPos.getY(), y2 = secondPos.getY();
BlockPos secondPos = secondPosTable.get(player.getUniqueID()); int z1 = firstPos.getZ(), z2 = secondPos.getZ();
BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, skipRaytrace); //limit axis
if (thirdPos == null) return list; if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//Limit amount of blocks you can place per row //Add diagonal line from first to second
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); list.addAll(getIntermediateBlocks(player, x1, y1, z1, x2, y2, z2));
int x1 = firstPos.getX(), x2 = secondPos.getX(), x3 = thirdPos.getX(); } else {
int y1 = firstPos.getY(), y2 = secondPos.getY(), y3 = thirdPos.getY(); BlockPos firstPos = firstPosTable.get(player.getUUID());
int z1 = firstPos.getZ(), z2 = secondPos.getZ(), z3 = thirdPos.getZ(); BlockPos secondPos = secondPosTable.get(player.getUUID());
//limit axis BlockPos thirdPos = findThirdPos(player, firstPos, secondPos, skipRaytrace);
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; if (thirdPos == null) return list;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
if (x3 - x1 >= axisLimit) x3 = x1 + axisLimit - 1; //Limit amount of blocks you can place per row
if (x1 - x3 >= axisLimit) x3 = x1 - axisLimit + 1; int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
if (y3 - y1 >= axisLimit) y3 = y1 + axisLimit - 1;
if (y1 - y3 >= axisLimit) y3 = y1 - axisLimit + 1;
if (z3 - z1 >= axisLimit) z3 = z1 + axisLimit - 1;
if (z1 - z3 >= axisLimit) z3 = z1 - axisLimit + 1;
//Add diagonal line from first to third int x1 = firstPos.getX(), x2 = secondPos.getX(), x3 = thirdPos.getX();
list.addAll(getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3)); int y1 = firstPos.getY(), y2 = secondPos.getY(), y3 = thirdPos.getY();
} int z1 = firstPos.getZ(), z2 = secondPos.getZ(), z3 = thirdPos.getZ();
return list; //limit axis
} if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
//Finds the place of the second block pos if (x3 - x1 >= axisLimit) x3 = x1 + axisLimit - 1;
protected abstract BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace); if (x1 - x3 >= axisLimit) x3 = x1 - axisLimit + 1;
if (y3 - y1 >= axisLimit) y3 = y1 + axisLimit - 1;
if (y1 - y3 >= axisLimit) y3 = y1 - axisLimit + 1;
if (z3 - z1 >= axisLimit) z3 = z1 + axisLimit - 1;
if (z1 - z3 >= axisLimit) z3 = z1 - axisLimit + 1;
//Finds the place of the third block pos //Add diagonal line from first to third
protected abstract BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace); list.addAll(getFinalBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3));
}
//After first and second pos are known, we want to visualize the blocks in a way (like floor for cube) return list;
protected abstract List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2); }
//After first, second and third pos are known, we want all the blocks //Finds the place of the second block pos
protected abstract List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3); protected abstract BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace);
//Finds height after floor has been chosen in buildmodes with 3 clicks //Finds the place of the third block pos
public static BlockPos findHeight(PlayerEntity player, BlockPos secondPos, boolean skipRaytrace) { protected abstract BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace);
Vec3d look = BuildModes.getPlayerLookVec(player);
Vec3d start = new Vec3d(player.getPosX(), player.getPosY() + player.getEyeHeight(), player.getPosZ());
List<HeightCriteria> criteriaList = new ArrayList<>(3); //After first and second pos are known, we want to visualize the blocks in a way (like floor for cube)
protected abstract List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2);
//X //After first, second and third pos are known, we want all the blocks
Vec3d xBound = BuildModes.findXBound(secondPos.getX(), start, look); protected abstract List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3);
criteriaList.add(new HeightCriteria(xBound, secondPos, start));
//Z static class HeightCriteria {
Vec3d zBound = BuildModes.findZBound(secondPos.getZ(), start, look); Vec3 planeBound;
criteriaList.add(new HeightCriteria(zBound, secondPos, start)); Vec3 lineBound;
double distToLineSq;
double distToPlayerSq;
//Remove invalid criteria HeightCriteria(Vec3 planeBound, BlockPos secondPos, Vec3 start) {
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach this.planeBound = planeBound;
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace)); this.lineBound = toLongestLine(this.planeBound, secondPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSqr();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
}
//If none are valid, return empty list of blocks //Make it from a plane into a line, on y axis only
if (criteriaList.isEmpty()) return null; private Vec3 toLongestLine(Vec3 boundVec, BlockPos secondPos) {
BlockPos bound = new BlockPos(boundVec);
return new Vec3(secondPos.getX(), bound.getY(), secondPos.getZ());
}
//If only 1 is valid, choose that one //check if its not behind the player and its not too close and not too far
HeightCriteria selected = criteriaList.get(0); //also check if raytrace from player to block does not intersect blocks
public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
//If multiple are valid, choose based on criteria return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
if (criteriaList.size() > 1) { }
//Select the one that is closest (from wall position to its line counterpart) }
for (int i = 1; i < criteriaList.size(); i++) {
HeightCriteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
}
return new BlockPos(selected.lineBound);
}
} }

View File

@@ -1,10 +1,9 @@
package nl.requios.effortlessbuilding.buildmode; package nl.requios.effortlessbuilding.buildmode;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList; import java.util.ArrayList;
@@ -14,74 +13,74 @@ import java.util.UUID;
public abstract class TwoClicksBuildMode extends BaseBuildMode { public abstract class TwoClicksBuildMode extends BaseBuildMode {
@Override @Override
public List<BlockPos> onRightClick(PlayerEntity player, BlockPos blockPos, Direction sideHit, Vec3d hitVec, boolean skipRaytrace) { public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID()); int rightClickNr = rightClickTable.get(player.getUUID());
rightClickNr++; rightClickNr++;
rightClickTable.put(player.getUniqueID(), rightClickNr); rightClickTable.put(player.getUUID(), rightClickNr);
if (rightClickNr == 1) { if (rightClickNr == 1) {
//If clicking in air, reset and try again //If clicking in air, reset and try again
if (blockPos == null) { if (blockPos == null) {
rightClickTable.put(player.getUniqueID(), 0); rightClickTable.put(player.getUUID(), 0);
return list; return list;
} }
//First click, remember starting position //First click, remember starting position
firstPosTable.put(player.getUniqueID(), blockPos); firstPosTable.put(player.getUUID(), blockPos);
sideHitTable.put(player.getUniqueID(), sideHit); sideHitTable.put(player.getUUID(), sideHit);
hitVecTable.put(player.getUniqueID(), hitVec); hitVecTable.put(player.getUUID(), hitVec);
//Keep list empty, dont place any blocks yet //Keep list empty, dont place any blocks yet
} else { } else {
//Second click, place blocks //Second click, place blocks
list = findCoordinates(player, blockPos, skipRaytrace); list = findCoordinates(player, blockPos, skipRaytrace);
rightClickTable.put(player.getUniqueID(), 0); rightClickTable.put(player.getUUID(), 0);
} }
return list; return list;
} }
@Override @Override
public List<BlockPos> findCoordinates(PlayerEntity player, BlockPos blockPos, boolean skipRaytrace) { public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
Dictionary<UUID, Integer> rightClickTable = player.world.isRemote ? rightClickClientTable : rightClickServerTable; Dictionary<UUID, Integer> rightClickTable = player.level.isClientSide ? rightClickClientTable : rightClickServerTable;
int rightClickNr = rightClickTable.get(player.getUniqueID()); int rightClickNr = rightClickTable.get(player.getUUID());
BlockPos firstPos = firstPosTable.get(player.getUniqueID()); BlockPos firstPos = firstPosTable.get(player.getUUID());
if (rightClickNr == 0) { if (rightClickNr == 0) {
if (blockPos != null) if (blockPos != null)
list.add(blockPos); list.add(blockPos);
} else { } else {
BlockPos secondPos = findSecondPos(player, firstPos, skipRaytrace); BlockPos secondPos = findSecondPos(player, firstPos, skipRaytrace);
if (secondPos == null) return list; if (secondPos == null) return list;
//Limit amount of blocks we can place per row //Limit amount of blocks we can place per row
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
int x1 = firstPos.getX(), x2 = secondPos.getX(); int x1 = firstPos.getX(), x2 = secondPos.getX();
int y1 = firstPos.getY(), y2 = secondPos.getY(); int y1 = firstPos.getY(), y2 = secondPos.getY();
int z1 = firstPos.getZ(), z2 = secondPos.getZ(); int z1 = firstPos.getZ(), z2 = secondPos.getZ();
//limit axis //limit axis
if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1; if (x2 - x1 >= axisLimit) x2 = x1 + axisLimit - 1;
if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1; if (x1 - x2 >= axisLimit) x2 = x1 - axisLimit + 1;
if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1; if (y2 - y1 >= axisLimit) y2 = y1 + axisLimit - 1;
if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1; if (y1 - y2 >= axisLimit) y2 = y1 - axisLimit + 1;
if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1; if (z2 - z1 >= axisLimit) z2 = z1 + axisLimit - 1;
if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1; if (z1 - z2 >= axisLimit) z2 = z1 - axisLimit + 1;
list.addAll(getAllBlocks(player, x1, y1, z1, x2, y2, z2)); list.addAll(getAllBlocks(player, x1, y1, z1, x2, y2, z2));
} }
return list; return list;
} }
//Finds the place of the second block pos based on criteria (floor must be on same height as first click, wall on same plane etc) //Finds the place of the second block pos based on criteria (floor must be on same height as first click, wall on same plane etc)
protected abstract BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace); protected abstract BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace);
//After first and second pos are known, we want all the blocks //After first and second pos are known, we want all the blocks
protected abstract List<BlockPos> getAllBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2); protected abstract List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2);
} }

View File

@@ -1,88 +1,89 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import java.util.*; import java.util.ArrayList;
import java.util.List;
public class Circle extends TwoClicksBuildMode { public class Circle extends TwoClicksBuildMode {
@Override public static List<BlockPos> getCircleBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { List<BlockPos> list = new ArrayList<>();
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override float centerX = x1;
protected List<BlockPos> getAllBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { float centerZ = z1;
return getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
public static List<BlockPos> getCircleBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { //Adjust for CIRCLE_START
List<BlockPos> list = new ArrayList<>(); if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
centerX = x1 + (x2 - x1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
z1 = (int) (centerZ - (z2 - centerZ));
}
float centerX = x1; float radiusX = Mth.abs(x2 - centerX);
float centerZ = z1; float radiusZ = Mth.abs(z2 - centerZ);
//Adjust for CIRCLE_START if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) { addCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
centerX = x1 + (x2 - x1) / 2f; else
centerZ = z1 + (z2 - z1) / 2f; addHollowCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
} else {
x1 = (int) (centerX - (x2 - centerX));
z1 = (int) (centerZ - (z2 - centerZ));
}
float radiusX = MathHelper.abs(x2 - centerX); return list;
float radiusZ = MathHelper.abs(z2 - centerZ); }
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL) public static void addCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
addCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
else
addHollowCircleBlocks(list, x1, y1, z1, x2, y2, z2, centerX, centerZ, radiusX, radiusZ);
return list; for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
}
public static void addCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) { for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, y1, n));
}
}
}
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { public static void addHollowCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) {
float distance = distance(l, n, centerX, centerZ); for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, y1, n));
}
}
}
public static void addHollowCircleBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, float centerX, float centerZ, float radiusX, float radiusZ) { for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { float distance = distance(l, n, centerX, centerZ);
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n);
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, y1, n));
}
}
}
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { private static float distance(float x1, float z1, float x2, float z2) {
return Mth.sqrt((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1));
}
float distance = distance(l, n, centerX, centerZ); public static float calculateEllipseRadius(float centerX, float centerZ, float radiusX, float radiusZ, int x, int z) {
float radius = calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, l, n); //https://math.stackexchange.com/questions/432902/how-to-get-the-radius-of-an-ellipse-at-a-specific-angle-by-knowing-its-semi-majo
if (distance < radius + 0.4f && distance > radius - 0.6f) float theta = (float) Mth.atan2(z - centerZ, x - centerX);
list.add(new BlockPos(l, y1, n)); float part1 = radiusX * radiusX * Mth.sin(theta) * Mth.sin(theta);
} float part2 = radiusZ * radiusZ * Mth.cos(theta) * Mth.cos(theta);
} return radiusX * radiusZ / Mth.sqrt(part1 + part2);
} }
private static float distance(float x1, float z1, float x2, float z2) { @Override
return MathHelper.sqrt((x2 - x1) * (x2 - x1) + (z2 - z1) * (z2 - z1)); protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
} return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static float calculateEllipseRadius(float centerX, float centerZ, float radiusX, float radiusZ, int x, int z) { @Override
//https://math.stackexchange.com/questions/432902/how-to-get-the-radius-of-an-ellipse-at-a-specific-angle-by-knowing-its-semi-majo protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
float theta = (float) MathHelper.atan2(z - centerZ, x - centerX); return getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
float part1 = radiusX * radiusX * MathHelper.sin(theta) * MathHelper.sin(theta); }
float part2 = radiusZ * radiusZ * MathHelper.cos(theta) * MathHelper.cos(theta);
return radiusX * radiusZ / MathHelper.sqrt(part1 + part2);
}
} }

View File

@@ -0,0 +1,31 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.List;
public class Cone extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//TODO
return SlopeFloor.getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,100 +1,101 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.*; import java.util.ArrayList;
import java.util.List;
public class Cube extends ThreeClicksBuildMode { public class Cube extends ThreeClicksBuildMode {
@Override public static List<BlockPos> getFloorBlocksUsingCubeFill(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { List<BlockPos> list = new ArrayList<>();
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override if (ModeOptions.getCubeFill() == ModeOptions.ActionEnum.CUBE_SKELETON)
protected BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) { Floor.addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
return findHeight(player, secondPos, skipRaytrace); else
} Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
@Override return list;
protected List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { }
return getFloorBlocksUsingCubeFill(player, x1, y1, z1, x2, y2, z2);
}
@Override public static List<BlockPos> getCubeBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
protected List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { List<BlockPos> list = new ArrayList<>();
return getCubeBlocks(player, x1, y1, z1, x3, y3, z3);
}
public static List<BlockPos> getFloorBlocksUsingCubeFill(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { switch (ModeOptions.getCubeFill()) {
List<BlockPos> list = new ArrayList<>(); case CUBE_FULL:
addCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_HOLLOW:
addHollowCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
case CUBE_SKELETON:
addSkeletonCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
}
if (ModeOptions.getCubeFill() == ModeOptions.ActionEnum.CUBE_SKELETON) return list;
Floor.addHollowFloorBlocks(list, x1, x2, y1, z1, z2); }
else
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
return list; public static void addCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
} for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
public static List<BlockPos> getCubeBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
List<BlockPos> list = new ArrayList<>();
switch (ModeOptions.getCubeFill()) { for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
case CUBE_FULL: list.add(new BlockPos(l, m, n));
addCubeBlocks(list, x1, x2, y1, y2, z1, z2); }
break; }
case CUBE_HOLLOW: }
addHollowCubeBlocks(list, x1, x2, y1, y2, z1, z2); }
break;
case CUBE_SKELETON:
addSkeletonCubeBlocks(list, x1, x2, y1, y2, z1, z2);
break;
}
return list; public static void addHollowCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
} Wall.addXWallBlocks(list, x1, y1, y2, z1, z2);
Wall.addXWallBlocks(list, x2, y1, y2, z1, z2);
public static void addCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) { Wall.addZWallBlocks(list, x1, x2, y1, y2, z1);
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { Wall.addZWallBlocks(list, x1, x2, y1, y2, z2);
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { Floor.addFloorBlocks(list, x1, x2, y1, z1, z2);
Floor.addFloorBlocks(list, x1, x2, y2, z1, z2);
}
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { public static void addSkeletonCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) {
list.add(new BlockPos(l, m, n)); Line.addXLineBlocks(list, x1, x2, y1, z1);
} Line.addXLineBlocks(list, x1, x2, y1, z2);
} Line.addXLineBlocks(list, x1, x2, y2, z1);
} Line.addXLineBlocks(list, x1, x2, y2, z2);
}
public static void addHollowCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) { Line.addYLineBlocks(list, y1, y2, x1, z1);
Wall.addXWallBlocks(list, x1, y1, y2, z1, z2); Line.addYLineBlocks(list, y1, y2, x1, z2);
Wall.addXWallBlocks(list, x2, y1, y2, z1, z2); Line.addYLineBlocks(list, y1, y2, x2, z1);
Line.addYLineBlocks(list, y1, y2, x2, z2);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z1); Line.addZLineBlocks(list, z1, z2, x1, y1);
Wall.addZWallBlocks(list, x1, x2, y1, y2, z2); Line.addZLineBlocks(list, z1, z2, x1, y2);
Line.addZLineBlocks(list, z1, z2, x2, y1);
Line.addZLineBlocks(list, z1, z2, x2, y2);
}
Floor.addFloorBlocks(list, x1, x2, y1, z1, z2); @Override
Floor.addFloorBlocks(list, x1, x2, y2, z1, z2); protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
} return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static void addSkeletonCubeBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z1, int z2) { @Override
Line.addXLineBlocks(list, x1, x2, y1, z1); protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
Line.addXLineBlocks(list, x1, x2, y1, z2); return findHeight(player, secondPos, skipRaytrace);
Line.addXLineBlocks(list, x1, x2, y2, z1); }
Line.addXLineBlocks(list, x1, x2, y2, z2);
Line.addYLineBlocks(list, y1, y2, x1, z1); @Override
Line.addYLineBlocks(list, y1, y2, x1, z2); protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
Line.addYLineBlocks(list, y1, y2, x2, z1); return getFloorBlocksUsingCubeFill(player, x1, y1, z1, x2, y2, z2);
Line.addYLineBlocks(list, y1, y2, x2, z2); }
Line.addZLineBlocks(list, z1, z2, x1, y1); @Override
Line.addZLineBlocks(list, z1, z2, x1, y2); protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
Line.addZLineBlocks(list, z1, z2, x2, y1); return getCubeBlocks(player, x1, y1, z1, x3, y3, z3);
Line.addZLineBlocks(list, z1, z2, x2, y2); }
}
} }

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.ArrayList; import java.util.ArrayList;
@@ -9,42 +9,42 @@ import java.util.List;
public class Cylinder extends ThreeClicksBuildMode { public class Cylinder extends ThreeClicksBuildMode {
@Override public static List<BlockPos> getCylinderBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
public BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { List<BlockPos> list = new ArrayList<>();
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override //Get circle blocks (using CIRCLE_START and FILL options built-in)
public BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) { List<BlockPos> circleBlocks = Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
return findHeight(player, secondPos, skipRaytrace);
}
@Override int lowest = Math.min(y1, y3);
public List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { int highest = Math.max(y1, y3);
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override //Copy circle on y axis
public List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { for (int y = lowest; y <= highest; y++) {
return getCylinderBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3); for (BlockPos blockPos : circleBlocks) {
} list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
public static List<BlockPos> getCylinderBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { return list;
List<BlockPos> list = new ArrayList<>(); }
//Get circle blocks (using CIRCLE_START and FILL options built-in) @Override
List<BlockPos> circleBlocks = Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2); public BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
int lowest = Math.min(y1, y3); @Override
int highest = Math.max(y1, y3); public BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Copy circle on y axis @Override
for (int y = lowest; y <= highest; y++) { public List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
for (BlockPos blockPos : circleBlocks) { return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ())); }
}
}
return list; @Override
} public List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getCylinderBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
} }

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.ArrayList; import java.util.ArrayList;
@@ -10,44 +10,44 @@ import java.util.List;
public class DiagonalLine extends ThreeClicksBuildMode { public class DiagonalLine extends ThreeClicksBuildMode {
@Override //Add diagonal line from first to second
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { public static List<BlockPos> getDiagonalLineBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, float sampleMultiplier) {
return Floor.findFloor(player, firstPos, skipRaytrace); List<BlockPos> list = new ArrayList<>();
}
@Override Vec3 first = new Vec3(x1, y1, z1).add(0.5, 0.5, 0.5);
protected BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) { Vec3 second = new Vec3(x2, y2, z2).add(0.5, 0.5, 0.5);
return findHeight(player, secondPos, skipRaytrace);
}
@Override int iterations = (int) Math.ceil(first.distanceTo(second) * sampleMultiplier);
protected List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { for (double t = 0; t <= 1.0; t += 1.0 / iterations) {
//Add diagonal line from first to second Vec3 lerp = first.add(second.subtract(first).scale(t));
return getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 10); BlockPos candidate = new BlockPos(lerp);
} //Only add if not equal to the last in the list
if (list.isEmpty() || !list.get(list.size() - 1).equals(candidate))
list.add(candidate);
}
@Override return list;
protected List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { }
//Add diagonal line from first to third
return getDiagonalLineBlocks(player, x1, y1, z1, x3, y3, z3, 10);
}
//Add diagonal line from first to second @Override
public static List<BlockPos> getDiagonalLineBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, float sampleMultiplier) { protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); return Floor.findFloor(player, firstPos, skipRaytrace);
}
Vec3d first = new Vec3d(x1, y1, z1).add(0.5, 0.5, 0.5); @Override
Vec3d second = new Vec3d(x2, y2, z2).add(0.5, 0.5, 0.5); protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
int iterations = (int) Math.ceil(first.distanceTo(second) * sampleMultiplier); @Override
for (double t = 0; t <= 1.0; t += 1.0/iterations) { protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
Vec3d lerp = first.add(second.subtract(first).scale(t)); //Add diagonal line from first to second
BlockPos candidate = new BlockPos(lerp); return getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 10);
//Only add if not equal to the last in the list }
if (list.isEmpty() || !list.get(list.size() - 1).equals(candidate))
list.add(candidate);
}
return list; @Override
} protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//Add diagonal line from first to third
return getDiagonalLineBlocks(player, x1, y1, z1, x3, y3, z3, 10);
}
} }

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.ArrayList; import java.util.ArrayList;
@@ -9,43 +9,43 @@ import java.util.List;
public class DiagonalWall extends ThreeClicksBuildMode { public class DiagonalWall extends ThreeClicksBuildMode {
@Override //Add diagonal wall from first to second
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { public static List<BlockPos> getDiagonalWallBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return Floor.findFloor(player, firstPos, skipRaytrace); List<BlockPos> list = new ArrayList<>();
}
@Override //Get diagonal line blocks
protected BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) { List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
return findHeight(player, secondPos, skipRaytrace);
}
@Override int lowest = Math.min(y1, y3);
protected List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { int highest = Math.max(y1, y3);
return DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
}
@Override //Copy diagonal line on y axis
protected List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { for (int y = lowest; y <= highest; y++) {
return getDiagonalWallBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3); for (BlockPos blockPos : diagonalLineBlocks) {
} list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ()));
}
}
//Add diagonal wall from first to second return list;
public static List<BlockPos> getDiagonalWallBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { }
List<BlockPos> list = new ArrayList<>();
//Get diagonal line blocks @Override
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1); protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
int lowest = Math.min(y1, y3); @Override
int highest = Math.max(y1, y3); protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Copy diagonal line on y axis @Override
for (int y = lowest; y <= highest; y++) { protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
for (BlockPos blockPos : diagonalLineBlocks) { return DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y2, z2, 1);
list.add(new BlockPos(blockPos.getX(), y, blockPos.getZ())); }
}
}
return list; @Override
} protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getDiagonalWallBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
} }

View File

@@ -0,0 +1,31 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import java.util.List;
public class Dome extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//TODO
return SlopeFloor.getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,93 +1,94 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*; import java.util.ArrayList;
import java.util.List;
public class Floor extends TwoClicksBuildMode { public class Floor extends TwoClicksBuildMode {
static class Criteria { public static BlockPos findFloor(Player player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d planeBound; Vec3 look = BuildModes.getPlayerLookVec(player);
double distToPlayerSq; Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
Criteria(Vec3d planeBound, Vec3d start) { List<Criteria> criteriaList = new ArrayList<>(3);
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
//check if its not behind the player and its not too close and not too far //Y
//also check if raytrace from player to block does not intersect blocks Vec3 yBound = BuildModes.findYBound(firstPos.getY(), start, look);
public boolean isValid(Vec3d start, Vec3d look, int reach, PlayerEntity player, boolean skipRaytrace) { criteriaList.add(new Criteria(yBound, start));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq); //Remove invalid criteria
} int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
} criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
@Override //If none are valid, return empty list of blocks
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { if (criteriaList.isEmpty()) return null;
return findFloor(player, firstPos, skipRaytrace);
}
public static BlockPos findFloor(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { //Then only 1 can be valid, return that one
Vec3d look = BuildModes.getPlayerLookVec(player); Criteria selected = criteriaList.get(0);
Vec3d start = new Vec3d(player.getPosX(), player.getPosY() + player.getEyeHeight(), player.getPosZ());
List<Criteria> criteriaList = new ArrayList<>(3); return new BlockPos(selected.planeBound);
}
//Y public static List<BlockPos> getFloorBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
Vec3d yBound = BuildModes.findYBound(firstPos.getY(), start, look); List<BlockPos> list = new ArrayList<>();
criteriaList.add(new Criteria(yBound, start));
//Remove invalid criteria if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach addFloorBlocks(list, x1, x2, y1, z1, z2);
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace)); else
addHollowFloorBlocks(list, x1, x2, y1, z1, z2);
//If none are valid, return empty list of blocks return list;
if (criteriaList.isEmpty()) return null; }
//Then only 1 can be valid, return that one public static void addFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
Criteria selected = criteriaList.get(0);
return new BlockPos(selected.planeBound); for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
}
@Override for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
protected List<BlockPos> getAllBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
public static List<BlockPos> getFloorBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { list.add(new BlockPos(l, y, n));
List<BlockPos> list = new ArrayList<>(); }
}
}
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL) public static void addHollowFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) {
addFloorBlocks(list, x1, x2, y1, z1, z2); Line.addXLineBlocks(list, x1, x2, y, z1);
else Line.addXLineBlocks(list, x1, x2, y, z2);
addHollowFloorBlocks(list, x1, x2, y1, z1, z2); Line.addZLineBlocks(list, z1, z2, x1, y);
Line.addZLineBlocks(list, z1, z2, x2, y);
}
return list; @Override
} protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return findFloor(player, firstPos, skipRaytrace);
}
public static void addFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) { @Override
protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { static class Criteria {
Vec3 planeBound;
double distToPlayerSq;
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { Criteria(Vec3 planeBound, Vec3 start) {
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
}
list.add(new BlockPos(l, y, n)); //check if its not behind the player and its not too close and not too far
} //also check if raytrace from player to block does not intersect blocks
} public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
}
public static void addHollowFloorBlocks(List<BlockPos> list, int x1, int x2, int y, int z1, int z2) { return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
Line.addXLineBlocks(list, x1, x2, y, z1); }
Line.addXLineBlocks(list, x1, x2, y, z2); }
Line.addZLineBlocks(list, z1, z2, x1, y);
Line.addZLineBlocks(list, z1, z2, x2, y);
}
} }

View File

@@ -1,9 +1,8 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -13,136 +12,136 @@ import java.util.List;
public class Line extends TwoClicksBuildMode { public class Line extends TwoClicksBuildMode {
static class Criteria { public static BlockPos findLine(Player player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d planeBound; Vec3 look = BuildModes.getPlayerLookVec(player);
Vec3d lineBound; Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
double distToLineSq;
double distToPlayerSq;
Criteria(Vec3d planeBound, BlockPos firstPos, Vec3d start) { List<Criteria> criteriaList = new ArrayList<>(3);
this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, firstPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSquared();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
}
//Make it from a plane into a line //X
//Select the axis that is longest Vec3 xBound = BuildModes.findXBound(firstPos.getX(), start, look);
private Vec3d toLongestLine(Vec3d boundVec, BlockPos firstPos) { criteriaList.add(new Criteria(xBound, firstPos, start));
BlockPos bound = new BlockPos(boundVec);
BlockPos firstToSecond = bound.subtract(firstPos); //Y
firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ())); Vec3 yBound = BuildModes.findYBound(firstPos.getY(), start, look);
int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ())); criteriaList.add(new Criteria(yBound, firstPos, start));
if (longest == firstToSecond.getX()) {
return new Vec3d(bound.getX(), firstPos.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getY()) {
return new Vec3d(firstPos.getX(), bound.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getZ()) {
return new Vec3d(firstPos.getX(), firstPos.getY(), bound.getZ());
}
return null;
}
//check if its not behind the player and its not too close and not too far //Z
//also check if raytrace from player to block does not intersect blocks Vec3 zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
public boolean isValid(Vec3d start, Vec3d look, int reach, PlayerEntity player, boolean skipRaytrace) { criteriaList.add(new Criteria(zBound, firstPos, start));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq); //Remove invalid criteria
} int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
} //If none are valid, return empty list of blocks
if (criteriaList.isEmpty()) return null;
@Override //If only 1 is valid, choose that one
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { Criteria selected = criteriaList.get(0);
return findLine(player, firstPos, skipRaytrace);
}
public static BlockPos findLine(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { //If multiple are valid, choose based on criteria
Vec3d look = BuildModes.getPlayerLookVec(player); if (criteriaList.size() > 1) {
Vec3d start = new Vec3d(player.getPosX(), player.getPosY() + player.getEyeHeight(), player.getPosZ()); //Select the one that is closest (from wall position to its line counterpart)
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
List<Criteria> criteriaList = new ArrayList<>(3); }
//X return new BlockPos(selected.lineBound);
Vec3d xBound = BuildModes.findXBound(firstPos.getX(), start, look); }
criteriaList.add(new Criteria(xBound, firstPos, start));
//Y public static List<BlockPos> getLineBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
Vec3d yBound = BuildModes.findYBound(firstPos.getY(), start, look); List<BlockPos> list = new ArrayList<>();
criteriaList.add(new Criteria(yBound, firstPos, start));
//Z if (x1 != x2) {
Vec3d zBound = BuildModes.findZBound(firstPos.getZ(), start, look); addXLineBlocks(list, x1, x2, y1, z1);
criteriaList.add(new Criteria(zBound, firstPos, start)); } else if (y1 != y2) {
addYLineBlocks(list, y1, y2, x1, z1);
} else {
addZLineBlocks(list, z1, z2, x1, y1);
}
//Remove invalid criteria return list;
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach }
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
//If none are valid, return empty list of blocks public static void addXLineBlocks(List<BlockPos> list, int x1, int x2, int y, int z) {
if (criteriaList.isEmpty()) return null; for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
//If only 1 is valid, choose that one public static void addYLineBlocks(List<BlockPos> list, int y1, int y2, int x, int z) {
Criteria selected = criteriaList.get(0); for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
//If multiple are valid, choose based on criteria public static void addZLineBlocks(List<BlockPos> list, int z1, int z2, int x, int y) {
if (criteriaList.size() > 1) { for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
//Select the one that is closest (from wall position to its line counterpart) list.add(new BlockPos(x, y, z));
for (int i = 1; i < criteriaList.size(); i++) { }
Criteria criteria = criteriaList.get(i); }
if (criteria.distToLineSq < 2.0 && selected.distToLineSq < 2.0) {
//Both very close to line, choose closest to player
if (criteria.distToPlayerSq < selected.distToPlayerSq)
selected = criteria;
} else {
//Pick closest to line
if (criteria.distToLineSq < selected.distToLineSq)
selected = criteria;
}
}
} @Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return findLine(player, firstPos, skipRaytrace);
}
return new BlockPos(selected.lineBound); @Override
} protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getLineBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override static class Criteria {
protected List<BlockPos> getAllBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { Vec3 planeBound;
return getLineBlocks(player, x1, y1, z1, x2, y2, z2); Vec3 lineBound;
} double distToLineSq;
double distToPlayerSq;
public static List<BlockPos> getLineBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { Criteria(Vec3 planeBound, BlockPos firstPos, Vec3 start) {
List<BlockPos> list = new ArrayList<>(); this.planeBound = planeBound;
this.lineBound = toLongestLine(this.planeBound, firstPos);
this.distToLineSq = this.lineBound.subtract(this.planeBound).lengthSqr();
this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
}
if (x1 != x2) { //Make it from a plane into a line
addXLineBlocks(list, x1, x2, y1, z1); //Select the axis that is longest
} else if (y1 != y2) { private Vec3 toLongestLine(Vec3 boundVec, BlockPos firstPos) {
addYLineBlocks(list, y1, y2, x1, z1); BlockPos bound = new BlockPos(boundVec);
} else {
addZLineBlocks(list, z1, z2, x1, y1);
}
return list; BlockPos firstToSecond = bound.subtract(firstPos);
} firstToSecond = new BlockPos(Math.abs(firstToSecond.getX()), Math.abs(firstToSecond.getY()), Math.abs(firstToSecond.getZ()));
int longest = Math.max(firstToSecond.getX(), Math.max(firstToSecond.getY(), firstToSecond.getZ()));
if (longest == firstToSecond.getX()) {
return new Vec3(bound.getX(), firstPos.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getY()) {
return new Vec3(firstPos.getX(), bound.getY(), firstPos.getZ());
}
if (longest == firstToSecond.getZ()) {
return new Vec3(firstPos.getX(), firstPos.getY(), bound.getZ());
}
return null;
}
public static void addXLineBlocks(List<BlockPos> list, int x1, int x2, int y, int z) { //check if its not behind the player and its not too close and not too far
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) { //also check if raytrace from player to block does not intersect blocks
list.add(new BlockPos(x, y, z)); public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
}
}
public static void addYLineBlocks(List<BlockPos> list, int y1, int y2, int x, int z) { return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, lineBound, planeBound, distToPlayerSq);
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) { }
list.add(new BlockPos(x, y, z));
}
}
public static void addZLineBlocks(List<BlockPos> list, int z1, int z2, int x, int y) { }
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
list.add(new BlockPos(x, y, z));
}
}
} }

View File

@@ -1,41 +1,41 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.IBuildMode; import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Normal implements IBuildMode { public class Normal implements IBuildMode {
@Override @Override
public void initialize(PlayerEntity player) { public void initialize(Player player) {
} }
@Override @Override
public List<BlockPos> onRightClick(PlayerEntity player, BlockPos blockPos, Direction sideHit, Vec3d hitVec, boolean skipRaytrace) { public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos); if (blockPos != null) list.add(blockPos);
return list; return list;
} }
@Override @Override
public List<BlockPos> findCoordinates(PlayerEntity player, BlockPos blockPos, boolean skipRaytrace) { public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos); if (blockPos != null) list.add(blockPos);
return list; return list;
} }
@Override @Override
public Direction getSideHit(PlayerEntity player) { public Direction getSideHit(Player player) {
return null; return null;
} }
@Override @Override
public Vec3d getHitVec(PlayerEntity player) { public Vec3 getHitVec(Player player) {
return null; return null;
} }
} }

View File

@@ -1,41 +1,41 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.IBuildMode; import nl.requios.effortlessbuilding.buildmode.IBuildMode;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class NormalPlus implements IBuildMode { public class NormalPlus implements IBuildMode {
@Override @Override
public void initialize(PlayerEntity player) { public void initialize(Player player) {
} }
@Override @Override
public List<BlockPos> onRightClick(PlayerEntity player, BlockPos blockPos, Direction sideHit, Vec3d hitVec, boolean skipRaytrace) { public List<BlockPos> onRightClick(Player player, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos); if (blockPos != null) list.add(blockPos);
return list; return list;
} }
@Override @Override
public List<BlockPos> findCoordinates(PlayerEntity player, BlockPos blockPos, boolean skipRaytrace) { public List<BlockPos> findCoordinates(Player player, BlockPos blockPos, boolean skipRaytrace) {
List<BlockPos> list = new ArrayList<>(); List<BlockPos> list = new ArrayList<>();
if (blockPos != null) list.add(blockPos); if (blockPos != null) list.add(blockPos);
return list; return list;
} }
@Override @Override
public Direction getSideHit(PlayerEntity player) { public Direction getSideHit(Player player) {
return null; return null;
} }
@Override @Override
public Vec3d getHitVec(PlayerEntity player) { public Vec3 getHitVec(Player player) {
return null; return null;
} }
} }

View File

@@ -0,0 +1,34 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.ArrayList;
import java.util.List;
public class Pyramid extends ThreeClicksBuildMode {
@Override
protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override
protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override
protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
//TODO
return SlopeFloor.getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
}

View File

@@ -1,7 +1,7 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
@@ -11,85 +11,85 @@ import java.util.List;
public class SlopeFloor extends ThreeClicksBuildMode { public class SlopeFloor extends ThreeClicksBuildMode {
@Override //Add slope floor from first to second
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { public static List<BlockPos> getSlopeFloorBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return Floor.findFloor(player, firstPos, skipRaytrace); List<BlockPos> list = new ArrayList<>();
}
@Override int axisLimit = ReachHelper.getMaxBlocksPerAxis(player);
protected BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
@Override //Determine whether to use x or z axis to slope up
protected List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { boolean onXAxis = true;
return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
}
@Override int xLength = Math.abs(x2 - x1);
protected List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { int zLength = Math.abs(z2 - z1);
return getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
//Add slope floor from first to second if (ModeOptions.getRaisedEdge() == ModeOptions.ActionEnum.SHORT_EDGE) {
public static List<BlockPos> getSlopeFloorBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { //Slope along short edge
List<BlockPos> list = new ArrayList<>(); if (zLength > xLength) onXAxis = false;
} else {
//Slope along long edge
if (zLength <= xLength) onXAxis = false;
}
int axisLimit = ReachHelper.getMaxBlocksPerAxis(player); if (onXAxis) {
//Along X goes up
//Determine whether to use x or z axis to slope up //Get diagonal line blocks
boolean onXAxis = true; List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y3, z1, 1f);
int xLength = Math.abs(x2 - x1); //Limit amount of blocks we can place
int zLength = Math.abs(z2 - z1); int lowest = Math.min(z1, z2);
int highest = Math.max(z1, z2);
if (ModeOptions.getRaisedEdge() == ModeOptions.ActionEnum.SHORT_EDGE) { if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
//Slope along short edge
if (zLength > xLength) onXAxis = false;
} else {
//Slope along long edge
if (zLength <= xLength) onXAxis = false;
}
if (onXAxis) { //Copy diagonal line on x axis
//Along X goes up for (int z = lowest; z <= highest; z++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), blockPos.getY(), z));
}
}
//Get diagonal line blocks } else {
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x2, y3, z1, 1f); //Along Z goes up
//Limit amount of blocks we can place //Get diagonal line blocks
int lowest = Math.min(z1, z2); List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x1, y3, z2, 1f);
int highest = Math.max(z1, z2);
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1; //Limit amount of blocks we can place
int lowest = Math.min(x1, x2);
int highest = Math.max(x1, x2);
//Copy diagonal line on x axis if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1;
for (int z = lowest; z <= highest; z++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(blockPos.getX(), blockPos.getY(), z));
}
}
} else { //Copy diagonal line on x axis
//Along Z goes up for (int x = lowest; x <= highest; x++) {
for (BlockPos blockPos : diagonalLineBlocks) {
list.add(new BlockPos(x, blockPos.getY(), blockPos.getZ()));
}
}
}
//Get diagonal line blocks return list;
List<BlockPos> diagonalLineBlocks = DiagonalLine.getDiagonalLineBlocks(player, x1, y1, z1, x1, y3, z2, 1f); }
//Limit amount of blocks we can place @Override
int lowest = Math.min(x1, x2); protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
int highest = Math.max(x1, x2); return Floor.findFloor(player, firstPos, skipRaytrace);
}
if (highest - lowest >= axisLimit) highest = lowest + axisLimit - 1; @Override
protected BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
return findHeight(player, secondPos, skipRaytrace);
}
//Copy diagonal line on x axis @Override
for (int x = lowest; x <= highest; x++) { protected List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
for (BlockPos blockPos : diagonalLineBlocks) { return Floor.getFloorBlocks(player, x1, y1, z1, x2, y2, z2);
list.add(new BlockPos(x, blockPos.getY(), blockPos.getZ())); }
}
}
}
return list; @Override
} protected List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSlopeFloorBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
} }

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode; import nl.requios.effortlessbuilding.buildmode.ThreeClicksBuildMode;
@@ -11,100 +11,100 @@ import java.util.List;
public class Sphere extends ThreeClicksBuildMode { public class Sphere extends ThreeClicksBuildMode {
@Override public static List<BlockPos> getSphereBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
public BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { List<BlockPos> list = new ArrayList<>();
return Floor.findFloor(player, firstPos, skipRaytrace);
}
@Override float centerX = x1;
public BlockPos findThirdPos(PlayerEntity player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) { float centerY = y1;
return findHeight(player, secondPos, skipRaytrace); float centerZ = z1;
}
@Override //Adjust for CIRCLE_START
public List<BlockPos> getIntermediateBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2); centerX = x1 + (x2 - x1) / 2f;
} centerY = y1 + (y3 - y1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
y1 = (int) (centerY - (y3 - centerY));
z1 = (int) (centerZ - (z2 - centerZ));
}
@Override float radiusX = Mth.abs(x2 - centerX);
public List<BlockPos> getFinalBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { float radiusY = Mth.abs(y3 - centerY);
return getSphereBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3); float radiusZ = Mth.abs(z2 - centerZ);
}
public static List<BlockPos> getSphereBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) { if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
List<BlockPos> list = new ArrayList<>(); addSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
else
addHollowSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
float centerX = x1; return list;
float centerY = y1; }
float centerZ = z1;
//Adjust for CIRCLE_START public static void addSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
if (ModeOptions.getCircleStart() == ModeOptions.ActionEnum.CIRCLE_START_CORNER) { float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
centerX = x1 + (x2 - x1) / 2f; for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
centerY = y1 + (y3 - y1) / 2f;
centerZ = z1 + (z2 - z1) / 2f;
} else {
x1 = (int) (centerX - (x2 - centerX));
y1 = (int) (centerY - (y3 - centerY));
z1 = (int) (centerZ - (z2 - centerZ));
}
float radiusX = MathHelper.abs(x2 - centerX); for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
float radiusY = MathHelper.abs(y3 - centerY);
float radiusZ = MathHelper.abs(z2 - centerZ);
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL) for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
addSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
else
addHollowSphereBlocks(list, x1, y1, z1, x3, y3, z3, centerX, centerY, centerZ, radiusX, radiusY, radiusZ);
return list; float distance = distance(l, m, n, centerX, centerY, centerZ);
} float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f)
list.add(new BlockPos(l, m, n));
}
}
}
}
public static void addSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, public static void addHollowSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2,
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) { float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) {
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) {
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) {
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) {
float distance = distance(l, m, n, centerX, centerY, centerZ); float distance = distance(l, m, n, centerX, centerY, centerZ);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n); float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n);
if (distance < radius + 0.4f) if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, m, n)); list.add(new BlockPos(l, m, n));
} }
} }
} }
} }
public static void addHollowSphereBlocks(List<BlockPos> list, int x1, int y1, int z1, int x2, int y2, int z2, private static float distance(float x1, float y1, float z1, float x2, float y2, float z2) {
float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ) { return Mth.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1));
for (int l = x1; x1 < x2 ? l <= x2 : l >= x2; l += x1 < x2 ? 1 : -1) { }
for (int n = z1; z1 < z2 ? n <= z2 : n >= z2; n += z1 < z2 ? 1 : -1) { public static float calculateSpheroidRadius(float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ, int x, int y, int z) {
//Twice ellipse radius
float radiusXZ = Circle.calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, x, z);
for (int m = y1; y1 < y2 ? m <= y2 : m >= y2; m += y1 < y2 ? 1 : -1) { //TODO project x to plane
float distance = distance(l, m, n, centerX, centerY, centerZ); return Circle.calculateEllipseRadius(centerX, centerY, radiusXZ, radiusY, x, y);
float radius = calculateSpheroidRadius(centerX, centerY, centerZ, radiusX, radiusY, radiusZ, l, m, n); }
if (distance < radius + 0.4f && distance > radius - 0.6f)
list.add(new BlockPos(l, m, n));
}
}
}
}
private static float distance(float x1, float y1, float z1, float x2, float y2, float z2) { @Override
return MathHelper.sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1) + (z2 - z1) * (z2 - z1)); public BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
} return Floor.findFloor(player, firstPos, skipRaytrace);
}
public static float calculateSpheroidRadius(float centerX, float centerY, float centerZ, float radiusX, float radiusY, float radiusZ, int x, int y, int z) { @Override
//Twice ellipse radius public BlockPos findThirdPos(Player player, BlockPos firstPos, BlockPos secondPos, boolean skipRaytrace) {
float radiusXZ = Circle.calculateEllipseRadius(centerX, centerZ, radiusX, radiusZ, x, z); return findHeight(player, secondPos, skipRaytrace);
}
//TODO project x to plane @Override
public List<BlockPos> getIntermediateBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return Circle.getCircleBlocks(player, x1, y1, z1, x2, y2, z2);
}
return Circle.calculateEllipseRadius(centerX, centerY, radiusXZ, radiusY, x, y); @Override
} public List<BlockPos> getFinalBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2, int x3, int y3, int z3) {
return getSphereBlocks(player, x1, y1, z1, x2, y2, z2, x3, y3, z3);
}
} }

View File

@@ -1,134 +1,135 @@
package nl.requios.effortlessbuilding.buildmode.buildmodes; package nl.requios.effortlessbuilding.buildmode.buildmodes;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.TwoClicksBuildMode;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import java.util.*; import java.util.ArrayList;
import java.util.List;
public class Wall extends TwoClicksBuildMode { public class Wall extends TwoClicksBuildMode {
static class Criteria { public static BlockPos findWall(Player player, BlockPos firstPos, boolean skipRaytrace) {
Vec3d planeBound; Vec3 look = BuildModes.getPlayerLookVec(player);
double distToPlayerSq; Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
double angle;
Criteria(Vec3d planeBound, BlockPos firstPos, Vec3d start, Vec3d look) { List<Criteria> criteriaList = new ArrayList<>(3);
this.planeBound = planeBound;
this.distToPlayerSq = this.planeBound.subtract(start).lengthSquared();
Vec3d wall = this.planeBound.subtract(new Vec3d(firstPos));
this.angle = wall.x * look.x + wall.z * look.z; //dot product ignoring y (looking up/down should not affect this angle)
}
//check if its not behind the player and its not too close and not too far //X
//also check if raytrace from player to block does not intersect blocks Vec3 xBound = BuildModes.findXBound(firstPos.getX(), start, look);
public boolean isValid(Vec3d start, Vec3d look, int reach, PlayerEntity player, boolean skipRaytrace) { criteriaList.add(new Criteria(xBound, firstPos, start, look));
return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq); //Z
} Vec3 zBound = BuildModes.findZBound(firstPos.getZ(), start, look);
} criteriaList.add(new Criteria(zBound, firstPos, start, look));
@Override //Remove invalid criteria
protected BlockPos findSecondPos(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach
return findWall(player, firstPos, skipRaytrace); criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
}
public static BlockPos findWall(PlayerEntity player, BlockPos firstPos, boolean skipRaytrace) { //If none are valid, return empty list of blocks
Vec3d look = BuildModes.getPlayerLookVec(player); if (criteriaList.isEmpty()) return null;
Vec3d start = new Vec3d(player.getPosX(), player.getPosY() + player.getEyeHeight(), player.getPosZ());
List<Criteria> criteriaList = new ArrayList<>(3); //If only 1 is valid, choose that one
Criteria selected = criteriaList.get(0);
//X //If multiple are valid, choose based on criteria
Vec3d xBound = BuildModes.findXBound(firstPos.getX(), start, look); if (criteriaList.size() > 1) {
criteriaList.add(new Criteria(xBound, firstPos, start, look)); //Select the one that is closest
//Limit the angle to not be too extreme
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToPlayerSq < selected.distToPlayerSq && Math.abs(criteria.angle) - Math.abs(selected.angle) < 3)
selected = criteria;
}
}
//Z return new BlockPos(selected.planeBound);
Vec3d zBound = BuildModes.findZBound(firstPos.getZ(), start, look); }
criteriaList.add(new Criteria(zBound, firstPos, start, look));
//Remove invalid criteria public static List<BlockPos> getWallBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
int reach = ReachHelper.getPlacementReach(player) * 4; //4 times as much as normal placement reach List<BlockPos> list = new ArrayList<>();
criteriaList.removeIf(criteria -> !criteria.isValid(start, look, reach, player, skipRaytrace));
//If none are valid, return empty list of blocks if (x1 == x2) {
if (criteriaList.isEmpty()) return null; if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addXWallBlocks(list, x1, y1, y2, z1, z2);
else
addXHollowWallBlocks(list, x1, y1, y2, z1, z2);
} else {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addZWallBlocks(list, x1, x2, y1, y2, z1);
else
addZHollowWallBlocks(list, x1, x2, y1, y2, z1);
}
//If only 1 is valid, choose that one return list;
Criteria selected = criteriaList.get(0); }
//If multiple are valid, choose based on criteria public static void addXWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
if (criteriaList.size() > 1) {
//Select the one that is closest
//Limit the angle to not be too extreme
for (int i = 1; i < criteriaList.size(); i++) {
Criteria criteria = criteriaList.get(i);
if (criteria.distToPlayerSq < selected.distToPlayerSq && Math.abs(criteria.angle) - Math.abs(selected.angle) < 3)
selected = criteria;
}
}
return new BlockPos(selected.planeBound); for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) {
}
@Override for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
protected List<BlockPos> getAllBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { list.add(new BlockPos(x, y, z));
return getWallBlocks(player, x1, y1, z1, x2, y2, z2); }
} }
}
public static List<BlockPos> getWallBlocks(PlayerEntity player, int x1, int y1, int z1, int x2, int y2, int z2) { public static void addZWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
List<BlockPos> list = new ArrayList<>();
if (x1 == x2) { for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addXWallBlocks(list, x1, y1, y2, z1, z2);
else
addXHollowWallBlocks(list, x1, y1, y2, z1, z2);
} else {
if (ModeOptions.getFill() == ModeOptions.ActionEnum.FULL)
addZWallBlocks(list, x1, x2, y1, y2, z1);
else
addZHollowWallBlocks(list, x1, x2, y1, y2, z1);
}
return list; for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) {
} list.add(new BlockPos(x, y, z));
}
}
}
public static void addXWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) { public static void addXHollowWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) {
Line.addZLineBlocks(list, z1, z2, x, y1);
Line.addZLineBlocks(list, z1, z2, x, y2);
Line.addYLineBlocks(list, y1, y2, x, z1);
Line.addYLineBlocks(list, y1, y2, x, z2);
}
for (int z = z1; z1 < z2 ? z <= z2 : z >= z2; z += z1 < z2 ? 1 : -1) { public static void addZHollowWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) {
Line.addXLineBlocks(list, x1, x2, y1, z);
Line.addXLineBlocks(list, x1, x2, y2, z);
Line.addYLineBlocks(list, y1, y2, x1, z);
Line.addYLineBlocks(list, y1, y2, x2, z);
}
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) { @Override
list.add(new BlockPos(x, y, z)); protected BlockPos findSecondPos(Player player, BlockPos firstPos, boolean skipRaytrace) {
} return findWall(player, firstPos, skipRaytrace);
} }
}
public static void addZWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) { @Override
protected List<BlockPos> getAllBlocks(Player player, int x1, int y1, int z1, int x2, int y2, int z2) {
return getWallBlocks(player, x1, y1, z1, x2, y2, z2);
}
for (int x = x1; x1 < x2 ? x <= x2 : x >= x2; x += x1 < x2 ? 1 : -1) { static class Criteria {
Vec3 planeBound;
double distToPlayerSq;
double angle;
for (int y = y1; y1 < y2 ? y <= y2 : y >= y2; y += y1 < y2 ? 1 : -1) { Criteria(Vec3 planeBound, BlockPos firstPos, Vec3 start, Vec3 look) {
list.add(new BlockPos(x, y, z)); this.planeBound = planeBound;
} this.distToPlayerSq = this.planeBound.subtract(start).lengthSqr();
} Vec3 wall = this.planeBound.subtract(Vec3.atLowerCornerOf(firstPos));
} this.angle = wall.x * look.x + wall.z * look.z; //dot product ignoring y (looking up/down should not affect this angle)
}
public static void addXHollowWallBlocks(List<BlockPos> list, int x, int y1, int y2, int z1, int z2) { //check if its not behind the player and its not too close and not too far
Line.addZLineBlocks(list, z1, z2, x, y1); //also check if raytrace from player to block does not intersect blocks
Line.addZLineBlocks(list, z1, z2, x, y2); public boolean isValid(Vec3 start, Vec3 look, int reach, Player player, boolean skipRaytrace) {
Line.addYLineBlocks(list, y1, y2, x, z1);
Line.addYLineBlocks(list, y1, y2, x, z2);
}
public static void addZHollowWallBlocks(List<BlockPos> list, int x1, int x2, int y1, int y2, int z) { return BuildModes.isCriteriaValid(start, look, reach, player, skipRaytrace, planeBound, planeBound, distToPlayerSq);
Line.addXLineBlocks(list, x1, x2, y1, z); }
Line.addXLineBlocks(list, x1, x2, y2, z); }
Line.addYLineBlocks(list, y1, y2, x1, z);
Line.addYLineBlocks(list, y1, y2, x2, z);
}
} }

View File

@@ -1,104 +1,104 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.Hand; import net.minecraft.world.InteractionHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraft.util.math.Vec3i; import net.minecraft.core.Vec3i;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Array { public class Array {
public static class ArraySettings{ public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) {
public boolean enabled = false; List<BlockPos> coordinates = new ArrayList<>();
public BlockPos offset = BlockPos.ZERO;
public int count = 5;
public ArraySettings() { //find arraysettings for the player
} ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates;
public ArraySettings(boolean enabled, BlockPos offset, int count) { BlockPos pos = startPos;
this.enabled = enabled; Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
this.offset = offset;
this.count = count;
}
public int getReach() { for (int i = 0; i < a.count; i++) {
//find largest offset pos = pos.offset(offset);
int x = Math.abs(offset.getX()); coordinates.add(pos);
int y = Math.abs(offset.getY()); }
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
return largestOffset * count; return coordinates;
} }
}
public static List<BlockPos> findCoordinates(PlayerEntity player, BlockPos startPos) { public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockState> blockStates = new ArrayList<>();
//find arraysettings for the player //find arraysettings for the player that placed the block
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings(); ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings();
if (!isEnabled(a)) return coordinates; if (!isEnabled(a)) return blockStates;
BlockPos pos = startPos; BlockPos pos = startPos;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ()); Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ());
for (int i = 0; i < a.count; i++) { //Randomizer bag synergy
pos = pos.add(offset); AbstractRandomizerBagItem randomizerBagItem = null;
coordinates.add(pos); IItemHandler bagInventory = null;
} if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
return coordinates; for (int i = 0; i < a.count; i++) {
} pos = pos.offset(offset);
public static List<BlockState> findBlockStates(PlayerEntity player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) { //Randomizer bag synergy
List<BlockState> blockStates = new ArrayList<>(); if (randomizerBagItem != null) {
itemStack = randomizerBagItem.pickRandomStack(bagInventory);
blockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3(0, 0, 0), InteractionHand.MAIN_HAND);
}
//find arraysettings for the player that placed the block //blockState = blockState.getBlock().getStateForPlacement(player.world, pos, )
ArraySettings a = ModifierSettingsManager.getModifierSettings(player).getArraySettings(); blockStates.add(blockState);
if (!isEnabled(a)) return blockStates; itemStacks.add(itemStack);
}
BlockPos pos = startPos; return blockStates;
Vec3i offset = new Vec3i(a.offset.getX(), a.offset.getY(), a.offset.getZ()); }
//Randomizer bag synergy public static boolean isEnabled(ArraySettings a) {
IItemHandler bagInventory = null; if (a == null || !a.enabled) return false;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) {
bagInventory = ItemRandomizerBag.getBagInventory(itemStack);
}
for (int i = 0; i < a.count; i++) { return a.offset.getX() != 0 || a.offset.getY() != 0 || a.offset.getZ() != 0;
pos = pos.add(offset); }
//Randomizer bag synergy public static class ArraySettings {
if (bagInventory != null) { public boolean enabled = false;
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); public BlockPos offset = BlockPos.ZERO;
blockState = BuildModifiers public int count = 5;
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3d(0, 0, 0), Hand.MAIN_HAND);
}
//blockState = blockState.getBlock().getStateForPlacement(player.world, pos, ) public ArraySettings() {
blockStates.add(blockState); }
itemStacks.add(itemStack);
}
return blockStates; public ArraySettings(boolean enabled, BlockPos offset, int count) {
} this.enabled = enabled;
this.offset = offset;
this.count = count;
}
public static boolean isEnabled(ArraySettings a) { public int getReach() {
if (a == null || !a.enabled) return false; //find largest offset
int x = Math.abs(offset.getX());
int y = Math.abs(offset.getY());
int z = Math.abs(offset.getZ());
int largestOffset = Math.max(Math.max(x, y), z);
if (a.offset.getX() == 0 && a.offset.getY() == 0 && a.offset.getZ() == 0) return false; return largestOffset * count;
}
return true; }
}
} }

View File

@@ -1,50 +1,50 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import java.util.List; import java.util.List;
public class BlockSet { public class BlockSet {
private List<BlockPos> coordinates; private final List<BlockPos> coordinates;
private List<BlockState> previousBlockStates; private final List<BlockState> previousBlockStates;
private List<BlockState> newBlockStates; private final List<BlockState> newBlockStates;
private Vec3d hitVec; private final Vec3 hitVec;
private BlockPos firstPos; private final BlockPos firstPos;
private BlockPos secondPos; private final BlockPos secondPos;
public BlockSet(List<BlockPos> coordinates, List<BlockState> previousBlockStates, List<BlockState> newBlockStates, Vec3d hitVec, public BlockSet(List<BlockPos> coordinates, List<BlockState> previousBlockStates, List<BlockState> newBlockStates, Vec3 hitVec,
BlockPos firstPos, BlockPos secondPos) { BlockPos firstPos, BlockPos secondPos) {
this.coordinates = coordinates; this.coordinates = coordinates;
this.previousBlockStates = previousBlockStates; this.previousBlockStates = previousBlockStates;
this.newBlockStates = newBlockStates; this.newBlockStates = newBlockStates;
this.hitVec = hitVec; this.hitVec = hitVec;
this.firstPos = firstPos; this.firstPos = firstPos;
this.secondPos = secondPos; this.secondPos = secondPos;
} }
public List<BlockPos> getCoordinates() { public List<BlockPos> getCoordinates() {
return coordinates; return coordinates;
} }
public List<BlockState> getPreviousBlockStates() { public List<BlockState> getPreviousBlockStates() {
return previousBlockStates; return previousBlockStates;
} }
public List<BlockState> getNewBlockStates() { public List<BlockState> getNewBlockStates() {
return newBlockStates; return newBlockStates;
} }
public Vec3d getHitVec() { public Vec3 getHitVec() {
return hitVec; return hitVec;
} }
public BlockPos getFirstPos() { public BlockPos getFirstPos() {
return firstPos; return firstPos;
} }
public BlockPos getSecondPos() { public BlockPos getSecondPos() {
return secondPos; return secondPos;
} }
} }

View File

@@ -1,260 +1,267 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.level.block.Blocks;
import net.minecraft.block.Blocks; import net.minecraft.world.entity.player.Player;
import net.minecraft.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.item.BlockItemUseContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.ItemUseContext; import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.Hand; import net.minecraft.world.InteractionHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.World; import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.InventoryHelper; import nl.requios.effortlessbuilding.helper.InventoryHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class BuildModifiers { public class BuildModifiers {
//Called from BuildModes //Called from BuildModes
public static void onBlockPlaced(PlayerEntity player, List<BlockPos> startCoordinates, Direction sideHit, Vec3d hitVec, boolean placeStartPos) { public static void onBlockPlaced(Player player, List<BlockPos> startCoordinates, Direction sideHit, Vec3 hitVec, boolean placeStartPos) {
World world = player.world; Level world = player.level;
ItemRandomizerBag.renewRandomness(); AbstractRandomizerBagItem.renewRandomness();
//Format hitvec to 0.x //Format hitvec to 0.x
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z))); hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), Math.abs(hitVec.z - ((int) hitVec.z)));
//find coordinates and blockstates //find coordinates and blockstates
List<BlockPos> coordinates = findCoordinates(player, startCoordinates); List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
List<ItemStack> itemStacks = new ArrayList<>(); List<ItemStack> itemStacks = new ArrayList<>();
List<BlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); List<BlockState> blockStates = findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
//check if valid blockstates //check if valid blockstates
if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return; if (blockStates.size() == 0 || coordinates.size() != blockStates.size()) return;
//remember previous blockstates for undo //remember previous blockstates for undo
List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size()); List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<BlockState> newBlockStates = new ArrayList<>(coordinates.size()); List<BlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) { for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate)); previousBlockStates.add(world.getBlockState(coordinate));
} }
if (world.isRemote) { if (world.isClientSide) {
BlockPreviewRenderer.onBlocksPlaced(); BlockPreviewRenderer.onBlocksPlaced();
newBlockStates = blockStates; newBlockStates = blockStates;
} else { } else {
//place blocks //place blocks
for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) { for (int i = placeStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos blockPos = coordinates.get(i); BlockPos blockPos = coordinates.get(i);
BlockState blockState = blockStates.get(i); BlockState blockState = blockStates.get(i);
ItemStack itemStack = itemStacks.get(i); ItemStack itemStack = itemStacks.get(i);
if (world.isBlockPresent(blockPos)) { if (world.isLoaded(blockPos)) {
//check itemstack empty //check itemstack empty
if (itemStack.isEmpty()) { if (itemStack.isEmpty()) {
//try to find new stack, otherwise continue //try to find new stack, otherwise continue
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
if (itemStack.isEmpty()) continue; if (itemStack.isEmpty()) continue;
} }
SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, Direction.UP, hitVec, false, false, false); SurvivalHelper.placeBlock(world, player, blockPos, blockState, itemStack, Direction.UP, hitVec, false, false, false);
} }
} }
//find actual new blockstates for undo //find actual new blockstates for undo
for (BlockPos coordinate : coordinates) { for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate)); newBlockStates.add(world.getBlockState(coordinate));
} }
} }
//Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work //Set first previousBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block is placed by the time it gets here, and unplaced after this) //(Block is placed by the time it gets here, and unplaced after this)
if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.getDefaultState()); if (!placeStartPos) previousBlockStates.set(0, Blocks.AIR.defaultBlockState());
//If all new blockstates are air then no use in adding it, no block was actually placed //If all new blockstates are air then no use in adding it, no block was actually placed
//Can happen when e.g. placing one block in yourself //Can happen when e.g. placing one block in yourself
if (Collections.frequency(newBlockStates, Blocks.AIR.getDefaultState()) != newBlockStates.size()) { if (Collections.frequency(newBlockStates, Blocks.AIR.defaultBlockState()) != newBlockStates.size()) {
//add to undo stack //add to undo stack
BlockPos firstPos = startCoordinates.get(0); BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos)); UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
} }
} }
public static void onBlockBroken(PlayerEntity player, List<BlockPos> startCoordinates, boolean breakStartPos) { public static void onBlockBroken(Player player, List<BlockPos> startCoordinates, boolean breakStartPos) {
World world = player.world; Level world = player.level;
List<BlockPos> coordinates = findCoordinates(player, startCoordinates); List<BlockPos> coordinates = findCoordinates(player, startCoordinates);
if (coordinates.isEmpty()) return; if (coordinates.isEmpty()) return;
//remember previous blockstates for undo //remember previous blockstates for undo
List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size()); List<BlockState> previousBlockStates = new ArrayList<>(coordinates.size());
List<BlockState> newBlockStates = new ArrayList<>(coordinates.size()); List<BlockState> newBlockStates = new ArrayList<>(coordinates.size());
for (BlockPos coordinate : coordinates) { for (BlockPos coordinate : coordinates) {
previousBlockStates.add(world.getBlockState(coordinate)); previousBlockStates.add(world.getBlockState(coordinate));
} }
if (world.isRemote) { if (world.isClientSide) {
BlockPreviewRenderer.onBlocksBroken(); BlockPreviewRenderer.onBlocksBroken();
//list of air blockstates //list of air blockstates
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
newBlockStates.add(Blocks.AIR.getDefaultState()); newBlockStates.add(Blocks.AIR.defaultBlockState());
} }
} else { } else {
//If the player is going to instabreak grass or a plant, only break other instabreaking things //If the player is going to instabreak grass or a plant, only break other instabreaking things
boolean onlyInstaBreaking = !player.isCreative() && boolean onlyInstaBreaking = !player.isCreative() &&
world.getBlockState(startCoordinates.get(0)).getBlockHardness(world, startCoordinates.get(0)) == 0f; world.getBlockState(startCoordinates.get(0)).getDestroySpeed(world, startCoordinates.get(0)) == 0f;
//break all those blocks //break all those blocks
for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) { for (int i = breakStartPos ? 0 : 1; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i); BlockPos coordinate = coordinates.get(i);
if (world.isBlockPresent(coordinate) && !world.isAirBlock(coordinate)) { if (world.isLoaded(coordinate) && !world.isEmptyBlock(coordinate)) {
if (!onlyInstaBreaking || world.getBlockState(coordinate).getBlockHardness(world, coordinate) == 0f) { if (!onlyInstaBreaking || world.getBlockState(coordinate).getDestroySpeed(world, coordinate) == 0f) {
SurvivalHelper.breakBlock(world, player, coordinate, false); SurvivalHelper.breakBlock(world, player, coordinate, false);
} }
} }
} }
//find actual new blockstates for undo //find actual new blockstates for undo
for (BlockPos coordinate : coordinates) { for (BlockPos coordinate : coordinates) {
newBlockStates.add(world.getBlockState(coordinate)); newBlockStates.add(world.getBlockState(coordinate));
} }
} }
//Set first newBlockState to empty if in NORMAL mode, to make undo/redo work //Set first newBlockState to empty if in NORMAL mode, to make undo/redo work
//(Block isn't broken yet by the time it gets here, and broken after this) //(Block isn't broken yet by the time it gets here, and broken after this)
if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.getDefaultState()); if (!breakStartPos) newBlockStates.set(0, Blocks.AIR.defaultBlockState());
//add to undo stack //add to undo stack
BlockPos firstPos = startCoordinates.get(0); BlockPos firstPos = startCoordinates.get(0);
BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1); BlockPos secondPos = startCoordinates.get(startCoordinates.size() - 1);
Vec3d hitVec = new Vec3d(0.5, 0.5, 0.5); Vec3 hitVec = new Vec3(0.5, 0.5, 0.5);
UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos)); UndoRedo.addUndo(player, new BlockSet(coordinates, previousBlockStates, newBlockStates, hitVec, firstPos, secondPos));
} }
public static List<BlockPos> findCoordinates(PlayerEntity player, List<BlockPos> posList) { public static List<BlockPos> findCoordinates(Player player, List<BlockPos> posList) {
List<BlockPos> coordinates = new ArrayList<>(); List<BlockPos> coordinates = new ArrayList<>();
//Add current blocks being placed too //Add current blocks being placed too
coordinates.addAll(posList); coordinates.addAll(posList);
//Find mirror/array/radial mirror coordinates for each blockpos //Find mirror/array/radial mirror coordinates for each blockpos
for (BlockPos blockPos : posList) { for (BlockPos blockPos : posList) {
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos); List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
coordinates.addAll(arrayCoordinates); coordinates.addAll(arrayCoordinates);
coordinates.addAll(Mirror.findCoordinates(player, blockPos)); coordinates.addAll(Mirror.findCoordinates(player, blockPos));
coordinates.addAll(RadialMirror.findCoordinates(player, blockPos)); coordinates.addAll(RadialMirror.findCoordinates(player, blockPos));
//get mirror for each array coordinate //get mirror for each array coordinate
for (BlockPos coordinate : arrayCoordinates) { for (BlockPos coordinate : arrayCoordinates) {
coordinates.addAll(Mirror.findCoordinates(player, coordinate)); coordinates.addAll(Mirror.findCoordinates(player, coordinate));
coordinates.addAll(RadialMirror.findCoordinates(player, coordinate)); coordinates.addAll(RadialMirror.findCoordinates(player, coordinate));
} }
} }
return coordinates; return coordinates;
} }
public static List<BlockPos> findCoordinates(PlayerEntity player, BlockPos blockPos) { public static List<BlockPos> findCoordinates(Player player, BlockPos blockPos) {
return findCoordinates(player, new ArrayList<>(Arrays.asList(blockPos))); return findCoordinates(player, new ArrayList<>(Collections.singletonList(blockPos)));
} }
public static List<BlockState> findBlockStates(PlayerEntity player, List<BlockPos> posList, Vec3d hitVec, Direction facing, List<ItemStack> itemStacks) { public static List<BlockState> findBlockStates(Player player, List<BlockPos> posList, Vec3 hitVec, Direction facing, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>(); List<BlockState> blockStates = new ArrayList<>();
itemStacks.clear(); itemStacks.clear();
//Get itemstack //Get itemstack
ItemStack itemStack = player.getHeldItem(Hand.MAIN_HAND); ItemStack itemStack = player.getItemInHand(InteractionHand.MAIN_HAND);
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) { if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
itemStack = player.getHeldItem(Hand.OFF_HAND); itemStack = player.getItemInHand(InteractionHand.OFF_HAND);
} }
if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) { if (itemStack.isEmpty() || !CompatHelper.isItemBlockProxy(itemStack)) {
return blockStates; return blockStates;
} }
//Get ItemBlock stack //Get ItemBlock stack
ItemStack itemBlock = ItemStack.EMPTY; ItemStack itemBlock = ItemStack.EMPTY;
if (itemStack.getItem() instanceof BlockItem) itemBlock = itemStack; if (itemStack.getItem() instanceof BlockItem) itemBlock = itemStack;
else itemBlock = CompatHelper.getItemBlockFromStack(itemStack); else itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
ItemRandomizerBag.resetRandomness(); AbstractRandomizerBagItem.resetRandomness();
//Add blocks in posList first //Add blocks in posList first
for (BlockPos blockPos : posList) { for (BlockPos blockPos : posList) {
if (!(itemStack.getItem() instanceof BlockItem)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack); if (!(itemStack.getItem() instanceof BlockItem)) itemBlock = CompatHelper.getItemBlockFromStack(itemStack);
BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, Hand.MAIN_HAND); BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, InteractionHand.MAIN_HAND);
blockStates.add(blockState); if (blockState == null) continue;
itemStacks.add(itemBlock);
}
for (BlockPos blockPos : posList) { blockStates.add(blockState);
BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, Hand.MAIN_HAND); itemStacks.add(itemBlock);
}
List<BlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks); for (BlockPos blockPos : posList) {
blockStates.addAll(arrayBlockStates); BlockState blockState = getBlockStateFromItem(itemBlock, player, blockPos, facing, hitVec, InteractionHand.MAIN_HAND);
blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks)); if (blockState == null) continue;
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
BlockState blockState1 = arrayBlockStates.get(i);
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side List<BlockState> arrayBlockStates = Array.findBlockStates(player, blockPos, blockState, itemStack, itemStacks);
//TODO optimize findCoordinates (done twice now) blockStates.addAll(arrayBlockStates);
//TODO fix mirror blockStates.addAll(Mirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, blockPos, blockState, itemStack, itemStacks));
//add mirror for each array coordinate
List<BlockPos> arrayCoordinates = Array.findCoordinates(player, blockPos);
for (int i = 0; i < arrayCoordinates.size(); i++) {
BlockPos coordinate = arrayCoordinates.get(i);
BlockState blockState1 = arrayBlockStates.get(i);
if (blockState1 == null) continue;
blockStates.addAll(Mirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
blockStates.addAll(RadialMirror.findBlockStates(player, coordinate, blockState1, itemStack, itemStacks));
}
//Adjust blockstates for torches and ladders etc to place on a valid side
//TODO optimize findCoordinates (done twice now)
//TODO fix mirror
// List<BlockPos> coordinates = findCoordinates(player, startPos); // List<BlockPos> coordinates = findCoordinates(player, startPos);
// for (int i = 0; i < blockStates.size(); i++) { // for (int i = 0; i < blockStates.size(); i++) {
// blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing, // blockStates.set(i, blockStates.get(i).getBlock().getStateForPlacement(player.world, coordinates.get(i), facing,
// (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND)); // (float) hitVec.x, (float) hitVec.y, (float) hitVec.z, itemStacks.get(i).getMetadata(), player, EnumHand.MAIN_HAND));
// } // }
} }
return blockStates; return blockStates;
} }
public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) { public static boolean isEnabled(ModifierSettingsManager.ModifierSettings modifierSettings, BlockPos startPos) {
return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) || return Mirror.isEnabled(modifierSettings.getMirrorSettings(), startPos) ||
Array.isEnabled(modifierSettings.getArraySettings()) || Array.isEnabled(modifierSettings.getArraySettings()) ||
RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) || RadialMirror.isEnabled(modifierSettings.getRadialMirrorSettings(), startPos) ||
modifierSettings.doQuickReplace(); modifierSettings.doQuickReplace();
} }
public static BlockState getBlockStateFromItem(ItemStack itemStack, PlayerEntity player, BlockPos blockPos, Direction facing, Vec3d hitVec, Hand hand) { public static BlockState getBlockStateFromItem(ItemStack itemStack, Player player, BlockPos blockPos, Direction facing, Vec3 hitVec, InteractionHand hand) {
return Block.getBlockFromItem(itemStack.getItem()).getStateForPlacement(new BlockItemUseContext(new ItemUseContext(player, hand, new BlockRayTraceResult(hitVec, facing, blockPos, false)))); return Block.byItem(itemStack.getItem()).getStateForPlacement(new BlockPlaceContext(new UseOnContext(player, hand, new BlockHitResult(hitVec, facing, blockPos, false))));
} }
//Returns true if equal (or both null) //Returns true if equal (or both null)
public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) { public static boolean compareCoordinates(List<BlockPos> coordinates1, List<BlockPos> coordinates2) {
if (coordinates1 == null && coordinates2 == null) return true; if (coordinates1 == null && coordinates2 == null) return true;
if (coordinates1 == null || coordinates2 == null) return false; if (coordinates1 == null || coordinates2 == null) return false;
//Check count, not actual values //Check count, not actual values
if (coordinates1.size() == coordinates2.size()){ if (coordinates1.size() == coordinates2.size()) {
if (coordinates1.size() == 1){ if (coordinates1.size() == 1) {
return coordinates1.get(0).equals(coordinates2.get(0)); return coordinates1.get(0).equals(coordinates2.get(0));
} }
return true; return true;
} else { } else {
return false; return false;
} }
// return coordinates1.equals(coordinates2); // return coordinates1.equals(coordinates2);
} }
} }

View File

@@ -1,228 +1,234 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.*; import net.minecraft.world.entity.player.Player;
import net.minecraft.block.StairsBlock; import net.minecraft.world.item.ItemStack;
import net.minecraft.block.DirectionalBlock; import net.minecraft.world.level.block.state.properties.Half;
import net.minecraft.block.SlabBlock; import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.block.BlockState; import net.minecraft.core.Direction;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.InteractionHand;
import net.minecraft.item.ItemStack; import net.minecraft.core.BlockPos;
import net.minecraft.state.properties.Half; import net.minecraft.world.phys.Vec3;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import net.minecraft.world.level.block.DirectionalBlock;
import net.minecraft.world.level.block.DispenserBlock;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.StairBlock;
import net.minecraft.world.level.block.state.BlockState;
public class Mirror { public class Mirror {
public static class MirrorSettings { public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) {
public boolean enabled = false; List<BlockPos> coordinates = new ArrayList<>();
public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
public int radius = 10;
public boolean drawLines = true, drawPlanes = true;
public MirrorSettings() { //find mirrorsettings for the player
} MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return coordinates;
public MirrorSettings(boolean mirrorEnabled, Vec3d position, boolean mirrorX, boolean mirrorY, boolean mirrorZ, int radius, boolean drawLines, boolean drawPlanes) { if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates);
this.enabled = mirrorEnabled; if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates);
this.position = position; if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates);
this.mirrorX = mirrorX;
this.mirrorY = mirrorY;
this.mirrorZ = mirrorZ;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() { return coordinates;
return radius * 2; //Change ModifierSettings#setReachUpgrade too }
}
}
public static List<BlockPos> findCoordinates(PlayerEntity player, BlockPos startPos) {
List<BlockPos> coordinates = new ArrayList<>();
//find mirrorsettings for the player private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings(); //find mirror position
if (!isEnabled(m, startPos)) return coordinates; double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorX) coordinateMirrorX(m, startPos, coordinates); if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates);
if (m.mirrorY) coordinateMirrorY(m, startPos, coordinates); if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
if (m.mirrorZ) coordinateMirrorZ(m, startPos, coordinates); }
return coordinates; private static void coordinateMirrorY(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
} //find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
coordinates.add(newBlockPos);
private static void coordinateMirrorX(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) { if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates);
//find mirror position }
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorY) coordinateMirrorY(m, newBlockPos, coordinates); private static void coordinateMirrorZ(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) {
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates); //find mirror position
} double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
coordinates.add(newBlockPos);
}
private static void coordinateMirrorY(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) { public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
//find mirror position List<BlockState> blockStates = new ArrayList<>();
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
coordinates.add(newBlockPos);
if (m.mirrorZ) coordinateMirrorZ(m, newBlockPos, coordinates); //find mirrorsettings for the player
} MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings();
if (!isEnabled(m, startPos)) return blockStates;
private static void coordinateMirrorZ(MirrorSettings m, BlockPos oldBlockPos, List<BlockPos> coordinates) { //Randomizer bag synergy
//find mirror position AbstractRandomizerBagItem randomizerBagItem = null;
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); IItemHandler bagInventory = null;
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z); if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
coordinates.add(newBlockPos); randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
} bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
public static List<BlockState> findBlockStates(PlayerEntity player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) { if (m.mirrorX)
List<BlockState> blockStates = new ArrayList<>(); blockStateMirrorX(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorY)
blockStateMirrorY(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
if (m.mirrorZ)
blockStateMirrorZ(player, m, startPos, blockState, bagInventory, itemStack, InteractionHand.MAIN_HAND, blockStates, itemStacks);
//find mirrorsettings for the player return blockStates;
MirrorSettings m = ModifierSettingsManager.getModifierSettings(player).getMirrorSettings(); }
if (!isEnabled(m, startPos)) return blockStates;
//Randomizer bag synergy private static void blockStateMirrorX(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState,
IItemHandler bagInventory = null; IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) {
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) { //find mirror position
bagInventory = ItemRandomizerBag.getBagInventory(itemStack); double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
} BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
if (m.mirrorX) blockStateMirrorX(player, m, startPos, blockState, bagInventory, itemStack, Hand.MAIN_HAND, blockStates, itemStacks); //Randomizer bag synergy
if (m.mirrorY) blockStateMirrorY(player, m, startPos, blockState, bagInventory, itemStack, Hand.MAIN_HAND, blockStates, itemStacks); if (bagInventory != null) {
if (m.mirrorZ) blockStateMirrorZ(player, m, startPos, blockState, bagInventory, itemStack, Hand.MAIN_HAND, blockStates, itemStacks); itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
return blockStates; //Find blockstate
} BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.world.level.block.Mirror.FRONT_BACK);
private static void blockStateMirrorX(PlayerEntity player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState, //Store blockstate and itemstack
IItemHandler bagInventory, ItemStack itemStack, Hand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) { blockStates.add(newBlockState);
//find mirror position itemStacks.add(itemStack);
double x = m.position.x + (m.position.x - oldBlockPos.getX() - 0.5);
BlockPos newBlockPos = new BlockPos(x, oldBlockPos.getY(), oldBlockPos.getZ());
//Randomizer bag synergy if (m.mirrorY)
if (bagInventory != null) { blockStateMirrorY(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); if (m.mirrorZ)
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3d(0, 0, 0), hand); blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
} }
//Find blockstate private static void blockStateMirrorY(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState,
BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.util.Mirror.FRONT_BACK); IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
//Store blockstate and itemstack //Randomizer bag synergy
blockStates.add(newBlockState); if (bagInventory != null) {
itemStacks.add(itemStack); itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
if (m.mirrorY) blockStateMirrorY(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks); //Find blockstate
if (m.mirrorZ) blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks); BlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState);
}
private static void blockStateMirrorY(PlayerEntity player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState, //Store blockstate and itemstack
IItemHandler bagInventory, ItemStack itemStack, Hand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) { blockStates.add(newBlockState);
//find mirror position itemStacks.add(itemStack);
double y = m.position.y + (m.position.y - oldBlockPos.getY() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), y, oldBlockPos.getZ());
//Randomizer bag synergy if (m.mirrorZ)
if (bagInventory != null) { blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks);
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); }
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3d(0, 0, 0), hand);
}
//Find blockstate private static void blockStateMirrorZ(Player player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState,
BlockState newBlockState = oldBlockState == null ? null : getVerticalMirror(oldBlockState); IItemHandler bagInventory, ItemStack itemStack, InteractionHand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) {
//find mirror position
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5);
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
//Store blockstate and itemstack //Randomizer bag synergy
blockStates.add(newBlockState); if (bagInventory != null) {
itemStacks.add(itemStack); itemStack = ((AbstractRandomizerBagItem)itemStack.getItem()).pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3(0, 0, 0), hand);
}
if (m.mirrorZ) blockStateMirrorZ(player, m, newBlockPos, newBlockState, bagInventory, itemStack, hand, blockStates, itemStacks); //Find blockstate
} BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.world.level.block.Mirror.LEFT_RIGHT);
private static void blockStateMirrorZ(PlayerEntity player, MirrorSettings m, BlockPos oldBlockPos, BlockState oldBlockState, //Store blockstate and itemstack
IItemHandler bagInventory, ItemStack itemStack, Hand hand, List<BlockState> blockStates, List<ItemStack> itemStacks) { blockStates.add(newBlockState);
//find mirror position itemStacks.add(itemStack);
double z = m.position.z + (m.position.z - oldBlockPos.getZ() - 0.5); }
BlockPos newBlockPos = new BlockPos(oldBlockPos.getX(), oldBlockPos.getY(), z);
//Randomizer bag synergy public static boolean isEnabled(MirrorSettings m, BlockPos startPos) {
if (bagInventory != null) { if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false;
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory);
oldBlockState = BuildModifiers.getBlockStateFromItem(itemStack, player, oldBlockPos, Direction.UP, new Vec3d(0, 0, 0), hand);
}
//Find blockstate //within mirror distance
BlockState newBlockState = oldBlockState == null ? null : oldBlockState.mirror(net.minecraft.util.Mirror.LEFT_RIGHT); return !(startPos.getX() + 0.5 < m.position.x - m.radius) && !(startPos.getX() + 0.5 > m.position.x + m.radius) &&
!(startPos.getY() + 0.5 < m.position.y - m.radius) && !(startPos.getY() + 0.5 > m.position.y + m.radius) &&
!(startPos.getZ() + 0.5 < m.position.z - m.radius) && !(startPos.getZ() + 0.5 > m.position.z + m.radius);
}
//Store blockstate and itemstack private static BlockState getVerticalMirror(BlockState blockState) {
blockStates.add(newBlockState); //Stairs
itemStacks.add(itemStack); if (blockState.getBlock() instanceof StairBlock) {
} if (blockState.getValue(StairBlock.HALF) == Half.BOTTOM) {
return blockState.setValue(StairBlock.HALF, Half.TOP);
} else {
return blockState.setValue(StairBlock.HALF, Half.BOTTOM);
}
}
public static boolean isEnabled(MirrorSettings m, BlockPos startPos) { //Slabs
if (m == null || !m.enabled || (!m.mirrorX && !m.mirrorY && !m.mirrorZ)) return false; if (blockState.getBlock() instanceof SlabBlock) {
if (blockState.getValue(SlabBlock.TYPE) == SlabType.DOUBLE) {
return blockState;
} else if (blockState.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) {
return blockState.setValue(SlabBlock.TYPE, SlabType.TOP);
} else {
return blockState.setValue(SlabBlock.TYPE, SlabType.BOTTOM);
}
}
//within mirror distance //Buttons, endrod, observer, piston
if (startPos.getX() + 0.5 < m.position.x - m.radius || startPos.getX() + 0.5 > m.position.x + m.radius || if (blockState.getBlock() instanceof DirectionalBlock) {
startPos.getY() + 0.5 < m.position.y - m.radius || startPos.getY() + 0.5 > m.position.y + m.radius || if (blockState.getValue(DirectionalBlock.FACING) == Direction.DOWN) {
startPos.getZ() + 0.5 < m.position.z - m.radius || startPos.getZ() + 0.5 > m.position.z + m.radius) return blockState.setValue(DirectionalBlock.FACING, Direction.UP);
return false; } else if (blockState.getValue(DirectionalBlock.FACING) == Direction.UP) {
return blockState.setValue(DirectionalBlock.FACING, Direction.DOWN);
}
}
return true; //Dispenser, dropper
} if (blockState.getBlock() instanceof DispenserBlock) {
if (blockState.getValue(DispenserBlock.FACING) == Direction.DOWN) {
return blockState.setValue(DispenserBlock.FACING, Direction.UP);
} else if (blockState.getValue(DispenserBlock.FACING) == Direction.UP) {
return blockState.setValue(DispenserBlock.FACING, Direction.DOWN);
}
}
private static BlockState getVerticalMirror(BlockState blockState) { return blockState;
//Stairs }
if (blockState.getBlock() instanceof StairsBlock) {
if (blockState.get(StairsBlock.HALF) == Half.BOTTOM) {
return blockState.with(StairsBlock.HALF, Half.TOP);
} else {
return blockState.with(StairsBlock.HALF, Half.BOTTOM);
}
}
//Slabs public static class MirrorSettings {
if (blockState.getBlock() instanceof SlabBlock) { public boolean enabled = false;
if (blockState.get(SlabBlock.TYPE) == SlabType.DOUBLE) { public Vec3 position = new Vec3(0.5, 64.5, 0.5);
return blockState; public boolean mirrorX = true, mirrorY = false, mirrorZ = false;
} else if (blockState.get(SlabBlock.TYPE) == SlabType.BOTTOM) { public int radius = 10;
return blockState.with(SlabBlock.TYPE, SlabType.TOP); public boolean drawLines = true, drawPlanes = true;
} else {
return blockState.with(SlabBlock.TYPE, SlabType.BOTTOM);
}
}
//Buttons, endrod, observer, piston public MirrorSettings() {
if (blockState.getBlock() instanceof DirectionalBlock) { }
if (blockState.get(DirectionalBlock.FACING) == Direction.DOWN) {
return blockState.with(DirectionalBlock.FACING, Direction.UP);
} else if (blockState.get(DirectionalBlock.FACING) == Direction.UP) {
return blockState.with(DirectionalBlock.FACING, Direction.DOWN);
}
}
//Dispenser, dropper public MirrorSettings(boolean mirrorEnabled, Vec3 position, boolean mirrorX, boolean mirrorY, boolean mirrorZ, int radius, boolean drawLines, boolean drawPlanes) {
if (blockState.getBlock() instanceof DispenserBlock) { this.enabled = mirrorEnabled;
if (blockState.get(DispenserBlock.FACING) == Direction.DOWN) { this.position = position;
return blockState.with(DispenserBlock.FACING, Direction.UP); this.mirrorX = mirrorX;
} else if (blockState.get(DispenserBlock.FACING) == Direction.UP) { this.mirrorY = mirrorY;
return blockState.with(DispenserBlock.FACING, Direction.DOWN); this.mirrorZ = mirrorZ;
} this.radius = radius;
} this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
return blockState; public int getReach() {
} return radius * 2; //Change ModifierSettings#setReachUpgrade too
}
}
} }

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager; import nl.requios.effortlessbuilding.capability.ModifierCapabilityManager;
@@ -17,191 +17,199 @@ import javax.annotation.Nonnull;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class ModifierSettingsManager { public class ModifierSettingsManager {
//Retrieves the buildsettings of a player through the modifierCapability capability //Retrieves the buildsettings of a player through the modifierCapability capability
//Never returns null //Never returns null
@Nonnull @Nonnull
public static ModifierSettings getModifierSettings(PlayerEntity player){ public static ModifierSettings getModifierSettings(Player player) {
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
player.getCapability(ModifierCapabilityManager.modifierCapability, null);
if (modifierCapability.isPresent()) { LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
ModifierCapabilityManager.IModifierCapability capability = modifierCapability.orElse(null); player.getCapability(ModifierCapabilityManager.MODIFIER_CAPABILITY, null);
if (capability.getModifierData() == null) {
capability.setModifierData(new ModifierSettings());
}
return capability.getModifierData();
}
//Player does not have modifierCapability capability if (modifierCapability.isPresent()) {
//Return dummy settings ModifierCapabilityManager.IModifierCapability capability = modifierCapability.orElse(null);
return new ModifierSettings(); if (capability.getModifierData() == null){
// throw new IllegalArgumentException("Player does not have modifierCapability capability"); capability.setModifierData(new ModifierSettings());
} }
return capability.getModifierData();
}
public static void setModifierSettings(PlayerEntity player, ModifierSettings modifierSettings) { // EffortlessBuilding.logger.warn("Player does not have modifierCapability: " + player);
if (player == null) { //Return dummy settings
EffortlessBuilding.log("Cannot set buildsettings, player is null"); return new ModifierSettings();
return; }
}
LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability = public static void setModifierSettings(Player player, ModifierSettings modifierSettings) {
player.getCapability(ModifierCapabilityManager.modifierCapability, null); if (player == null) {
EffortlessBuilding.log("Cannot set buildsettings, player is null");
return;
}
modifierCapability.ifPresent((capability) -> { LazyOptional<ModifierCapabilityManager.IModifierCapability> modifierCapability =
capability.setModifierData(modifierSettings); player.getCapability(ModifierCapabilityManager.MODIFIER_CAPABILITY, null);
});
if (!modifierCapability.isPresent()) { modifierCapability.ifPresent((capability) -> {
EffortlessBuilding.log(player, "Saving buildsettings failed."); capability.setModifierData(modifierSettings);
} });
}
public static String sanitize(ModifierSettings modifierSettings, PlayerEntity player) { if (!modifierCapability.isPresent()) {
int maxReach = ReachHelper.getMaxReach(player); EffortlessBuilding.log(player, "Saving buildsettings failed.");
String error = ""; }
}
//Mirror settings public static String sanitize(ModifierSettings modifierSettings, Player player) {
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); int maxReach = ReachHelper.getMaxReach(player);
if (m.radius < 1) { String error = "";
m.radius = 1;
error += "Mirror size has to be at least 1. This has been corrected. ";
}
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to "+ (maxReach / 2) + ". ";
}
//Array settings //Mirror settings
Array.ArraySettings a = modifierSettings.getArraySettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (a.count < 0) { if (m.radius < 1) {
a.count = 0; m.radius = 1;
error += "Array count may not be negative. It has been reset to 0."; error += "Mirror size has to be at least 1. This has been corrected. ";
} }
if (m.getReach() > maxReach) {
m.radius = maxReach / 2;
error += "Mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
}
if (a.getReach() > maxReach) { //Array settings
a.count = 0; Array.ArraySettings a = modifierSettings.getArraySettings();
error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. "; if (a.count < 0) {
} a.count = 0;
error += "Array count may not be negative. It has been reset to 0.";
}
//Radial mirror settings if (a.getReach() > maxReach) {
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); a.count = 0;
if (r.slices < 2) { error += "Array exceeds your maximum reach of " + maxReach + ". Array count has been reset to 0. ";
r.slices = 2; }
error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
}
if (r.radius < 1) { //Radial mirror settings
r.radius = 1; RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
error += "Radial mirror radius has to be at least 1. This has been corrected. "; if (r.slices < 2) {
} r.slices = 2;
if (r.getReach() > maxReach) { error += "Radial mirror needs to have at least 2 slices. Slices has been set to 2.";
r.radius = maxReach / 2; }
error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to "+ (maxReach / 2) + ". ";
}
//Other if (r.radius < 1) {
if (modifierSettings.reachUpgrade < 0) { r.radius = 1;
modifierSettings.reachUpgrade = 0; error += "Radial mirror radius has to be at least 1. This has been corrected. ";
} }
if (modifierSettings.reachUpgrade > 3) { if (r.getReach() > maxReach) {
modifierSettings.reachUpgrade = 3; r.radius = maxReach / 2;
} error += "Radial mirror exceeds your maximum reach of " + (maxReach / 2) + ". Radius has been set to " + (maxReach / 2) + ". ";
}
return error; //Other
} if (modifierSettings.reachUpgrade < 0) {
modifierSettings.reachUpgrade = 0;
}
if (modifierSettings.reachUpgrade > 3) {
modifierSettings.reachUpgrade = 3;
}
public static class ModifierSettings { return error;
private Mirror.MirrorSettings mirrorSettings; }
private Array.ArraySettings arraySettings;
private RadialMirror.RadialMirrorSettings radialMirrorSettings;
private boolean quickReplace = false;
private int reachUpgrade = 0;
public ModifierSettings() { public static void handleNewPlayer(Player player) {
mirrorSettings = new Mirror.MirrorSettings(); //Makes sure player has modifier settings (if it doesnt it will create it)
arraySettings = new Array.ArraySettings(); getModifierSettings(player);
radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
}
public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings, //Only on server
RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) { if (!player.level.isClientSide) {
this.mirrorSettings = mirrorSettings; //Send to client
this.arraySettings = arraySettings; ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player));
this.radialMirrorSettings = radialMirrorSettings; PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), msg);
this.quickReplace = quickReplace; }
this.reachUpgrade = reachUpgrade; }
}
public Mirror.MirrorSettings getMirrorSettings() { public static class ModifierSettings {
if (this.mirrorSettings == null) this.mirrorSettings = new Mirror.MirrorSettings(); private Mirror.MirrorSettings mirrorSettings;
return this.mirrorSettings; private Array.ArraySettings arraySettings;
} private RadialMirror.RadialMirrorSettings radialMirrorSettings;
private boolean quickReplace = false;
private int reachUpgrade = 0;
public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) { public ModifierSettings() {
if (mirrorSettings == null) return; mirrorSettings = new Mirror.MirrorSettings();
this.mirrorSettings = mirrorSettings; arraySettings = new Array.ArraySettings();
} radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
}
public Array.ArraySettings getArraySettings() { public ModifierSettings(Mirror.MirrorSettings mirrorSettings, Array.ArraySettings arraySettings,
if (this.arraySettings == null) this.arraySettings = new Array.ArraySettings(); RadialMirror.RadialMirrorSettings radialMirrorSettings, boolean quickReplace, int reachUpgrade) {
return this.arraySettings; this.mirrorSettings = mirrorSettings;
} this.arraySettings = arraySettings;
this.radialMirrorSettings = radialMirrorSettings;
this.quickReplace = quickReplace;
this.reachUpgrade = reachUpgrade;
}
public void setArraySettings(Array.ArraySettings arraySettings) { public Mirror.MirrorSettings getMirrorSettings() {
if (arraySettings == null) return; if (this.mirrorSettings == null) this.mirrorSettings = new Mirror.MirrorSettings();
this.arraySettings = arraySettings; return this.mirrorSettings;
} }
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() { public void setMirrorSettings(Mirror.MirrorSettings mirrorSettings) {
if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings(); if (mirrorSettings == null) return;
return this.radialMirrorSettings; this.mirrorSettings = mirrorSettings;
} }
public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) { public Array.ArraySettings getArraySettings() {
if (radialMirrorSettings == null) return; if (this.arraySettings == null) this.arraySettings = new Array.ArraySettings();
this.radialMirrorSettings = radialMirrorSettings; return this.arraySettings;
} }
public boolean doQuickReplace() { public void setArraySettings(Array.ArraySettings arraySettings) {
return quickReplace; if (arraySettings == null) return;
} this.arraySettings = arraySettings;
}
public void setQuickReplace(boolean quickReplace) { public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
this.quickReplace = quickReplace; if (this.radialMirrorSettings == null) this.radialMirrorSettings = new RadialMirror.RadialMirrorSettings();
} return this.radialMirrorSettings;
}
public int getReachUpgrade() { public void setRadialMirrorSettings(RadialMirror.RadialMirrorSettings radialMirrorSettings) {
return reachUpgrade; if (radialMirrorSettings == null) return;
} this.radialMirrorSettings = radialMirrorSettings;
}
public void setReachUpgrade(int reachUpgrade) { public boolean doQuickReplace() {
this.reachUpgrade = reachUpgrade; return quickReplace;
//Set mirror radius to max }
int reach = 10;
switch (reachUpgrade) {
case 0: reach = BuildConfig.reach.maxReachLevel0.get(); break;
case 1: reach = BuildConfig.reach.maxReachLevel1.get(); break;
case 2: reach = BuildConfig.reach.maxReachLevel2.get(); break;
case 3: reach = BuildConfig.reach.maxReachLevel3.get(); break;
}
if (this.mirrorSettings != null) public void setQuickReplace(boolean quickReplace) {
this.mirrorSettings.radius = reach / 2; this.quickReplace = quickReplace;
if (this.radialMirrorSettings != null) }
this.radialMirrorSettings.radius = reach / 2;
}
}
public static void handleNewPlayer(PlayerEntity player){ public int getReachUpgrade() {
//Makes sure player has modifier settings (if it doesnt it will create it) return reachUpgrade;
getModifierSettings(player); }
//Only on server public void setReachUpgrade(int reachUpgrade) {
if (!player.world.isRemote) { this.reachUpgrade = reachUpgrade;
//Send to client //Set mirror radius to max
ModifierSettingsMessage msg = new ModifierSettingsMessage(getModifierSettings(player)); int reach = 10;
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), msg); switch (reachUpgrade) {
} case 0:
} reach = BuildConfig.reach.maxReachLevel0.get();
break;
case 1:
reach = BuildConfig.reach.maxReachLevel1.get();
break;
case 2:
reach = BuildConfig.reach.maxReachLevel2.get();
break;
case 3:
reach = BuildConfig.reach.maxReachLevel3.get();
break;
}
if (this.mirrorSettings != null)
this.mirrorSettings.radius = reach / 2;
if (this.radialMirrorSettings != null)
this.radialMirrorSettings.radius = reach / 2;
}
}
} }

View File

@@ -1,195 +1,194 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.Hand; import net.minecraft.world.InteractionHand;
import net.minecraft.util.Mirror; import net.minecraft.world.level.block.Mirror;
import net.minecraft.util.Rotation; import net.minecraft.world.level.block.Rotation;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.Mth;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class RadialMirror { public class RadialMirror {
public static class RadialMirrorSettings { public static List<BlockPos> findCoordinates(Player player, BlockPos startPos) {
public boolean enabled = false; List<BlockPos> coordinates = new ArrayList<>();
public Vec3d position = new Vec3d(0.5, 64.5, 0.5);
public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true, drawPlanes = false;
public RadialMirrorSettings() { //find radial mirror settings for the player
} RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return coordinates;
public RadialMirrorSettings(boolean enabled, Vec3d position, int slices, boolean alternate, int radius, boolean drawLines, boolean drawPlanes) { //get angle between slices
this.enabled = enabled; double sliceAngle = 2 * Math.PI / r.slices;
this.position = position;
this.slices = slices;
this.alternate = alternate;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() { Vec3 startVec = new Vec3(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
return radius * 2; Vec3 relStartVec = startVec.subtract(r.position);
}
}
public static List<BlockPos> findCoordinates(PlayerEntity player, BlockPos startPos) { double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z);
List<BlockPos> coordinates = new ArrayList<>(); if (startAngleToCenter < 0) startAngleToCenter += Math.PI;
double startAngleInSlice = startAngleToCenter % sliceAngle;
//find radial mirror settings for the player for (int i = 1; i < r.slices; i++) {
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings(); double curAngle = sliceAngle * i;
if (!isEnabled(r, startPos)) return coordinates;
//get angle between slices //alternate mirroring of slices
double sliceAngle = 2 * Math.PI / r.slices; if (r.alternate && i % 2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
}
Vec3d startVec = new Vec3d(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f); Vec3 relNewVec = relStartVec.yRot((float) curAngle);
Vec3d relStartVec = startVec.subtract(r.position); BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (!coordinates.contains(newBlockPos) && !newBlockPos.equals(startPos)) coordinates.add(newBlockPos);
}
double startAngleToCenter = MathHelper.atan2(relStartVec.x, relStartVec.z); return coordinates;
if (startAngleToCenter < 0) startAngleToCenter += Math.PI; }
double startAngleInSlice = startAngleToCenter % sliceAngle;
for (int i = 1; i < r.slices; i++) { public static List<BlockState> findBlockStates(Player player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
double curAngle = sliceAngle * i; List<BlockState> blockStates = new ArrayList<>();
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//alternate mirroring of slices //find radial mirror settings for the player that placed the block
if (r.alternate && i%2 == 1) { RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice); if (!isEnabled(r, startPos)) return blockStates;
}
Vec3d relNewVec = relStartVec.rotateYaw((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (!coordinates.contains(newBlockPos) && !newBlockPos.equals(startPos)) coordinates.add(newBlockPos);
}
return coordinates;
}
public static List<BlockState> findBlockStates(PlayerEntity player, BlockPos startPos, BlockState blockState, ItemStack itemStack, List<ItemStack> itemStacks) {
List<BlockState> blockStates = new ArrayList<>();
List<BlockPos> coordinates = new ArrayList<>(); //to keep track of duplicates
//find radial mirror settings for the player that placed the block
RadialMirrorSettings r = ModifierSettingsManager.getModifierSettings(player).getRadialMirrorSettings();
if (!isEnabled(r, startPos)) return blockStates;
//get angle between slices //get angle between slices
double sliceAngle = 2 * Math.PI / r.slices; double sliceAngle = 2 * Math.PI / r.slices;
Vec3d startVec = new Vec3d(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f); Vec3 startVec = new Vec3(startPos.getX() + 0.5f, startPos.getY() + 0.5f, startPos.getZ() + 0.5f);
Vec3d relStartVec = startVec.subtract(r.position); Vec3 relStartVec = startVec.subtract(r.position);
double startAngleToCenter = MathHelper.atan2(relStartVec.x, relStartVec.z); double startAngleToCenter = Mth.atan2(relStartVec.x, relStartVec.z);
double startAngleToCenterMod = startAngleToCenter < 0 ? startAngleToCenter + Math.PI : startAngleToCenter; double startAngleToCenterMod = startAngleToCenter < 0 ? startAngleToCenter + Math.PI : startAngleToCenter;
double startAngleInSlice = startAngleToCenterMod % sliceAngle; double startAngleInSlice = startAngleToCenterMod % sliceAngle;
//Rotate the original blockstate //Rotate the original blockstate
blockState = rotateOriginalBlockState(startAngleToCenter, blockState); blockState = rotateOriginalBlockState(player, startPos, startAngleToCenter, blockState);
//Randomizer bag synergy //Randomizer bag synergy
IItemHandler bagInventory = null; AbstractRandomizerBagItem randomizerBagItem = null;
if (!itemStack.isEmpty() && itemStack.getItem() instanceof ItemRandomizerBag) { IItemHandler bagInventory = null;
bagInventory = ItemRandomizerBag.getBagInventory(itemStack); if (!itemStack.isEmpty() && itemStack.getItem() instanceof AbstractRandomizerBagItem) {
} randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem() ;
bagInventory = randomizerBagItem.getBagInventory(itemStack);
}
BlockState newBlockState; BlockState newBlockState;
for (int i = 1; i < r.slices; i++) { for (int i = 1; i < r.slices; i++) {
newBlockState = blockState; newBlockState = blockState;
double curAngle = sliceAngle * i; double curAngle = sliceAngle * i;
//alternate mirroring of slices //alternate mirroring of slices
if (r.alternate && i%2 == 1) { if (r.alternate && i % 2 == 1) {
curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice); curAngle = curAngle - startAngleInSlice + (sliceAngle - startAngleInSlice);
} }
Vec3d relNewVec = relStartVec.rotateYaw((float) curAngle); Vec3 relNewVec = relStartVec.yRot((float) curAngle);
BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec)); BlockPos newBlockPos = new BlockPos(r.position.add(relNewVec));
if (coordinates.contains(newBlockPos) || newBlockPos.equals(startPos)) continue; //filter out duplicates if (coordinates.contains(newBlockPos) || newBlockPos.equals(startPos)) continue; //filter out duplicates
coordinates.add(newBlockPos); coordinates.add(newBlockPos);
//Randomizer bag synergy //Randomizer bag synergy
if (bagInventory != null) { if (randomizerBagItem != null) {
itemStack = ItemRandomizerBag.pickRandomStack(bagInventory); itemStack = randomizerBagItem.pickRandomStack(bagInventory);
newBlockState = BuildModifiers newBlockState = BuildModifiers
.getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3d(0, 0, 0), Hand.MAIN_HAND); .getBlockStateFromItem(itemStack, player, startPos, Direction.UP, new Vec3(0, 0, 0), InteractionHand.MAIN_HAND);
newBlockState = rotateOriginalBlockState(startAngleToCenter, newBlockState); newBlockState = rotateOriginalBlockState(player, startPos, startAngleToCenter, newBlockState);
} }
//rotate //rotate
newBlockState = rotateBlockState(relNewVec, newBlockState, r.alternate && i%2 == 1); newBlockState = rotateBlockState(player, startPos, relNewVec, newBlockState, r.alternate && i % 2 == 1);
blockStates.add(newBlockState); blockStates.add(newBlockState);
itemStacks.add(itemStack); itemStacks.add(itemStack);
} }
return blockStates; return blockStates;
} }
private static BlockState rotateOriginalBlockState(double startAngleToCenter, BlockState blockState) { private static BlockState rotateOriginalBlockState(Player player, BlockPos startPos, double startAngleToCenter, BlockState blockState) {
BlockState newBlockState = blockState; BlockState newBlockState = blockState;
if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) { if (startAngleToCenter < -0.751 * Math.PI || startAngleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180); newBlockState = blockState.rotate(player.level, startPos, Rotation.CLOCKWISE_180);
} else if (startAngleToCenter < -0.251 * Math.PI) { } else if (startAngleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90); newBlockState = blockState.rotate(player.level, startPos, Rotation.COUNTERCLOCKWISE_90);
} else if (startAngleToCenter > 0.249 * Math.PI) { } else if (startAngleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90); newBlockState = blockState.rotate(player.level, startPos, Rotation.CLOCKWISE_90);
} }
return newBlockState; return newBlockState;
} }
private static BlockState rotateBlockState(Vec3d relVec, BlockState blockState, boolean alternate) { private static BlockState rotateBlockState(Player player, BlockPos startPos, Vec3 relVec, BlockState blockState, boolean alternate) {
BlockState newBlockState; BlockState newBlockState;
double angleToCenter = MathHelper.atan2(relVec.x, relVec.z); //between -PI and PI double angleToCenter = Mth.atan2(relVec.x, relVec.z); //between -PI and PI
if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) { if (angleToCenter < -0.751 * Math.PI || angleToCenter > 0.749 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_180); newBlockState = blockState.rotate(player.level, startPos, Rotation.CLOCKWISE_180);
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK); newBlockState = newBlockState.mirror(Mirror.FRONT_BACK);
} }
} else if (angleToCenter < -0.251 * Math.PI) { } else if (angleToCenter < -0.251 * Math.PI) {
newBlockState = blockState.rotate(Rotation.CLOCKWISE_90); newBlockState = blockState.rotate(player.level, startPos, Rotation.CLOCKWISE_90);
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT); newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT);
} }
} else if (angleToCenter > 0.249 * Math.PI) { } else if (angleToCenter > 0.249 * Math.PI) {
newBlockState = blockState.rotate(Rotation.COUNTERCLOCKWISE_90); newBlockState = blockState.rotate(player.level, startPos, Rotation.COUNTERCLOCKWISE_90);
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT); newBlockState = newBlockState.mirror(Mirror.LEFT_RIGHT);
} }
} else { } else {
newBlockState = blockState; newBlockState = blockState;
if (alternate) { if (alternate) {
newBlockState = newBlockState.mirror(Mirror.FRONT_BACK); newBlockState = newBlockState.mirror(Mirror.FRONT_BACK);
} }
} }
return newBlockState; return newBlockState;
} }
public static boolean isEnabled(RadialMirrorSettings r, BlockPos startPos) { public static boolean isEnabled(RadialMirrorSettings r, BlockPos startPos) {
if (r == null || !r.enabled) return false; if (r == null || !r.enabled) return false;
if (new Vec3d(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(r.position).lengthSquared() > return !(new Vec3(startPos.getX() + 0.5, startPos.getY() + 0.5, startPos.getZ() + 0.5).subtract(r.position).lengthSqr() >
r.radius * r.radius) r.radius * r.radius);
return false; }
return true; public static class RadialMirrorSettings {
} public boolean enabled = false;
public Vec3 position = new Vec3(0.5, 64.5, 0.5);
public int slices = 4;
public boolean alternate = false;
public int radius = 20;
public boolean drawLines = true, drawPlanes = false;
public RadialMirrorSettings() {
}
public RadialMirrorSettings(boolean enabled, Vec3 position, int slices, boolean alternate, int radius, boolean drawLines, boolean drawPlanes) {
this.enabled = enabled;
this.position = position;
this.slices = slices;
this.alternate = alternate;
this.radius = radius;
this.drawLines = drawLines;
this.drawPlanes = drawPlanes;
}
public int getReach() {
return radius * 2;
}
}
} }

View File

@@ -1,18 +1,15 @@
package nl.requios.effortlessbuilding.buildmodifier; package nl.requios.effortlessbuilding.buildmodifier;
import net.minecraft.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.world.level.block.Blocks;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.item.Item; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.ItemStack; import net.minecraft.core.Direction;
import net.minecraft.util.Direction; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.BlockPos; import net.minecraft.world.phys.Vec3;
import net.minecraft.util.math.Vec3d; import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootParameterSet;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.helper.FixedStack; import nl.requios.effortlessbuilding.helper.FixedStack;
@@ -24,26 +21,26 @@ import java.util.*;
public class UndoRedo { public class UndoRedo {
//Undo and redo stacks per player //Undo and redo stacks per player
//Gets added to twice in singleplayer (server and client) if not careful. So separate stacks. //Gets added to twice in singleplayer (server and client) if not careful. So separate stacks.
private static Map<UUID, FixedStack<BlockSet>> undoStacksClient = new HashMap<>(); private static final Map<UUID, FixedStack<BlockSet>> undoStacksClient = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> undoStacksServer = new HashMap<>(); private static final Map<UUID, FixedStack<BlockSet>> undoStacksServer = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacksClient = new HashMap<>(); private static final Map<UUID, FixedStack<BlockSet>> redoStacksClient = new HashMap<>();
private static Map<UUID, FixedStack<BlockSet>> redoStacksServer = new HashMap<>(); private static final Map<UUID, FixedStack<BlockSet>> redoStacksServer = new HashMap<>();
//add to undo stack //add to undo stack
public static void addUndo(PlayerEntity player, BlockSet blockSet) { public static void addUndo(Player player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer; Map<UUID, FixedStack<BlockSet>> undoStacks = player.level.isClientSide ? undoStacksClient : undoStacksServer;
//Assert coordinates is as long as previous and new blockstate lists //Assert coordinates is as long as previous and new blockstate lists
if (blockSet.getCoordinates().size() != blockSet.getPreviousBlockStates().size() || if (blockSet.getCoordinates().size() != blockSet.getPreviousBlockStates().size() ||
blockSet.getCoordinates().size() != blockSet.getNewBlockStates().size()) { blockSet.getCoordinates().size() != blockSet.getNewBlockStates().size()) {
EffortlessBuilding.logger.error("Coordinates and blockstate lists are not equal length. Coordinates: {}. Previous blockstates: {}. New blockstates: {}.", EffortlessBuilding.logger.error("Coordinates and blockstate lists are not equal length. Coordinates: {}. Previous blockstates: {}. New blockstates: {}.",
blockSet.getCoordinates().size(), blockSet.getPreviousBlockStates().size(), blockSet.getNewBlockStates().size()); blockSet.getCoordinates().size(), blockSet.getPreviousBlockStates().size(), blockSet.getNewBlockStates().size());
} }
//Warn if previous and new blockstate are equal //Warn if previous and new blockstate are equal
//Can happen in a lot of valid cases //Can happen in a lot of valid cases
// for (int i = 0; i < blockSet.getCoordinates().size(); i++) { // for (int i = 0; i < blockSet.getCoordinates().size(); i++) {
// if (blockSet.getPreviousBlockStates().get(i).equals(blockSet.getNewBlockStates().get(i))) { // if (blockSet.getPreviousBlockStates().get(i).equals(blockSet.getNewBlockStates().get(i))) {
// EffortlessBuilding.logger.warn("Previous and new blockstates are equal at index {}. Blockstate: {}.", // EffortlessBuilding.logger.warn("Previous and new blockstates are equal at index {}. Blockstate: {}.",
@@ -51,193 +48,192 @@ public class UndoRedo {
// } // }
// } // }
//If no stack exists, make one //If no stack exists, make one
if (!undoStacks.containsKey(player.getUniqueID())) { if (!undoStacks.containsKey(player.getUUID())) {
undoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()])); undoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
} }
undoStacks.get(player.getUniqueID()).push(blockSet); undoStacks.get(player.getUUID()).push(blockSet);
} }
private static void addRedo(PlayerEntity player, BlockSet blockSet) { private static void addRedo(Player player, BlockSet blockSet) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer; Map<UUID, FixedStack<BlockSet>> redoStacks = player.level.isClientSide ? redoStacksClient : redoStacksServer;
//(No asserts necessary, it's private) //(No asserts necessary, it's private)
//If no stack exists, make one //If no stack exists, make one
if (!redoStacks.containsKey(player.getUniqueID())) { if (!redoStacks.containsKey(player.getUUID())) {
redoStacks.put(player.getUniqueID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()])); redoStacks.put(player.getUUID(), new FixedStack<>(new BlockSet[BuildConfig.survivalBalancers.undoStackSize.get()]));
} }
redoStacks.get(player.getUniqueID()).push(blockSet); redoStacks.get(player.getUUID()).push(blockSet);
} }
public static boolean undo(PlayerEntity player) { public static boolean undo(Player player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer; Map<UUID, FixedStack<BlockSet>> undoStacks = player.level.isClientSide ? undoStacksClient : undoStacksServer;
if (!undoStacks.containsKey(player.getUniqueID())) return false; if (!undoStacks.containsKey(player.getUUID())) return false;
FixedStack<BlockSet> undoStack = undoStacks.get(player.getUniqueID()); FixedStack<BlockSet> undoStack = undoStacks.get(player.getUUID());
if (undoStack.isEmpty()) return false; if (undoStack.isEmpty()) return false;
BlockSet blockSet = undoStack.pop(); BlockSet blockSet = undoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates(); List<BlockPos> coordinates = blockSet.getCoordinates();
List<BlockState> previousBlockStates = blockSet.getPreviousBlockStates(); List<BlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<BlockState> newBlockStates = blockSet.getNewBlockStates(); List<BlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec(); Vec3 hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory //Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, previousBlockStates); List<ItemStack> itemStacks = findItemStacksInInventory(player, previousBlockStates);
if (player.world.isRemote) { if (player.level.isClientSide) {
BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos()); BlockPreviewRenderer.onBlocksBroken(coordinates, itemStacks, newBlockStates, blockSet.getSecondPos(), blockSet.getFirstPos());
} else { } else {
//break all those blocks, reset to what they were //break all those blocks, reset to what they were
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i); BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i); ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue; if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack //get blockstate from itemstack
BlockState previousBlockState = Blocks.AIR.getDefaultState(); BlockState previousBlockState = Blocks.AIR.defaultBlockState();
if (itemStack.getItem() instanceof BlockItem) { if (itemStack.getItem() instanceof BlockItem) {
previousBlockState = ((BlockItem) itemStack.getItem()).getBlock().getDefaultState(); previousBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
} }
if (player.world.isBlockPresent(coordinate)) { if (player.level.isLoaded(coordinate)) {
//check itemstack empty //check itemstack empty
if (itemStack.isEmpty()) { if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, previousBlockStates.get(i)); itemStack = findItemStackInInventory(player, previousBlockStates.get(i));
//get blockstate from new itemstack //get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) { if (!itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) {
previousBlockState = ((BlockItem) itemStack.getItem()).getBlock().getDefaultState(); previousBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
} else { } else {
if (previousBlockStates.get(i).getBlock() != Blocks.AIR) if (previousBlockStates.get(i).getBlock() != Blocks.AIR)
EffortlessBuilding.logTranslate(player, "", previousBlockStates.get(i).getBlock().getTranslationKey(), " not found in inventory", true); EffortlessBuilding.logTranslate(player, "", previousBlockStates.get(i).getBlock().getDescriptionId(), " not found in inventory", true);
previousBlockState = Blocks.AIR.getDefaultState(); previousBlockState = Blocks.AIR.defaultBlockState();
} }
} }
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true); if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.level, player, coordinate, true);
//if previousBlockState is air, placeBlock will set it to air //if previousBlockState is air, placeBlock will set it to air
SurvivalHelper.placeBlock(player.world, player, coordinate, previousBlockState, itemStack, Direction.UP, hitVec, true, false, false); SurvivalHelper.placeBlock(player.level, player, coordinate, previousBlockState, itemStack, Direction.UP, hitVec, true, false, false);
} }
} }
} }
//add to redo //add to redo
addRedo(player, blockSet); addRedo(player, blockSet);
return true; return true;
} }
public static boolean redo(PlayerEntity player) { public static boolean redo(Player player) {
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer; Map<UUID, FixedStack<BlockSet>> redoStacks = player.level.isClientSide ? redoStacksClient : redoStacksServer;
if (!redoStacks.containsKey(player.getUniqueID())) return false; if (!redoStacks.containsKey(player.getUUID())) return false;
FixedStack<BlockSet> redoStack = redoStacks.get(player.getUniqueID()); FixedStack<BlockSet> redoStack = redoStacks.get(player.getUUID());
if (redoStack.isEmpty()) return false; if (redoStack.isEmpty()) return false;
BlockSet blockSet = redoStack.pop(); BlockSet blockSet = redoStack.pop();
List<BlockPos> coordinates = blockSet.getCoordinates(); List<BlockPos> coordinates = blockSet.getCoordinates();
List<BlockState> previousBlockStates = blockSet.getPreviousBlockStates(); List<BlockState> previousBlockStates = blockSet.getPreviousBlockStates();
List<BlockState> newBlockStates = blockSet.getNewBlockStates(); List<BlockState> newBlockStates = blockSet.getNewBlockStates();
Vec3d hitVec = blockSet.getHitVec(); Vec3 hitVec = blockSet.getHitVec();
//Find up to date itemstacks in player inventory //Find up to date itemstacks in player inventory
List<ItemStack> itemStacks = findItemStacksInInventory(player, newBlockStates); List<ItemStack> itemStacks = findItemStacksInInventory(player, newBlockStates);
if (player.world.isRemote) { if (player.level.isClientSide) {
BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos()); BlockPreviewRenderer.onBlocksPlaced(coordinates, itemStacks, newBlockStates, blockSet.getFirstPos(), blockSet.getSecondPos());
} else { } else {
//place blocks //place blocks
for (int i = 0; i < coordinates.size(); i++) { for (int i = 0; i < coordinates.size(); i++) {
BlockPos coordinate = coordinates.get(i); BlockPos coordinate = coordinates.get(i);
ItemStack itemStack = itemStacks.get(i); ItemStack itemStack = itemStacks.get(i);
if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue; if (previousBlockStates.get(i).equals(newBlockStates.get(i))) continue;
//get blockstate from itemstack //get blockstate from itemstack
BlockState newBlockState = Blocks.AIR.getDefaultState(); BlockState newBlockState = Blocks.AIR.defaultBlockState();
if (itemStack.getItem() instanceof BlockItem) { if (itemStack.getItem() instanceof BlockItem) {
newBlockState = ((BlockItem) itemStack.getItem()).getBlock().getDefaultState(); newBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
} }
if (player.world.isBlockPresent(coordinate)) { if (player.level.isLoaded(coordinate)) {
//check itemstack empty //check itemstack empty
if (itemStack.isEmpty()) { if (itemStack.isEmpty()) {
itemStack = findItemStackInInventory(player, newBlockStates.get(i)); itemStack = findItemStackInInventory(player, newBlockStates.get(i));
//get blockstate from new itemstack //get blockstate from new itemstack
if (!itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) { if (!itemStack.isEmpty() && itemStack.getItem() instanceof BlockItem) {
newBlockState = ((BlockItem) itemStack.getItem()).getBlock().getDefaultState(); newBlockState = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
} else { } else {
if (newBlockStates.get(i).getBlock() != Blocks.AIR) if (newBlockStates.get(i).getBlock() != Blocks.AIR)
EffortlessBuilding.logTranslate(player, "", newBlockStates.get(i).getBlock().getTranslationKey(), " not found in inventory", true); EffortlessBuilding.logTranslate(player, "", newBlockStates.get(i).getBlock().getDescriptionId(), " not found in inventory", true);
newBlockState = Blocks.AIR.getDefaultState(); newBlockState = Blocks.AIR.defaultBlockState();
} }
} }
if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.world, player, coordinate, true); if (itemStack.isEmpty()) SurvivalHelper.breakBlock(player.level, player, coordinate, true);
SurvivalHelper.placeBlock(player.world, player, coordinate, newBlockState, itemStack, Direction.UP, hitVec, true, false, false); SurvivalHelper.placeBlock(player.level, player, coordinate, newBlockState, itemStack, Direction.UP, hitVec, true, false, false);
} }
} }
} }
//add to undo //add to undo
addUndo(player, blockSet); addUndo(player, blockSet);
return true; return true;
} }
public static void clear(PlayerEntity player) { public static void clear(Player player) {
Map<UUID, FixedStack<BlockSet>> undoStacks = player.world.isRemote ? undoStacksClient : undoStacksServer; Map<UUID, FixedStack<BlockSet>> undoStacks = player.level.isClientSide ? undoStacksClient : undoStacksServer;
Map<UUID, FixedStack<BlockSet>> redoStacks = player.world.isRemote ? redoStacksClient : redoStacksServer; Map<UUID, FixedStack<BlockSet>> redoStacks = player.level.isClientSide ? redoStacksClient : redoStacksServer;
if (undoStacks.containsKey(player.getUniqueID())) { if (undoStacks.containsKey(player.getUUID())) {
undoStacks.get(player.getUniqueID()).clear(); undoStacks.get(player.getUUID()).clear();
} }
if (redoStacks.containsKey(player.getUniqueID())) { if (redoStacks.containsKey(player.getUUID())) {
redoStacks.get(player.getUniqueID()).clear(); redoStacks.get(player.getUUID()).clear();
} }
} }
private static List<ItemStack> findItemStacksInInventory(PlayerEntity player, List<BlockState> blockStates) { private static List<ItemStack> findItemStacksInInventory(Player player, List<BlockState> blockStates) {
List<ItemStack> itemStacks = new ArrayList<>(blockStates.size()); List<ItemStack> itemStacks = new ArrayList<>(blockStates.size());
for (BlockState blockState : blockStates) { for (BlockState blockState : blockStates) {
itemStacks.add(findItemStackInInventory(player, blockState)); itemStacks.add(findItemStackInInventory(player, blockState));
} }
return itemStacks; return itemStacks;
} }
private static ItemStack findItemStackInInventory(PlayerEntity player, BlockState blockState) { private static ItemStack findItemStackInInventory(Player player, BlockState blockState) {
ItemStack itemStack = ItemStack.EMPTY; ItemStack itemStack = ItemStack.EMPTY;
if (blockState == null) return itemStack; if (blockState == null) return itemStack;
//First try previousBlockStates //First try previousBlockStates
//TODO try to find itemstack with right blockstate first //TODO try to find itemstack with right blockstate first
// then change line 103 back (get state from item) // then change line 103 back (get state from item)
itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock()); itemStack = InventoryHelper.findItemStackInInventory(player, blockState.getBlock());
//then anything it drops //then anything it drops
if (itemStack.isEmpty()) { if (itemStack.isEmpty()) {
//Cannot check drops on clientside because loot tables are server only //Cannot check drops on clientside because loot tables are server only
if (!player.world.isRemote) if (!player.level.isClientSide) {
{ List<ItemStack> itemsDropped = Block.getDrops(blockState, (ServerLevel) player.level, BlockPos.ZERO, null);
List<ItemStack> itemsDropped = Block.getDrops(blockState, (ServerWorld) player.world, BlockPos.ZERO, null); for (ItemStack itemStackDropped : itemsDropped) {
for (ItemStack itemStackDropped : itemsDropped) { if (itemStackDropped.getItem() instanceof BlockItem) {
if (itemStackDropped.getItem() instanceof BlockItem) { Block block = ((BlockItem) itemStackDropped.getItem()).getBlock();
Block block = ((BlockItem) itemStackDropped.getItem()).getBlock(); itemStack = InventoryHelper.findItemStackInInventory(player, block);
itemStack = InventoryHelper.findItemStackInInventory(player, block); }
} }
} }
} }
}
//then air //then air
//(already empty) //(already empty)
return itemStack; return itemStack;
} }
} }

View File

@@ -1,34 +1,37 @@
package nl.requios.effortlessbuilding.capability; package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilitySerializable; import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class ItemHandlerCapabilityProvider implements ICapabilitySerializable<CompoundNBT> { public class ItemHandlerCapabilityProvider implements ICapabilitySerializable<CompoundTag> {
IItemHandler itemHandler = new ItemStackHandler(ItemRandomizerBag.INV_SIZE); IItemHandler itemHandler;
@Nonnull public ItemHandlerCapabilityProvider(int size) {
@Override itemHandler = new ItemStackHandler(size);
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { }
return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> itemHandler));
}
@Override @Nonnull
public CompoundNBT serializeNBT() { @Override
return ((ItemStackHandler) itemHandler).serializeNBT(); public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
} return CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.orEmpty(cap, LazyOptional.of(() -> itemHandler));
}
@Override @Override
public void deserializeNBT(CompoundNBT nbt) { public CompoundTag serializeNBT() {
((ItemStackHandler) itemHandler).deserializeNBT(nbt); return ((ItemStackHandler) itemHandler).serializeNBT();
} }
@Override
public void deserializeNBT(CompoundTag nbt) {
((ItemStackHandler) itemHandler).deserializeNBT(nbt);
}
} }

View File

@@ -1,11 +1,9 @@
package nl.requios.effortlessbuilding.capability; package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.INBT; import net.minecraft.nbt.Tag;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.*;
import net.minecraftforge.common.capabilities.CapabilityInject;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -15,89 +13,96 @@ import nl.requios.effortlessbuilding.buildmode.BuildModes;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager.ModeSettings;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class ModeCapabilityManager { public class ModeCapabilityManager {
@CapabilityInject(IModeCapability.class) public static Capability<IModeCapability> MODE_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){});
public final static Capability<IModeCapability> modeCapability = null;
public interface IModeCapability { // Allows for the capability to persist after death.
ModeSettings getModeData(); @SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModeCapability> original = event.getOriginal().getCapability(MODE_CAPABILITY, null);
LazyOptional<IModeCapability> clone = event.getEntity().getCapability(MODE_CAPABILITY, null);
clone.ifPresent(cloneModeCapability ->
original.ifPresent(originalModeCapability ->
cloneModeCapability.setModeData(originalModeCapability.getModeData())));
}
void setModeData(ModeSettings modeSettings); public interface IModeCapability {
} ModeSettings getModeData();
public static class ModeCapability implements IModeCapability { void setModeData(ModeSettings modeSettings);
private ModeSettings modeSettings; }
@Override public static class ModeCapability implements IModeCapability {
public ModeSettings getModeData() { private ModeSettings modeSettings;
return modeSettings;
}
@Override @Override
public void setModeData(ModeSettings modeSettings) { public ModeSettings getModeData() {
this.modeSettings = modeSettings; return modeSettings;
} }
}
public static class Storage implements Capability.IStorage<IModeCapability> { @Override
@Override public void setModeData(ModeSettings modeSettings) {
public INBT writeNBT(Capability<IModeCapability> capability, IModeCapability instance, Direction side) { this.modeSettings = modeSettings;
CompoundNBT compound = new CompoundNBT(); }
ModeSettings modeSettings = instance.getModeData(); }
if (modeSettings == null) modeSettings = new ModeSettings();
//compound.putInteger("buildMode", modeSettings.getBuildMode().ordinal()); public static class Provider extends CapabilityProvider<Provider> implements ICapabilitySerializable<Tag> {
//TODO add mode settings private IModeCapability instance = new ModeCapability();
private LazyOptional<IModeCapability> modeCapabilityOptional = LazyOptional.of(() -> instance);
return compound; public Provider() {
} super(Provider.class);
gatherCapabilities();
}
@Override @Nonnull
public void readNBT(Capability<IModeCapability> capability, IModeCapability instance, Direction side, INBT nbt) { @Override
CompoundNBT compound = (CompoundNBT) nbt; public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == MODE_CAPABILITY) return modeCapabilityOptional.cast();
return LazyOptional.empty();
}
//BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")]; @Override
public void invalidateCaps() {
super.invalidateCaps();
modeCapabilityOptional.invalidate();
}
//TODO add mode settings @Override
public void reviveCaps() {
super.reviveCaps();
modeCapabilityOptional = LazyOptional.of(() -> instance);
}
ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.NORMAL); @Override
instance.setModeData(modeSettings); public Tag serializeNBT() {
} CompoundTag compound = new CompoundTag();
} ModeSettings modeSettings = instance.getModeData();
if (modeSettings == null) modeSettings = new ModeSettings();
public static class Provider implements ICapabilitySerializable<INBT> { //compound.putInteger("buildMode", modeSettings.getBuildMode().ordinal());
IModeCapability inst = modeCapability.getDefaultInstance();
@Nonnull //TODO add mode settings
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
return modeCapability.orEmpty(cap, LazyOptional.of(() -> inst));
}
@Override return compound;
public INBT serializeNBT() { }
return modeCapability.getStorage().writeNBT(modeCapability, inst, null);
}
@Override @Override
public void deserializeNBT(INBT nbt) { public void deserializeNBT(Tag nbt) {
modeCapability.getStorage().readNBT(modeCapability, inst, null, nbt); CompoundTag compound = (CompoundTag) nbt;
}
} //BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[compound.getInteger("buildMode")];
// Allows for the capability to persist after death. //TODO add mode settings
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) { ModeSettings modeSettings = new ModeSettings(BuildModes.BuildModeEnum.NORMAL);
LazyOptional<IModeCapability> original = event.getOriginal().getCapability(modeCapability, null); instance.setModeData(modeSettings);
LazyOptional<IModeCapability> clone = event.getEntity().getCapability(modeCapability, null); }
clone.ifPresent(cloneModeCapability ->
original.ifPresent(originalModeCapability -> }
cloneModeCapability.setModeData(originalModeCapability.getModeData())));
}
} }

View File

@@ -1,13 +1,12 @@
package nl.requios.effortlessbuilding.capability; package nl.requios.effortlessbuilding.capability;
import net.minecraft.nbt.CompoundNBT; import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.INBT; import net.minecraft.nbt.Tag;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.*;
import net.minecraftforge.common.capabilities.CapabilityInject; import net.minecraftforge.common.util.INBTSerializable;
import net.minecraftforge.common.capabilities.ICapabilitySerializable;
import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -19,164 +18,169 @@ import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.*; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
@Mod.EventBusSubscriber @Mod.EventBusSubscriber
public class ModifierCapabilityManager { public class ModifierCapabilityManager {
@CapabilityInject(IModifierCapability.class) public final static Capability<IModifierCapability> MODIFIER_CAPABILITY = CapabilityManager.get(new CapabilityToken<>(){});
public final static Capability<IModifierCapability> modifierCapability = null;
public interface IModifierCapability { // Allows for the capability to persist after death.
ModifierSettings getModifierData(); @SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModifierCapability> original = event.getOriginal().getCapability(MODIFIER_CAPABILITY, null);
LazyOptional<IModifierCapability> clone = event.getEntity().getCapability(MODIFIER_CAPABILITY, null);
clone.ifPresent(cloneModifierCapability ->
original.ifPresent(originalModifierCapability ->
cloneModifierCapability.setModifierData(originalModifierCapability.getModifierData())));
}
void setModifierData(ModifierSettings modifierSettings); public interface IModifierCapability {
} ModifierSettings getModifierData();
public static class ModifierCapability implements IModifierCapability { void setModifierData(ModifierSettings modifierSettings);
private ModifierSettings modifierSettings; }
@Override public static class ModifierCapability implements IModifierCapability {
public ModifierSettings getModifierData() { private ModifierSettings modifierSettings;
return modifierSettings;
}
@Override @Override
public void setModifierData(ModifierSettings modifierSettings) { public ModifierSettings getModifierData() {
this.modifierSettings = modifierSettings; return modifierSettings;
} }
}
public static class Storage implements Capability.IStorage<IModifierCapability> { @Override
@Override public void setModifierData(ModifierSettings modifierSettings) {
public INBT writeNBT(Capability<IModifierCapability> capability, IModifierCapability instance, Direction side) { this.modifierSettings = modifierSettings;
CompoundNBT compound = new CompoundNBT(); }
ModifierSettings modifierSettings = instance.getModifierData(); }
if (modifierSettings == null) modifierSettings = new ModifierSettings();
//MIRROR public static class Provider extends CapabilityProvider<Provider> implements INBTSerializable<Tag> {
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m == null) m = new Mirror.MirrorSettings();
compound.putBoolean("mirrorEnabled", m.enabled);
compound.putDouble("mirrorPosX", m.position.x);
compound.putDouble("mirrorPosY", m.position.y);
compound.putDouble("mirrorPosZ", m.position.z);
compound.putBoolean("mirrorX", m.mirrorX);
compound.putBoolean("mirrorY", m.mirrorY);
compound.putBoolean("mirrorZ", m.mirrorZ);
compound.putInt("mirrorRadius", m.radius);
compound.putBoolean("mirrorDrawLines", m.drawLines);
compound.putBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY private final IModifierCapability instance = new ModifierCapability();
Array.ArraySettings a = modifierSettings.getArraySettings(); private LazyOptional<IModifierCapability> modifierCapabilityOptional = LazyOptional.of(() -> instance);
if (a == null) a = new Array.ArraySettings();
compound.putBoolean("arrayEnabled", a.enabled);
compound.putInt("arrayOffsetX", a.offset.getX());
compound.putInt("arrayOffsetY", a.offset.getY());
compound.putInt("arrayOffsetZ", a.offset.getZ());
compound.putInt("arrayCount", a.count);
compound.putInt("reachUpgrade", modifierSettings.getReachUpgrade()); public Provider() {
super(Provider.class);
gatherCapabilities();
}
//compound.putBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace @Nonnull
@Override
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
if (cap == MODIFIER_CAPABILITY) return modifierCapabilityOptional.cast();
return LazyOptional.empty();
}
//RADIAL MIRROR @Override
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); public void invalidateCaps() {
if (r == null) r = new RadialMirror.RadialMirrorSettings(); super.invalidateCaps();
compound.putBoolean("radialMirrorEnabled", r.enabled); modifierCapabilityOptional.invalidate();
compound.putDouble("radialMirrorPosX", r.position.x); }
compound.putDouble("radialMirrorPosY", r.position.y);
compound.putDouble("radialMirrorPosZ", r.position.z);
compound.putInt("radialMirrorSlices", r.slices);
compound.putBoolean("radialMirrorAlternate", r.alternate);
compound.putInt("radialMirrorRadius", r.radius);
compound.putBoolean("radialMirrorDrawLines", r.drawLines);
compound.putBoolean("radialMirrorDrawPlanes", r.drawPlanes);
return compound; @Override
} public void reviveCaps() {
super.reviveCaps();
modifierCapabilityOptional = LazyOptional.of(() -> instance);
}
@Override @Override
public void readNBT(Capability<IModifierCapability> capability, IModifierCapability instance, Direction side, INBT nbt) { public Tag serializeNBT() {
CompoundNBT compound = (CompoundNBT) nbt; CompoundTag compound = new CompoundTag();
ModifierSettings modifierSettings = instance.getModifierData();
if (modifierSettings == null) modifierSettings = new ModifierSettings();
//MIRROR //MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled"); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
Vec3d mirrorPosition = new Vec3d( if (m == null) m = new Mirror.MirrorSettings();
compound.getDouble("mirrorPosX"), compound.putBoolean("mirrorEnabled", m.enabled);
compound.getDouble("mirrorPosY"), compound.putDouble("mirrorPosX", m.position.x);
compound.getDouble("mirrorPosZ")); compound.putDouble("mirrorPosY", m.position.y);
boolean mirrorX = compound.getBoolean("mirrorX"); compound.putDouble("mirrorPosZ", m.position.z);
boolean mirrorY = compound.getBoolean("mirrorY"); compound.putBoolean("mirrorX", m.mirrorX);
boolean mirrorZ = compound.getBoolean("mirrorZ"); compound.putBoolean("mirrorY", m.mirrorY);
int mirrorRadius = compound.getInt("mirrorRadius"); compound.putBoolean("mirrorZ", m.mirrorZ);
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines"); compound.putInt("mirrorRadius", m.radius);
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes"); compound.putBoolean("mirrorDrawLines", m.drawLines);
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes); compound.putBoolean("mirrorDrawPlanes", m.drawPlanes);
//ARRAY //ARRAY
boolean arrayEnabled = compound.getBoolean("arrayEnabled"); Array.ArraySettings a = modifierSettings.getArraySettings();
BlockPos arrayOffset = new BlockPos( if (a == null) a = new Array.ArraySettings();
compound.getInt("arrayOffsetX"), compound.putBoolean("arrayEnabled", a.enabled);
compound.getInt("arrayOffsetY"), compound.putInt("arrayOffsetX", a.offset.getX());
compound.getInt("arrayOffsetZ")); compound.putInt("arrayOffsetY", a.offset.getY());
int arrayCount = compound.getInt("arrayCount"); compound.putInt("arrayOffsetZ", a.offset.getZ());
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); compound.putInt("arrayCount", a.count);
int reachUpgrade = compound.getInt("reachUpgrade"); compound.putInt("reachUpgrade", modifierSettings.getReachUpgrade());
//boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace //compound.putBoolean("quickReplace", buildSettings.doQuickReplace()); dont save quickreplace
//RADIAL MIRROR //RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled"); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
Vec3d radialMirrorPosition = new Vec3d( if (r == null) r = new RadialMirror.RadialMirrorSettings();
compound.getDouble("radialMirrorPosX"), compound.putBoolean("radialMirrorEnabled", r.enabled);
compound.getDouble("radialMirrorPosY"), compound.putDouble("radialMirrorPosX", r.position.x);
compound.getDouble("radialMirrorPosZ")); compound.putDouble("radialMirrorPosY", r.position.y);
int radialMirrorSlices = compound.getInt("radialMirrorSlices"); compound.putDouble("radialMirrorPosZ", r.position.z);
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate"); compound.putInt("radialMirrorSlices", r.slices);
int radialMirrorRadius = compound.getInt("radialMirrorRadius"); compound.putBoolean("radialMirrorAlternate", r.alternate);
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines"); compound.putInt("radialMirrorRadius", r.radius);
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes"); compound.putBoolean("radialMirrorDrawLines", r.drawLines);
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, compound.putBoolean("radialMirrorDrawPlanes", r.drawPlanes);
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade); return compound;
instance.setModifierData(modifierSettings); }
}
}
public static class Provider implements ICapabilitySerializable<INBT> { @Override
public void deserializeNBT(Tag nbt) {
CompoundTag compound = (CompoundTag) nbt;
IModifierCapability inst = modifierCapability.getDefaultInstance(); //MIRROR
boolean mirrorEnabled = compound.getBoolean("mirrorEnabled");
Vec3 mirrorPosition = new Vec3(
compound.getDouble("mirrorPosX"),
compound.getDouble("mirrorPosY"),
compound.getDouble("mirrorPosZ"));
boolean mirrorX = compound.getBoolean("mirrorX");
boolean mirrorY = compound.getBoolean("mirrorY");
boolean mirrorZ = compound.getBoolean("mirrorZ");
int mirrorRadius = compound.getInt("mirrorRadius");
boolean mirrorDrawLines = compound.getBoolean("mirrorDrawLines");
boolean mirrorDrawPlanes = compound.getBoolean("mirrorDrawPlanes");
Mirror.MirrorSettings mirrorSettings = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, mirrorDrawLines, mirrorDrawPlanes);
@Nonnull //ARRAY
@Override boolean arrayEnabled = compound.getBoolean("arrayEnabled");
public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) { BlockPos arrayOffset = new BlockPos(
return modifierCapability.orEmpty(cap, LazyOptional.of(() -> inst)); compound.getInt("arrayOffsetX"),
} compound.getInt("arrayOffsetY"),
compound.getInt("arrayOffsetZ"));
int arrayCount = compound.getInt("arrayCount");
Array.ArraySettings arraySettings = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
@Override int reachUpgrade = compound.getInt("reachUpgrade");
public INBT serializeNBT() {
return modifierCapability.getStorage().writeNBT(modifierCapability, inst, null);
}
@Override //boolean quickReplace = compound.getBoolean("quickReplace"); //dont load quickreplace
public void deserializeNBT(INBT nbt) {
modifierCapability.getStorage().readNBT(modifierCapability, inst, null, nbt);
}
} //RADIAL MIRROR
boolean radialMirrorEnabled = compound.getBoolean("radialMirrorEnabled");
Vec3 radialMirrorPosition = new Vec3(
compound.getDouble("radialMirrorPosX"),
compound.getDouble("radialMirrorPosY"),
compound.getDouble("radialMirrorPosZ"));
int radialMirrorSlices = compound.getInt("radialMirrorSlices");
boolean radialMirrorAlternate = compound.getBoolean("radialMirrorAlternate");
int radialMirrorRadius = compound.getInt("radialMirrorRadius");
boolean radialMirrorDrawLines = compound.getBoolean("radialMirrorDrawLines");
boolean radialMirrorDrawPlanes = compound.getBoolean("radialMirrorDrawPlanes");
RadialMirror.RadialMirrorSettings radialMirrorSettings = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition,
radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
ModifierSettings modifierSettings = new ModifierSettings(mirrorSettings, arraySettings, radialMirrorSettings, false, reachUpgrade);
instance.setModifierData(modifierSettings);
}
// Allows for the capability to persist after death. }
@SubscribeEvent
public static void clonePlayer(PlayerEvent.Clone event) {
LazyOptional<IModifierCapability> original = event.getOriginal().getCapability(modifierCapability, null);
LazyOptional<IModifierCapability> clone = event.getEntity().getCapability(modifierCapability, null);
clone.ifPresent(cloneModifierCapability ->
original.ifPresent(originalModifierCapability ->
cloneModifierCapability.setModifierData(originalModifierCapability.getModifierData())));
}
} }

View File

@@ -1,43 +0,0 @@
package nl.requios.effortlessbuilding.command;
import com.mojang.brigadier.CommandDispatcher;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import net.minecraft.command.CommandSource;
import net.minecraft.command.Commands;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.util.text.StringTextComponent;
import net.minecraftforge.fml.network.PacketDistributor;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.network.ModifierSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
public class CommandReach {
public static void register(CommandDispatcher<CommandSource> dispatcher) {
dispatcher.register(Commands.literal("reach").then(Commands.literal("set").then(Commands.argument("level", IntegerArgumentType.integer(0, 3)).executes((context) -> {
return setReachLevel(context.getSource().asPlayer(), IntegerArgumentType.getInteger(context, "level"));
}))).then(Commands.literal("get").executes((context -> {
return getReachLevel(context.getSource().asPlayer());
}))));
}
private static int setReachLevel(ServerPlayerEntity player, int level){
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setReachUpgrade(level);
ModifierSettingsManager.setModifierSettings(player, modifierSettings);
//Send to client
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), new ModifierSettingsMessage(modifierSettings));
player.sendMessage(new StringTextComponent("Reach level of " + player.getName().getString() + " set to " + modifierSettings.getReachUpgrade()));
return 1;
}
private static int getReachLevel(ServerPlayerEntity player){
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
EffortlessBuilding.log(player, "Current reach: level "+reachUpgrade);
return 1;
}
}

View File

@@ -1,132 +1,63 @@
package nl.requios.effortlessbuilding.compatibility; package nl.requios.effortlessbuilding.compatibility;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.item.BlockItem;
import net.minecraft.item.BlockItem; import net.minecraft.world.item.Item;
import net.minecraft.item.Item; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.ItemStack;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag;
public class CompatHelper { public class CompatHelper {
//TODO 1.13 compatibility
// // Get a handle to the dank null item instance. This will remain null if the mod doesn't load
// // and all checks will fail, so it works.
// @GameRegistry.ObjectHolder("danknull:dank_null")
// public static final Item dankNullItem = null;
//
// public static IChiselsAndBitsProxy chiselsAndBitsProxy;
//
public static void setup() {
//TODO 1.13 compatibility
// if (Loader.isModLoaded("chiselsandbits")) {
// // reflection to avoid hard dependency
// try {
// chiselsAndBitsProxy = Class.forName("nl.requios.effortlessbuilding.compatibility.ActiveChiselsAndBitsProxy").asSubclass(ActiveChiselsAndBitsProxy.class).newInstance();
// } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
// e.printStackTrace();
// }
// } else {
// chiselsAndBitsProxy = new DummyChiselsAndBitsProxy();
// }
}
// Check if the item given is a proxy for blocks. For now, we check for the randomizer bag, public static void setup() {
// /dank/null, or plain old blocks.
public static boolean isItemBlockProxy(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof BlockItem)
return true;
if ((item instanceof ItemRandomizerBag))
return true;
//TODO 1.13 compatibility
// if (item == dankNullItem)
// return true;
return false;
}
// Get the block to be placed by this proxy. For the /dank/null, it's the slot stack }
// pointed to by nbt integer selectedIndex.
public static ItemStack getItemBlockFromStack(ItemStack proxy) {
Item proxyItem = proxy.getItem();
if (proxyItem instanceof BlockItem) // Check if the item given is a proxy for blocks. For now, we check for the randomizer bag,
return proxy; // /dank/null, or plain old blocks.
public static boolean isItemBlockProxy(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof BlockItem)
return true;
return item instanceof AbstractRandomizerBagItem;
}
//Randomizer Bag // Get the block to be placed by this proxy. For the /dank/null, it's the slot stack
if (proxyItem instanceof ItemRandomizerBag) { // pointed to by nbt integer selectedIndex.
ItemStack itemStack = proxy; public static ItemStack getItemBlockFromStack(ItemStack proxy) {
while (!(itemStack.getItem() instanceof BlockItem || itemStack.isEmpty())) { Item proxyItem = proxy.getItem();
if (itemStack.getItem() instanceof ItemRandomizerBag)
itemStack = ItemRandomizerBag.pickRandomStack(ItemRandomizerBag.getBagInventory(itemStack));
}
return itemStack;
}
//TODO 1.13 compatibility if (proxyItem instanceof BlockItem)
//Dank Null return proxy;
// if (proxyItem == dankNullItem) {
// int index = 0;
// if (proxy.hasTagCompound() && proxy.getTagCompound().hasKey("selectedIndex"))
// index = proxy.getTagCompound().getInteger("selectedIndex");
// return proxy.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
// }
return ItemStack.EMPTY; //Randomizer Bag
} if (proxyItem instanceof AbstractRandomizerBagItem) {
ItemStack itemStack = proxy;
while (!(itemStack.getItem() instanceof BlockItem || itemStack.isEmpty())) {
if (itemStack.getItem() instanceof AbstractRandomizerBagItem) {
AbstractRandomizerBagItem randomizerBagItem = (AbstractRandomizerBagItem) itemStack.getItem();
itemStack = randomizerBagItem.pickRandomStack(randomizerBagItem.getBagInventory(itemStack));
}
}
return itemStack;
}
public static ItemStack getItemBlockByState(ItemStack stack, BlockState state) { return ItemStack.EMPTY;
if (state == null) return ItemStack.EMPTY; }
Item blockItem = Item.getItemFromBlock(state.getBlock()); public static ItemStack getItemBlockByState(ItemStack stack, BlockState state) {
if (stack.getItem() instanceof BlockItem) if (state == null) return ItemStack.EMPTY;
return stack;
else if (stack.getItem() instanceof ItemRandomizerBag) {
IItemHandler bagInventory = ItemRandomizerBag.getBagInventory(stack);
return ItemRandomizerBag.findStack(bagInventory, blockItem);
}
//TODO 1.13 compatibility
// else if (stack.getItem() == dankNullItem) {
// int index = itemHandlerSlotForItem(stack, blockItem);
// if (index >= 0)
// return stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).getStackInSlot(index);
// }
return ItemStack.EMPTY;
}
// Handle IItemHandler slot stacks not being modifiable. We must call IItemHandler#extractItem, Item blockItem = Item.byBlock(state.getBlock());
// because the ItemStack returned by IItemHandler#getStackInSlot isn't modifiable. if (stack.getItem() instanceof BlockItem)
public static void shrinkStack(ItemStack origStack, ItemStack curStack, PlayerEntity player) { return stack;
//TODO 1.13 compatibility, offhand support else if (stack.getItem() instanceof AbstractRandomizerBagItem) {
//Hacky way to get the origstack, because given origStack is itemblock stack and never proxy AbstractRandomizerBagItem randomizerBagItem = (AbstractRandomizerBagItem) stack.getItem();
// origStack = player.getHeldItem(EnumHand.MAIN_HAND); IItemHandler bagInventory = randomizerBagItem.getBagInventory(stack);
return randomizerBagItem.findStack(bagInventory, blockItem);
}
// if (origStack.getItem() == dankNullItem) { return ItemStack.EMPTY;
// int index = itemHandlerSlotForItem(origStack, curStack.getItem()); }
// origStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).extractItem(index, 1, false);
// } else
curStack.shrink(1);
}
private static int itemHandlerSlotForItem(ItemStack stack, Item blockItem) {
LazyOptional<IItemHandler> itemHandlerLazyOptional = stack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null);
IItemHandler handler = itemHandlerLazyOptional.orElse(null);
if (handler == null) {
EffortlessBuilding.logger.warn("Itemblock proxy has no item handler capability!");
return -1;
}
for (int i = 0; i < handler.getSlots(); i++) {
ItemStack ref = handler.getStackInSlot(i);
if (ref.getItem() instanceof BlockItem)
if (ref.getItem() == blockItem)
return i;
}
return -1;
}
} }

View File

@@ -0,0 +1,148 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.DiamondRandomizerBagItem;
public class DiamondRandomizerBagContainer extends AbstractContainerMenu {
private static final int INV_START = DiamondRandomizerBagItem.INV_SIZE,
INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1,
HOTBAR_END = HOTBAR_START + 8;
private final IItemHandler bagInventory;
public DiamondRandomizerBagContainer(MenuType<?> type, int id){
super(type, id);
bagInventory = null;
}
//Client
public DiamondRandomizerBagContainer(int id, Inventory playerInventory, FriendlyByteBuf packetBuffer) {
this(id, playerInventory);
}
//Server?
public DiamondRandomizerBagContainer(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, new ItemStackHandler(DiamondRandomizerBagItem.INV_SIZE));
}
public DiamondRandomizerBagContainer(int containerId, Inventory playerInventory, IItemHandler inventory) {
super(EffortlessBuilding.DIAMOND_RANDOMIZER_BAG_CONTAINER.get(), containerId);
bagInventory = inventory;
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
this.addSlot(new SlotItemHandler(bagInventory, j + i * 9, 8 + j * 18, 18 + i * 18));
}
}
// add player inventory slots
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 84 + i * 18));
}
}
// add hotbar slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 142));
}
}
@Override
public boolean stillValid(Player playerIn) {
return true;
}
@Override
public Slot getSlot(int parSlotIndex) {
if (parSlotIndex >= slots.size())
parSlotIndex = slots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override
public ItemStack quickMoveStack(Player playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(slotIndex);
if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy();
// If item is in our custom inventory
if (slotIndex < INV_START) {
// try to place in player inventory / action bar
if (!this.moveItemStackTo(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY;
}
slot.onQuickCraft(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place in custom inventory or armor slots
else {
/**
* Implementation number 1: Shift-click into your custom inventory
*/
if (slotIndex >= INV_START) {
// place in custom inventory
if (!this.moveItemStackTo(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY;
}
}
}
if (itemstack1.getCount() == 0) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
}
return itemstack;
}
/**
* You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public void clicked(int slot, int dragType, ClickType clickTypeIn, Player player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getItem().equals(player.getItemInHand(InteractionHand.MAIN_HAND))) {
//Do nothing;
return;
}
super.clicked(slot, dragType, clickTypeIn, player);
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void removed(Player player) {
super.removed(player);
if (!player.level.isClientSide) {
broadcastChanges();
}
}
}

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public class DiamondRandomizerBagScreen extends AbstractContainerScreen<DiamondRandomizerBagContainer> {
private Inventory inventory;
private static final ResourceLocation guiTextures = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/diamondrandomizerbag.png");
public DiamondRandomizerBagScreen(DiamondRandomizerBagContainer randomizerBagContainer, Inventory playerInventory, Component title) {
super(randomizerBagContainer, playerInventory, title);
this.inventory = playerInventory;
imageHeight = 167;
}
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms);
super.render(ms, mouseX, mouseY, partialTicks);
this.renderTooltip(ms, mouseX, mouseY);
}
@Override
protected void renderLabels(PoseStack ms, int mouseX, int mouseY) {
this.font.draw(ms, this.title, 8, 6, 0x404040);
this.font.draw(ms, this.playerInventoryTitle, 8, imageHeight - 96 + 2, 0x404040);
}
@Override
protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) {
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1f);
RenderSystem.setShaderTexture(0, guiTextures);
int marginHorizontal = (width - imageWidth) / 2;
int marginVertical = (height - imageHeight) / 2;
blit(ms, marginHorizontal, marginVertical, 0, 0, imageWidth, imageHeight);
}
}

View File

@@ -0,0 +1,146 @@
package nl.requios.effortlessbuilding.gui;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.inventory.ClickType;
import net.minecraft.world.inventory.MenuType;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.GoldenRandomizerBagItem;
public class GoldenRandomizerBagContainer extends AbstractContainerMenu {
private static final int INV_START = GoldenRandomizerBagItem.INV_SIZE,
INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1,
HOTBAR_END = HOTBAR_START + 8;
private final IItemHandler bagInventory;
public GoldenRandomizerBagContainer(MenuType<?> type, int id){
super(type, id);
bagInventory = null;
}
//Client
public GoldenRandomizerBagContainer(int id, Inventory playerInventory, FriendlyByteBuf packetBuffer) {
this(id, playerInventory);
}
//Server?
public GoldenRandomizerBagContainer(int containerId, Inventory playerInventory) {
this(containerId, playerInventory, new ItemStackHandler(GoldenRandomizerBagItem.INV_SIZE));
}
public GoldenRandomizerBagContainer(int containerId, Inventory playerInventory, IItemHandler inventory) {
super(EffortlessBuilding.GOLDEN_RANDOMIZER_BAG_CONTAINER.get(), containerId);
bagInventory = inventory;
for (int i = 0; i < GoldenRandomizerBagItem.INV_SIZE; ++i) {
this.addSlot(new SlotItemHandler(bagInventory, i, 8 + (18 * i), 20));
}
// add player inventory slots
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
}
}
// add hotbar slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 109));
}
}
@Override
public boolean stillValid(Player playerIn) {
return true;
}
@Override
public Slot getSlot(int parSlotIndex) {
if (parSlotIndex >= slots.size())
parSlotIndex = slots.size() - 1;
return super.getSlot(parSlotIndex);
}
@Override
public ItemStack quickMoveStack(Player playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.slots.get(slotIndex);
if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy();
// If item is in our custom inventory
if (slotIndex < INV_START) {
// try to place in player inventory / action bar
if (!this.moveItemStackTo(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY;
}
slot.onQuickCraft(itemstack1, itemstack);
}
// Item is in inventory / hotbar, try to place in custom inventory or armor slots
else {
/**
* Implementation number 1: Shift-click into your custom inventory
*/
if (slotIndex >= INV_START) {
// place in custom inventory
if (!this.moveItemStackTo(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY;
}
}
}
if (itemstack1.getCount() == 0) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) {
return ItemStack.EMPTY;
}
slot.onTake(playerIn, itemstack1);
}
return itemstack;
}
/**
* You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public void clicked(int slot, int dragType, ClickType clickTypeIn, Player player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getItem().equals(player.getItemInHand(InteractionHand.MAIN_HAND))) {
//Do nothing;
return;
}
super.clicked(slot, dragType, clickTypeIn, player);
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void removed(Player player) {
super.removed(player);
if (!player.level.isClientSide) {
broadcastChanges();
}
}
}

View File

@@ -0,0 +1,49 @@
package nl.requios.effortlessbuilding.gui;
import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Inventory;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public class GoldenRandomizerBagScreen extends AbstractContainerScreen<GoldenRandomizerBagContainer> {
private Inventory inventory;
private static final ResourceLocation guiTextures = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/goldenrandomizerbag.png");
public GoldenRandomizerBagScreen(GoldenRandomizerBagContainer randomizerBagContainer, Inventory playerInventory, Component title) {
super(randomizerBagContainer, playerInventory, title);
this.inventory = playerInventory;
imageHeight = 134;
}
@Override
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
renderBackground(ms);
super.render(ms, mouseX, mouseY, partialTicks);
this.renderTooltip(ms, mouseX, mouseY);
}
@Override
protected void renderLabels(PoseStack ms, int mouseX, int mouseY) {
this.font.draw(ms, this.title, 8, 6, 0x404040);
this.font.draw(ms, this.playerInventoryTitle, 8, imageHeight - 96 + 2, 0x404040);
}
@Override
protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) {
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1f);
RenderSystem.setShaderTexture(0, guiTextures);
int marginHorizontal = (width - imageWidth) / 2;
int marginVertical = (height - imageHeight) / 2;
blit(ms, marginHorizontal, marginVertical, 0, 0, imageWidth, imageHeight);
}
}

View File

@@ -1,138 +1,146 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.inventory.IInventory; import net.minecraft.world.inventory.ClickType;
import net.minecraft.inventory.Inventory; import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.inventory.container.ClickType; import net.minecraft.world.inventory.MenuType;
import net.minecraft.inventory.container.Container; import net.minecraft.world.inventory.Slot;
import net.minecraft.inventory.container.Slot; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.ItemStack; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.Hand; import net.minecraft.world.InteractionHand;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler; import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.items.SlotItemHandler; import net.minecraftforge.items.SlotItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.RandomizerBagItem;
public class RandomizerBagContainer extends Container { public class RandomizerBagContainer extends AbstractContainerMenu {
private final IItemHandler bagInventory; private static final int INV_START = RandomizerBagItem.INV_SIZE,
INV_END = INV_START + 26,
HOTBAR_START = INV_END + 1,
HOTBAR_END = HOTBAR_START + 8;
private final IItemHandler bagInventory;
private static final int INV_START = ItemRandomizerBag.INV_SIZE, INV_END = INV_START + 26, public RandomizerBagContainer(MenuType<?> type, int id){
HOTBAR_START = INV_END + 1, HOTBAR_END = HOTBAR_START + 8; super(type, id);
bagInventory = null;
}
public RandomizerBagContainer(int containerId, PlayerInventory playerInventory) { //Client
this(containerId, playerInventory, new ItemStackHandler(ItemRandomizerBag.INV_SIZE)); public RandomizerBagContainer(int id, Inventory playerInventory, FriendlyByteBuf packetBuffer) {
} this(id, playerInventory);
}
public RandomizerBagContainer(int containerId, PlayerInventory playerInventory, IItemHandler inventory) { //Server?
super(EffortlessBuilding.RANDOMIZER_BAG_CONTAINER, containerId); public RandomizerBagContainer(int containerId, Inventory playerInventory) {
bagInventory = inventory; this(containerId, playerInventory, new ItemStackHandler(RandomizerBagItem.INV_SIZE));
}
for (int i = 0; i < ItemRandomizerBag.INV_SIZE; ++i) { public RandomizerBagContainer(int containerId, Inventory playerInventory, IItemHandler inventory) {
this.addSlot(new SlotItemHandler(bagInventory, i, 44 + (18 * i), 20)); super(EffortlessBuilding.RANDOMIZER_BAG_CONTAINER.get(), containerId);
} bagInventory = inventory;
// add player inventory slots for (int i = 0; i < RandomizerBagItem.INV_SIZE; ++i) {
int i; this.addSlot(new SlotItemHandler(bagInventory, i, 44 + (18 * i), 20));
for (i = 0; i < 3; ++i) { }
for (int j = 0; j < 9; ++j) {
addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
}
}
// add hotbar slots // add player inventory slots
for (i = 0; i < 9; ++i) { for (int i = 0; i < 3; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 109)); for (int j = 0; j < 9; ++j) {
} addSlot(new Slot(playerInventory, j + i * 9 + 9, 8 + j * 18, 51 + i * 18));
} }
}
// add hotbar slots
for (int i = 0; i < 9; ++i) {
addSlot(new Slot(playerInventory, i, 8 + i * 18, 109));
}
}
@Override @Override
public boolean canInteractWith(PlayerEntity playerIn) { public boolean stillValid(Player playerIn) {
return true; return true;
} }
@Override @Override
public Slot getSlot(int parSlotIndex) public Slot getSlot(int parSlotIndex) {
{ if (parSlotIndex >= slots.size())
if(parSlotIndex >= inventorySlots.size()) parSlotIndex = slots.size() - 1;
parSlotIndex = inventorySlots.size() - 1; return super.getSlot(parSlotIndex);
return super.getSlot(parSlotIndex); }
}
@Override @Override
public ItemStack transferStackInSlot(PlayerEntity playerIn, int slotIndex) { public ItemStack quickMoveStack(Player playerIn, int slotIndex) {
ItemStack itemstack = ItemStack.EMPTY; ItemStack itemstack = ItemStack.EMPTY;
Slot slot = this.inventorySlots.get(slotIndex); Slot slot = this.slots.get(slotIndex);
if (slot != null && slot.getHasStack()) { if (slot != null && slot.hasItem()) {
ItemStack itemstack1 = slot.getStack(); ItemStack itemstack1 = slot.getItem();
itemstack = itemstack1.copy(); itemstack = itemstack1.copy();
// If item is in our custom inventory // If item is in our custom inventory
if (slotIndex < INV_START) { if (slotIndex < INV_START) {
// try to place in player inventory / action bar // try to place in player inventory / action bar
if (!this.mergeItemStack(itemstack1, INV_START, HOTBAR_END + 1, true)) { if (!this.moveItemStackTo(itemstack1, INV_START, HOTBAR_END + 1, true)) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
slot.onSlotChange(itemstack1, itemstack); slot.onQuickCraft(itemstack1, itemstack);
} }
// Item is in inventory / hotbar, try to place in custom inventory or armor slots // Item is in inventory / hotbar, try to place in custom inventory or armor slots
else { else {
/** /**
* Implementation number 1: Shift-click into your custom inventory * Implementation number 1: Shift-click into your custom inventory
*/ */
if (slotIndex >= INV_START) { if (slotIndex >= INV_START) {
// place in custom inventory // place in custom inventory
if (!this.mergeItemStack(itemstack1, 0, INV_START, false)) { if (!this.moveItemStackTo(itemstack1, 0, INV_START, false)) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
} }
}
} if (itemstack1.getCount() == 0) {
slot.set(ItemStack.EMPTY);
} else {
slot.setChanged();
}
if (itemstack1.getCount() == 0) { if (itemstack1.getCount() == itemstack.getCount()) {
slot.putStack(ItemStack.EMPTY); return ItemStack.EMPTY;
} else { }
slot.onSlotChanged();
}
if (itemstack1.getCount() == itemstack.getCount()) { slot.onTake(playerIn, itemstack1);
return ItemStack.EMPTY; }
}
slot.onTake(playerIn, itemstack1); return itemstack;
} }
return itemstack; /**
} * You should override this method to prevent the player from moving the stack that
* opened the inventory, otherwise if the player moves it, the inventory will not
* be able to save properly
*/
@Override
public void clicked(int slot, int dragType, ClickType clickTypeIn, Player player) {
// this will prevent the player from interacting with the item that opened the inventory:
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getItem().equals(player.getItemInHand(InteractionHand.MAIN_HAND))) {
//Do nothing;
return;
}
super.clicked(slot, dragType, clickTypeIn, player);
}
/** /**
* You should override this method to prevent the player from moving the stack that * Callback for when the crafting gui is closed.
* opened the inventory, otherwise if the player moves it, the inventory will not */
* be able to save properly @Override
*/ public void removed(Player player) {
@Override super.removed(player);
public ItemStack slotClick(int slot, int dragType, ClickType clickTypeIn, PlayerEntity player) { if (!player.level.isClientSide) {
// this will prevent the player from interacting with the item that opened the inventory: broadcastChanges();
if (slot >= 0 && getSlot(slot) != null && getSlot(slot).getStack().equals(player.getHeldItem(Hand.MAIN_HAND))) { }
return ItemStack.EMPTY; }
}
return super.slotClick(slot, dragType, clickTypeIn, player);
}
/**
* Callback for when the crafting gui is closed.
*/
@Override
public void onContainerClosed(PlayerEntity player)
{
super.onContainerClosed(player);
if(!player.world.isRemote)
{
detectAndSendChanges();
}
}
} }

View File

@@ -1,46 +1,49 @@
package nl.requios.effortlessbuilding.gui; package nl.requios.effortlessbuilding.gui;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.screen.inventory.ContainerScreen; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen;
import net.minecraft.entity.player.PlayerInventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.util.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.text.ITextComponent; import net.minecraft.network.chat.Component;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class RandomizerBagScreen extends ContainerScreen<RandomizerBagContainer> { @ParametersAreNonnullByDefault
private static final ResourceLocation guiTextures = public class RandomizerBagScreen extends AbstractContainerScreen<RandomizerBagContainer> {
new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png"); private Inventory inventory;
public RandomizerBagScreen(RandomizerBagContainer randomizerBagContainer, PlayerInventory playerInventory, ITextComponent title) { private static final ResourceLocation guiTextures = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/container/randomizerbag.png");
super(randomizerBagContainer, playerInventory, title);//new TranslationTextComponent("effortlessbuilding.screen.randomizer_bag"));
ySize = 134;
}
@Override public RandomizerBagScreen(RandomizerBagContainer randomizerBagContainer, Inventory playerInventory, Component title) {
public void render(int mouseX, int mouseY, float partialTicks) { super(randomizerBagContainer, playerInventory, title);
renderBackground(); this.inventory = playerInventory;
super.render(mouseX, mouseY, partialTicks); imageHeight = 134;
this.renderHoveredToolTip(mouseX, mouseY); }
}
@Override @Override
protected void drawGuiContainerForegroundLayer(int mouseX, int mouseY) { public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
font.drawString(this.title.getFormattedText(), 8, 6, 0x404040); renderBackground(ms);
font.drawString(playerInventory.getDisplayName().getFormattedText(), 8, ySize - 96 + 2, 0x404040); super.render(ms, mouseX, mouseY, partialTicks);
} this.renderTooltip(ms, mouseX, mouseY);
}
@Override @Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) { protected void renderLabels(PoseStack ms, int mouseX, int mouseY) {
RenderSystem.color3f(1.0F, 1.0F, 1.0F); this.font.draw(ms, this.title, 8, 6, 0x404040);
minecraft.getTextureManager().bindTexture(guiTextures); this.font.draw(ms, this.playerInventoryTitle, 8, imageHeight - 96 + 2, 0x404040);
int marginHorizontal = (width - xSize) / 2; }
int marginVertical = (height - ySize) / 2;
blit(marginHorizontal, marginVertical, 0, 0, xSize, ySize); @Override
} protected void renderBg(PoseStack ms, float partialTicks, int mouseX, int mouseY) {
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1f);
RenderSystem.setShaderTexture(0, guiTextures);
int marginHorizontal = (width - imageWidth) / 2;
int marginVertical = (height - imageHeight) / 2;
blit(ms, marginHorizontal, marginVertical, 0, 0, imageWidth, imageHeight);
}
} }

View File

@@ -1,251 +1,224 @@
package nl.requios.effortlessbuilding.gui.buildmode; package nl.requios.effortlessbuilding.gui.buildmode;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SimpleSound; import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.client.gui.AbstractGui; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.IGuiEventListener; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screen.LanguageScreen; import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.sounds.SoundEvents;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.util.Mth;
import net.minecraft.client.gui.widget.list.ExtendedList; import net.minecraft.network.chat.Component;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.SoundEvents;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.client.gui.widget.ExtendedButton; import net.minecraftforge.client.gui.widget.ExtendedButton;
import net.minecraftforge.fml.client.gui.widget.Slider; import net.minecraftforge.client.gui.widget.ForgeSlider;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import javax.annotation.ParametersAreNonnullByDefault;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class PlayerSettingsGui extends Screen { public class PlayerSettingsGui extends Screen {
protected int left, right, top, bottom; protected int left, right, top, bottom;
protected boolean showShaderList = false;
private Button shaderTypeButton;
private ShaderTypeList shaderTypeList;
private Button closeButton;
private Button shaderTypeButton; public PlayerSettingsGui() {
private ShaderTypeList shaderTypeList; super(Component.translatable("effortlessbuilding.screen.player_settings"));
private Button closeButton; }
protected boolean showShaderList = false; @Override
protected void init() {
left = this.width / 2 - 140;
right = this.width / 2 + 140;
top = this.height / 2 - 100;
bottom = this.height / 2 + 100;
public enum ShaderType { int yy = top;
DISSOLVE_BLUE("Dissolve Blue"), shaderTypeList = new ShaderTypeList(this.minecraft);
DISSOLVE_ORANGE("Dissolve Orange"); addWidget(shaderTypeList);
//TODO set selected name
Component currentShaderName = ShaderType.DISSOLVE_BLUE.name;
shaderTypeButton = new ExtendedButton(right - 180, yy, 180, 20, currentShaderName, (button) -> {
showShaderList = !showShaderList;
});
addRenderableOnly(shaderTypeButton);
public String name; yy += 50;
ShaderType(String name) { ForgeSlider slider = new ForgeSlider(right - 200, yy, 200, 20, Component.empty(), Component.empty(), 0.5, 2.0, 1.0, true);
this.name = name; addRenderableOnly(slider);
}
}
public PlayerSettingsGui() { closeButton = new ExtendedButton(left + 50, bottom - 20, 180, 20, Component.literal("Done"), (button) -> this.minecraft.player.closeContainer());
super(new TranslationTextComponent("effortlessbuilding.screen.player_settings")); addRenderableOnly(closeButton);
} }
@Override @Override
protected void init() { public void tick() {
left = this.width / 2 - 140; super.tick();
right = this.width / 2 + 140; }
top = this.height / 2 - 100;
bottom = this.height / 2 + 100;
int yy = top; @Override
shaderTypeList = new ShaderTypeList(this.minecraft); public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
this.children.add(shaderTypeList); this.renderBackground(ms);
//TODO set selected name
String currentShaderName = ShaderType.DISSOLVE_BLUE.name;
shaderTypeButton = new ExtendedButton(right - 180, yy, 180, 20, currentShaderName, (button) -> {
showShaderList = !showShaderList;
});
addButton(shaderTypeButton);
yy += 50; int yy = top;
Slider slider = new Slider(right - 200, yy, 200, 20, "", "", 0.5, 2.0, 1.0, true, true, (button) -> { font.draw(ms, "Shader type", left, yy + 5, 0xFFFFFF);
}); yy += 50;
addButton(slider); font.draw(ms, "Shader speed", left, yy + 5, 0xFFFFFF);
closeButton = new ExtendedButton(left + 50, bottom - 20, 180, 20, "Done", (button) -> { super.render(ms, mouseX, mouseY, partialTicks);
this.minecraft.player.closeScreen();
});
addButton(closeButton);
}
@Override if (showShaderList)
public void tick() { this.shaderTypeList.render(ms, mouseX, mouseY, partialTicks);
super.tick(); }
}
@Override @Override
public void render(int mouseX, int mouseY, float partialTicks) { public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
this.renderBackground(); super.mouseClicked(mouseX, mouseY, mouseButton);
if (showShaderList) {
if (!shaderTypeList.isMouseOver(mouseX, mouseY) && !shaderTypeButton.isMouseOver(mouseX, mouseY))
showShaderList = false;
}
return true;
}
int yy = top; @Override
font.drawString("Shader type", left, yy + 5, 0xFFFFFF); public void removed() {
ShaderTypeList.ShaderTypeEntry selectedShader = shaderTypeList.getSelected();
//TODO save and remove
}
yy += 50; public enum ShaderType {
font.drawString("Shader speed", left, yy + 5, 0xFFFFFF); DISSOLVE_BLUE("Dissolve Blue"),
DISSOLVE_ORANGE("Dissolve Orange");
super.render(mouseX, mouseY, partialTicks); public Component name;
if (showShaderList) ShaderType(Component name) {
this.shaderTypeList.render(mouseX, mouseY, partialTicks); this.name = name;
} }
@Override ShaderType(String name) {
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { this.name = Component.literal(name);
super.mouseClicked(mouseX, mouseY, mouseButton); }
if (showShaderList) { }
if (!shaderTypeList.isMouseOver(mouseX, mouseY) && !shaderTypeButton.isMouseOver(mouseX, mouseY))
showShaderList = false;
}
return true;
}
@Override //Inspired by LanguageScreen
public void removed() { @OnlyIn(Dist.CLIENT)
ShaderTypeList.ShaderTypeEntry selectedShader = shaderTypeList.getSelected(); class ShaderTypeList extends ObjectSelectionList<PlayerSettingsGui.ShaderTypeList.ShaderTypeEntry> {
//TODO save
}
//Inspired by LanguageScreen public ShaderTypeList(Minecraft mcIn) {
@OnlyIn(Dist.CLIENT) super(mcIn, 180, 140, top + 20, top + 100, 18);
class ShaderTypeList extends ExtendedList<PlayerSettingsGui.ShaderTypeList.ShaderTypeEntry> { this.setLeftPos(right - width);
public ShaderTypeList(Minecraft mcIn) { for (int i = 0; i < 40; i++) {
super(mcIn, 180, 140, top + 20, top + 100, 18);
this.setLeftPos(right - width);
for (int i = 0; i < 40; i++) { for (ShaderType shaderType : ShaderType.values()) {
ShaderTypeEntry shaderTypeEntry = new ShaderTypeEntry(shaderType);
addEntry(shaderTypeEntry);
//TODO setSelected to this if appropriate
}
for (ShaderType shaderType : ShaderType.values()) { }
ShaderTypeEntry shaderTypeEntry = new ShaderTypeEntry(shaderType);
addEntry(shaderTypeEntry);
//TODO setSelected to this if appropriate
}
} if (this.getSelected() != null) {
this.centerScrollOn(this.getSelected());
}
}
if (this.getSelected() != null) { @Override
this.centerScrollOn(this.getSelected()); public int getRowWidth() {
} return width;
} }
@Override @Override
public int getRowWidth() { public void setSelected(PlayerSettingsGui.ShaderTypeList.ShaderTypeEntry selected) {
return width; super.setSelected(selected);
} Minecraft.getInstance().getSoundManager().play(SimpleSoundInstance.forUI(SoundEvents.UI_BUTTON_CLICK, 1.0F));
EffortlessBuilding.log("Selected shader " + selected.shaderType.name);
@Override shaderTypeButton.setMessage(selected.shaderType.name);
public void setSelected(PlayerSettingsGui.ShaderTypeList.ShaderTypeEntry selected) {
super.setSelected(selected);
Minecraft.getInstance().getSoundHandler().play(SimpleSound.master(SoundEvents.UI_BUTTON_CLICK, 1.0F));
EffortlessBuilding.log("Selected shader " + selected.shaderType.name);
shaderTypeButton.setMessage(selected.shaderType.name);
// showShaderList = false; // showShaderList = false;
} }
@Override @Override
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) { public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
if (!showShaderList) return false; if (!showShaderList) return false;
return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_); return super.mouseClicked(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
} }
@Override @Override
public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) { public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) {
if (!showShaderList) return false; if (!showShaderList) return false;
return super.mouseReleased(p_mouseReleased_1_, p_mouseReleased_3_, p_mouseReleased_5_); return super.mouseReleased(p_mouseReleased_1_, p_mouseReleased_3_, p_mouseReleased_5_);
} }
@Override @Override
public boolean mouseDragged(double p_mouseDragged_1_, double p_mouseDragged_3_, int p_mouseDragged_5_, double p_mouseDragged_6_, double p_mouseDragged_8_) { public boolean mouseDragged(double p_mouseDragged_1_, double p_mouseDragged_3_, int p_mouseDragged_5_, double p_mouseDragged_6_, double p_mouseDragged_8_) {
if (!showShaderList) return false; if (!showShaderList) return false;
return super.mouseDragged(p_mouseDragged_1_, p_mouseDragged_3_, p_mouseDragged_5_, p_mouseDragged_6_, p_mouseDragged_8_); return super.mouseDragged(p_mouseDragged_1_, p_mouseDragged_3_, p_mouseDragged_5_, p_mouseDragged_6_, p_mouseDragged_8_);
} }
@Override @Override
public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) { public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) {
if (!showShaderList) return false; if (!showShaderList) return false;
return super.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_); return super.mouseScrolled(p_mouseScrolled_1_, p_mouseScrolled_3_, p_mouseScrolled_5_);
} }
@Override @Override
public boolean isMouseOver(double p_isMouseOver_1_, double p_isMouseOver_3_) { public boolean isMouseOver(double p_isMouseOver_1_, double p_isMouseOver_3_) {
if (!showShaderList) return false; if (!showShaderList) return false;
return super.isMouseOver(p_isMouseOver_1_, p_isMouseOver_3_); return super.isMouseOver(p_isMouseOver_1_, p_isMouseOver_3_);
} }
protected boolean isFocused() { protected boolean isFocused() {
return PlayerSettingsGui.this.getFocused() == this; return PlayerSettingsGui.this.getFocused() == this;
} }
@Override @Override
protected int getScrollbarPosition() { protected int getScrollbarPosition() {
return right - 6; return right - 6;
} }
@OnlyIn(Dist.CLIENT) //From AbstractSelectionList, disabled parts
public class ShaderTypeEntry extends ExtendedList.AbstractListEntry<ShaderTypeEntry> { @Override
private final ShaderType shaderType; public void render(PoseStack ms, int p_render_1_, int p_render_2_, float p_render_3_) {
this.renderBackground(ms);
public ShaderTypeEntry(ShaderType shaderType) { int i = this.getScrollbarPosition();
this.shaderType = shaderType; int j = i + 6;
} Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
public void render(int itemIndex, int rowTop, int rowLeft, int rowWidth, int rowHeight, int mouseX, int mouseY, boolean hovered, float partialTicks) {
if (rowTop + 10 > ShaderTypeList.this.y0 && rowTop + rowHeight - 5 < ShaderTypeList.this.y1)
drawString(font, shaderType.name, ShaderTypeList.this.x0 + 8, rowTop + 4, 0xFFFFFF);
}
@Override
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
if (p_mouseClicked_5_ == 0) {
setSelected(this);
return true;
} else {
return false;
}
}
}
//From AbstractList, disabled parts
public void render(int p_render_1_, int p_render_2_, float p_render_3_) {
this.renderBackground();
int i = this.getScrollbarPosition();
int j = i + 6;
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer();
// this.minecraft.getTextureManager().bindTexture(AbstractGui.BACKGROUND_LOCATION); // this.minecraft.getTextureManager().bindTexture(AbstractGui.BACKGROUND_LOCATION);
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F); RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
float f = 32.0F; float f = 32.0F;
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
bufferbuilder.pos((double)this.x0, (double)this.y1, 0.0D).color(20, 20, 20, 180).endVertex(); bufferbuilder.vertex(this.x0, this.y1, 0.0D).color(20, 20, 20, 180).endVertex();
bufferbuilder.pos((double)this.x1, (double)this.y1, 0.0D).color(20, 20, 20, 180).endVertex(); bufferbuilder.vertex(this.x1, this.y1, 0.0D).color(20, 20, 20, 180).endVertex();
bufferbuilder.pos((double)this.x1, (double)this.y0, 0.0D).color(20, 20, 20, 180).endVertex(); bufferbuilder.vertex(this.x1, this.y0, 0.0D).color(20, 20, 20, 180).endVertex();
bufferbuilder.pos((double)this.x0, (double)this.y0, 0.0D).color(20, 20, 20, 180).endVertex(); bufferbuilder.vertex(this.x0, this.y0, 0.0D).color(20, 20, 20, 180).endVertex();
tessellator.draw(); tessellator.end();
int k = this.getRowLeft(); int k = this.getRowLeft();
int l = this.y0 + 4 - (int)this.getScrollAmount(); int l = this.y0 + 4 - (int) this.getScrollAmount();
if (this.renderHeader) { if (this.renderHeader) {
this.renderHeader(k, l, tessellator); this.renderHeader(ms, k, l, tessellator);
} }
this.renderList(k, l, p_render_1_, p_render_2_, p_render_3_); this.renderList(ms, p_render_1_, p_render_2_, p_render_3_);
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
// this.renderHoleBackground(0, this.y0, 255, 255); // this.renderHoleBackground(0, this.y0, 255, 255);
// this.renderHoleBackground(this.y1, this.height, 255, 255); // this.renderHoleBackground(this.y1, this.height, 255, 255);
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
RenderSystem.disableAlphaTest(); RenderSystem.disableTexture();
RenderSystem.shadeModel(7425);
RenderSystem.disableTexture();
// int i1 = 4; // int i1 = 4;
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); // bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.x0, (double)(this.y0 + 4), 0.0D).tex(0.0F, 1.0F).color(0, 0, 0, 0).endVertex(); // bufferbuilder.pos((double)this.x0, (double)(this.y0 + 4), 0.0D).tex(0.0F, 1.0F).color(0, 0, 0, 0).endVertex();
@@ -260,45 +233,73 @@ public class PlayerSettingsGui extends Screen {
// bufferbuilder.pos((double)this.x0, (double)(this.y1 - 4), 0.0D).tex(0.0F, 0.0F).color(0, 0, 0, 0).endVertex(); // bufferbuilder.pos((double)this.x0, (double)(this.y1 - 4), 0.0D).tex(0.0F, 0.0F).color(0, 0, 0, 0).endVertex();
// tessellator.draw(); // tessellator.draw();
//SCROLLBAR //SCROLLBAR
int j1 = this.getMaxScroll(); int j1 = this.getMaxScroll();
if (j1 > 0) { if (j1 > 0) {
int k1 = (int)((float)((this.y1 - this.y0) * (this.y1 - this.y0)) / (float)this.getMaxPosition()); int k1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition());
k1 = MathHelper.clamp(k1, 32, this.y1 - this.y0 - 8); k1 = Mth.clamp(k1, 32, this.y1 - this.y0 - 8);
int l1 = (int)this.getScrollAmount() * (this.y1 - this.y0 - k1) / j1 + this.y0; int l1 = (int) this.getScrollAmount() * (this.y1 - this.y0 - k1) / j1 + this.y0;
if (l1 < this.y0) { if (l1 < this.y0) {
l1 = this.y0; l1 = this.y0;
} }
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.pos((double)i, (double)this.y1, 0.0D).tex(0.0F, 1.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(i, this.y1, 0.0D).uv(0.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)j, (double)this.y1, 0.0D).tex(1.0F, 1.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(j, this.y1, 0.0D).uv(1.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)j, (double)this.y0, 0.0D).tex(1.0F, 0.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(j, this.y0, 0.0D).uv(1.0F, 0.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double)i, (double)this.y0, 0.0D).tex(0.0F, 0.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(i, this.y0, 0.0D).uv(0.0F, 0.0F).color(0, 0, 0, 255).endVertex();
tessellator.draw(); tessellator.end();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.pos((double)i, (double)(l1 + k1), 0.0D).tex(0.0F, 1.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(i, l1 + k1, 0.0D).uv(0.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)j, (double)(l1 + k1), 0.0D).tex(1.0F, 1.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(j, l1 + k1, 0.0D).uv(1.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)j, (double)l1, 0.0D).tex(1.0F, 0.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(j, l1, 0.0D).uv(1.0F, 0.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double)i, (double)l1, 0.0D).tex(0.0F, 0.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(i, l1, 0.0D).uv(0.0F, 0.0F).color(128, 128, 128, 255).endVertex();
tessellator.draw(); tessellator.end();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.pos((double)i, (double)(l1 + k1 - 1), 0.0D).tex(0.0F, 1.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(i, l1 + k1 - 1, 0.0D).uv(0.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)(j - 1), (double)(l1 + k1 - 1), 0.0D).tex(1.0F, 1.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(j - 1, l1 + k1 - 1, 0.0D).uv(1.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)(j - 1), (double)l1, 0.0D).tex(1.0F, 0.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(j - 1, l1, 0.0D).uv(1.0F, 0.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double)i, (double)l1, 0.0D).tex(0.0F, 0.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(i, l1, 0.0D).uv(0.0F, 0.0F).color(192, 192, 192, 255).endVertex();
tessellator.draw(); tessellator.end();
} }
// this.renderDecorations(p_render_1_, p_render_2_); // this.renderDecorations(p_render_1_, p_render_2_);
RenderSystem.enableTexture(); RenderSystem.enableTexture();
RenderSystem.shadeModel(7424); RenderSystem.disableBlend();
RenderSystem.enableAlphaTest(); }
RenderSystem.disableBlend();
}
private int getMaxScroll() { public int getMaxScroll() {
return Math.max(0, this.getMaxPosition() - (this.y1 - this.y0 - 4)); return Math.max(0, this.getMaxPosition() - (this.y1 - this.y0 - 4));
} }
}
@OnlyIn(Dist.CLIENT)
public class ShaderTypeEntry extends ObjectSelectionList.Entry<ShaderTypeEntry> {
private final ShaderType shaderType;
public ShaderTypeEntry(ShaderType shaderType) {
this.shaderType = shaderType;
}
@Override
public void render(PoseStack ms, int itemIndex, int rowTop, int rowLeft, int rowWidth, int rowHeight, int mouseX, int mouseY, boolean hovered, float partialTicks) {
if (rowTop + 10 > ShaderTypeList.this.y0 && rowTop + rowHeight - 5 < ShaderTypeList.this.y1)
drawString(ms, font, shaderType.name, ShaderTypeList.this.x0 + 8, rowTop + 4, 0xFFFFFF);
}
@Override
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
if (p_mouseClicked_5_ == 0) {
setSelected(this);
return true;
} else {
return false;
}
}
@Override
public Component getNarration() {
return null;
}
}
}
} }

View File

@@ -1,492 +1,524 @@
package nl.requios.effortlessbuilding.gui.buildmode; package nl.requios.effortlessbuilding.gui.buildmode;
import java.util.ArrayList; import com.mojang.blaze3d.vertex.*;
import java.util.concurrent.TimeUnit;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.screen.Screen; import com.mojang.math.Vector4f;
import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.resources.I18n; import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.util.Direction; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.util.text.ITextComponent; import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.util.text.TextFormatting; import net.minecraft.client.resources.language.I18n;
import net.minecraft.util.text.TranslationTextComponent; import net.minecraft.client.KeyMapping;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.core.Direction;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.ModClientEventHandler; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.ModEventHandler;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.network.ModeActionMessage;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.commons.lang3.text.WordUtils; import org.apache.commons.lang3.text.WordUtils;
import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL11;
import com.google.common.base.Stopwatch; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import static nl.requios.effortlessbuilding.buildmode.BuildModes.*;
import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*; import static nl.requios.effortlessbuilding.buildmode.ModeOptions.*;
import nl.requios.effortlessbuilding.buildmode.BuildModes.BuildModeEnum;
import nl.requios.effortlessbuilding.buildmode.ModeOptions.ActionEnum;
import nl.requios.effortlessbuilding.buildmode.ModeOptions.OptionEnum;
/** /**
* From Chisels and Bits by AlgorithmX2 * Initially from Chisels and Bits by AlgorithmX2
* https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/client/gui/ChiselsAndBitsMenu.java * https://github.com/AlgorithmX2/Chisels-and-Bits/blob/1.12/src/main/java/mod/chiselsandbits/client/gui/ChiselsAndBitsMenu.java
*/ */
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class RadialMenu extends Screen { public class RadialMenu extends Screen {
private final float TIME_SCALE = 0.01f; public static final RadialMenu instance = new RadialMenu();
public static final RadialMenu instance = new RadialMenu();
private float visibility = 0.0f; private final Vector4f radialButtonColor = new Vector4f(0f, 0f, 0f, .5f);
private Stopwatch lastChange = Stopwatch.createStarted(); private final Vector4f sideButtonColor = new Vector4f(.5f, .5f, .5f, .5f);
public BuildModeEnum switchTo = null; private final Vector4f highlightColor = new Vector4f(.6f, .8f, 1f, .6f);
public ActionEnum doAction = null; private final Vector4f selectedColor = new Vector4f(0f, .5f, 1f, .5f);
public boolean actionUsed = false; private final Vector4f highlightSelectedColor = new Vector4f(0.2f, .7f, 1f, .7f);
public RadialMenu() { private final int whiteTextColor = 0xffffffff;
super(new TranslationTextComponent("effortlessbuilding.screen.radial_menu")); private final int watermarkTextColor = 0x88888888;
} private final int descriptionTextColor = 0xdd888888;
private final int optionTextColor = 0xeeeeeeff;
private float clampVis(final float f) {
return Math.max( 0.0f, Math.min( 1.0f, f ) ); private final double ringInnerEdge = 30;
} private final double ringOuterEdge = 65;
private final double categoryLineWidth = 1;
public void raiseVisibility() { private final double textDistance = 75;
visibility = clampVis( visibility + lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE ); private final double buttonDistance = 105;
lastChange = Stopwatch.createStarted(); private final float fadeSpeed = 0.3f;
} private final int descriptionHeight = 100;
public void decreaseVisibility() { public BuildModeEnum switchTo = null;
visibility = clampVis( visibility - lastChange.elapsed( TimeUnit.MILLISECONDS ) * TIME_SCALE ); public ActionEnum doAction = null;
lastChange = Stopwatch.createStarted(); public boolean performedActionUsingMouse;
}
private float visibility;
public void setVisibility(float visibility) {
this.visibility = visibility; public RadialMenu() {
} super(Component.translatable("effortlessbuilding.screen.radial_menu"));
}
public boolean isVisible() {
return visibility > 0.001; public boolean isVisible() {
} return Minecraft.getInstance().screen instanceof RadialMenu;
}
public void configure(final int scaledWidth, final int scaledHeight ) {
Minecraft mc = Minecraft.getInstance(); @Override
font = mc.fontRenderer; protected void init() {
width = scaledWidth; super.init();
height = scaledHeight; performedActionUsingMouse = false;
} visibility = 0f;
}
private static class MenuButton {
@Override
public double x1, x2; public void tick() {
public double y1, y2; super.tick();
public boolean highlighted;
if (!ClientProxy.isKeybindDown(2)) {
public final ActionEnum action; onClose();
public String name; }
public Direction textSide; }
public MenuButton(final String name, final ActionEnum action, final double x, final double y, @Override
final Direction textSide) { public void render(PoseStack ms, final int mouseX, final int mouseY, final float partialTicks) {
this.name = I18n.format(name); BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(minecraft.player).getBuildMode();
this.action = action;
x1 = x - 10; ms.pushPose();
x2 = x + 10; ms.translate(0, 0, 200);
y1 = y - 10;
y2 = y + 10; visibility += fadeSpeed * partialTicks;
this.textSide = textSide; if (visibility > 1f) visibility = 1f;
}
final int startColor = (int) (visibility * 98) << 24;
} final int endColor = (int) (visibility * 128) << 24;
static class MenuRegion { fillGradient(ms, 0, 0, width, height, startColor, endColor);
public final BuildModeEnum mode; RenderSystem.disableTexture();
public double x1, x2; RenderSystem.enableBlend();
public double y1, y2; RenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
public boolean highlighted; final Tesselator tessellator = Tesselator.getInstance();
final BufferBuilder buffer = tessellator.getBuilder();
public MenuRegion(final BuildModeEnum mode) {
this.mode = mode; buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_COLOR);
}
final double middleX = width / 2.0;
} final double middleY = height / 2.0;
@Override //Fix for high def (retina) displays: use custom mouse coordinates
public void render(final int mouseX, final int mouseY, final float partialTicks) { //Borrowed from GameRenderer::updateCameraAndRender
if (!isVisible()) return; int mouseXX = (int) (minecraft.mouseHandler.xpos() * (double) minecraft.getWindow().getGuiScaledWidth() / (double) minecraft.getWindow().getScreenWidth());
int mouseYY = (int) (minecraft.mouseHandler.ypos() * (double) minecraft.getWindow().getGuiScaledHeight() / (double) minecraft.getWindow().getScreenHeight());
BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(Minecraft.getInstance().player).getBuildMode();
final double mouseXCenter = mouseXX - middleX;
RenderSystem.pushMatrix(); final double mouseYCenter = mouseYY - middleY;
RenderSystem.translatef( 0.0F, 0.0F, 200.0F ); double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter);
final int startColor = (int) ( visibility * 98 ) << 24; final double quarterCircle = Math.PI / 2.0;
final int endColor = (int) ( visibility * 128 ) << 24;
if (mouseRadians < -quarterCircle) {
fillGradient(0, 0, width, height, startColor, endColor); mouseRadians = mouseRadians + Math.PI * 2;
}
RenderSystem.disableTexture();
RenderSystem.enableBlend(); final ArrayList<MenuRegion> modes = new ArrayList<MenuRegion>();
RenderSystem.disableAlphaTest(); final ArrayList<MenuButton> buttons = new ArrayList<MenuButton>();
RenderSystem.blendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, 1, 0);
RenderSystem.shadeModel(GL11.GL_SMOOTH); //Add build modes
final Tessellator tessellator = Tessellator.getInstance(); for (final BuildModeEnum mode : BuildModeEnum.values()) {
final BufferBuilder buffer = tessellator.getBuffer(); modes.add(new MenuRegion(mode));
}
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_COLOR);
//Add actions
final double middleX = width / 2.0; buttons.add(new MenuButton(ActionEnum.UNDO.name, ActionEnum.UNDO, -buttonDistance - 26, -13, Direction.UP));
final double middleY = height / 2.0; buttons.add(new MenuButton(ActionEnum.REDO.name, ActionEnum.REDO, -buttonDistance, -13, Direction.UP));
// buttons.add(new MenuButton(ActionEnum.OPEN_PLAYER_SETTINGS.name, ActionEnum.OPEN_PLAYER_SETTINGS, -buttonDistance - 26 - 13, 13, Direction.DOWN));
//Fix for high def (retina) displays: use custom mouse coordinates buttons.add(new MenuButton(ActionEnum.OPEN_MODIFIER_SETTINGS.name, ActionEnum.OPEN_MODIFIER_SETTINGS, -buttonDistance - 26, 13, Direction.DOWN));
//Borrowed from GameRenderer::updateCameraAndRender buttons.add(new MenuButton(ActionEnum.REPLACE.name, ActionEnum.REPLACE, -buttonDistance, 13, Direction.DOWN));
Minecraft mc = Minecraft.getInstance();
int mouseXX = (int)(mc.mouseHelper.getMouseX() * (double)mc.getMainWindow().getScaledWidth() / (double)mc.getMainWindow().getWidth()); //Add buildmode dependent options
int mouseYY = (int)(mc.mouseHelper.getMouseY() * (double)mc.getMainWindow().getScaledHeight() / (double)mc.getMainWindow().getHeight()); OptionEnum[] options = currentBuildMode.options;
for (int i = 0; i < options.length; i++) {
final double mouseXCenter = mouseXX - middleX; for (int j = 0; j < options[i].actions.length; j++) {
final double mouseYCenter = mouseYY - middleY; ActionEnum action = options[i].actions[j];
double mouseRadians = Math.atan2(mouseYCenter, mouseXCenter); buttons.add(new MenuButton(action.name, action, buttonDistance + j * 26, -13 + i * 39, Direction.DOWN));
}
final double ringInnerEdge = 30; }
final double ringOuterEdge = 65;
final double textDistance = 75; switchTo = null;
final double buttonDistance = 105; doAction = null;
final double quarterCircle = Math.PI / 2.0;
//Draw buildmode backgrounds
if ( mouseRadians < -quarterCircle ) { drawRadialButtonBackgrounds(currentBuildMode, buffer, middleX, middleY, mouseXCenter, mouseYCenter, mouseRadians,
mouseRadians = mouseRadians + Math.PI * 2; quarterCircle, modes);
}
//Draw action backgrounds
final ArrayList<MenuRegion> modes = new ArrayList<MenuRegion>(); drawSideButtonBackgrounds(buffer, middleX, middleY, mouseXCenter, mouseYCenter, buttons);
final ArrayList<MenuButton> buttons = new ArrayList<MenuButton>();
tessellator.end();
//Add build modes RenderSystem.disableBlend();
for (final BuildModeEnum mode : BuildModeEnum.values()) { RenderSystem.enableTexture();
modes.add(new MenuRegion(mode));
} drawIcons(ms, middleX, middleY, modes, buttons);
//Add actions drawTexts(ms, currentBuildMode, middleX, middleY, modes, buttons, options);
buttons.add(new MenuButton(ActionEnum.UNDO.name, ActionEnum.UNDO, -buttonDistance - 26, -13, Direction.UP));
buttons.add(new MenuButton(ActionEnum.REDO.name, ActionEnum.REDO, -buttonDistance, -13, Direction.UP)); ms.popPose();
buttons.add(new MenuButton(ActionEnum.OPEN_PLAYER_SETTINGS.name, ActionEnum.OPEN_PLAYER_SETTINGS, -buttonDistance - 26 - 13, 13, Direction.DOWN)); }
buttons.add(new MenuButton(ActionEnum.OPEN_MODIFIER_SETTINGS.name, ActionEnum.OPEN_MODIFIER_SETTINGS, -buttonDistance - 13, 13, Direction.DOWN));
buttons.add(new MenuButton(ActionEnum.REPLACE.name, ActionEnum.REPLACE, -buttonDistance + 13, 13, Direction.DOWN)); private void drawRadialButtonBackgrounds(BuildModeEnum currentBuildMode, BufferBuilder buffer, double middleX, double middleY,
double mouseXCenter, double mouseYCenter, double mouseRadians, double quarterCircle, ArrayList<MenuRegion> modes) {
//Add buildmode dependent options if (!modes.isEmpty()) {
OptionEnum[] options = currentBuildMode.options; final int totalModes = Math.max(3, modes.size());
for (int i = 0; i < options.length; i++) { final double fragment = Math.PI * 0.005; //gap between buttons in radians at inner edge
for (int j = 0; j < options[i].actions.length; j++) { final double fragment2 = Math.PI * 0.0025; //gap between buttons in radians at outer edge
ActionEnum action = options[i].actions[j]; final double radiansPerObject = 2.0 * Math.PI / totalModes;
buttons.add(new MenuButton(action.name, action, buttonDistance + j * 26, -13 + i * 39, Direction.DOWN));
} for (int i = 0; i < modes.size(); i++) {
} MenuRegion menuRegion = modes.get(i);
final double beginRadians = i * radiansPerObject - quarterCircle;
switchTo = null; final double endRadians = (i + 1) * radiansPerObject - quarterCircle;
doAction = null;
menuRegion.x1 = Math.cos(beginRadians);
//Draw buildmode backgrounds menuRegion.x2 = Math.cos(endRadians);
if (!modes.isEmpty()) { menuRegion.y1 = Math.sin(beginRadians);
final int totalModes = Math.max( 3, modes.size() ); menuRegion.y2 = Math.sin(endRadians);
int currentMode = 0;
final double fragment = Math.PI * 0.005; final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge;
final double fragment2 = Math.PI * 0.0025; final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge;
final double perObject = 2.0 * Math.PI / totalModes; final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge;
final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge;
for (int i = 0; i < modes.size(); i++) {
MenuRegion menuRegion = modes.get(i); final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge;
final double beginRadians = currentMode * perObject - quarterCircle; final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge;
final double endRadians = (currentMode + 1) * perObject - quarterCircle; final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge;
final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge;
menuRegion.x1 = Math.cos(beginRadians);
menuRegion.x2 = Math.cos(endRadians); final boolean isSelected = currentBuildMode.ordinal() == i;
menuRegion.y1 = Math.sin(beginRadians); final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter)
menuRegion.y2 = Math.sin(endRadians); || inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter);
final boolean isHighlighted = beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad;
final double x1m1 = Math.cos(beginRadians + fragment) * ringInnerEdge;
final double x2m1 = Math.cos(endRadians - fragment) * ringInnerEdge; Vector4f color = radialButtonColor;
final double y1m1 = Math.sin(beginRadians + fragment) * ringInnerEdge; if (isSelected) color = selectedColor;
final double y2m1 = Math.sin(endRadians - fragment) * ringInnerEdge; if (isHighlighted) color = highlightColor;
if (isSelected && isHighlighted) color = highlightSelectedColor;
final double x1m2 = Math.cos(beginRadians + fragment2) * ringOuterEdge;
final double x2m2 = Math.cos(endRadians - fragment2) * ringOuterEdge; if (isHighlighted) {
final double y1m2 = Math.sin(beginRadians + fragment2) * ringOuterEdge; menuRegion.highlighted = true;
final double y2m2 = Math.sin(endRadians - fragment2) * ringOuterEdge; switchTo = menuRegion.mode;
}
float r = 0.0f;
float g = 0.0f; buffer.vertex(middleX + x1m1, middleY + y1m1, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
float b = 0.0f; buffer.vertex(middleX + x2m1, middleY + y2m1, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
float a = 0.5f; buffer.vertex(middleX + x2m2, middleY + y2m2, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
buffer.vertex(middleX + x1m2, middleY + y1m2, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
//check if current mode
int buildMode = currentBuildMode.ordinal(); //Category line
if (buildMode == i) { color = menuRegion.mode.category.color;
r = 0f; final double categoryLineOuterEdge = ringInnerEdge + categoryLineWidth;
g = 0.5f;
b = 1f; final double x1m3 = Math.cos(beginRadians + fragment) * categoryLineOuterEdge;
a = 0.5f; final double x2m3 = Math.cos(endRadians - fragment) * categoryLineOuterEdge;
//menuRegion.highlighted = true; //draw text final double y1m3 = Math.sin(beginRadians + fragment) * categoryLineOuterEdge;
} final double y2m3 = Math.sin(endRadians - fragment) * categoryLineOuterEdge;
//check if mouse is over this region buffer.vertex(middleX + x1m1, middleY + y1m1, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
final boolean isMouseInQuad = inTriangle(x1m1, y1m1, x2m2, y2m2, x2m1, y2m1, mouseXCenter, mouseYCenter) buffer.vertex(middleX + x2m1, middleY + y2m1, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
|| inTriangle(x1m1, y1m1, x1m2, y1m2, x2m2, y2m2, mouseXCenter, mouseYCenter); buffer.vertex(middleX + x2m3, middleY + y2m3, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
buffer.vertex(middleX + x1m3, middleY + y1m3, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
if (beginRadians <= mouseRadians && mouseRadians <= endRadians && isMouseInQuad) { }
r = 0.6f; }
g = 0.8f; }
b = 1f;
a = 0.6f; private void drawSideButtonBackgrounds(BufferBuilder buffer, double middleX, double middleY, double mouseXCenter, double mouseYCenter, ArrayList<MenuButton> buttons) {
menuRegion.highlighted = true; for (final MenuButton btn : buttons) {
switchTo = menuRegion.mode;
} final boolean isSelected =
btn.action == getBuildSpeed() ||
buffer.pos(middleX + x1m1, middleY + y1m1, getBlitOffset()).color(r, g, b, a).endVertex(); btn.action == getFill() ||
buffer.pos(middleX + x2m1, middleY + y2m1, getBlitOffset()).color(r, g, b, a).endVertex(); btn.action == getCubeFill() ||
buffer.pos(middleX + x2m2, middleY + y2m2, getBlitOffset()).color(r, g, b, a).endVertex(); btn.action == getRaisedEdge() ||
buffer.pos(middleX + x1m2, middleY + y1m2, getBlitOffset()).color(r, g, b, a).endVertex(); btn.action == getLineThickness() ||
btn.action == getCircleStart();
currentMode++;
} final boolean isHighlighted = btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter;
}
Vector4f color = sideButtonColor;
//Draw action backgrounds if (isSelected) color = selectedColor;
for (final MenuButton btn : buttons) { if (isHighlighted) color = highlightColor;
float r = 0.5f; if (isSelected && isHighlighted) color = highlightSelectedColor;
float g = 0.5f;
float b = 0.5f; if (isHighlighted) {
float a = 0.5f; btn.highlighted = true;
doAction = btn.action;
//highlight when active option }
if (btn.action == getBuildSpeed() ||
btn.action == getFill() || buffer.vertex(middleX + btn.x1, middleY + btn.y1, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
btn.action == getCubeFill() || buffer.vertex(middleX + btn.x1, middleY + btn.y2, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
btn.action == getRaisedEdge() || buffer.vertex(middleX + btn.x2, middleY + btn.y2, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
btn.action == getLineThickness() || buffer.vertex(middleX + btn.x2, middleY + btn.y1, getBlitOffset()).color(color.x(), color.y(), color.z(), color.w()).endVertex();
btn.action == getCircleStart()) { }
r = 0.0f; }
g = 0.5f;
b = 1f; private void drawIcons(PoseStack ms, double middleX, double middleY,
a = 0.6f; ArrayList<MenuRegion> modes, ArrayList<MenuButton> buttons) {
} ms.pushPose();
RenderSystem.enableTexture();
//highlight when mouse over RenderSystem.setShader(GameRenderer::getPositionColorTexShader);
if (btn.x1 <= mouseXCenter && btn.x2 >= mouseXCenter && btn.y1 <= mouseYCenter && btn.y2 >= mouseYCenter) { RenderSystem.setShaderColor(1f, 1f, 1f, 1f);
r = 0.6f;
g = 0.8f; //Draw buildmode icons
b = 1f; for (final MenuRegion menuRegion : modes) {
a = 0.6f;
btn.highlighted = true; final double x = (menuRegion.x1 + menuRegion.x2) * 0.5 * (ringOuterEdge * 0.55 + 0.45 * ringInnerEdge);
doAction = btn.action; final double y = (menuRegion.y1 + menuRegion.y2) * 0.5 * (ringOuterEdge * 0.55 + 0.45 * ringInnerEdge);
}
RenderSystem.setShaderTexture(0, new ResourceLocation(EffortlessBuilding.MODID, "textures/icons/" + menuRegion.mode.getName() + ".png"));
buffer.pos(middleX + btn.x1, middleY + btn.y1, getBlitOffset()).color(r, g, b, a).endVertex(); blit(ms, (int) (middleX + x - 8), (int) (middleY + y - 8), 16, 16, 0, 0, 18, 18, 18, 18);
buffer.pos(middleX + btn.x1, middleY + btn.y2, getBlitOffset()).color(r, g, b, a).endVertex(); }
buffer.pos(middleX + btn.x2, middleY + btn.y2, getBlitOffset()).color(r, g, b, a).endVertex();
buffer.pos(middleX + btn.x2, middleY + btn.y1, getBlitOffset()).color(r, g, b, a).endVertex(); //Draw action icons
} for (final MenuButton button : buttons) {
tessellator.draw(); final double x = (button.x1 + button.x2) / 2 + 0.01;
final double y = (button.y1 + button.y2) / 2 + 0.01;
RenderSystem.shadeModel(GL11.GL_FLAT);
RenderSystem.setShaderTexture(0, new ResourceLocation(EffortlessBuilding.MODID, "textures/icons/" + button.action.name().toLowerCase() + ".png"));
RenderSystem.translatef(0f, 0f, 5f); blit(ms, (int) (middleX + x - 8), (int) (middleY + y - 8), 16, 16, 0, 0, 18, 18, 18, 18);
RenderSystem.enableTexture(); }
RenderSystem.color3f(1f, 1f, 1f);
RenderSystem.disableBlend(); ms.popPose();
RenderSystem.enableAlphaTest(); }
mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);
private void drawTexts(PoseStack ms, BuildModeEnum currentBuildMode, double middleX, double middleY, ArrayList<MenuRegion> modes, ArrayList<MenuButton> buttons, OptionEnum[] options) {
buffer.begin(GL11.GL_QUADS, DefaultVertexFormats.POSITION_TEX_COLOR); //font.drawStringWithShadow("Actions", (int) (middleX - buttonDistance - 13) - font.getStringWidth("Actions") * 0.5f, (int) middleY - 38, 0xffffffff);
//Draw buildmode icons //Draw option strings
for (final MenuRegion menuRegion : modes) { for (int i = 0; i < currentBuildMode.options.length; i++) {
OptionEnum option = options[i];
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge); font.drawShadow(ms, I18n.get(option.name), (int) (middleX + buttonDistance - 9), (int) middleY - 37 + i * 39, optionTextColor);
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5 * (ringOuterEdge * 0.6 + 0.4 * ringInnerEdge); }
final TextureAtlasSprite sprite = ModClientEventHandler.getBuildModeIcon(menuRegion.mode); String credits = "Effortless Building";
font.drawShadow(ms, credits, width - font.width(credits) - 4, height - 10, watermarkTextColor);
final double x1 = x - 8;
final double x2 = x + 8; //Draw buildmode text
final double y1 = y - 8; for (final MenuRegion menuRegion : modes) {
final double y2 = y + 8;
if (menuRegion.highlighted) {
final float f = 1f; final double x = (menuRegion.x1 + menuRegion.x2) * 0.5;
final float a = 1f; final double y = (menuRegion.y1 + menuRegion.y2) * 0.5;
final double u1 = 0; int fixed_x = (int) (x * textDistance);
final double u2 = 16; int fixed_y = (int) (y * textDistance) - font.lineHeight / 2;
final double v1 = 0; String text = I18n.get(menuRegion.mode.getNameKey());
final double v2 = 16;
if (x <= -0.2) {
buffer.pos(middleX + x1, middleY + y1, getBlitOffset()).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex(); fixed_x -= font.width(text);
buffer.pos(middleX + x1, middleY + y2, getBlitOffset()).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex(); } else if (-0.2 <= x && x <= 0.2) {
buffer.pos(middleX + x2, middleY + y2, getBlitOffset()).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex(); fixed_x -= font.width(text) / 2;
buffer.pos(middleX + x2, middleY + y1, getBlitOffset()).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex(); }
}
font.drawShadow(ms, text, (int) middleX + fixed_x, (int) middleY + fixed_y, whiteTextColor);
//Draw action icons
for (final MenuButton button : buttons) { //Draw description
text = I18n.get(menuRegion.mode.getDescriptionKey());
final float f = 1f; font.drawShadow(ms, text, (int) middleX - font.width(text) / 2f, (int) middleY + descriptionHeight, descriptionTextColor);
final float a = 1f; }
}
final double u1 = 0;
final double u2 = 16; //Draw action text
final double v1 = 0; for (final MenuButton button : buttons) {
final double v2 = 16; if (button.highlighted) {
String text = ChatFormatting.AQUA + button.name;
final TextureAtlasSprite sprite = ModClientEventHandler.getModeOptionIcon(button.action);
//Add keybind in brackets
final double btnmiddleX = (button.x1 + button.x2) / 2 + 0.01; String keybind = findKeybind(button, currentBuildMode);
final double btnmiddleY = (button.y1 + button.y2) / 2 + 0.01; String keybindFormatted = "";
final double btnx1 = btnmiddleX - 8; if (!keybind.isEmpty())
final double btnx2 = btnmiddleX + 8; keybindFormatted = ChatFormatting.GRAY + "(" + WordUtils.capitalizeFully(keybind) + ")";
final double btny1 = btnmiddleY - 8;
final double btny2 = btnmiddleY + 8; if (button.textSide == Direction.WEST) {
buffer.pos(middleX + btnx1, middleY + btny1, getBlitOffset()).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex(); font.draw(ms, text, (int) (middleX + button.x1 - 8) - font.width(text),
buffer.pos(middleX + btnx1, middleY + btny2, getBlitOffset()).tex(sprite.getInterpolatedU(u1), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex(); (int) (middleY + button.y1 + 6), whiteTextColor);
buffer.pos(middleX + btnx2, middleY + btny2, getBlitOffset()).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v2)).color(f, f, f, a).endVertex();
buffer.pos(middleX + btnx2, middleY + btny1, getBlitOffset()).tex(sprite.getInterpolatedU(u2), sprite.getInterpolatedV(v1)).color(f, f, f, a).endVertex(); } else if (button.textSide == Direction.EAST) {
}
font.draw(ms, text, (int) (middleX + button.x2 + 8),
tessellator.draw(); (int) (middleY + button.y1 + 6), whiteTextColor);
//Draw strings } else if (button.textSide == Direction.UP || button.textSide == Direction.NORTH) {
//font.drawStringWithShadow("Actions", (int) (middleX - buttonDistance - 13) - font.getStringWidth("Actions") * 0.5f, (int) middleY - 38, 0xffffffff);
font.draw(ms, keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(keybindFormatted) * 0.5),
//Draw option strings (int) (middleY + button.y1 - 26), whiteTextColor);
for (int i = 0; i < currentBuildMode.options.length; i++) {
OptionEnum option = options[i]; font.draw(ms, text, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(text) * 0.5),
font.drawStringWithShadow(I18n.format(option.name), (int) (middleX + buttonDistance - 9), (int) middleY - 37 + i * 39, 0xeeeeeeff); (int) (middleY + button.y1 - 14), whiteTextColor);
}
} else if (button.textSide == Direction.DOWN || button.textSide == Direction.SOUTH) {
String credits = "Effortless Building";
font.drawStringWithShadow(credits, width - font.getStringWidth(credits) - 4, height - 10, 0x88888888); font.draw(ms, text, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(text) * 0.5),
(int) (middleY + button.y1 + 26), whiteTextColor);
//Draw buildmode text
for (final MenuRegion menuRegion : modes) { font.draw(ms, keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.width(keybindFormatted) * 0.5),
(int) (middleY + button.y1 + 38), whiteTextColor);
if (menuRegion.highlighted) {
final double x = (menuRegion.x1 + menuRegion.x2) * 0.5; }
final double y = (menuRegion.y1 + menuRegion.y2) * 0.5;
}
int fixed_x = (int) (x * textDistance); }
final int fixed_y = (int) (y * textDistance) - font.FONT_HEIGHT / 2; }
final String text = I18n.format(menuRegion.mode.name);
private String findKeybind(MenuButton button, BuildModeEnum currentBuildMode){
if ( x <= -0.2 ) { String result = "";
fixed_x -= font.getStringWidth(text); int keybindingIndex = -1;
} else if ( -0.2 <= x && x <= 0.2 ) { if (button.action == ActionEnum.UNDO) keybindingIndex = 3;
fixed_x -= font.getStringWidth(text) / 2; if (button.action == ActionEnum.REDO) keybindingIndex = 4;
} if (button.action == ActionEnum.REPLACE) keybindingIndex = 1;
if (button.action == ActionEnum.OPEN_MODIFIER_SETTINGS) keybindingIndex = 0;
font.drawStringWithShadow(text, (int) middleX + fixed_x, (int) middleY + fixed_y, 0xffffffff);
} if (keybindingIndex != -1) {
} KeyMapping keyMap = ClientProxy.keyBindings[keybindingIndex];
//Draw action text if (!keyMap.getKeyModifier().name().equals("none")) {
for (final MenuButton button : buttons) { result = keyMap.getKeyModifier().name() + " ";
if (button.highlighted) { }
String text = TextFormatting.AQUA + button.name; result += I18n.get(keyMap.getKey().getName());
int wrap = 120; }
String keybind = "";
String keybindFormatted = ""; if (currentBuildMode.options.length > 0) {
//Add (ctrl) to first two actions of first option
//Add keybind in brackets if (button.action == currentBuildMode.options[0].actions[0]
if (button.action == ActionEnum.UNDO) { || button.action == currentBuildMode.options[0].actions[1]) {
keybind = ClientProxy.keyBindings[4].getLocalizedName(); result = I18n.get(ClientProxy.keyBindings[5].getKey().getName());
} if (result.equals("Left Control")) result = "Ctrl";
if (button.action == ActionEnum.REDO) { }
keybind = ClientProxy.keyBindings[5].getLocalizedName(); }
} return result;
if (button.action == ActionEnum.REPLACE) { }
keybind = ClientProxy.keyBindings[1].getLocalizedName();
} private boolean inTriangle(final double x1, final double y1, final double x2, final double y2,
if (button.action == ActionEnum.OPEN_MODIFIER_SETTINGS) { final double x3, final double y3, final double x, final double y) {
keybind = ClientProxy.keyBindings[0].getLocalizedName(); final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y);
} final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y);
if (currentBuildMode.options.length > 0) { final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y);
//Add (ctrl) to first two actions of first option return sign(ab) == sign(bc) && sign(bc) == sign(ca);
if (button.action == currentBuildMode.options[0].actions[0] }
|| button.action == currentBuildMode.options[0].actions[1]) {
keybind = ClientProxy.keyBindings[6].getLocalizedName(); private int sign(final double n) {
if (keybind.equals("Left Control")) keybind = "Ctrl"; return n > 0 ? 1 : -1;
} }
}
if (!keybind.isEmpty()) keybindFormatted = TextFormatting.GRAY + "(" + WordUtils.capitalizeFully(keybind) + ")"; @Override
public boolean isPauseScreen() {
if (button.textSide == Direction.WEST) { return false;
}
font.drawSplitString( text, (int) (middleX + button.x1 - 8 ) - font.getStringWidth(text),
(int) (middleY + button.y1 + 6), wrap, 0xffffffff); @Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
} else if (button.textSide == Direction.EAST) { performAction(true);
font.drawSplitString(text, (int) (middleX + button.x2 + 8), return super.mouseClicked(mouseX, mouseY, mouseButton);
(int) (middleY + button.y1 + 6 ), wrap, 0xffffffff); }
} else if (button.textSide == Direction.UP || button.textSide == Direction.NORTH) { @Override
public void onClose() {
font.drawSplitString( keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.getStringWidth(keybindFormatted) * 0.5), super.onClose();
(int) (middleY + button.y1 - 26), wrap,0xffffffff); //After onClose so it can open another screen
if (!performedActionUsingMouse) performAction(false);
font.drawSplitString( text, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.getStringWidth(text) * 0.5), }
(int) (middleY + button.y1 - 14), wrap,0xffffffff);
private void performAction(boolean fromMouseClick) {
} else if (button.textSide == Direction.DOWN || button.textSide == Direction.SOUTH) { LocalPlayer player = Minecraft.getInstance().player;
font.drawSplitString(text, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.getStringWidth(text) * 0.5), ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
(int) (middleY + button.y1 + 26), wrap, 0xffffffff);
if (switchTo != null) {
font.drawSplitString(keybindFormatted, (int) (middleX + (button.x1 + button.x2) * 0.5 - font.getStringWidth(keybindFormatted) * 0.5), playRadialMenuSound();
(int) (middleY + button.y1 + 38), wrap, 0xffffffff);
modeSettings.setBuildMode(switchTo);
} ModeSettingsManager.setModeSettings(player, modeSettings);
PacketHandler.INSTANCE.sendToServer(new ModeSettingsMessage(modeSettings));
}
} EffortlessBuilding.log(player, I18n.get(modeSettings.getBuildMode().getNameKey()), true);
RenderSystem.popMatrix(); if (fromMouseClick) performedActionUsingMouse = true;
} }
private boolean inTriangle(final double x1, final double y1, final double x2, final double y2, //Perform button action
final double x3, final double y3, final double x, final double y ) { ModeOptions.ActionEnum action = doAction;
final double ab = (x1 - x) * (y2 - y) - (x2 - x) * (y1 - y); if (action != null) {
final double bc = (x2 - x) * (y3 - y) - (x3 - x) * (y2 - y); playRadialMenuSound();
final double ca = (x3 - x) * (y1 - y) - (x1 - x) * (y3 - y);
return sign(ab) == sign(bc) && sign(bc) == sign(ca); ModeOptions.performAction(player, action);
} PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
private int sign(final double n) { if (fromMouseClick) performedActionUsingMouse = true;
return n > 0 ? 1 : -1; }
} }
/** public static void playRadialMenuSound() {
* Called when the mouse is clicked. Args : mouseX, mouseY, clickedButton final float volume = 0.1f;
*/ if (volume >= 0.0001f) {
@Override SimpleSoundInstance sound = new SimpleSoundInstance(SoundEvents.UI_BUTTON_CLICK, SoundSource.MASTER, volume,
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { 1.0f, RandomSource.create(), Minecraft.getInstance().player.blockPosition());
EffortlessBuilding.log("mouse clicked"); Minecraft.getInstance().getSoundManager().play(sound);
}
KeyBinding.updateKeyBindState(); }
KeyBinding.setKeyBindState(ClientProxy.keyBindings[3].getKey(), true);
private static class MenuButton {
if (mouseButton == 0) {
this.minecraft.displayGuiScreen(null); public final ActionEnum action;
public double x1, x2;
if (this.minecraft.currentScreen == null) { public double y1, y2;
this.minecraft.setGameFocused(true); public boolean highlighted;
} public String name;
} public Direction textSide;
return super.mouseClicked(mouseX, mouseY, mouseButton);
} public MenuButton(final String name, final ActionEnum action, final double x, final double y,
final Direction textSide) {
this.name = I18n.get(name);
this.action = action;
x1 = x - 10;
x2 = x + 10;
y1 = y - 10;
y2 = y + 10;
this.textSide = textSide;
}
}
static class MenuRegion {
public final BuildModeEnum mode;
public double x1, x2;
public double y1, y2;
public boolean highlighted;
public MenuRegion(final BuildModeEnum mode) {
this.mode = mode;
}
}
} }

View File

@@ -1,10 +1,11 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.screen.Screen; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.text.TextFormatting; import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
@@ -22,181 +23,179 @@ import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ArraySettingsGui extends GuiCollapsibleScrollEntry { public class ArraySettingsGui extends GuiCollapsibleScrollEntry {
protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>(); protected List<GuiNumberField> arrayNumberFieldList = new ArrayList<>();
private GuiCheckBoxFixed buttonArrayEnabled; private GuiCheckBoxFixed buttonArrayEnabled;
private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount; private GuiNumberField textArrayOffsetX, textArrayOffsetY, textArrayOffsetZ, textArrayCount;
public ArraySettingsGui(GuiScrollPane scrollPane) { public ArraySettingsGui(GuiScrollPane scrollPane) {
super(scrollPane); super(scrollPane);
} }
@Override @Override
public void init(List<Widget> buttons) { public void init(List<Widget> renderables) {
super.init(buttons); super.init(renderables);
int y = top; int y = top;
buttonArrayEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) { buttonArrayEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) {
@Override @Override
public void onClick(double mouseX, double mouseY) { public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY); super.onClick(mouseX, mouseY);
setCollapsed(!buttonArrayEnabled.isChecked()); setCollapsed(!buttonArrayEnabled.isChecked());
} }
}; };
buttons.add(buttonArrayEnabled); renderables.add(buttonArrayEnabled);
y = top + 20; y = top + 20;
textArrayOffsetX = new GuiNumberField(font, buttons, left + 70, y, 50, 18); textArrayOffsetX = new GuiNumberField(font, renderables, left + 70, y, 50, 18);
textArrayOffsetX.setNumber(0); textArrayOffsetX.setNumber(0);
textArrayOffsetX.setTooltip("How much each copy is shifted."); textArrayOffsetX.setTooltip(Component.literal("How much each copy is shifted."));
arrayNumberFieldList.add(textArrayOffsetX); arrayNumberFieldList.add(textArrayOffsetX);
textArrayOffsetY = new GuiNumberField(font, buttons, left + 140, y, 50, 18); textArrayOffsetY = new GuiNumberField(font, renderables, left + 140, y, 50, 18);
textArrayOffsetY.setNumber(0); textArrayOffsetY.setNumber(0);
textArrayOffsetY.setTooltip("How much each copy is shifted."); textArrayOffsetY.setTooltip(Component.literal("How much each copy is shifted."));
arrayNumberFieldList.add(textArrayOffsetY); arrayNumberFieldList.add(textArrayOffsetY);
textArrayOffsetZ = new GuiNumberField(font, buttons, left + 210, y, 50, 18); textArrayOffsetZ = new GuiNumberField(font, renderables, left + 210, y, 50, 18);
textArrayOffsetZ.setNumber(0); textArrayOffsetZ.setNumber(0);
textArrayOffsetZ.setTooltip("How much each copy is shifted."); textArrayOffsetZ.setTooltip(Component.literal("How much each copy is shifted."));
arrayNumberFieldList.add(textArrayOffsetZ); arrayNumberFieldList.add(textArrayOffsetZ);
y = top + 50; y = top + 50;
textArrayCount = new GuiNumberField(font, buttons, left + 55, y, 50, 18); textArrayCount = new GuiNumberField(font, renderables, left + 55, y, 50, 18);
textArrayCount.setNumber(5); textArrayCount.setNumber(5);
textArrayCount.setTooltip("How many copies should be made."); textArrayCount.setTooltip(Component.literal("How many copies should be made."));
arrayNumberFieldList.add(textArrayCount); arrayNumberFieldList.add(textArrayCount);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) { if (modifierSettings != null) {
Array.ArraySettings a = modifierSettings.getArraySettings(); Array.ArraySettings a = modifierSettings.getArraySettings();
buttonArrayEnabled.setIsChecked(a.enabled); buttonArrayEnabled.setIsChecked(a.enabled);
textArrayOffsetX.setNumber(a.offset.getX()); textArrayOffsetX.setNumber(a.offset.getX());
textArrayOffsetY.setNumber(a.offset.getY()); textArrayOffsetY.setNumber(a.offset.getY());
textArrayOffsetZ.setNumber(a.offset.getZ()); textArrayOffsetZ.setNumber(a.offset.getZ());
textArrayCount.setNumber(a.count); textArrayCount.setNumber(a.count);
} }
setCollapsed(!buttonArrayEnabled.isChecked()); setCollapsed(!buttonArrayEnabled.isChecked());
} }
public void updateScreen() { public void updateScreen() {
arrayNumberFieldList.forEach(GuiNumberField::update); arrayNumberFieldList.forEach(GuiNumberField::update);
} }
@Override @Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, public void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) { boolean isSelected, float partialTicks) {
int yy = y; int yy = y;
int offset = 8; int offset = 8;
buttonArrayEnabled.render(mouseX, mouseY, partialTicks); buttonArrayEnabled.render(ms, mouseX, mouseY, partialTicks);
if (buttonArrayEnabled.isChecked()) { if (buttonArrayEnabled.isChecked()) {
buttonArrayEnabled.y = yy; buttonArrayEnabled.y = yy;
font.drawString("Array enabled", left + offset, yy + 2, 0xFFFFFF); font.draw(ms, "Array enabled", left + offset, yy + 2, 0xFFFFFF);
yy = y + 20; yy = y + 20;
font.drawString("Offset", left + offset, yy + 5, 0xFFFFFF); font.draw(ms, "Offset", left + offset, yy + 5, 0xFFFFFF);
font.drawString("X", left + 50 + offset, yy + 5, 0xFFFFFF); font.draw(ms, "X", left + 50 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetX.y = yy; textArrayOffsetX.y = yy;
font.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF); font.draw(ms, "Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetY.y = yy; textArrayOffsetY.y = yy;
font.drawString("Z", left + 190 + offset, yy + 5, 0xFFFFFF); font.draw(ms, "Z", left + 190 + offset, yy + 5, 0xFFFFFF);
textArrayOffsetZ.y = yy; textArrayOffsetZ.y = yy;
yy = y + 50; yy = y + 50;
font.drawString("Count", left + offset, yy + 5, 0xFFFFFF); font.draw(ms, "Count", left + offset, yy + 5, 0xFFFFFF);
textArrayCount.y = yy; textArrayCount.y = yy;
int currentReach = Math.max(-1, getArrayReach()); int currentReach = Math.max(-1, getArrayReach());
int maxReach = ReachHelper.getMaxReach(mc.player); int maxReach = ReachHelper.getMaxReach(mc.player);
TextFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? TextFormatting.GRAY : TextFormatting.RED; ChatFormatting reachColor = isCurrentReachValid(currentReach, maxReach) ? ChatFormatting.GRAY : ChatFormatting.RED;
String reachText = "Reach: " + reachColor + currentReach + TextFormatting.GRAY + "/" + TextFormatting.GRAY + maxReach; String reachText = "Reach: " + reachColor + currentReach + ChatFormatting.GRAY + "/" + ChatFormatting.GRAY + maxReach;
font.drawString(reachText, left + 176 + offset, yy + 5, 0xFFFFFF); font.draw(ms, reachText, left + 176 + offset, yy + 5, 0xFFFFFF);
arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks)); arrayNumberFieldList.forEach(numberField -> numberField.drawNumberField(ms, mouseX, mouseY, partialTicks));
} else { } else {
buttonArrayEnabled.y = yy; buttonArrayEnabled.y = yy;
font.drawString("Array disabled", left + offset, yy + 2, 0x999999); font.draw(ms, "Array disabled", left + offset, yy + 2, 0x999999);
} }
} }
public void drawTooltip(Screen guiScreen, int mouseX, int mouseY) { public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
//Draw tooltips last //Draw tooltips last
if (buttonArrayEnabled.isChecked()) if (buttonArrayEnabled.isChecked()) {
{ arrayNumberFieldList.forEach(numberField -> numberField.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
arrayNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY)); }
} }
}
@Override @Override
public boolean charTyped(char typedChar, int keyCode) { public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode); super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : arrayNumberFieldList) { for (GuiNumberField numberField : arrayNumberFieldList) {
numberField.charTyped(typedChar, keyCode); numberField.charTyped(typedChar, keyCode);
} }
return true; return true;
} }
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent)); arrayNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12; boolean insideArrayEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
if (insideArrayEnabledLabel) { if (insideArrayEnabledLabel) {
buttonArrayEnabled.playDownSound(this.mc.getSoundHandler()); buttonArrayEnabled.playDownSound(this.mc.getSoundManager());
buttonArrayEnabled.onClick(mouseX, mouseY); buttonArrayEnabled.onClick(mouseX, mouseY);
} }
return true; return true;
} }
public Array.ArraySettings getArraySettings() { public Array.ArraySettings getArraySettings() {
boolean arrayEnabled = buttonArrayEnabled.isChecked(); boolean arrayEnabled = buttonArrayEnabled.isChecked();
BlockPos arrayOffset = new BlockPos(0, 0, 0); BlockPos arrayOffset = new BlockPos(0, 0, 0);
try { try {
arrayOffset = new BlockPos(textArrayOffsetX.getNumber(), textArrayOffsetY.getNumber(), textArrayOffsetZ.getNumber()); arrayOffset = new BlockPos(textArrayOffsetX.getNumber(), textArrayOffsetY.getNumber(), textArrayOffsetZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) { } catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array offset not a valid number."); EffortlessBuilding.log(mc.player, "Array offset not a valid number.");
} }
int arrayCount = 5; int arrayCount = 5;
try { try {
arrayCount = (int) textArrayCount.getNumber(); arrayCount = (int) textArrayCount.getNumber();
} catch (NumberFormatException | NullPointerException ex) { } catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Array count not a valid number."); EffortlessBuilding.log(mc.player, "Array count not a valid number.");
} }
return new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); return new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
} }
@Override @Override
protected String getName() { protected String getName() {
return "Array"; return "Array";
} }
@Override @Override
protected int getExpandedHeight() { protected int getExpandedHeight() {
return 80; return 80;
} }
private int getArrayReach() { private int getArrayReach() {
try try {
{ //find largest offset
//find largest offset double x = Math.abs(textArrayOffsetX.getNumber());
double x = Math.abs(textArrayOffsetX.getNumber()); double y = Math.abs(textArrayOffsetY.getNumber());
double y = Math.abs(textArrayOffsetY.getNumber()); double z = Math.abs(textArrayOffsetZ.getNumber());
double z = Math.abs(textArrayOffsetZ.getNumber()); double largestOffset = Math.max(Math.max(x, y), z);
double largestOffset = Math.max(Math.max(x, y), z); return (int) (largestOffset * textArrayCount.getNumber());
return (int) (largestOffset * textArrayCount.getNumber()); } catch (NumberFormatException | NullPointerException ex) {
} catch (NumberFormatException | NullPointerException ex) { return -1;
return -1; }
} }
}
private boolean isCurrentReachValid(int currentReach, int maxReach) { private boolean isCurrentReachValid(int currentReach, int maxReach) {
return currentReach <= maxReach && currentReach > -1; return currentReach <= maxReach && currentReach > -1;
} }
} }

View File

@@ -1,11 +1,13 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.widget.Widget; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.util.ResourceLocation; import net.minecraft.client.gui.components.Button;
import net.minecraft.util.math.Vec3d; import net.minecraft.network.chat.Component;
import net.minecraft.util.text.TextFormatting; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
@@ -22,262 +24,261 @@ import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class MirrorSettingsGui extends GuiCollapsibleScrollEntry { public class MirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected List<Button> mirrorButtonList = new ArrayList<>(); protected List<Button> mirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>(); protected List<GuiIconButton> mirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> mirrorNumberFieldList = new ArrayList<>(); protected List<GuiNumberField> mirrorNumberFieldList = new ArrayList<>();
private GuiNumberField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius; private GuiNumberField textMirrorPosX, textMirrorPosY, textMirrorPosZ, textMirrorRadius;
private GuiCheckBoxFixed buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ; private GuiCheckBoxFixed buttonMirrorEnabled, buttonMirrorX, buttonMirrorY, buttonMirrorZ;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines; private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd; private boolean drawPlanes, drawLines, toggleOdd;
public MirrorSettingsGui(GuiScrollPane scrollPane) { public MirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane); super(scrollPane);
} }
@Override @Override
public void init(List<Widget> buttonList) { public void init(List<Widget> renderables) {
super.init(buttonList); super.init(renderables);
int y = top - 2; int y = top - 2;
buttonMirrorEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) { buttonMirrorEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) {
@Override @Override
public void onClick(double mouseX, double mouseY) { public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY); super.onClick(mouseX, mouseY);
setCollapsed(!buttonMirrorEnabled.isChecked()); setCollapsed(!buttonMirrorEnabled.isChecked());
} }
}; };
buttonList.add(buttonMirrorEnabled); renderables.add(buttonMirrorEnabled);
y = top + 18; y = top + 18;
textMirrorPosX = new GuiNumberField(font, buttonList, left + 58, y, 62, 18); textMirrorPosX = new GuiNumberField(font, renderables, left + 58, y, 62, 18);
textMirrorPosX.setNumber(0); textMirrorPosX.setNumber(0);
textMirrorPosX.setTooltip( textMirrorPosX.setTooltip(
Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5.")); Arrays.asList(Component.literal("The position of the mirror."), Component.literal("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorPosX); mirrorNumberFieldList.add(textMirrorPosX);
textMirrorPosY = new GuiNumberField(font, buttonList, left + 138, y, 62, 18); textMirrorPosY = new GuiNumberField(font, renderables, left + 138, y, 62, 18);
textMirrorPosY.setNumber(64); textMirrorPosY.setNumber(64);
textMirrorPosY.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5.")); textMirrorPosY.setTooltip(Arrays.asList(Component.literal("The position of the mirror."), Component.literal("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorPosY); mirrorNumberFieldList.add(textMirrorPosY);
textMirrorPosZ = new GuiNumberField(font, buttonList, left + 218, y, 62, 18); textMirrorPosZ = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textMirrorPosZ.setNumber(0); textMirrorPosZ.setNumber(0);
textMirrorPosZ.setTooltip(Arrays.asList("The position of the mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5.")); textMirrorPosZ.setTooltip(Arrays.asList(Component.literal("The position of the mirror."), Component.literal("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorPosZ); mirrorNumberFieldList.add(textMirrorPosZ);
y = top + 50; y = top + 50;
buttonMirrorX = new GuiCheckBoxFixed(left + 60, y, " X", true); buttonMirrorX = new GuiCheckBoxFixed(left + 60, y, " X", true);
mirrorButtonList.add(buttonMirrorX); mirrorButtonList.add(buttonMirrorX);
buttonMirrorY = new GuiCheckBoxFixed(left + 100, y, " Y", false); buttonMirrorY = new GuiCheckBoxFixed(left + 100, y, " Y", false);
mirrorButtonList.add(buttonMirrorY); mirrorButtonList.add(buttonMirrorY);
buttonMirrorZ = new GuiCheckBoxFixed(left + 140, y, " Z", false); buttonMirrorZ = new GuiCheckBoxFixed(left + 140, y, " Z", false);
mirrorButtonList.add(buttonMirrorZ); mirrorButtonList.add(buttonMirrorZ);
y = top + 47; y = top + 47;
textMirrorRadius = new GuiNumberField(font, buttonList, left + 218, y, 62, 18); textMirrorRadius = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textMirrorRadius.setNumber(50); textMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2) //TODO change to diameter (remove /2)
textMirrorRadius.setTooltip(Arrays.asList("How far the mirror reaches in any direction.", textMirrorRadius.setTooltip(Arrays.asList(Component.literal("How far the mirror reaches in any direction."),
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + ReachHelper.getMaxReach(mc.player) / 2, Component.literal("Max: ").withStyle(ChatFormatting.GRAY).append(Component.literal(String.valueOf(ReachHelper.getMaxReach(mc.player) / 2)).withStyle(ChatFormatting.GOLD)),
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades.")); Component.literal("Upgradeable in survival with reach upgrades.").withStyle(ChatFormatting.GRAY)));
mirrorNumberFieldList.add(textMirrorRadius); mirrorNumberFieldList.add(textMirrorRadius);
y = top + 72; y = top + 72;
buttonCurrentPosition = new GuiIconButton(left + 5, y, 0, 0, BUILDING_ICONS, button -> { buttonCurrentPosition = new GuiIconButton(left + 5, y, 0, 0, BUILDING_ICONS, button -> {
Vec3d pos = new Vec3d(Math.floor(mc.player.getPosX()) + 0.5, Math.floor(mc.player.getPosY()) + 0.5, Math.floor(mc.player.getPosZ()) + 0.5); Vec3 pos = new Vec3(Math.floor(mc.player.getX()) + 0.5, Math.floor(mc.player.getY()) + 0.5, Math.floor(mc.player.getZ()) + 0.5);
textMirrorPosX.setNumber(pos.x); textMirrorPosX.setNumber(pos.x);
textMirrorPosY.setNumber(pos.y); textMirrorPosY.setNumber(pos.y);
textMirrorPosZ.setNumber(pos.z); textMirrorPosZ.setNumber(pos.z);
}); });
buttonCurrentPosition.setTooltip("Set mirror position to current player position"); buttonCurrentPosition.setTooltip(Component.literal("Set mirror position to current player position"));
mirrorIconButtonList.add(buttonCurrentPosition); mirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(left + 35, y, 0, 20, BUILDING_ICONS, button -> { buttonToggleOdd = new GuiIconButton(left + 35, y, 0, 20, BUILDING_ICONS, button -> {
toggleOdd = !toggleOdd; toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd); buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) { if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to corner of block"), Component.literal("for even numbered builds")));
textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5); textMirrorPosX.setNumber(textMirrorPosX.getNumber() + 0.5);
textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5); textMirrorPosY.setNumber(textMirrorPosY.getNumber() + 0.5);
textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5); textMirrorPosZ.setNumber(textMirrorPosZ.getNumber() + 0.5);
} else { } else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to middle of block"), Component.literal("for odd numbered builds")));
textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber())); textMirrorPosX.setNumber(Math.floor(textMirrorPosX.getNumber()));
textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber())); textMirrorPosY.setNumber(Math.floor(textMirrorPosY.getNumber()));
textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber())); textMirrorPosZ.setNumber(Math.floor(textMirrorPosZ.getNumber()));
} }
}); });
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to middle of block"), Component.literal("for odd numbered builds")));
mirrorIconButtonList.add(buttonToggleOdd); mirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(left + 65, y, 0, 40, BUILDING_ICONS, button -> { buttonDrawLines = new GuiIconButton(left + 65, y, 0, 40, BUILDING_ICONS, button -> {
drawLines = !drawLines; drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines); buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines"); buttonDrawLines.setTooltip(Component.literal(drawLines ? "Hide lines" : "Show lines"));
}); });
buttonDrawLines.setTooltip("Show lines"); buttonDrawLines.setTooltip(Component.literal("Show lines"));
mirrorIconButtonList.add(buttonDrawLines); mirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(left + 95, y, 0, 60, BUILDING_ICONS, button -> { buttonDrawPlanes = new GuiIconButton(left + 95, y, 0, 60, BUILDING_ICONS, button -> {
drawPlanes = !drawPlanes; drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes); buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area"); buttonDrawPlanes.setTooltip(Component.literal(drawPlanes ? "Hide area" : "Show area"));
}); });
buttonDrawPlanes.setTooltip("Show area"); buttonDrawPlanes.setTooltip(Component.literal("Show area"));
mirrorIconButtonList.add(buttonDrawPlanes); mirrorIconButtonList.add(buttonDrawPlanes);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) { if (modifierSettings != null) {
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
buttonMirrorEnabled.setIsChecked(m.enabled); buttonMirrorEnabled.setIsChecked(m.enabled);
textMirrorPosX.setNumber(m.position.x); textMirrorPosX.setNumber(m.position.x);
textMirrorPosY.setNumber(m.position.y); textMirrorPosY.setNumber(m.position.y);
textMirrorPosZ.setNumber(m.position.z); textMirrorPosZ.setNumber(m.position.z);
buttonMirrorX.setIsChecked(m.mirrorX); buttonMirrorX.setIsChecked(m.mirrorX);
buttonMirrorY.setIsChecked(m.mirrorY); buttonMirrorY.setIsChecked(m.mirrorY);
buttonMirrorZ.setIsChecked(m.mirrorZ); buttonMirrorZ.setIsChecked(m.mirrorZ);
textMirrorRadius.setNumber(m.radius); textMirrorRadius.setNumber(m.radius);
drawLines = m.drawLines; drawLines = m.drawLines;
drawPlanes = m.drawPlanes; drawPlanes = m.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines); buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes); buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines"); buttonDrawLines.setTooltip(Component.literal(drawLines ? "Hide lines" : "Show lines"));
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area"); buttonDrawPlanes.setTooltip(Component.literal(drawPlanes ? "Hide area" : "Show area"));
if (textMirrorPosX.getNumber() == Math.floor(textMirrorPosX.getNumber())) { if (textMirrorPosX.getNumber() == Math.floor(textMirrorPosX.getNumber())) {
toggleOdd = false; toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to middle of block"), Component.literal("for odd numbered builds")));
} else { } else {
toggleOdd = true; toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to corner of block"), Component.literal("for even numbered builds")));
} }
buttonToggleOdd.setUseAlternateIcon(toggleOdd); buttonToggleOdd.setUseAlternateIcon(toggleOdd);
} }
buttonList.addAll(mirrorButtonList); renderables.addAll(mirrorButtonList);
buttonList.addAll(mirrorIconButtonList); renderables.addAll(mirrorIconButtonList);
setCollapsed(!buttonMirrorEnabled.isChecked()); setCollapsed(!buttonMirrorEnabled.isChecked());
} }
@Override @Override
public void updateScreen() { public void updateScreen() {
super.updateScreen(); super.updateScreen();
mirrorNumberFieldList.forEach(GuiNumberField::update); mirrorNumberFieldList.forEach(GuiNumberField::update);
} }
@Override @Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, public void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) { boolean isSelected, float partialTicks) {
int yy = y;
int offset = 8;
buttonMirrorEnabled.render(mouseX, mouseY, partialTicks); int yy = y;
if (buttonMirrorEnabled.isChecked()) { int offset = 8;
buttonMirrorEnabled.y = yy;
font.drawString("Mirror enabled", left + offset, yy + 2, 0xFFFFFF);
yy = y + 18; buttonMirrorEnabled.render(ms, mouseX, mouseY, partialTicks);
font.drawString("Position", left + offset, yy + 5, 0xFFFFFF); if (buttonMirrorEnabled.isChecked()) {
font.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF); buttonMirrorEnabled.y = yy;
textMirrorPosX.y = yy; font.draw(ms, "Mirror enabled", left + offset, yy + 2, 0xFFFFFF);
font.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textMirrorPosY.y = yy;
font.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textMirrorPosZ.y = yy;
yy = y + 50; yy = y + 18;
font.drawString("Direction", left + offset, yy + 2, 0xFFFFFF); font.draw(ms, "Position", left + offset, yy + 5, 0xFFFFFF);
buttonMirrorX.y = yy; font.draw(ms, "X", left + 40 + offset, yy + 5, 0xFFFFFF);
buttonMirrorY.y = yy; textMirrorPosX.y = yy;
buttonMirrorZ.y = yy; font.draw(ms, "Y", left + 120 + offset, yy + 5, 0xFFFFFF);
font.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF); textMirrorPosY.y = yy;
textMirrorRadius.y = yy - 3; font.draw(ms, "Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textMirrorPosZ.y = yy;
yy = y + 72; yy = y + 50;
buttonCurrentPosition.y = yy; font.draw(ms, "Direction", left + offset, yy + 2, 0xFFFFFF);
buttonToggleOdd.y = yy; buttonMirrorX.y = yy;
buttonDrawLines.y = yy; buttonMirrorY.y = yy;
buttonDrawPlanes.y = yy; buttonMirrorZ.y = yy;
font.draw(ms, "Radius", left + 176 + offset, yy + 2, 0xFFFFFF);
textMirrorRadius.y = yy - 3;
mirrorButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); yy = y + 72;
mirrorIconButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); buttonCurrentPosition.y = yy;
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks)); buttonToggleOdd.y = yy;
} else { buttonDrawLines.y = yy;
buttonMirrorEnabled.y = yy; buttonDrawPlanes.y = yy;
font.drawString("Mirror disabled", left + offset, yy + 2, 0x999999);
}
} mirrorButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
mirrorIconButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
mirrorNumberFieldList.forEach(numberField -> numberField.drawNumberField(ms, mouseX, mouseY, partialTicks));
} else {
buttonMirrorEnabled.y = yy;
font.draw(ms, "Mirror disabled", left + offset, yy + 2, 0x999999);
}
public void drawTooltip(Screen guiScreen, int mouseX, int mouseY) { }
//Draw tooltips last
if (buttonMirrorEnabled.isChecked())
{
mirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(scrollPane.parent, mouseX, mouseY));
mirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
@Override public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
public boolean charTyped(char typedChar, int keyCode) { //Draw tooltips last
super.charTyped(typedChar, keyCode); if (buttonMirrorEnabled.isChecked()) {
for (GuiNumberField numberField : mirrorNumberFieldList) { mirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
numberField.charTyped(typedChar, keyCode); mirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
} }
return true; }
}
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean charTyped(char typedChar, int keyCode) {
mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent)); super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : mirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12; @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
mirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
if (insideMirrorEnabledLabel) { boolean insideMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
buttonMirrorEnabled.playDownSound(this.mc.getSoundHandler());
buttonMirrorEnabled.onClick(mouseX, mouseY);
}
return true; if (insideMirrorEnabledLabel) {
} buttonMirrorEnabled.playDownSound(this.mc.getSoundManager());
buttonMirrorEnabled.onClick(mouseX, mouseY);
}
public Mirror.MirrorSettings getMirrorSettings() { return true;
boolean mirrorEnabled = buttonMirrorEnabled.isChecked(); }
Vec3d mirrorPos = new Vec3d(0, 64, 0); public Mirror.MirrorSettings getMirrorSettings() {
try { boolean mirrorEnabled = buttonMirrorEnabled.isChecked();
mirrorPos = new Vec3d(textMirrorPosX.getNumber(), textMirrorPosY.getNumber(), textMirrorPosZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror position not a valid number.");
}
boolean mirrorX = buttonMirrorX.isChecked(); Vec3 mirrorPos = new Vec3(0, 64, 0);
boolean mirrorY = buttonMirrorY.isChecked(); try {
boolean mirrorZ = buttonMirrorZ.isChecked(); mirrorPos = new Vec3(textMirrorPosX.getNumber(), textMirrorPosY.getNumber(), textMirrorPosZ.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror position not a valid number.");
}
int mirrorRadius = 50; boolean mirrorX = buttonMirrorX.isChecked();
try { boolean mirrorY = buttonMirrorY.isChecked();
mirrorRadius = (int) textMirrorRadius.getNumber(); boolean mirrorZ = buttonMirrorZ.isChecked();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
return new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes); int mirrorRadius = 50;
} try {
mirrorRadius = (int) textMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
@Override return new Mirror.MirrorSettings(mirrorEnabled, mirrorPos, mirrorX, mirrorY, mirrorZ, mirrorRadius, drawLines, drawPlanes);
protected String getName() { }
return "Mirror";
}
@Override @Override
protected int getExpandedHeight() { protected String getName() {
return 100; return "Mirror";
} }
@Override
protected int getExpandedHeight() {
return 100;
}
} }

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui.buildmodifier;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.util.text.ITextComponent; import net.minecraft.network.chat.Component;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
@@ -20,124 +20,136 @@ import nl.requios.effortlessbuilding.proxy.ClientProxy;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ModifierSettingsGui extends Screen { public class ModifierSettingsGui extends Screen {
private GuiScrollPane scrollPane; private GuiScrollPane scrollPane;
private Button buttonClose; private Button buttonClose;
private MirrorSettingsGui mirrorSettingsGui; private MirrorSettingsGui mirrorSettingsGui;
private ArraySettingsGui arraySettingsGui; private ArraySettingsGui arraySettingsGui;
private RadialMirrorSettingsGui radialMirrorSettingsGui; private RadialMirrorSettingsGui radialMirrorSettingsGui;
public ModifierSettingsGui() { public ModifierSettingsGui() {
super(new TranslationTextComponent("effortlessbuilding.screen.modifier_settings")); super(Component.translatable("effortlessbuilding.screen.modifier_settings"));
} }
@Override @Override
//Create buttons and labels and add them to buttonList/labelList //Create buttons and labels and add them to buttonList/labelList
protected void init() { protected void init() {
scrollPane = new GuiScrollPane(this, font, 8, height - 30);
mirrorSettingsGui = new MirrorSettingsGui(scrollPane); scrollPane = new GuiScrollPane(this, font, 8, height - 30);
scrollPane.AddListEntry(mirrorSettingsGui);
arraySettingsGui = new ArraySettingsGui(scrollPane); mirrorSettingsGui = new MirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(arraySettingsGui); scrollPane.AddListEntry(mirrorSettingsGui);
radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane); arraySettingsGui = new ArraySettingsGui(scrollPane);
scrollPane.AddListEntry(radialMirrorSettingsGui); scrollPane.AddListEntry(arraySettingsGui);
scrollPane.init(buttons); radialMirrorSettingsGui = new RadialMirrorSettingsGui(scrollPane);
scrollPane.AddListEntry(radialMirrorSettingsGui);
//Close button scrollPane.init(renderables);
int y = height - 26;
buttonClose = new Button(width / 2 - 100, y, 200, 20, "Close", (button) -> {
Minecraft.getInstance().player.closeScreen();
});
buttons.add(buttonClose);
}
@Override //Close button
//Process general logic, i.e. hide buttons int y = height - 26;
public void tick() { buttonClose = new Button(width / 2 - 100, y, 200, 20, Component.literal("Close"), (button) -> {
scrollPane.updateScreen(); Minecraft.getInstance().player.closeContainer();
});
addRenderableOnly(buttonClose);
}
handleMouseInput(); @Override
} //Process general logic, i.e. hide buttons
public void tick() {
scrollPane.updateScreen();
@Override handleMouseInput();
//Set colors using GL11, use the fontObj field to display text }
//Use drawTexturedModalRect() to transfers areas of a texture resource to the screen
public void render(int mouseX, int mouseY, float partialTicks) {
this.renderBackground();
scrollPane.render(mouseX, mouseY, partialTicks); @Override
//Set colors using GL11, use the fontObj field to display text
//Use drawTexturedModalRect() to transfers areas of a texture resource to the screen
public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
this.renderBackground(ms);
buttonClose.render(mouseX, mouseY, partialTicks); scrollPane.render(ms, mouseX, mouseY, partialTicks);
scrollPane.drawTooltip(this, mouseX, mouseY); buttonClose.render(ms, mouseX, mouseY, partialTicks);
}
scrollPane.drawTooltip(ms, this, mouseX, mouseY);
}
@Override @Override
public boolean charTyped(char typedChar, int keyCode) { public boolean charTyped(char typedChar, int keyCode) {
super.charTyped(typedChar, keyCode); super.charTyped(typedChar, keyCode);
scrollPane.charTyped(typedChar, keyCode); scrollPane.charTyped(typedChar, keyCode);
if (keyCode == ClientProxy.keyBindings[0].getKey().getKeyCode()) { return false;
minecraft.player.closeScreen(); }
}
return false;
}
@Override @Override
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { public boolean keyPressed(int keyCode, int p_96553_, int p_96554_) {
super.mouseClicked(mouseX, mouseY, mouseButton); if (keyCode == ClientProxy.keyBindings[0].getKey().getValue()) {
buttons.forEach(button -> button.mouseClicked(mouseX, mouseY, mouseButton)); minecraft.player.closeContainer();
return scrollPane.mouseClicked(mouseX, mouseY, mouseButton); return true;
} }
@Override return super.keyPressed(keyCode, p_96553_, p_96554_);
public boolean mouseReleased(double mouseX, double mouseY, int state) { }
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state))
{
return super.mouseReleased(mouseX, mouseY, state);
}
return false;
}
public void handleMouseInput() { @Override
//super.handleMouseInput(); public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
scrollPane.handleMouseInput(); super.mouseClicked(mouseX, mouseY, mouseButton);
renderables.forEach(renderable -> {
if (renderable instanceof Button) {
Button button = (Button) renderable;
button.mouseClicked(mouseX, mouseY, mouseButton);
}
});
return scrollPane.mouseClicked(mouseX, mouseY, mouseButton);
}
//Scrolling numbers @Override
public boolean mouseReleased(double mouseX, double mouseY, int state) {
if (state != 0 || !scrollPane.mouseReleased(mouseX, mouseY, state)) {
return super.mouseReleased(mouseX, mouseY, state);
}
return false;
}
public void handleMouseInput() {
//super.handleMouseInput();
scrollPane.handleMouseInput();
//Scrolling numbers
// int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth; // int mouseX = Mouse.getEventX() * this.width / this.mc.displayWidth;
// int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1; // int mouseY = this.height - Mouse.getEventY() * this.height / this.mc.displayHeight - 1;
// numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY)); // numberFieldList.forEach(numberField -> numberField.handleMouseInput(mouseX, mouseY));
} }
@Override @Override
public void removed() { public void removed() {
scrollPane.onGuiClosed(); scrollPane.onGuiClosed();
//save everything //save everything
Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings(); Mirror.MirrorSettings m = mirrorSettingsGui.getMirrorSettings();
Array.ArraySettings a = arraySettingsGui.getArraySettings(); Array.ArraySettings a = arraySettingsGui.getArraySettings();
RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = radialMirrorSettingsGui.getRadialMirrorSettings();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(minecraft.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(minecraft.player);
if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings(); if (modifierSettings == null) modifierSettings = new ModifierSettingsManager.ModifierSettings();
modifierSettings.setMirrorSettings(m); modifierSettings.setMirrorSettings(m);
modifierSettings.setArraySettings(a); modifierSettings.setArraySettings(a);
modifierSettings.setRadialMirrorSettings(r); modifierSettings.setRadialMirrorSettings(r);
//Sanitize //Sanitize
String error = ModifierSettingsManager.sanitize(modifierSettings, minecraft.player); String error = ModifierSettingsManager.sanitize(modifierSettings, minecraft.player);
if (!error.isEmpty()) EffortlessBuilding.log(minecraft.player, error); if (!error.isEmpty()) EffortlessBuilding.log(minecraft.player, error);
ModifierSettingsManager.setModifierSettings(minecraft.player, modifierSettings); ModifierSettingsManager.setModifierSettings(minecraft.player, modifierSettings);
//Send to server //Send to server
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings)); PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
Minecraft.getInstance().mouseHelper.grabMouse(); Minecraft.getInstance().mouseHandler.grabMouse();
} }
} }

View File

@@ -1,11 +1,13 @@
package nl.requios.effortlessbuilding.gui.buildmodifier; package nl.requios.effortlessbuilding.gui.buildmodifier;
import net.minecraft.client.gui.widget.Widget; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.util.ResourceLocation; import net.minecraft.client.gui.components.Button;
import net.minecraft.util.math.Vec3d; import net.minecraft.network.chat.Component;
import net.minecraft.util.text.TextFormatting; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
@@ -22,267 +24,266 @@ import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry { public class RadialMirrorSettingsGui extends GuiCollapsibleScrollEntry {
protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png"); protected static final ResourceLocation BUILDING_ICONS = new ResourceLocation(EffortlessBuilding.MODID, "textures/gui/building_icons.png");
protected List<Button> radialMirrorButtonList = new ArrayList<>(); protected List<Button> radialMirrorButtonList = new ArrayList<>();
protected List<GuiIconButton> radialMirrorIconButtonList = new ArrayList<>(); protected List<GuiIconButton> radialMirrorIconButtonList = new ArrayList<>();
protected List<GuiNumberField> radialMirrorNumberFieldList = new ArrayList<>(); protected List<GuiNumberField> radialMirrorNumberFieldList = new ArrayList<>();
private GuiNumberField textRadialMirrorPosX, textRadialMirrorPosY, textRadialMirrorPosZ, textRadialMirrorSlices, textRadialMirrorRadius; private GuiNumberField textRadialMirrorPosX, textRadialMirrorPosY, textRadialMirrorPosZ, textRadialMirrorSlices, textRadialMirrorRadius;
private GuiCheckBoxFixed buttonRadialMirrorEnabled, buttonRadialMirrorAlternate; private GuiCheckBoxFixed buttonRadialMirrorEnabled, buttonRadialMirrorAlternate;
private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines; private GuiIconButton buttonCurrentPosition, buttonToggleOdd, buttonDrawPlanes, buttonDrawLines;
private boolean drawPlanes, drawLines, toggleOdd; private boolean drawPlanes, drawLines, toggleOdd;
public RadialMirrorSettingsGui(GuiScrollPane scrollPane) { public RadialMirrorSettingsGui(GuiScrollPane scrollPane) {
super(scrollPane); super(scrollPane);
} }
@Override @Override
public void init(List<Widget> buttonList) { public void init(List<Widget> renderables) {
super.init(buttonList); super.init(renderables);
int y = top - 2; int y = top - 2;
buttonRadialMirrorEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) { buttonRadialMirrorEnabled = new GuiCheckBoxFixed(left - 15 + 8, y, "", false) {
@Override @Override
public void onClick(double mouseX, double mouseY) { public void onClick(double mouseX, double mouseY) {
super.onClick(mouseX, mouseY); super.onClick(mouseX, mouseY);
setCollapsed(!buttonRadialMirrorEnabled.isChecked()); setCollapsed(!buttonRadialMirrorEnabled.isChecked());
} }
}; };
buttonList.add(buttonRadialMirrorEnabled); renderables.add(buttonRadialMirrorEnabled);
y = top + 18; y = top + 18;
textRadialMirrorPosX = new GuiNumberField(font, buttonList, left + 58, y, 62, 18); textRadialMirrorPosX = new GuiNumberField(font, renderables, left + 58, y, 62, 18);
textRadialMirrorPosX.setNumber(0); textRadialMirrorPosX.setNumber(0);
textRadialMirrorPosX.setTooltip( textRadialMirrorPosX.setTooltip(
Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5.")); Arrays.asList(Component.literal("The position of the radial mirror."), Component.literal("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorPosX); radialMirrorNumberFieldList.add(textRadialMirrorPosX);
textRadialMirrorPosY = new GuiNumberField(font, buttonList, left + 138, y, 62, 18); textRadialMirrorPosY = new GuiNumberField(font, renderables, left + 138, y, 62, 18);
textRadialMirrorPosY.setNumber(64); textRadialMirrorPosY.setNumber(64);
textRadialMirrorPosY.setTooltip(Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5.")); textRadialMirrorPosY.setTooltip(Arrays.asList(Component.literal("The position of the radial mirror."), Component.literal("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorPosY); radialMirrorNumberFieldList.add(textRadialMirrorPosY);
textRadialMirrorPosZ = new GuiNumberField(font, buttonList, left + 218, y, 62, 18); textRadialMirrorPosZ = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textRadialMirrorPosZ.setNumber(0); textRadialMirrorPosZ.setNumber(0);
textRadialMirrorPosZ.setTooltip(Arrays.asList("The position of the radial mirror.", TextFormatting.GRAY + "For odd numbered builds add 0.5.")); textRadialMirrorPosZ.setTooltip(Arrays.asList(Component.literal("The position of the radial mirror."), Component.literal("For odd numbered builds add 0.5.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorPosZ); radialMirrorNumberFieldList.add(textRadialMirrorPosZ);
y = top + 47; y = top + 47;
textRadialMirrorSlices = new GuiNumberField(font, buttonList, left + 55, y, 50, 18); textRadialMirrorSlices = new GuiNumberField(font, renderables, left + 55, y, 50, 18);
textRadialMirrorSlices.setNumber(4); textRadialMirrorSlices.setNumber(4);
textRadialMirrorSlices.setTooltip(Arrays.asList("The number of repeating slices.", TextFormatting.GRAY + "Minimally 2.")); textRadialMirrorSlices.setTooltip(Arrays.asList(Component.literal("The number of repeating slices."), Component.literal("Minimally 2.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorSlices); radialMirrorNumberFieldList.add(textRadialMirrorSlices);
textRadialMirrorRadius = new GuiNumberField(font, buttonList, left + 218, y, 62, 18); textRadialMirrorRadius = new GuiNumberField(font, renderables, left + 218, y, 62, 18);
textRadialMirrorRadius.setNumber(50); textRadialMirrorRadius.setNumber(50);
//TODO change to diameter (remove /2) //TODO change to diameter (remove /2)
textRadialMirrorRadius.setTooltip(Arrays.asList("How far the radial mirror reaches from its center position.", textRadialMirrorRadius.setTooltip(Arrays.asList(Component.literal("How far the radial mirror reaches from its center position."),
TextFormatting.GRAY + "Max: " + TextFormatting.GOLD + ReachHelper.getMaxReach(mc.player) / 2, Component.literal("Max: ").withStyle(ChatFormatting.GRAY).append(Component.literal(String.valueOf(ReachHelper.getMaxReach(mc.player) / 2)).withStyle(ChatFormatting.GOLD)),
TextFormatting.GRAY + "Upgradeable in survival with reach upgrades.")); Component.literal("Upgradeable in survival with reach upgrades.").withStyle(ChatFormatting.GRAY)));
radialMirrorNumberFieldList.add(textRadialMirrorRadius); radialMirrorNumberFieldList.add(textRadialMirrorRadius);
y = top + 72; y = top + 72;
buttonCurrentPosition = new GuiIconButton(left + 5, y, 0, 0, BUILDING_ICONS, button -> { buttonCurrentPosition = new GuiIconButton(left + 5, y, 0, 0, BUILDING_ICONS, button -> {
Vec3d pos = new Vec3d(Math.floor(mc.player.getPosX()) + 0.5, Math.floor(mc.player.getPosY()) + 0.5, Math.floor(mc.player.getPosZ()) + 0.5); Vec3 pos = new Vec3(Math.floor(mc.player.getX()) + 0.5, Math.floor(mc.player.getY()) + 0.5, Math.floor(mc.player.getZ()) + 0.5);
textRadialMirrorPosX.setNumber(pos.x); textRadialMirrorPosX.setNumber(pos.x);
textRadialMirrorPosY.setNumber(pos.y); textRadialMirrorPosY.setNumber(pos.y);
textRadialMirrorPosZ.setNumber(pos.z); textRadialMirrorPosZ.setNumber(pos.z);
}); });
buttonCurrentPosition.setTooltip("Set radial mirror position to current player position"); buttonCurrentPosition.setTooltip(Component.literal("Set radial mirror position to current player position"));
radialMirrorIconButtonList.add(buttonCurrentPosition); radialMirrorIconButtonList.add(buttonCurrentPosition);
buttonToggleOdd = new GuiIconButton(left + 35, y, 0, 20, BUILDING_ICONS, button -> { buttonToggleOdd = new GuiIconButton(left + 35, y, 0, 20, BUILDING_ICONS, button -> {
toggleOdd = !toggleOdd; toggleOdd = !toggleOdd;
buttonToggleOdd.setUseAlternateIcon(toggleOdd); buttonToggleOdd.setUseAlternateIcon(toggleOdd);
if (toggleOdd) { if (toggleOdd) {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to corner of block", "for even numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to corner of block"), Component.literal("for even numbered builds")));
textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5); textRadialMirrorPosX.setNumber(textRadialMirrorPosX.getNumber() + 0.5);
textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5); textRadialMirrorPosY.setNumber(textRadialMirrorPosY.getNumber() + 0.5);
textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5); textRadialMirrorPosZ.setNumber(textRadialMirrorPosZ.getNumber() + 0.5);
} else { } else {
buttonToggleOdd.setTooltip(Arrays.asList("Set mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set mirror position to middle of block"), Component.literal("for odd numbered builds")));
textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber())); textRadialMirrorPosX.setNumber(Math.floor(textRadialMirrorPosX.getNumber()));
textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber())); textRadialMirrorPosY.setNumber(Math.floor(textRadialMirrorPosY.getNumber()));
textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.getNumber())); textRadialMirrorPosZ.setNumber(Math.floor(textRadialMirrorPosZ.getNumber()));
} }
}); });
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set radial mirror position to middle of block"), Component.literal("for odd numbered builds")));
radialMirrorIconButtonList.add(buttonToggleOdd); radialMirrorIconButtonList.add(buttonToggleOdd);
buttonDrawLines = new GuiIconButton(left + 65, y, 0, 40, BUILDING_ICONS, button -> { buttonDrawLines = new GuiIconButton(left + 65, y, 0, 40, BUILDING_ICONS, button -> {
drawLines = !drawLines; drawLines = !drawLines;
buttonDrawLines.setUseAlternateIcon(drawLines); buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines"); buttonDrawLines.setTooltip(Component.literal(drawLines ? "Hide lines" : "Show lines"));
}); });
buttonDrawLines.setTooltip("Show lines"); buttonDrawLines.setTooltip(Component.literal("Show lines"));
radialMirrorIconButtonList.add(buttonDrawLines); radialMirrorIconButtonList.add(buttonDrawLines);
buttonDrawPlanes = new GuiIconButton(left + 95, y, 0, 60, BUILDING_ICONS, button -> { buttonDrawPlanes = new GuiIconButton(left + 95, y, 0, 60, BUILDING_ICONS, button -> {
drawPlanes = !drawPlanes; drawPlanes = !drawPlanes;
buttonDrawPlanes.setUseAlternateIcon(drawPlanes); buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area"); buttonDrawPlanes.setTooltip(Component.literal(drawPlanes ? "Hide area" : "Show area"));
}); });
buttonDrawPlanes.setTooltip("Show area"); buttonDrawPlanes.setTooltip(Component.literal("Show area"));
radialMirrorIconButtonList.add(buttonDrawPlanes); radialMirrorIconButtonList.add(buttonDrawPlanes);
y = top + 76; y = top + 76;
buttonRadialMirrorAlternate = new GuiCheckBoxFixed(left + 140, y, " Alternate", false); buttonRadialMirrorAlternate = new GuiCheckBoxFixed(left + 140, y, " Alternate", false);
radialMirrorButtonList.add(buttonRadialMirrorAlternate); radialMirrorButtonList.add(buttonRadialMirrorAlternate);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(mc.player);
if (modifierSettings != null) { if (modifierSettings != null) {
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
buttonRadialMirrorEnabled.setIsChecked(r.enabled); buttonRadialMirrorEnabled.setIsChecked(r.enabled);
textRadialMirrorPosX.setNumber(r.position.x); textRadialMirrorPosX.setNumber(r.position.x);
textRadialMirrorPosY.setNumber(r.position.y); textRadialMirrorPosY.setNumber(r.position.y);
textRadialMirrorPosZ.setNumber(r.position.z); textRadialMirrorPosZ.setNumber(r.position.z);
textRadialMirrorSlices.setNumber(r.slices); textRadialMirrorSlices.setNumber(r.slices);
buttonRadialMirrorAlternate.setIsChecked(r.alternate); buttonRadialMirrorAlternate.setIsChecked(r.alternate);
textRadialMirrorRadius.setNumber(r.radius); textRadialMirrorRadius.setNumber(r.radius);
drawLines = r.drawLines; drawLines = r.drawLines;
drawPlanes = r.drawPlanes; drawPlanes = r.drawPlanes;
buttonDrawLines.setUseAlternateIcon(drawLines); buttonDrawLines.setUseAlternateIcon(drawLines);
buttonDrawPlanes.setUseAlternateIcon(drawPlanes); buttonDrawPlanes.setUseAlternateIcon(drawPlanes);
buttonDrawLines.setTooltip(drawLines ? "Hide lines" : "Show lines"); buttonDrawLines.setTooltip(Component.literal(drawLines ? "Hide lines" : "Show lines"));
buttonDrawPlanes.setTooltip(drawPlanes ? "Hide area" : "Show area"); buttonDrawPlanes.setTooltip(Component.literal(drawPlanes ? "Hide area" : "Show area"));
if (textRadialMirrorPosX.getNumber() == Math.floor(textRadialMirrorPosX.getNumber())) { if (textRadialMirrorPosX.getNumber() == Math.floor(textRadialMirrorPosX.getNumber())) {
toggleOdd = false; toggleOdd = false;
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to middle of block", "for odd numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set radial mirror position to middle of block"), Component.literal("for odd numbered builds")));
} else { } else {
toggleOdd = true; toggleOdd = true;
buttonToggleOdd.setTooltip(Arrays.asList("Set radial mirror position to corner of block", "for even numbered builds")); buttonToggleOdd.setTooltip(Arrays.asList(Component.literal("Set radial mirror position to corner of block"), Component.literal("for even numbered builds")));
} }
buttonToggleOdd.setUseAlternateIcon(toggleOdd); buttonToggleOdd.setUseAlternateIcon(toggleOdd);
} }
buttonList.addAll(radialMirrorButtonList); renderables.addAll(radialMirrorButtonList);
buttonList.addAll(radialMirrorIconButtonList); renderables.addAll(radialMirrorIconButtonList);
setCollapsed(!buttonRadialMirrorEnabled.isChecked()); setCollapsed(!buttonRadialMirrorEnabled.isChecked());
} }
public void updateScreen() { public void updateScreen() {
radialMirrorNumberFieldList.forEach(GuiNumberField::update); radialMirrorNumberFieldList.forEach(GuiNumberField::update);
} }
@Override
public void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
int yy = y; @Override
int offset = 8; public void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY,
boolean isSelected, float partialTicks) {
buttonRadialMirrorEnabled.render(mouseX, mouseY, partialTicks); int yy = y;
if (buttonRadialMirrorEnabled.isChecked()) { int offset = 8;
buttonRadialMirrorEnabled.y = yy;
font.drawString("Radial mirror enabled", left + offset, yy + 2, 0xFFFFFF);
yy = y + 18; buttonRadialMirrorEnabled.render(ms, mouseX, mouseY, partialTicks);
font.drawString("Position", left + offset, yy + 5, 0xFFFFFF); if (buttonRadialMirrorEnabled.isChecked()) {
font.drawString("X", left + 40 + offset, yy + 5, 0xFFFFFF); buttonRadialMirrorEnabled.y = yy;
textRadialMirrorPosX.y = yy; font.draw(ms, "Radial mirror enabled", left + offset, yy + 2, 0xFFFFFF);
font.drawString("Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosY.y = yy;
font.drawString("Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosZ.y = yy;
yy = y + 50; yy = y + 18;
font.drawString("Slices", left + offset, yy + 2, 0xFFFFFF); font.draw(ms, "Position", left + offset, yy + 5, 0xFFFFFF);
textRadialMirrorSlices.y = yy - 3; font.draw(ms, "X", left + 40 + offset, yy + 5, 0xFFFFFF);
font.drawString("Radius", left + 176 + offset, yy + 2, 0xFFFFFF); textRadialMirrorPosX.y = yy;
textRadialMirrorRadius.y = yy - 3; font.draw(ms, "Y", left + 120 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosY.y = yy;
font.draw(ms, "Z", left + 200 + offset, yy + 5, 0xFFFFFF);
textRadialMirrorPosZ.y = yy;
yy = y + 72; yy = y + 50;
buttonCurrentPosition.y = yy; font.draw(ms, "Slices", left + offset, yy + 2, 0xFFFFFF);
buttonToggleOdd.y = yy; textRadialMirrorSlices.y = yy - 3;
buttonDrawLines.y = yy; font.draw(ms, "Radius", left + 176 + offset, yy + 2, 0xFFFFFF);
buttonDrawPlanes.y = yy; textRadialMirrorRadius.y = yy - 3;
yy = y + 76; yy = y + 72;
buttonRadialMirrorAlternate.y = yy; buttonCurrentPosition.y = yy;
buttonToggleOdd.y = yy;
buttonDrawLines.y = yy;
buttonDrawPlanes.y = yy;
radialMirrorButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); yy = y + 76;
radialMirrorIconButtonList.forEach(button -> button.render(mouseX, mouseY, partialTicks)); buttonRadialMirrorAlternate.y = yy;
radialMirrorNumberFieldList
.forEach(numberField -> numberField.drawNumberField(mouseX, mouseY, partialTicks));
} else {
buttonRadialMirrorEnabled.y = yy;
font.drawString("Radial mirror disabled", left + offset, yy + 2, 0x999999);
}
} radialMirrorButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
radialMirrorIconButtonList.forEach(button -> button.render(ms, mouseX, mouseY, partialTicks));
radialMirrorNumberFieldList
.forEach(numberField -> numberField.drawNumberField(ms, mouseX, mouseY, partialTicks));
} else {
buttonRadialMirrorEnabled.y = yy;
font.draw(ms, "Radial mirror disabled", left + offset, yy + 2, 0x999999);
}
public void drawTooltip(Screen guiScreen, int mouseX, int mouseY) { }
//Draw tooltips last
if (buttonRadialMirrorEnabled.isChecked())
{
radialMirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(scrollPane.parent, mouseX, mouseY));
radialMirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(scrollPane.parent, mouseX, mouseY));
}
}
@Override public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
public boolean charTyped(char typedChar, int keyCode) { //Draw tooltips last
super.charTyped(typedChar, keyCode); if (buttonRadialMirrorEnabled.isChecked()) {
for (GuiNumberField numberField : radialMirrorNumberFieldList) { radialMirrorIconButtonList.forEach(iconButton -> iconButton.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
numberField.charTyped(typedChar, keyCode); radialMirrorNumberFieldList.forEach(numberField -> numberField.drawTooltip(ms, scrollPane.parent, mouseX, mouseY));
} }
return true; }
}
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean charTyped(char typedChar, int keyCode) {
radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent)); super.charTyped(typedChar, keyCode);
for (GuiNumberField numberField : radialMirrorNumberFieldList) {
numberField.charTyped(typedChar, keyCode);
}
return true;
}
boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12; @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
radialMirrorNumberFieldList.forEach(numberField -> numberField.mouseClicked(mouseX, mouseY, mouseEvent));
if (insideRadialMirrorEnabledLabel) { boolean insideRadialMirrorEnabledLabel = mouseX >= left && mouseX < right && relativeY >= -2 && relativeY < 12;
buttonRadialMirrorEnabled.playDownSound(this.mc.getSoundHandler());
buttonRadialMirrorEnabled.onClick(mouseX, mouseY);
}
return true; if (insideRadialMirrorEnabledLabel) {
} buttonRadialMirrorEnabled.playDownSound(this.mc.getSoundManager());
buttonRadialMirrorEnabled.onClick(mouseX, mouseY);
}
public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() { return true;
boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked(); }
Vec3d radialMirrorPos = new Vec3d(0, 64, 0); public RadialMirror.RadialMirrorSettings getRadialMirrorSettings() {
try { boolean radialMirrorEnabled = buttonRadialMirrorEnabled.isChecked();
radialMirrorPos = new Vec3d(textRadialMirrorPosX.getNumber(), textRadialMirrorPosY.getNumber(), textRadialMirrorPosZ
.getNumber());
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror position not a valid number.");
}
int radialMirrorSlices = 4; Vec3 radialMirrorPos = new Vec3(0, 64, 0);
try { try {
radialMirrorSlices = (int) textRadialMirrorSlices.getNumber(); radialMirrorPos = new Vec3(textRadialMirrorPosX.getNumber(), textRadialMirrorPosY.getNumber(), textRadialMirrorPosZ
} catch (NumberFormatException | NullPointerException ex) { .getNumber());
EffortlessBuilding.log(mc.player, "Radial mirror slices not a valid number."); } catch (NumberFormatException | NullPointerException ex) {
} EffortlessBuilding.log(mc.player, "Radial mirror position not a valid number.");
}
boolean radialMirrorAlternate = buttonRadialMirrorAlternate.isChecked(); int radialMirrorSlices = 4;
try {
radialMirrorSlices = (int) textRadialMirrorSlices.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Radial mirror slices not a valid number.");
}
int radialMirrorRadius = 50; boolean radialMirrorAlternate = buttonRadialMirrorAlternate.isChecked();
try {
radialMirrorRadius = (int) textRadialMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
return new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPos, radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, drawLines, drawPlanes); int radialMirrorRadius = 50;
} try {
radialMirrorRadius = (int) textRadialMirrorRadius.getNumber();
} catch (NumberFormatException | NullPointerException ex) {
EffortlessBuilding.log(mc.player, "Mirror radius not a valid number.");
}
@Override return new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPos, radialMirrorSlices, radialMirrorAlternate, radialMirrorRadius, drawLines, drawPlanes);
protected String getName() { }
return "Radial mirror";
}
@Override @Override
protected int getExpandedHeight() { protected String getName() {
return 100; return "Radial mirror";
} }
@Override
protected int getExpandedHeight() {
return 100;
}
} }

View File

@@ -1,66 +1,62 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.components.Button;
import net.minecraftforge.fml.client.gui.GuiUtils; import net.minecraft.network.chat.Component;
import net.minecraftforge.client.gui.ScreenUtils;
import javax.annotation.ParametersAreNonnullByDefault;
/** /**
* This class provides a checkbox style control. * This class provides a checkbox style control.
*/ */
public class GuiCheckBoxFixed extends Button @ParametersAreNonnullByDefault
{ public class GuiCheckBoxFixed extends Button {
private boolean isChecked; private final int boxWidth;
private int boxWidth; private boolean isChecked;
public GuiCheckBoxFixed(int xPos, int yPos, String displayString, boolean isChecked) public GuiCheckBoxFixed(int xPos, int yPos, String displayString, boolean isChecked) {
{ super(xPos, yPos, Minecraft.getInstance().font.width(displayString) + 2 + 11, 11, Component.literal(displayString), b -> {
super(xPos, yPos, Minecraft.getInstance().fontRenderer.getStringWidth(displayString) + 2 + 11, 11, displayString, b -> {}); });
this.isChecked = isChecked; this.isChecked = isChecked;
this.boxWidth = 11; this.boxWidth = 11;
this.height = 11; this.height = 11;
this.width = this.boxWidth + 2 + Minecraft.getInstance().fontRenderer.getStringWidth(displayString); this.width = this.boxWidth + 2 + Minecraft.getInstance().font.width(displayString);
} }
@Override @Override
public void renderButton(int mouseX, int mouseY, float partial) public void renderButton(PoseStack ms, int mouseX, int mouseY, float partial) {
{ if (this.visible) {
if (this.visible) Minecraft mc = Minecraft.getInstance();
{ this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.boxWidth && mouseY < this.y + this.height;
Minecraft mc = Minecraft.getInstance(); ScreenUtils.blitWithBorder(ms, WIDGETS_LOCATION, this.x, this.y, 0, 46, this.boxWidth, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset());
this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.boxWidth && mouseY < this.y + this.height; this.renderBg(ms, mc, mouseX, mouseY);
GuiUtils.drawContinuousTexturedBox(WIDGETS_LOCATION, this.x, this.y, 0, 46, this.boxWidth, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset()); int color = 14737632;
this.renderBg(mc, mouseX, mouseY);
int color = 14737632;
if (packedFGColor != 0) if (packedFGColor != 0) {
{ color = packedFGColor;
color = packedFGColor; } else if (!this.active) {
} color = 10526880;
else if (!this.active) }
{
color = 10526880;
}
if (this.isChecked) if (this.isChecked)
this.drawCenteredString(mc.fontRenderer, "x", this.x + this.boxWidth / 2 + 1, this.y + 1, 14737632); drawCenteredString(ms, mc.font, "x", this.x + this.boxWidth / 2 + 1, this.y + 1, 14737632);
this.drawString(mc.fontRenderer, getMessage(), this.x + this.boxWidth + 2, this.y + 2, color); drawString(ms, mc.font, getMessage(), this.x + this.boxWidth + 2, this.y + 2, color);
} }
} }
@Override @Override
public void onPress() public void onPress() {
{ this.isChecked = !this.isChecked;
this.isChecked = !this.isChecked; }
}
public boolean isChecked() public boolean isChecked() {
{ return this.isChecked;
return this.isChecked; }
}
public void setIsChecked(boolean isChecked) public void setIsChecked(boolean isChecked) {
{ this.isChecked = isChecked;
this.isChecked = isChecked; }
}
} }

View File

@@ -1,10 +1,11 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.FontRenderer; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
@@ -13,77 +14,77 @@ import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScrollEntry { public abstract class GuiCollapsibleScrollEntry implements GuiScrollPane.IScrollEntry {
public GuiScrollPane scrollPane; public GuiScrollPane scrollPane;
protected FontRenderer font; protected Font font;
protected Minecraft mc; protected Minecraft mc;
protected boolean isCollapsed = true; protected boolean isCollapsed = true;
protected int left, right, top, bottom; protected int left, right, top, bottom;
public GuiCollapsibleScrollEntry(GuiScrollPane scrollPane) { public GuiCollapsibleScrollEntry(GuiScrollPane scrollPane) {
this.scrollPane = scrollPane; this.scrollPane = scrollPane;
this.font = scrollPane.font; this.font = scrollPane.font;
this.mc = Minecraft.getInstance(); this.mc = Minecraft.getInstance();
} }
@Override @Override
public void init(List<Widget> buttonList) { public void init(List<Widget> renderables) {
left = scrollPane.getWidth() / 2 - 140; left = scrollPane.getWidth() / 2 - 140;
right = scrollPane.getWidth() / 2 + 140; right = scrollPane.getWidth() / 2 + 140;
top = scrollPane.getHeight() / 2 - 100; top = scrollPane.getHeight() / 2 - 100;
bottom = scrollPane.getHeight() / 2 + 100; bottom = scrollPane.getHeight() / 2 + 100;
} }
@Override @Override
public void updateScreen() { public void updateScreen() {
} }
@Override @Override
public void drawTooltip(Screen guiScreen, int mouseX, int mouseY) { public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
} }
@Override @Override
public void updatePosition(int slotIndex, int x, int y, float partialTicks) { public void updatePosition(int slotIndex, int x, int y, float partialTicks) {
} }
@Override @Override
public boolean charTyped(char eventChar, int eventKey) { public boolean charTyped(char eventChar, int eventKey) {
return false; return false;
} }
@Override @Override
public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) { public boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY) {
return false; return false;
} }
@Override @Override
public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) { public void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY) {
} }
@Override @Override
public void onGuiClosed() { public void onGuiClosed() {
} }
@Override @Override
public int getHeight() { public int getHeight() {
return isCollapsed ? getCollapsedHeight() : getExpandedHeight(); return isCollapsed ? getCollapsedHeight() : getExpandedHeight();
} }
public void setCollapsed(boolean collapsed) { public void setCollapsed(boolean collapsed) {
this.isCollapsed = collapsed; this.isCollapsed = collapsed;
} }
protected String getName() { protected String getName() {
return "Collapsible scroll entry"; return "Collapsible scroll entry";
} }
protected int getCollapsedHeight() { protected int getCollapsedHeight() {
return 24; return 24;
} }
protected int getExpandedHeight() { protected int getExpandedHeight() {
return 100; return 100;
} }
} }

View File

@@ -1,79 +1,79 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.Minecraft; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.gui.widget.button.Button; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.util.ResourceLocation; import net.minecraft.client.gui.components.Button;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.network.chat.Component;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public class GuiIconButton extends Button { public class GuiIconButton extends Button {
private final ResourceLocation resourceLocation; private final ResourceLocation resourceLocation;
private final int iconX, iconY, iconWidth, iconHeight, iconAltX, iconAltY; private final int iconX, iconY, iconWidth, iconHeight, iconAltX, iconAltY;
List<String> tooltip = new ArrayList<>(); List<Component> tooltip = new ArrayList<>();
private boolean useAltIcon = false; private boolean useAltIcon = false;
public GuiIconButton(int x, int y, int iconX, int iconY, ResourceLocation resourceLocation, Button.IPressable onPress) { public GuiIconButton(int x, int y, int iconX, int iconY, ResourceLocation resourceLocation, Button.OnPress onPress) {
this(x, y, 20, 20, iconX, iconY, 20, 20, 20, 0, resourceLocation, onPress); this(x, y, 20, 20, iconX, iconY, 20, 20, 20, 0, resourceLocation, onPress);
} }
public GuiIconButton(int x, int y, int width, int height, int iconX, int iconY, int iconWidth, int iconHeight, int iconAltX, int iconAltY, ResourceLocation resourceLocation, Button.IPressable onPress) { public GuiIconButton(int x, int y, int width, int height, int iconX, int iconY, int iconWidth, int iconHeight, int iconAltX, int iconAltY, ResourceLocation resourceLocation, Button.OnPress onPress) {
super(x, y, width, height, "", onPress); super(x, y, width, height, Component.empty(), onPress);
this.iconX = iconX; this.iconX = iconX;
this.iconY = iconY; this.iconY = iconY;
this.iconWidth = iconWidth; this.iconWidth = iconWidth;
this.iconHeight = iconHeight; this.iconHeight = iconHeight;
this.iconAltX = iconAltX; this.iconAltX = iconAltX;
this.iconAltY = iconAltY; this.iconAltY = iconAltY;
this.resourceLocation = resourceLocation; this.resourceLocation = resourceLocation;
} }
public void setTooltip(String tooltip) { public void setTooltip(Component tooltip) {
setTooltip(Arrays.asList(tooltip)); setTooltip(Collections.singletonList(tooltip));
} }
public void setTooltip(List<String> tooltip) { public void setTooltip(List<Component> tooltip) {
this.tooltip = tooltip; this.tooltip = tooltip;
} }
public void setUseAlternateIcon(boolean useAlternateIcon) { public void setUseAlternateIcon(boolean useAlternateIcon) {
this.useAltIcon = useAlternateIcon; this.useAltIcon = useAlternateIcon;
} }
@Override @Override
public void render(int mouseX, int mouseY, float partialTicks) { public void render(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
super.render(mouseX, mouseY, partialTicks); super.render(ms, mouseX, mouseY, partialTicks);
if (this.visible) if (this.visible) {
{ this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height; RenderSystem.setShaderTexture(0, this.resourceLocation);
Minecraft.getInstance().getTextureManager().bindTexture(this.resourceLocation); int currentIconX = this.iconX;
int currentIconX = this.iconX; int currentIconY = this.iconY;
int currentIconY = this.iconY;
if (useAltIcon) if (useAltIcon) {
{ currentIconX += iconAltX;
currentIconX += iconAltX; currentIconY += iconAltY;
currentIconY += iconAltY; }
}
//Draws a textured rectangle at the current z-value. Used to be drawTexturedModalRect in Gui. //Draws a textured rectangle at the current z-value. Used to be drawTexturedModalRect in Gui.
this.blit(this.x, this.y, currentIconX, currentIconY, this.iconWidth, this.iconHeight); this.blit(ms, this.x, this.y, currentIconX, currentIconY, this.iconWidth, this.iconHeight);
} }
} }
public void drawTooltip(Screen screen, int mouseX, int mouseY) { public void drawTooltip(PoseStack ms, Screen screen, int mouseX, int mouseY) {
boolean flag = mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height; boolean flag = mouseX >= x && mouseX < x + width && mouseY >= y && mouseY < y + height;
if (flag) { if (flag) {
List<String> textLines = new ArrayList<>(); screen.renderComponentTooltip(ms, tooltip, mouseX - 10, mouseY + 25);
textLines.addAll(tooltip); }
screen.renderTooltip(textLines, mouseX - 10, mouseY + 25); }
}
}
} }

View File

@@ -1,146 +1,160 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui.elements;
import net.minecraft.client.gui.*; import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.gui.widget.TextFieldWidget; import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.widget.button.Button; import net.minecraft.client.gui.components.Widget;
import net.minecraft.util.text.TextFormatting; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Button;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault;
import java.awt.*;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.text.ParseException; import java.text.ParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Collections;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class GuiNumberField extends AbstractGui { @ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class GuiNumberField extends GuiComponent {
public int x, y, width, height; public int x, y, width, height;
public int buttonWidth = 10; public int buttonWidth = 10;
protected TextFieldWidget textField; protected EditBox textField;
protected Button minusButton, plusButton; protected Button minusButton, plusButton;
List<String> tooltip = new ArrayList<>(); List<Component> tooltip = new ArrayList<>();
public GuiNumberField(FontRenderer font, List<Widget> buttonList, int x, int y, int width, int height) { public GuiNumberField(Font font, List<Widget> renderables, int x, int y, int width, int height) {
this.x = x; this.x = x;
this.y = y; this.y = y;
this.width = width; this.width = width;
this.height = height; this.height = height;
textField = new TextFieldWidget(font, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2, ""); textField = new EditBox(font, x + buttonWidth + 1, y + 1, width - 2 * buttonWidth - 2, height - 2, Component.empty());
minusButton = new Button(x, y - 1, buttonWidth, height + 2, "-", button -> { minusButton = new Button(x, y - 1, buttonWidth, height + 2, Component.literal("-"), button -> {
float valueChanged = 1f; float valueChanged = 1f;
if (Screen.hasControlDown()) valueChanged = 5f; if (Screen.hasControlDown()) valueChanged = 5f;
if (Screen.hasShiftDown()) valueChanged = 10f; if (Screen.hasShiftDown()) valueChanged = 10f;
setNumber(getNumber() - valueChanged); setNumber(getNumber() - valueChanged);
}); });
plusButton = new Button(x + width - buttonWidth, y - 1, buttonWidth, height + 2, "+", button -> { plusButton = new Button(x + width - buttonWidth, y - 1, buttonWidth, height + 2, Component.literal("+"), button -> {
float valueChanged = 1f; float valueChanged = 1f;
if (Screen.hasControlDown()) valueChanged = 5f; if (Screen.hasControlDown()) valueChanged = 5f;
if (Screen.hasShiftDown()) valueChanged = 10f; if (Screen.hasShiftDown()) valueChanged = 10f;
setNumber(getNumber() + valueChanged); setNumber(getNumber() + valueChanged);
}); });
buttonList.add(minusButton); renderables.add(minusButton);
buttonList.add(plusButton); renderables.add(plusButton);
} }
public void setNumber(double number) { public double getNumber() {
textField.setText(DecimalFormat.getInstance().format(number)); if (textField.getValue().isEmpty()) return 0;
} try {
return DecimalFormat.getInstance().parse(textField.getValue()).doubleValue();
} catch (ParseException e) {
return 0;
}
}
public double getNumber() { public void setNumber(double number) {
if (textField.getText().isEmpty()) return 0; textField.setValue(DecimalFormat.getInstance().format(number));
try { }
return DecimalFormat.getInstance().parse(textField.getText()).doubleValue();
} catch (ParseException e) {
return 0;
}
}
public void setTooltip(String tooltip) { public void setTooltip(Component tooltip) {
setTooltip(Arrays.asList(tooltip)); setTooltip(Collections.singletonList(tooltip));
} }
public void setTooltip(List<String> tooltip) { public void setTooltip(List<Component> tooltip) {
this.tooltip = tooltip; this.tooltip = tooltip;
} }
public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) { public boolean mouseClicked(double mouseX, double mouseY, int mouseButton) {
boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton); boolean result = textField.mouseClicked(mouseX, mouseY, mouseButton);
//Check if clicked inside textfield //Check if clicked inside textfield
boolean flag = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height; boolean flag = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
//Rightclicked inside textfield //Rightclicked inside textfield
if (flag && mouseButton == 1) { if (flag && mouseButton == 1) {
textField.setText(""); textField.setValue("");
textField.setFocused2(true); textField.setFocus(true);
result = true; result = true;
} }
return result; return result;
} }
public void drawNumberField(int mouseX, int mouseY, float partialTicks) { public void drawNumberField(PoseStack ms, int mouseX, int mouseY, float partialTicks) {
textField.y = y + 1; textField.y = y + 1;
minusButton.y = y - 1; minusButton.y = y - 1;
plusButton.y = y - 1; plusButton.y = y - 1;
textField.render(mouseX, mouseY, partialTicks); textField.render(ms, mouseX, mouseY, partialTicks);
minusButton.render(mouseX, mouseY, partialTicks); minusButton.render(ms, mouseX, mouseY, partialTicks);
plusButton.render(mouseX, mouseY, partialTicks); plusButton.render(ms, mouseX, mouseY, partialTicks);
} }
public void drawTooltip(Screen screen, int mouseX, int mouseY) { public void drawTooltip(PoseStack ms, Screen screen, int mouseX, int mouseY) {
boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height; boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
boolean insideMinusButton = mouseX >= x && mouseX < x + buttonWidth && mouseY >= y && mouseY < y + height; boolean insideMinusButton = mouseX >= x && mouseX < x + buttonWidth && mouseY >= y && mouseY < y + height;
boolean insidePlusButton = mouseX >= x + width - buttonWidth && mouseX < x + width && mouseY >= y && mouseY < y + height; boolean insidePlusButton = mouseX >= x + width - buttonWidth && mouseX < x + width && mouseY >= y && mouseY < y + height;
List<String> textLines = new ArrayList<>(); // List<String> textLines = new ArrayList<>();
if (insideTextField) { List<Component> textLines = new ArrayList<>();
if (!tooltip.isEmpty())
textLines.addAll(tooltip);
if (insideTextField) {
textLines.addAll(tooltip);
// textLines.add(TextFormatting.GRAY + "Tip: try scrolling."); // textLines.add(TextFormatting.GRAY + "Tip: try scrolling.");
} }
if (insideMinusButton) { if (insideMinusButton) {
textLines.add("Hold " + TextFormatting.AQUA + "shift " + TextFormatting.RESET + "for " + TextFormatting.RED + "10"); textLines.add(Component.literal("Hold ").append(Component.literal("shift ").withStyle(ChatFormatting.AQUA)).append("for ")
textLines.add("Hold " + TextFormatting.AQUA + "ctrl " + TextFormatting.RESET + "for " + TextFormatting.RED + "5"); .append(Component.literal("10").withStyle(ChatFormatting.RED)));
} textLines.add(Component.literal("Hold ").append(Component.literal("ctrl ").withStyle(ChatFormatting.AQUA)).append("for ")
.append(Component.literal("5").withStyle(ChatFormatting.RED)));
}
if (insidePlusButton) { if (insidePlusButton) {
textLines.add("Hold " + TextFormatting.AQUA + "shift " + TextFormatting.RESET + "for " + TextFormatting.DARK_GREEN + "10"); textLines.add(Component.literal("Hold ").append(Component.literal("shift ").withStyle(ChatFormatting.DARK_GREEN)).append("for ")
textLines.add("Hold " + TextFormatting.AQUA + "ctrl " + TextFormatting.RESET + "for " + TextFormatting.DARK_GREEN + "5"); .append(Component.literal("10").withStyle(ChatFormatting.RED)));
} textLines.add(Component.literal("Hold ").append(Component.literal("ctrl ").withStyle(ChatFormatting.DARK_GREEN)).append("for ")
.append(Component.literal("5").withStyle(ChatFormatting.RED)));
}
screen.renderTooltip(textLines, mouseX - 10, mouseY + 25); screen.renderComponentTooltip(ms, textLines, mouseX - 10, mouseY + 25);
} }
public void update() { public void update() {
textField.tick(); textField.tick();
} }
public boolean charTyped(char typedChar, int keyCode) { public boolean charTyped(char typedChar, int keyCode) {
if (!textField.isFocused()) return false; if (!textField.isFocused()) return false;
// if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK // if (Character.isDigit(typedChar) || typedChar == '.' || typedChar == '-' || keyCode == Keyboard.KEY_BACK
// || keyCode == Keyboard.KEY_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT // || keyCode == Keyboard.KEY_DELETE || keyCode == Keyboard.KEY_LEFT || keyCode == Keyboard.KEY_RIGHT
// || keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN) { // || keyCode == Keyboard.KEY_UP || keyCode == Keyboard.KEY_DOWN) {
return textField.charTyped(typedChar, keyCode); return textField.charTyped(typedChar, keyCode);
// } // }
} }
//Scroll inside textfield to change number //Scroll inside textfield to change number
//Disabled because entire screen can be scrolled //Disabled because entire screen can be scrolled
// public void handleMouseInput(int mouseX, int mouseY) { // public void handleMouseInput(int mouseX, int mouseY) {
// boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height; // boolean insideTextField = mouseX >= x + buttonWidth && mouseX < x + width - buttonWidth && mouseY >= y && mouseY < y + height;
// //

View File

@@ -1,107 +1,108 @@
package nl.requios.effortlessbuilding.gui.elements; package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.*; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.gui.components.Widget;
import net.minecraft.client.gui.widget.Widget; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.gui.components.AbstractWidget;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.Mth;
import net.minecraft.util.math.MathHelper;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public class GuiScrollPane extends SlotGui { public class GuiScrollPane extends SlotGui {
public Screen parent; public Screen parent;
public FontRenderer font; public Font font;
private List<IScrollEntry> listEntries; private final List<IScrollEntry> listEntries;
private float scrollMultiplier = 1f; private float scrollMultiplier = 1f;
private int mouseX; private int mouseX;
private int mouseY; private int mouseY;
public GuiScrollPane(Screen parent, FontRenderer font, int top, int bottom) { public GuiScrollPane(Screen parent, Font font, int top, int bottom) {
super(Minecraft.getInstance(), parent.width, parent.height, top, bottom, 100); super(Minecraft.getInstance(), parent.width, parent.height, top, bottom, 100);
this.parent = parent; this.parent = parent;
this.font = font; this.font = font;
this.renderSelection = false; this.renderSelection = false;
listEntries = new ArrayList<>(); listEntries = new ArrayList<>();
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
} }
public IScrollEntry getListEntry(int index) { public IScrollEntry getListEntry(int index) {
return listEntries.get(index); return listEntries.get(index);
} }
public void AddListEntry(IScrollEntry listEntry){ public void AddListEntry(IScrollEntry listEntry) {
listEntries.add(listEntry); listEntries.add(listEntry);
} }
@Override @Override
protected int getItemCount() { protected int getItemCount() {
return listEntries.size(); return listEntries.size();
} }
@Override @Override
protected boolean isSelectedItem(int slotIndex) { protected boolean isSelectedItem(int slotIndex) {
return false; return false;
} }
@Override @Override
protected int getScrollbarPosition() { protected int getScrollbarPosition() {
//return width / 2 + 140 + 10; //return width / 2 + 140 + 10;
return width - 15; return width - 15;
} }
@Override @Override
public int getRowWidth() { public int getRowWidth() {
return 280; return 280;
} }
//Removed background //Removed background
@Override @Override
public void render(int mouseXIn, int mouseYIn, float partialTicks) public void render(PoseStack ms, int mouseXIn, int mouseYIn, float partialTicks) {
{ if (this.visible) {
if (this.visible) { this.mouseX = mouseXIn;
this.mouseX = mouseXIn; this.mouseY = mouseYIn;
this.mouseY = mouseYIn; this.renderBackground();
this.renderBackground(); int scrollbarLeft = this.getScrollbarPosition();
int scrollbarLeft = this.getScrollbarPosition(); int scrollbarRight = scrollbarLeft + 6;
int scrollbarRight = scrollbarLeft + 6; this.capYPosition();
this.capYPosition();
Tessellator tessellator = Tessellator.getInstance(); Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuffer(); BufferBuilder bufferbuilder = tessellator.getBuilder();
int insideLeft = this.x0 + this.width / 2 - this.getRowWidth() / 2 + 2; int insideLeft = this.x0 + this.width / 2 - this.getRowWidth() / 2 + 2;
int insideTop = this.y0 + 4 - (int) this.yo; int insideTop = this.y0 + 4 - (int) this.yo;
if (this.renderHeader) { if (this.renderHeader) {
this.renderHeader(insideLeft, insideTop, tessellator); this.renderHeader(insideLeft, insideTop, tessellator);
} }
//All entries //All entries
this.renderList(insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks); this.renderList(ms, insideLeft, insideTop, mouseXIn, mouseYIn, partialTicks);
RenderSystem.disableDepthTest(); RenderSystem.disableDepthTest();
//Dirt overlays on top and bottom //Dirt overlays on top and bottom
// this.renderHoleBackground(0, this.y0, 255, 255); // this.renderHoleBackground(0, this.y0, 255, 255);
// this.renderHoleBackground(this.y1, this.height, 255, 255); // this.renderHoleBackground(this.y1, this.height, 255, 255);
RenderSystem.enableBlend(); RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE); RenderSystem.blendFuncSeparate(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SourceFactor.ZERO, GlStateManager.DestFactor.ONE);
RenderSystem.disableAlphaTest(); RenderSystem.disableTexture();
RenderSystem.shadeModel(7425);
RenderSystem.disableTexture();
//top //top
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); // bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.x0, (double)(this.y0 + 4), 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 0).endVertex(); // bufferbuilder.pos((double)this.x0, (double)(this.y0 + 4), 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 0).endVertex();
// bufferbuilder.pos((double)this.x1, (double)(this.y0 + 4), 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 0).endVertex(); // bufferbuilder.pos((double)this.x1, (double)(this.y0 + 4), 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 0).endVertex();
@@ -109,7 +110,7 @@ public class GuiScrollPane extends SlotGui {
// bufferbuilder.pos((double)this.x0, (double)this.y0, 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex(); // bufferbuilder.pos((double)this.x0, (double)this.y0, 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 255).endVertex();
// tessellator.draw(); // tessellator.draw();
//bottom //bottom
// bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); // bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR);
// bufferbuilder.pos((double)this.x0, (double)this.y1, 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex(); // bufferbuilder.pos((double)this.x0, (double)this.y1, 0.0D).tex(0.0D, 1.0D).color(0, 0, 0, 255).endVertex();
// bufferbuilder.pos((double)this.x1, (double)this.y1, 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex(); // bufferbuilder.pos((double)this.x1, (double)this.y1, 0.0D).tex(1.0D, 1.0D).color(0, 0, 0, 255).endVertex();
@@ -117,103 +118,106 @@ public class GuiScrollPane extends SlotGui {
// bufferbuilder.pos((double)this.x0, (double)(this.y1 - 4), 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 0).endVertex(); // bufferbuilder.pos((double)this.x0, (double)(this.y1 - 4), 0.0D).tex(0.0D, 0.0D).color(0, 0, 0, 0).endVertex();
// tessellator.draw(); // tessellator.draw();
//Draw scrollbar //Draw scrollbar
int maxScroll = this.getMaxScroll(); int maxScroll = this.getMaxScroll();
if (maxScroll > 0) { if (maxScroll > 0) {
int k1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition()); int k1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition());
k1 = MathHelper.clamp(k1, 32, this.y1 - this.y0 - 8); k1 = Mth.clamp(k1, 32, this.y1 - this.y0 - 8);
int l1 = (int) this.yo * (this.y1 - this.y0 - k1) / maxScroll + this.y0; int l1 = (int) this.yo * (this.y1 - this.y0 - k1) / maxScroll + this.y0;
if (l1 < this.y0) { if (l1 < this.y0) {
l1 = this.y0; l1 = this.y0;
} }
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.pos((double) scrollbarLeft, (double) this.y1, 0.0F).tex(0.0F, 1.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(scrollbarLeft, this.y1, 0.0F).uv(0.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double) scrollbarRight, (double) this.y1, 0.0F).tex(1.0F, 1.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(scrollbarRight, this.y1, 0.0F).uv(1.0F, 1.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double) scrollbarRight, (double) this.y0, 0.0F).tex(1.0F, 0.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(scrollbarRight, this.y0, 0.0F).uv(1.0F, 0.0F).color(0, 0, 0, 255).endVertex();
bufferbuilder.pos((double) scrollbarLeft, (double) this.y0, 0.0F).tex(0.0F, 0.0F).color(0, 0, 0, 255).endVertex(); bufferbuilder.vertex(scrollbarLeft, this.y0, 0.0F).uv(0.0F, 0.0F).color(0, 0, 0, 255).endVertex();
tessellator.draw(); tessellator.end();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.pos((double) scrollbarLeft, (double) (l1 + k1), 0.0F).tex(0.0F, 1.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(scrollbarLeft, l1 + k1, 0.0F).uv(0.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double) scrollbarRight, (double) (l1 + k1), 0.0F).tex(1.0F, 1.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(scrollbarRight, l1 + k1, 0.0F).uv(1.0F, 1.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double) scrollbarRight, (double) l1, 0.0F).tex(1.0F, 0.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(scrollbarRight, l1, 0.0F).uv(1.0F, 0.0F).color(128, 128, 128, 255).endVertex();
bufferbuilder.pos((double) scrollbarLeft, (double) l1, 0.0F).tex(0.0F, 0.0F).color(128, 128, 128, 255).endVertex(); bufferbuilder.vertex(scrollbarLeft, l1, 0.0F).uv(0.0F, 0.0F).color(128, 128, 128, 255).endVertex();
tessellator.draw(); tessellator.end();
bufferbuilder.begin(7, DefaultVertexFormats.POSITION_TEX_COLOR); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION_TEX_COLOR);
bufferbuilder.pos((double) scrollbarLeft, (double) (l1 + k1 - 1), 0.0F).tex(0.0F, 1.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(scrollbarLeft, l1 + k1 - 1, 0.0F).uv(0.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double) (scrollbarRight - 1), (double) (l1 + k1 - 1), 0.0F).tex(1.0F, 1.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(scrollbarRight - 1, l1 + k1 - 1, 0.0F).uv(1.0F, 1.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double) (scrollbarRight - 1), (double) l1, 0.0F).tex(1.0F, 0.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(scrollbarRight - 1, l1, 0.0F).uv(1.0F, 0.0F).color(192, 192, 192, 255).endVertex();
bufferbuilder.pos((double) scrollbarLeft, (double) l1, 0.0F).tex(0.0F, 0.0F).color(192, 192, 192, 255).endVertex(); bufferbuilder.vertex(scrollbarLeft, l1, 0.0F).uv(0.0F, 0.0F).color(192, 192, 192, 255).endVertex();
tessellator.draw(); tessellator.end();
} }
//this.renderDecorations(mouseXIn, mouseYIn); //this.renderDecorations(mouseXIn, mouseYIn);
RenderSystem.enableTexture(); RenderSystem.enableTexture();
RenderSystem.shadeModel(7424); RenderSystem.disableBlend();
RenderSystem.enableAlphaTest(); }
RenderSystem.disableBlend(); }
}
}
//SLOTHEIGHT MODIFICATIONS //SLOTHEIGHT MODIFICATIONS
//SlotHeight is still relied on for determining how much to scroll //SlotHeight is still relied on for determining how much to scroll
@Override @Override
protected int getMaxPosition() { protected int getMaxPosition() {
//Add every entry height //Add every entry height
int height = this.headerHeight; int height = this.headerHeight;
for (IScrollEntry entry : listEntries) { for (IScrollEntry entry : listEntries) {
height += entry.getHeight(); height += entry.getHeight();
} }
return height; return height;
} }
@Override @Override
protected void renderBackground() { protected void renderBackground() {
} }
@Override @Override
protected void renderItem(int slotIndex, int xPos, int yPos, int heightIn, int mouseXIn, int mouseYIn, float partialTicks) { protected void renderItem(PoseStack ms, int slotIndex, int xPos, int yPos, int heightIn, int mouseXIn, int mouseYIn, float partialTicks) {
this.getListEntry(slotIndex).drawEntry(slotIndex, xPos, yPos, this.getRowWidth(), heightIn, mouseXIn, mouseYIn, this.getListEntry(slotIndex).drawEntry(ms, slotIndex, xPos, yPos, this.getRowWidth(), heightIn, mouseXIn, mouseYIn,
this.getSlotIndexFromScreenCoords(mouseXIn, mouseYIn) == slotIndex, partialTicks); this.getSlotIndexFromScreenCoords(mouseXIn, mouseYIn) == slotIndex, partialTicks);
} }
public int getMaxPosition(int count) { public int getMaxPosition(int count) {
//Add all count entry heights //Add all count entry heights
int height = this.headerHeight; int height = this.headerHeight;
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
IScrollEntry entry = listEntries.get(i); IScrollEntry entry = listEntries.get(i);
height += entry.getHeight(); height += entry.getHeight();
} }
return height; return height;
} }
public int getSlotIndexFromScreenCoords(double posX, double posY) { public int getSlotIndexFromScreenCoords(double posX, double posY) {
int left = this.x0 + (this.width - this.getRowWidth()) / 2; int left = this.x0 + (this.width - this.getRowWidth()) / 2;
int right = this.x0 + (this.width + this.getRowWidth()) / 2; int right = this.x0 + (this.width + this.getRowWidth()) / 2;
double relativeMouseY = getRelativeMouseY(mouseY, 0); double relativeMouseY = getRelativeMouseY(mouseY, 0);
//Iterate over every entry until relativeMouseY falls within its height //Iterate over every entry until relativeMouseY falls within its height
for (int i = 0; i < listEntries.size(); i++) { for (int i = 0; i < listEntries.size(); i++) {
IScrollEntry entry = listEntries.get(i); IScrollEntry entry = listEntries.get(i);
if (relativeMouseY <= entry.getHeight()) if (relativeMouseY <= entry.getHeight())
return posX < this.getScrollbarPosition() && posX >= left && posX <= right && i >= 0 && return posX < this.getScrollbarPosition() && posX >= left && posX <= right && i >= 0 &&
relativeMouseY >= 0 && i < this.getItemCount() ? i : -1; relativeMouseY >= 0 && i < this.getItemCount() ? i : -1;
relativeMouseY -= entry.getHeight(); relativeMouseY -= entry.getHeight();
} }
return -1; return -1;
} }
@Override @Override
public boolean mouseClicked(double mouseX, double mouseY, int button) { public List<? extends GuiEventListener> children() {
int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY); return null;
double relativeX = getRelativeMouseX(mouseX); }
//Always pass through mouseclicked, to be able to unfocus textfields @Override
for (int i = 0; i < this.listEntries.size(); i++) { public boolean mouseClicked(double mouseX, double mouseY, int button) {
double relativeY = getRelativeMouseY(mouseY, i); int selectedSlot = this.getSlotIndexFromScreenCoords(mouseX, mouseY);
this.getListEntry(i).mousePressed(selectedSlot, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY); double relativeX = getRelativeMouseX(mouseX);
}
//Always pass through mouseclicked, to be able to unfocus textfields
for (int i = 0; i < this.listEntries.size(); i++) {
double relativeY = getRelativeMouseY(mouseY, i);
this.getListEntry(i).mousePressed(selectedSlot, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY);
}
// if (this.isMouseYWithinSlotBounds(mouseY)) // if (this.isMouseYWithinSlotBounds(mouseY))
@@ -233,234 +237,230 @@ public class GuiScrollPane extends SlotGui {
// } // }
// } // }
return false; return false;
} }
@Override @Override
public boolean mouseReleased(double mouseX, double mouseY, int button) { public boolean mouseReleased(double mouseX, double mouseY, int button) {
for (int i = 0; i < this.getItemCount(); ++i) for (int i = 0; i < this.getItemCount(); ++i) {
{ double relativeX = getRelativeMouseX(mouseX);
double relativeX = getRelativeMouseX(mouseX); double relativeY = getRelativeMouseY(mouseY, i);
double relativeY = getRelativeMouseY(mouseY, i); this.getListEntry(i).mouseReleased(i, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY);
this.getListEntry(i).mouseReleased(i, (int) mouseX, (int) mouseY, button, (int) relativeX, (int) relativeY); }
}
this.visible = true; this.visible = true;
return false; return false;
} }
public void handleMouseInput() { public void handleMouseInput() {
if (this.isMouseInList(this.mouseX, this.mouseY)) { if (this.isMouseInList(this.mouseX, this.mouseY)) {
if (minecraft.mouseHelper.isLeftDown() && this.mouseY >= this.y0 && if (minecraft.mouseHandler.isLeftPressed() && this.mouseY >= this.y0 &&
this.mouseY <= this.y1) { this.mouseY <= this.y1) {
int i = this.x0 + (this.width - this.getRowWidth()) / 2; int i = this.x0 + (this.width - this.getRowWidth()) / 2;
int j = this.x0 + (this.width + this.getRowWidth()) / 2; int j = this.x0 + (this.width + this.getRowWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY); int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex); double relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (slotIndex > -1) { if (slotIndex > -1) {
this.mouseClicked(this.mouseX, this.mouseY, 0); this.mouseClicked(this.mouseX, this.mouseY, 0);
} else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) { } else if (this.mouseX >= i && this.mouseX <= j && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i, this.mouseY - this.y0 + (int) this.yo - 4); this.clickedHeader(this.mouseX - i, this.mouseY - this.y0 + (int) this.yo - 4);
} }
} }
if (minecraft.mouseHelper.isLeftDown() && this.isVisible()) { if (minecraft.mouseHandler.isLeftPressed() && this.isVisible()) {
if (this.yDrag == -1) { if (this.yDrag == -1) {
boolean flag1 = true; boolean flag1 = true;
if (this.mouseY >= this.y0 && this.mouseY <= this.y1) { if (this.mouseY >= this.y0 && this.mouseY <= this.y1) {
int i2 = this.x0 + (this.width - this.getRowWidth()) / 2; int i2 = this.x0 + (this.width - this.getRowWidth()) / 2;
int j2 = this.x0 + (this.width + this.getRowWidth()) / 2; int j2 = this.x0 + (this.width + this.getRowWidth()) / 2;
int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY); int slotIndex = getSlotIndexFromScreenCoords(this.mouseX, this.mouseY);
double relativeMouseY = getRelativeMouseY(mouseY, slotIndex); double relativeMouseY = getRelativeMouseY(mouseY, slotIndex);
if (slotIndex > -1) { if (slotIndex > -1) {
this.mouseClicked(slotIndex, this.mouseX, this.mouseY); this.mouseClicked(slotIndex, this.mouseX, this.mouseY);
} else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) { } else if (this.mouseX >= i2 && this.mouseX <= j2 && relativeMouseY < 0) {
this.clickedHeader(this.mouseX - i2, this.clickedHeader(this.mouseX - i2,
this.mouseY - this.y0 + (int) this.yo - 4); this.mouseY - this.y0 + (int) this.yo - 4);
flag1 = false; flag1 = false;
} }
int i3 = this.getScrollbarPosition(); int i3 = this.getScrollbarPosition();
int j1 = i3 + 6; int j1 = i3 + 6;
if (this.mouseX >= i3 && this.mouseX <= j1) { if (this.mouseX >= i3 && this.mouseX <= j1) {
this.scrollMultiplier = -1.0F; this.scrollMultiplier = -1.0F;
int maxScroll = this.getMaxScroll(); int maxScroll = this.getMaxScroll();
if (maxScroll < 1) { if (maxScroll < 1) {
maxScroll = 1; maxScroll = 1;
} }
int l1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / int l1 = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) /
(float) this.getMaxPosition()); (float) this.getMaxPosition());
l1 = MathHelper.clamp(l1, 32, this.y1 - this.y0 - 8); l1 = Mth.clamp(l1, 32, this.y1 - this.y0 - 8);
this.scrollMultiplier /= (float) (this.y1 - this.y0 - l1) / (float) maxScroll; this.scrollMultiplier /= (float) (this.y1 - this.y0 - l1) / (float) maxScroll;
} else { } else {
this.scrollMultiplier = 1.0F; this.scrollMultiplier = 1.0F;
} }
if (flag1) { if (flag1) {
this.yDrag = this.mouseY; this.yDrag = this.mouseY;
} else { } else {
this.yDrag = -2; this.yDrag = -2;
} }
} else { } else {
this.yDrag = -2; this.yDrag = -2;
} }
} else if (this.yDrag >= 0) { } else if (this.yDrag >= 0) {
this.yo -= (float) (this.mouseY - this.yDrag) * this.scrollMultiplier; this.yo -= (float) (this.mouseY - this.yDrag) * this.scrollMultiplier;
this.yDrag = this.mouseY; this.yDrag = this.mouseY;
} }
} else { } else {
this.yDrag = -1; this.yDrag = -1;
} }
} }
} }
//Draw in center if it fits //Draw in center if it fits
@Override @Override
protected void renderList(int insideLeft, int insideTop, int mouseXIn, int mouseYIn, float partialTicks) protected void renderList(PoseStack ms, int insideLeft, int insideTop, int mouseXIn, int mouseYIn, float partialTicks) {
{ int itemCount = this.getItemCount();
int itemCount = this.getItemCount(); Tesselator tessellator = Tesselator.getInstance();
Tessellator tessellator = Tessellator.getInstance(); BufferBuilder bufferbuilder = tessellator.getBuilder();
BufferBuilder bufferbuilder = tessellator.getBuffer();
//Find y to start with //Find y to start with
int y = this.headerHeight + insideTop; int y = this.headerHeight + insideTop;
int contentHeight = getMaxPosition(); int contentHeight = getMaxPosition();
int insideHeight = this.y1 - this.y0 - 4; int insideHeight = this.y1 - this.y0 - 4;
if (contentHeight < insideHeight) { if (contentHeight < insideHeight) {
//it fits, so we can center it vertically //it fits, so we can center it vertically
y += (insideHeight - contentHeight) / 2; y += (insideHeight - contentHeight) / 2;
} }
//Draw all entries //Draw all entries
for (int i = 0; i < itemCount; ++i) for (int i = 0; i < itemCount; ++i) {
{ int entryHeight = listEntries.get(i).getHeight();
int entryHeight = listEntries.get(i).getHeight(); int entryHeight2 = entryHeight - 4;
int entryHeight2 = entryHeight - 4;
if (y > this.y1 || y + entryHeight2 < this.y0) if (y > this.y1 || y + entryHeight2 < this.y0) {
{ this.updateItemPosition(i, insideLeft, y, partialTicks);
this.updateItemPosition(i, insideLeft, y, partialTicks); }
}
if (this.renderSelection && this.isSelectedItem(i)) { if (this.renderSelection && this.isSelectedItem(i)) {
int i1 = this.x0 + this.width / 2 - this.getRowWidth() / 2; int i1 = this.x0 + this.width / 2 - this.getRowWidth() / 2;
int j1 = this.x0 + this.width / 2 + this.getRowWidth() / 2; int j1 = this.x0 + this.width / 2 + this.getRowWidth() / 2;
RenderSystem.disableTexture(); RenderSystem.disableTexture();
float f = this.isFocused() ? 1.0F : 0.5F; float f = this.isFocused() ? 1.0F : 0.5F;
RenderSystem.color4f(f, f, f, 1.0F); RenderSystem.setShaderColor(f, f, f, 1.0F);
bufferbuilder.begin(7, DefaultVertexFormats.POSITION); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.pos((double)i1, (double)(y + entryHeight2 + 2), 0.0D).endVertex(); bufferbuilder.vertex(i1, y + entryHeight2 + 2, 0.0D).endVertex();
bufferbuilder.pos((double)j1, (double)(y + entryHeight2 + 2), 0.0D).endVertex(); bufferbuilder.vertex(j1, y + entryHeight2 + 2, 0.0D).endVertex();
bufferbuilder.pos((double)j1, (double)(y - 2), 0.0D).endVertex(); bufferbuilder.vertex(j1, y - 2, 0.0D).endVertex();
bufferbuilder.pos((double)i1, (double)(y - 2), 0.0D).endVertex(); bufferbuilder.vertex(i1, y - 2, 0.0D).endVertex();
tessellator.draw(); tessellator.end();
RenderSystem.color4f(0.0F, 0.0F, 0.0F, 1.0F); RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F);
bufferbuilder.begin(7, DefaultVertexFormats.POSITION); bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.pos((double)(i1 + 1), (double)(y + entryHeight2 + 1), 0.0D).endVertex(); bufferbuilder.vertex(i1 + 1, y + entryHeight2 + 1, 0.0D).endVertex();
bufferbuilder.pos((double)(j1 - 1), (double)(y + entryHeight2 + 1), 0.0D).endVertex(); bufferbuilder.vertex(j1 - 1, y + entryHeight2 + 1, 0.0D).endVertex();
bufferbuilder.pos((double)(j1 - 1), (double)(y - 1), 0.0D).endVertex(); bufferbuilder.vertex(j1 - 1, y - 1, 0.0D).endVertex();
bufferbuilder.pos((double)(i1 + 1), (double)(y - 1), 0.0D).endVertex(); bufferbuilder.vertex(i1 + 1, y - 1, 0.0D).endVertex();
tessellator.draw(); tessellator.end();
RenderSystem.enableTexture(); RenderSystem.enableTexture();
} }
this.renderItem(i, insideLeft, y, entryHeight2, mouseXIn, mouseYIn, partialTicks); this.renderItem(ms, i, insideLeft, y, entryHeight2, mouseXIn, mouseYIn, partialTicks);
y += entryHeight; y += entryHeight;
} }
} }
private double getRelativeMouseX(double mouseX) { private double getRelativeMouseX(double mouseX) {
int j = this.x0 + this.width / 2 - this.getRowWidth() / 2 + 2; int j = this.x0 + this.width / 2 - this.getRowWidth() / 2 + 2;
return mouseX - j; return mouseX - j;
} }
private double getRelativeMouseY(double mouseY, int contentIndex) { private double getRelativeMouseY(double mouseY, int contentIndex) {
int k = this.y0 + 4 - this.getScroll() + getMaxPosition(contentIndex) + this.headerHeight; int k = this.y0 + 4 - this.getScroll() + getMaxPosition(contentIndex) + this.headerHeight;
double relativeMouseY = mouseY - k; double relativeMouseY = mouseY - k;
//Content might be centered, adjust relative mouse y accordingly //Content might be centered, adjust relative mouse y accordingly
int contentHeight = getMaxPosition(); int contentHeight = getMaxPosition();
int insideHeight = this.y1 - this.y0 - 4; int insideHeight = this.y1 - this.y0 - 4;
if (contentHeight < insideHeight) { if (contentHeight < insideHeight) {
//it fits, so we can center it vertically //it fits, so we can center it vertically
relativeMouseY -= (insideHeight - contentHeight) / 2f; relativeMouseY -= (insideHeight - contentHeight) / 2f;
} }
return relativeMouseY; return relativeMouseY;
} }
//PASSTHROUGHS //PASSTHROUGHS
public void init(List<Widget> buttonList) { public void init(List<Widget> renderables) {
for (IScrollEntry entry : this.listEntries) { for (IScrollEntry entry : this.listEntries) {
entry.init(buttonList); entry.init(renderables);
} }
} }
public void updateScreen() { public void updateScreen() {
for (IScrollEntry entry : this.listEntries) for (IScrollEntry entry : this.listEntries)
entry.updateScreen(); entry.updateScreen();
} }
public void drawTooltip(Screen guiScreen, int mouseX, int mouseY) { public void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY) {
for (IScrollEntry entry : this.listEntries) for (IScrollEntry entry : this.listEntries)
entry.drawTooltip(guiScreen, mouseX, mouseY); entry.drawTooltip(ms, guiScreen, mouseX, mouseY);
} }
@Override @Override
public boolean charTyped(char eventChar, int eventKey) { public boolean charTyped(char eventChar, int eventKey) {
for (IScrollEntry entry : this.listEntries) for (IScrollEntry entry : this.listEntries)
entry.charTyped(eventChar, eventKey); entry.charTyped(eventChar, eventKey);
return false; return false;
} }
public void onGuiClosed() { public void onGuiClosed() {
for (IScrollEntry entry : this.listEntries) for (IScrollEntry entry : this.listEntries)
entry.onGuiClosed(); entry.onGuiClosed();
} }
//Make protected values available //Make protected values available
public int getWidth() { public int getWidth() {
return width; return width;
} }
public int getHeight() { public int getHeight() {
return height; return height;
} }
public interface IScrollEntry { public interface IScrollEntry {
void init(List<Widget> buttonList); void init(List<Widget> renderables);
void updateScreen(); void updateScreen();
void drawTooltip(Screen guiScreen, int mouseX, int mouseY); void drawTooltip(PoseStack ms, Screen guiScreen, int mouseX, int mouseY);
boolean charTyped(char eventChar, int eventKey); boolean charTyped(char eventChar, int eventKey);
void onGuiClosed(); void onGuiClosed();
int getHeight(); int getHeight();
void updatePosition(int slotIndex, int x, int y, float partialTicks); void updatePosition(int slotIndex, int x, int y, float partialTicks);
void drawEntry(int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partialTicks); void drawEntry(PoseStack ms, int slotIndex, int x, int y, int listWidth, int slotHeight, int mouseX, int mouseY, boolean isSelected, float partialTicks);
/** /**
* Called when the mouse is clicked within this entry. Returning true means that something within this entry was * Called when the mouse is clicked within this entry. Returning true means that something within this entry was
* clicked and the list should not be dragged. * clicked and the list should not be dragged.
*/ */
boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY); boolean mousePressed(int slotIndex, int mouseX, int mouseY, int mouseEvent, int relativeX, int relativeY);
/** /**
* Fired when the mouse button is released. Arguments: index, x, y, mouseEvent, relativeX, relativeY * Fired when the mouse button is released. Arguments: index, x, y, mouseEvent, relativeX, relativeY
*/ */
void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY); void mouseReleased(int slotIndex, int x, int y, int mouseEvent, int relativeX, int relativeY);
} }
} }

View File

@@ -0,0 +1,260 @@
package nl.requios.effortlessbuilding.gui.elements;
import com.mojang.blaze3d.vertex.*;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.components.Widget;
import net.minecraft.util.Mth;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.Collections;
import java.util.List;
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
@SuppressWarnings("deprecation")
public abstract class SlotGui extends AbstractContainerEventHandler implements Widget {
protected final Minecraft minecraft;
protected final int itemHeight;
protected int width;
protected int height;
protected int y0;
protected int y1;
protected int x1;
protected int x0;
protected int yDrag = -2;
protected double yo;
protected boolean visible = true;
protected boolean renderSelection = true;
protected boolean renderHeader;
protected int headerHeight;
private boolean scrolling;
public SlotGui(Minecraft mcIn, int width, int height, int topIn, int bottomIn, int slotHeightIn) {
this.minecraft = mcIn;
this.width = width;
this.height = height;
this.y0 = topIn;
this.y1 = bottomIn;
this.itemHeight = slotHeightIn;
this.x0 = 0;
this.x1 = width;
}
public boolean isVisible() {
return this.visible;
}
protected abstract int getItemCount();
public List<? extends GuiEventListener> children() {
return Collections.emptyList();
}
protected boolean selectItem(int p_selectItem_1_, int p_selectItem_2_, double p_selectItem_3_, double p_selectItem_5_) {
return true;
}
protected abstract boolean isSelectedItem(int p_isSelectedItem_1_);
protected int getMaxPosition() {
return this.getItemCount() * this.itemHeight + this.headerHeight;
}
protected abstract void renderBackground();
protected void updateItemPosition(int p_updateItemPosition_1_, int p_updateItemPosition_2_, int p_updateItemPosition_3_, float p_updateItemPosition_4_) {
}
protected abstract void renderItem(PoseStack ms, int p_renderItem_1_, int p_renderItem_2_, int p_renderItem_3_, int p_renderItem_4_, int p_renderItem_5_, int p_renderItem_6_, float p_renderItem_7_);
protected void renderHeader(int p_renderHeader_1_, int p_renderHeader_2_, Tesselator p_renderHeader_3_) {
}
protected void clickedHeader(int p_clickedHeader_1_, int p_clickedHeader_2_) {
}
public int getItemAtPosition(double p_getItemAtPosition_1_, double p_getItemAtPosition_3_) {
int i = this.x0 + this.width / 2 - this.getRowWidth() / 2;
int j = this.x0 + this.width / 2 + this.getRowWidth() / 2;
int k = Mth.floor(p_getItemAtPosition_3_ - (double) this.y0) - this.headerHeight + (int) this.yo - 4;
int l = k / this.itemHeight;
return p_getItemAtPosition_1_ < (double) this.getScrollbarPosition() && p_getItemAtPosition_1_ >= (double) i && p_getItemAtPosition_1_ <= (double) j && l >= 0 && k >= 0 && l < this.getItemCount() ? l : -1;
}
protected void capYPosition() {
this.yo = Mth.clamp(this.yo, 0.0D, this.getMaxScroll());
}
public int getMaxScroll() {
return Math.max(0, this.getMaxPosition() - (this.y1 - this.y0 - 4));
}
public int getScroll() {
return (int) this.yo;
}
public boolean isMouseInList(double p_isMouseInList_1_, double p_isMouseInList_3_) {
return p_isMouseInList_3_ >= (double) this.y0 && p_isMouseInList_3_ <= (double) this.y1 && p_isMouseInList_1_ >= (double) this.x0 && p_isMouseInList_1_ <= (double) this.x1;
}
public abstract void render(PoseStack ms, int p_render_1_, int p_render_2_, float p_render_3_);
protected void updateScrollingState(double p_updateScrollingState_1_, double p_updateScrollingState_3_, int p_updateScrollingState_5_) {
this.scrolling = p_updateScrollingState_5_ == 0 && p_updateScrollingState_1_ >= (double) this.getScrollbarPosition() && p_updateScrollingState_1_ < (double) (this.getScrollbarPosition() + 6);
}
public boolean mouseClicked(double p_mouseClicked_1_, double p_mouseClicked_3_, int p_mouseClicked_5_) {
this.updateScrollingState(p_mouseClicked_1_, p_mouseClicked_3_, p_mouseClicked_5_);
if (this.isVisible() && this.isMouseInList(p_mouseClicked_1_, p_mouseClicked_3_)) {
int i = this.getItemAtPosition(p_mouseClicked_1_, p_mouseClicked_3_);
if (i == -1 && p_mouseClicked_5_ == 0) {
this.clickedHeader((int) (p_mouseClicked_1_ - (double) (this.x0 + this.width / 2 - this.getRowWidth() / 2)), (int) (p_mouseClicked_3_ - (double) this.y0) + (int) this.yo - 4);
return true;
} else if (i != -1 && this.selectItem(i, p_mouseClicked_5_, p_mouseClicked_1_, p_mouseClicked_3_)) {
if (this.children().size() > i) {
this.setFocused(this.children().get(i));
}
this.setDragging(true);
return true;
} else {
return this.scrolling;
}
} else {
return false;
}
}
public boolean mouseReleased(double p_mouseReleased_1_, double p_mouseReleased_3_, int p_mouseReleased_5_) {
if (this.getFocused() != null) {
this.getFocused().mouseReleased(p_mouseReleased_1_, p_mouseReleased_3_, p_mouseReleased_5_);
}
return false;
}
public boolean mouseDragged(double p_mouseDragged_1_, double p_mouseDragged_3_, int p_mouseDragged_5_, double p_mouseDragged_6_, double p_mouseDragged_8_) {
if (super.mouseDragged(p_mouseDragged_1_, p_mouseDragged_3_, p_mouseDragged_5_, p_mouseDragged_6_, p_mouseDragged_8_)) {
return true;
} else if (this.isVisible() && p_mouseDragged_5_ == 0 && this.scrolling) {
if (p_mouseDragged_3_ < (double) this.y0) {
this.yo = 0.0D;
} else if (p_mouseDragged_3_ > (double) this.y1) {
this.yo = this.getMaxScroll();
} else {
double d0 = this.getMaxScroll();
if (d0 < 1.0D) {
d0 = 1.0D;
}
int i = (int) ((float) ((this.y1 - this.y0) * (this.y1 - this.y0)) / (float) this.getMaxPosition());
i = Mth.clamp(i, 32, this.y1 - this.y0 - 8);
double d1 = d0 / (double) (this.y1 - this.y0 - i);
if (d1 < 1.0D) {
d1 = 1.0D;
}
this.yo += p_mouseDragged_8_ * d1;
this.capYPosition();
}
return true;
} else {
return false;
}
}
public boolean mouseScrolled(double p_mouseScrolled_1_, double p_mouseScrolled_3_, double p_mouseScrolled_5_) {
if (!this.isVisible()) {
return false;
} else {
this.yo -= p_mouseScrolled_5_ * (double) this.itemHeight / 2.0D;
return true;
}
}
public boolean keyPressed(int p_keyPressed_1_, int p_keyPressed_2_, int p_keyPressed_3_) {
if (!this.isVisible()) {
return false;
} else if (super.keyPressed(p_keyPressed_1_, p_keyPressed_2_, p_keyPressed_3_)) {
return true;
} else if (p_keyPressed_1_ == 264) {
this.moveSelection(1);
return true;
} else if (p_keyPressed_1_ == 265) {
this.moveSelection(-1);
return true;
} else {
return false;
}
}
protected void moveSelection(int p_moveSelection_1_) {
}
public boolean charTyped(char p_charTyped_1_, int p_charTyped_2_) {
return this.isVisible() && super.charTyped(p_charTyped_1_, p_charTyped_2_);
}
public boolean isMouseOver(double p_isMouseOver_1_, double p_isMouseOver_3_) {
return this.isMouseInList(p_isMouseOver_1_, p_isMouseOver_3_);
}
public int getRowWidth() {
return 220;
}
protected void renderList(PoseStack ms, int p_renderList_1_, int p_renderList_2_, int p_renderList_3_, int p_renderList_4_, float p_renderList_5_) {
int i = this.getItemCount();
Tesselator tessellator = Tesselator.getInstance();
BufferBuilder bufferbuilder = tessellator.getBuilder();
for (int j = 0; j < i; ++j) {
int k = p_renderList_2_ + j * this.itemHeight + this.headerHeight;
int l = this.itemHeight - 4;
if (k > this.y1 || k + l < this.y0) {
this.updateItemPosition(j, p_renderList_1_, k, p_renderList_5_);
}
if (this.renderSelection && this.isSelectedItem(j)) {
int i1 = this.x0 + this.width / 2 - this.getRowWidth() / 2;
int j1 = this.x0 + this.width / 2 + this.getRowWidth() / 2;
RenderSystem.disableTexture();
float f = this.isFocused() ? 1.0F : 0.5F;
RenderSystem.setShaderColor(f, f, f, 1.0F);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.vertex(i1, k + l + 2, 0.0D).endVertex();
bufferbuilder.vertex(j1, k + l + 2, 0.0D).endVertex();
bufferbuilder.vertex(j1, k - 2, 0.0D).endVertex();
bufferbuilder.vertex(i1, k - 2, 0.0D).endVertex();
tessellator.end();
RenderSystem.setShaderColor(0.0F, 0.0F, 0.0F, 1.0F);
bufferbuilder.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.POSITION);
bufferbuilder.vertex(i1 + 1, k + l + 1, 0.0D).endVertex();
bufferbuilder.vertex(j1 - 1, k + l + 1, 0.0D).endVertex();
bufferbuilder.vertex(j1 - 1, k - 1, 0.0D).endVertex();
bufferbuilder.vertex(i1 + 1, k - 1, 0.0D).endVertex();
tessellator.end();
RenderSystem.enableTexture();
}
this.renderItem(ms, j, p_renderList_1_, k, l, p_renderList_3_, p_renderList_4_, p_renderList_5_);
}
}
protected boolean isFocused() {
return false;
}
protected int getScrollbarPosition() {
return this.width / 2 + 124;
}
}

View File

@@ -1,54 +1,52 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import nl.requios.effortlessbuilding.EffortlessBuilding;
//Stack with fixed size. Removes (overwrites) oldest element on push. //Stack with fixed size. Removes (overwrites) oldest element on push.
public class FixedStack<T> { public class FixedStack<T> {
private T[] stack; private final T[] stack;
private int size; private final int size;
private int top; private int top;
private int filled = 0; //how many valid items are in the stack private int filled = 0; //how many valid items are in the stack
public FixedStack(T[] stack) { public FixedStack(T[] stack) {
this.stack = stack; this.stack = stack;
this.top = 0; this.top = 0;
this.size = stack.length; this.size = stack.length;
} }
public void push(T object) { public void push(T object) {
if (top == stack.length) if (top == stack.length)
top = 0; top = 0;
stack[top] = object; stack[top] = object;
top++; top++;
if (filled < size) if (filled < size)
filled++; filled++;
} }
public T pop() { public T pop() {
if (filled <= 0) return null; if (filled <= 0) return null;
if (top - 1 < 0) if (top - 1 < 0)
top = size; top = size;
top--; top--;
T object = stack[top]; T object = stack[top];
filled--; filled--;
return object; return object;
} }
public void clear() { public void clear() {
top = 0; top = 0;
filled = 0; filled = 0;
} }
public int size() { public int size() {
return size; return size;
} }
public boolean isEmpty() { public boolean isEmpty() {
return filled <= 0; return filled <= 0;
} }
} }

View File

@@ -1,30 +1,30 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
public class InventoryHelper { public class InventoryHelper {
public static ItemStack findItemStackInInventory(PlayerEntity player, Block block) { public static ItemStack findItemStackInInventory(Player player, Block block) {
for (ItemStack invStack : player.inventory.mainInventory) { for (ItemStack invStack : player.getInventory().items) {
if (!invStack.isEmpty() && invStack.getItem() instanceof BlockItem && if (!invStack.isEmpty() && invStack.getItem() instanceof BlockItem &&
((BlockItem) invStack.getItem()).getBlock().equals(block)) { ((BlockItem) invStack.getItem()).getBlock().equals(block)) {
return invStack; return invStack;
} }
} }
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }
public static int findTotalBlocksInInventory(PlayerEntity player, Block block) { public static int findTotalBlocksInInventory(Player player, Block block) {
int total = 0; int total = 0;
for (ItemStack invStack : player.inventory.mainInventory) { for (ItemStack invStack : player.getInventory().items) {
if (!invStack.isEmpty() && invStack.getItem() instanceof BlockItem && if (!invStack.isEmpty() && invStack.getItem() instanceof BlockItem &&
((BlockItem) invStack.getItem()).getBlock().equals(block)) { ((BlockItem) invStack.getItem()).getBlock().equals(block)) {
total += invStack.getCount(); total += invStack.getCount();
} }
} }
return total; return total;
} }
} }

View File

@@ -1,50 +1,54 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.Mth;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
public class ReachHelper { public class ReachHelper {
public static int getMaxReach(PlayerEntity player) { public static int getMaxReach(Player player) {
if (player.isCreative()) return BuildConfig.reach.maxReachCreative.get(); if (player.isCreative()) return BuildConfig.reach.maxReachCreative.get();
if (!BuildConfig.reach.enableReachUpgrades.get()) return BuildConfig.reach.maxReachLevel3.get(); if (!BuildConfig.reach.enableReachUpgrades.get()) return BuildConfig.reach.maxReachLevel3.get();
//Check buildsettings for reachUpgrade //Check buildsettings for reachUpgrade
int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade(); int reachUpgrade = ModifierSettingsManager.getModifierSettings(player).getReachUpgrade();
switch (reachUpgrade) { switch (reachUpgrade) {
case 0: return BuildConfig.reach.maxReachLevel0.get(); case 0:
case 1: return BuildConfig.reach.maxReachLevel1.get(); return BuildConfig.reach.maxReachLevel0.get();
case 2: return BuildConfig.reach.maxReachLevel2.get(); case 1:
case 3: return BuildConfig.reach.maxReachLevel3.get(); return BuildConfig.reach.maxReachLevel1.get();
} case 2:
return BuildConfig.reach.maxReachLevel0.get(); return BuildConfig.reach.maxReachLevel2.get();
} case 3:
return BuildConfig.reach.maxReachLevel3.get();
}
return BuildConfig.reach.maxReachLevel0.get();
}
public static int getPlacementReach(PlayerEntity player) { public static int getPlacementReach(Player player) {
return getMaxReach(player) / 4; return getMaxReach(player) / 4;
} }
public static int getMaxBlocksPlacedAtOnce(PlayerEntity player) { public static int getMaxBlocksPlacedAtOnce(Player player) {
if (player.isCreative()) return 1000000; if (player.isCreative()) return 1000000;
return MathHelper.ceil(Math.pow(getMaxReach(player), 1.6)); return Mth.ceil(Math.pow(getMaxReach(player), 1.6));
//Level 0: 121 //Level 0: 121
//Level 1: 523 //Level 1: 523
//Level 2: 1585 //Level 2: 1585
//Level 3: 4805 //Level 3: 4805
} }
public static int getMaxBlocksPerAxis(PlayerEntity player) { public static int getMaxBlocksPerAxis(Player player) {
if (player.isCreative()) return 2000; if (player.isCreative()) return 2000;
return MathHelper.ceil(getMaxReach(player) * 0.3); return Mth.ceil(getMaxReach(player) * 0.3);
//Level 0: 6 //Level 0: 6
//Level 1: 15 //Level 1: 15
//Level 2: 30 //Level 2: 30
//Level 3: 60 //Level 3: 60
} }
public static boolean canBreakFar(PlayerEntity player) { public static boolean canBreakFar(Player player) {
return player.isCreative() || BuildConfig.survivalBalancers.breakFar.get(); return player.isCreative();
} }
} }

View File

@@ -1,90 +1,92 @@
package nl.requios.effortlessbuilding.helper; package nl.requios.effortlessbuilding.helper;
import net.minecraft.advancements.CriteriaTriggers; import net.minecraft.advancements.CriteriaTriggers;
import net.minecraft.block.*; import net.minecraft.core.BlockPos;
import net.minecraft.block.SlabBlock; import net.minecraft.core.Direction;
import net.minecraft.block.material.Material; import net.minecraft.core.Registry;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.sounds.SoundSource;
import net.minecraft.item.BlockItem; import net.minecraft.tags.BlockTags;
import net.minecraft.util.*; import net.minecraft.world.InteractionHand;
import net.minecraft.block.BlockState; import net.minecraft.world.entity.Entity;
import net.minecraft.entity.Entity; import net.minecraft.world.entity.player.Player;
import net.minecraft.block.Blocks; import net.minecraft.world.item.BlockItem;
import net.minecraft.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.util.CachedBlockInfo; import net.minecraft.world.level.Level;
import net.minecraft.util.Direction; import net.minecraft.world.level.block.Block;
import net.minecraft.util.Hand; import net.minecraft.world.level.block.Blocks;
import net.minecraft.util.math.BlockPos; import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.level.block.SoundType;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.World; import net.minecraft.world.level.block.state.pattern.BlockInWorld;
import net.minecraftforge.common.ToolType; import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.event.ForgeEventFactory;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
public class SurvivalHelper { public class SurvivalHelper {
//Used for all placing of blocks in this mod. //Used for all placing of blocks in this mod.
//Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack. //Checks if area is loaded, if player has the right permissions, if existing block can be replaced (drops it if so) and consumes an item from the stack.
//Based on ItemBlock#onItemUse //Based on ItemBlock#onItemUse
public static boolean placeBlock(World world, PlayerEntity player, BlockPos pos, BlockState blockState, public static boolean placeBlock(Level world, Player player, BlockPos pos, BlockState blockState,
ItemStack origstack, Direction facing, Vec3d hitVec, boolean skipPlaceCheck, ItemStack origstack, Direction facing, Vec3 hitVec, boolean skipPlaceCheck,
boolean skipCollisionCheck, boolean playSound) { boolean skipCollisionCheck, boolean playSound) {
if (!world.isBlockPresent(pos)) return false; if (!world.isLoaded(pos)) return false;
ItemStack itemstack = origstack; ItemStack itemstack = origstack;
if (blockState.getBlock().isAir(blockState, world, pos) || itemstack.isEmpty()) { if (blockState.isAir() || itemstack.isEmpty()) {
dropBlock(world, player, pos); dropBlock(world, player, pos);
world.removeBlock(pos, false); world.removeBlock(pos, false);
return true; return true;
} }
//Randomizer bag, other proxy item synergy //Randomizer bag, other proxy item synergy
//Preliminary compatibility code for other items that hold blocks //Preliminary compatibility code for other items that hold blocks
if (CompatHelper.isItemBlockProxy(itemstack)) if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
if (!(itemstack.getItem() instanceof BlockItem)) if (!(itemstack.getItem() instanceof BlockItem))
return false; return false;
Block block = ((BlockItem) itemstack.getItem()).getBlock(); Block block = ((BlockItem) itemstack.getItem()).getBlock();
//More manual with ItemBlock#placeBlockAt //More manual with ItemBlock#placeBlockAt
if (skipPlaceCheck || canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) { if (skipPlaceCheck || canPlace(world, player, pos, blockState, itemstack, skipCollisionCheck, facing.getOpposite())) {
//Drop existing block //Drop existing block
dropBlock(world, player, pos); dropBlock(world, player, pos);
//TryPlace sets block with offset and reduces itemstack count in creative, so we copy only parts of it //TryPlace sets block with offset and reduces itemstack count in creative, so we copy only parts of it
// BlockItemUseContext blockItemUseContext = new BlockItemUseContext(world, player, itemstack, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z); // BlockItemUseContext blockItemUseContext = new BlockItemUseContext(world, player, itemstack, pos, facing, (float) hitVec.x, (float) hitVec.y, (float) hitVec.z);
// EnumActionResult result = ((ItemBlock) itemstack.getItem()).tryPlace(blockItemUseContext); // EnumActionResult result = ((ItemBlock) itemstack.getItem()).tryPlace(blockItemUseContext);
if (!world.setBlockState(pos, blockState, 3)) return false; if (!world.setBlock(pos, blockState, 3)) return false;
BlockItem.setTileEntityNBT(world, player, pos, itemstack); //Actually BlockItem::onBlockPlaced but that is protected BlockItem.updateCustomBlockEntityTag(world, player, pos, itemstack); //Actually BlockItem::onBlockPlaced but that is protected
block.onBlockPlacedBy(world, pos, blockState, player, itemstack); block.setPlacedBy(world, pos, blockState, player, itemstack);
if (player instanceof ServerPlayerEntity) { if (player instanceof ServerPlayer) {
CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayerEntity)player, pos, itemstack); CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, pos, itemstack);
} }
BlockState afterState = world.getBlockState(pos); BlockState afterState = world.getBlockState(pos);
if (playSound) { if (playSound) {
SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player); SoundType soundtype = afterState.getBlock().getSoundType(afterState, world, pos, player);
world.playSound(null, pos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); world.playSound(null, pos, soundtype.getPlaceSound(), SoundSource.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F);
} }
if (!player.isCreative() && Block.getBlockFromItem(itemstack.getItem()) == block) { if (!player.isCreative() && Block.byItem(itemstack.getItem()) == block) {
CompatHelper.shrinkStack(origstack, itemstack, player); itemstack.shrink(1);
} }
return true; return true;
} }
return false; return false;
//Using ItemBlock#onItemUse //Using ItemBlock#onItemUse
// EnumActionResult result; // EnumActionResult result;
// PlayerInteractEvent.RightClickBlock event = ForgeHooks.onRightClickBlock(player, EnumHand.MAIN_HAND, pos, facing, net.minecraftforge.common.ForgeHooks.rayTraceEyeHitVec(player, ReachHelper.getPlacementReach(player))); // PlayerInteractEvent.RightClickBlock event = ForgeHooks.onRightClickBlock(player, EnumHand.MAIN_HAND, pos, facing, net.minecraftforge.common.ForgeHooks.rayTraceEyeHitVec(player, ReachHelper.getPlacementReach(player)));
// if (player.isCreative()) // if (player.isCreative())
@@ -107,40 +109,40 @@ public class SurvivalHelper {
// return false; // return false;
// } // }
} }
//Used for all breaking of blocks in this mod. //Used for all breaking of blocks in this mod.
//Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory //Checks if area is loaded, if appropriate tool is used in survival mode, and drops the block directly into the players inventory
public static boolean breakBlock(World world, PlayerEntity player, BlockPos pos, boolean skipChecks) { public static boolean breakBlock(Level world, Player player, BlockPos pos, boolean skipChecks) {
if (!world.isBlockPresent(pos) && !world.isAirBlock(pos)) return false; if (!world.isLoaded(pos) && !world.isEmptyBlock(pos)) return false;
//Check if can break //Check if can break
if (skipChecks || canBreak(world, player, pos)) { if (skipChecks || canBreak(world, player, pos)) {
// player.addStat(StatList.getBlockStats(world.getNewBlockState(pos).getBlock())); // player.addStat(StatList.getBlockStats(world.getNewBlockState(pos).getBlock()));
// player.addExhaustion(0.005F); // player.addExhaustion(0.005F);
//Drop existing block //Drop existing block
dropBlock(world, player, pos); dropBlock(world, player, pos);
//Damage tool //Damage tool
player.getHeldItemMainhand().onBlockDestroyed(world, world.getBlockState(pos), pos, player); player.getMainHandItem().mineBlock(world, world.getBlockState(pos), pos, player);
world.removeBlock(pos, false); world.removeBlock(pos, false);
return true; return true;
} }
return false; return false;
} }
//Gives items directly to player //Gives items directly to player
public static void dropBlock(World world, PlayerEntity player, BlockPos pos){ public static void dropBlock(Level world, Player player, BlockPos pos) {
if (player.isCreative()) return; if (player.isCreative()) return;
BlockState blockState = world.getBlockState(pos); BlockState blockState = world.getBlockState(pos);
Block block = blockState.getBlock(); Block block = blockState.getBlock();
block.harvestBlock(world, player, pos, blockState, world.getTileEntity(pos), player.getHeldItemMainhand()); block.playerDestroy(world, player, pos, blockState, world.getBlockEntity(pos), player.getMainHandItem());
//TODO drop items in inventory instead of world //TODO drop items in inventory instead of world
// List<ItemStack> drops = new ArrayList<>(); // List<ItemStack> drops = new ArrayList<>();
// //
@@ -168,167 +170,137 @@ public class SurvivalHelper {
// { // {
// ItemHandlerHelper.giveItemToPlayer(player, drop); // ItemHandlerHelper.giveItemToPlayer(player, drop);
// } // }
} }
/** /**
* Check if player can place a block. * Check if player can place a block.
* Turn randomizer bag into itemstack inside before. * Turn randomizer bag into itemstack inside before.
* @param world *
* @param player * @param world
* @param pos * @param player
* @param newBlockState the blockstate that is going to be placed * @param pos
* @param itemStack the itemstack used for placing * @param newBlockState the blockstate that is going to be placed
* @param skipCollisionCheck skips collision check with entities * @param itemStack the itemstack used for placing
* @param sidePlacedOn * @param skipCollisionCheck skips collision check with entities
* @return Whether the player may place the block at pos with itemstack * @param sidePlacedOn
*/ * @return Whether the player may place the block at pos with itemstack
public static boolean canPlace(World world, PlayerEntity player, BlockPos pos, BlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, Direction sidePlacedOn) { */
public static boolean canPlace(Level world, Player player, BlockPos pos, BlockState newBlockState, ItemStack itemStack, boolean skipCollisionCheck, Direction sidePlacedOn) {
//Check if itemstack is correct //Check if itemstack is correct
if (!(itemStack.getItem() instanceof BlockItem) || Block.getBlockFromItem(itemStack.getItem()) != newBlockState.getBlock()) { if (!(itemStack.getItem() instanceof BlockItem) || Block.byItem(itemStack.getItem()) != newBlockState.getBlock()) {
// EffortlessBuilding.log(player, "Cannot (re)place block", true); // EffortlessBuilding.log(player, "Cannot (re)place block", true);
// EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString()); // EffortlessBuilding.log("SurvivalHelper#canPlace: itemstack " + itemStack.toString() + " does not match blockstate " + newBlockState.toString());
//Happens when breaking blocks, no need to notify in that case //Happens when breaking blocks, no need to notify in that case
return false; return false;
} }
Block block = ((BlockItem) itemStack.getItem()).getBlock(); Block block = ((BlockItem) itemStack.getItem()).getBlock();
return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) && return !itemStack.isEmpty() && canPlayerEdit(player, world, pos, itemStack) &&
mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) && mayPlace(world, block, newBlockState, pos, skipCollisionCheck, sidePlacedOn, player) &&
canReplace(world, player, pos); canReplace(world, player, pos);
} }
//Can be harvested with hand? (or in creative) //Can be harvested with hand? (or in creative)
private static boolean canReplace(World world, PlayerEntity player, BlockPos pos){ private static boolean canReplace(Level world, Player player, BlockPos pos) {
if (player.isCreative()) return true; if (player.isCreative()) return true;
BlockState state = world.getBlockState(pos); BlockState state = world.getBlockState(pos);
switch (BuildConfig.survivalBalancers.quickReplaceMiningLevel.get()) { int miningLevel = BuildConfig.survivalBalancers.quickReplaceMiningLevel.get();
case -1: return state.getMaterial().isToolNotRequired(); switch (miningLevel) {
case 0: return state.getBlock().getHarvestLevel(state) <= 0; case -1:
case 1: return state.getBlock().getHarvestLevel(state) <= 1; return !state.requiresCorrectToolForDrops();
case 2: return state.getBlock().getHarvestLevel(state) <= 2; case 0:
case 3: return state.getBlock().getHarvestLevel(state) <= 3; return !state.is(BlockTags.NEEDS_STONE_TOOL) &&
} !state.is(BlockTags.NEEDS_IRON_TOOL) &&
!state.is(BlockTags.NEEDS_DIAMOND_TOOL);
case 1:
return !state.is(BlockTags.NEEDS_IRON_TOOL) &&
!state.is(BlockTags.NEEDS_DIAMOND_TOOL);
case 2:
return !state.is(BlockTags.NEEDS_DIAMOND_TOOL);
case 3:
case 4:
return true;
}
return false; return false;
} }
//From EntityPlayer#canPlayerEdit //From Player#mayUseItemAt
private static boolean canPlayerEdit(PlayerEntity player, World world, BlockPos pos, ItemStack stack) private static boolean canPlayerEdit(Player player, Level world, BlockPos pos, ItemStack stack) {
{ if (!world.mayInteract(player, pos)) return false;
if (!world.isBlockModifiable(player, pos)) return false;
if (player.abilities.allowEdit) if (player.getAbilities().mayBuild) {
{ //True in creative and survival mode
//True in creative and survival mode return true;
return true; } else {
} //Adventure mode
else BlockInWorld blockinworld = new BlockInWorld(world, pos, false);
{ return stack.hasAdventureModePlaceTagForBlock(world.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), blockinworld);
//Adventure mode }
CachedBlockInfo blockworldstate = new CachedBlockInfo(world, pos, false); }
return stack.canPlaceOn(world.getTags(), blockworldstate);
} //From World#mayPlace
} private static boolean mayPlace(Level world, Block blockIn, BlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, Direction sidePlacedOn, @Nullable Entity placer) {
BlockState iblockstate1 = world.getBlockState(pos);
VoxelShape voxelShape = skipCollisionCheck ? null : blockIn.defaultBlockState().getCollisionShape(world, pos);
//From World#mayPlace if (voxelShape != null && !world.isUnobstructed(placer, voxelShape)) {
private static boolean mayPlace(World world, Block blockIn, BlockState newBlockState, BlockPos pos, boolean skipCollisionCheck, Direction sidePlacedOn, @Nullable Entity placer) return false;
{ }
BlockState iblockstate1 = world.getBlockState(pos);
VoxelShape voxelShape = skipCollisionCheck ? null : blockIn.getDefaultState().getCollisionShape(world, pos);
if (voxelShape != null && !world.checkNoEntityCollision(placer, voxelShape)) //Check if double slab
{ if (placer != null && doesBecomeDoubleSlab(((Player) placer), pos, sidePlacedOn)) {
return false; return true;
} }
//Check if double slab //Check if same block
if (placer != null && doesBecomeDoubleSlab(((PlayerEntity) placer), pos, sidePlacedOn)) { //Necessary otherwise extra items will be dropped
return true; if (iblockstate1 == newBlockState) {
} return false;
}
//Check if same block //TODO 1.14 check what Material.CIRCUITS has become
//Necessary otherwise extra items will be dropped if (iblockstate1.getMaterial() == Material.BUILDABLE_GLASS && blockIn == Blocks.ANVIL) {
if (iblockstate1 == newBlockState) { return true;
return false; }
}
//TODO 1.14 check what Material.CIRCUITS has become //Check quickreplace
if (iblockstate1.getMaterial() == Material.REDSTONE_LIGHT && blockIn == Blocks.ANVIL) if (placer instanceof Player && ModifierSettingsManager.getModifierSettings(((Player) placer)).doQuickReplace()) {
{ return true;
return true; }
}
//Check quickreplace //TODO 1.13 replaceable
if (placer instanceof PlayerEntity && ModifierSettingsManager.getModifierSettings(((PlayerEntity) placer)).doQuickReplace()) { return iblockstate1.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/;
return true; }
}
//TODO 1.13 replaceable
return iblockstate1.getMaterial().isReplaceable() /*&& canPlaceBlockOnSide(world, pos, sidePlacedOn)*/;
}
//Can break using held tool? (or in creative)
public static boolean canBreak(Level world, Player player, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if (!world.getFluidState(pos).isEmpty()) return false;
//Can break using held tool? (or in creative) if (player.isCreative()) return true;
public static boolean canBreak(World world, PlayerEntity player, BlockPos pos) {
BlockState blockState = world.getBlockState(pos);
if (!world.getFluidState(pos).isEmpty()) return false;
if (player.isCreative()) return true; return ForgeEventFactory.doPlayerHarvestCheck(player, blockState, true);
}
return canHarvestBlock(blockState.getBlock(), player, world, pos); public static boolean doesBecomeDoubleSlab(Player player, BlockPos pos, Direction facing) {
} BlockState placedBlockState = player.level.getBlockState(pos);
//From ForgeHooks#canHarvestBlock ItemStack itemstack = player.getItemInHand(InteractionHand.MAIN_HAND);
public static boolean canHarvestBlock(@Nonnull Block block, @Nonnull PlayerEntity player, @Nonnull World world, @Nonnull BlockPos pos) if (CompatHelper.isItemBlockProxy(itemstack))
{ itemstack = CompatHelper.getItemBlockFromStack(itemstack);
BlockState state = world.getBlockState(pos);
//Dont break bedrock if (itemstack.isEmpty() || !(itemstack.getItem() instanceof BlockItem) || !(((BlockItem) itemstack.getItem()).getBlock() instanceof SlabBlock))
if (state.getBlockHardness(world, pos) < 0) { return false;
return false; SlabBlock heldSlab = (SlabBlock) ((BlockItem) itemstack.getItem()).getBlock();
}
if (state.getMaterial().isToolNotRequired()) if (placedBlockState.getBlock() == heldSlab) {
{ //TODO 1.13
return true;
}
ItemStack stack = player.getHeldItemMainhand();
ToolType tool = block.getHarvestTool(state);
if (stack.isEmpty() || tool == null)
{
return player.canHarvestBlock(state);
}
if (stack.getDamage() >= stack.getMaxDamage()) return false;
int toolLevel = stack.getItem().getHarvestLevel(stack, tool, player, state);
if (toolLevel < 0)
{
return player.canHarvestBlock(state);
}
return toolLevel >= block.getHarvestLevel(state);
}
public static boolean doesBecomeDoubleSlab(PlayerEntity player, BlockPos pos, Direction facing) {
BlockState placedBlockState = player.world.getBlockState(pos);
ItemStack itemstack = player.getHeldItem(Hand.MAIN_HAND);
if (CompatHelper.isItemBlockProxy(itemstack))
itemstack = CompatHelper.getItemBlockFromStack(itemstack);
if (itemstack.isEmpty() || !(itemstack.getItem() instanceof BlockItem) || !(((BlockItem) itemstack.getItem()).getBlock() instanceof SlabBlock)) return false;
SlabBlock heldSlab = (SlabBlock) ((BlockItem) itemstack.getItem()).getBlock();
if (placedBlockState.getBlock() == heldSlab) {
//TODO 1.13
// IProperty<?> variantProperty = heldSlab.getVariantProperty(); // IProperty<?> variantProperty = heldSlab.getVariantProperty();
// Comparable<?> placedVariant = placedBlockState.getValue(variantProperty); // Comparable<?> placedVariant = placedBlockState.getValue(variantProperty);
// BlockSlab.EnumBlockHalf placedHalf = placedBlockState.getValue(BlockSlab.HALF); // BlockSlab.EnumBlockHalf placedHalf = placedBlockState.getValue(BlockSlab.HALF);
@@ -339,7 +311,7 @@ public class SurvivalHelper {
// { // {
// return true; // return true;
// } // }
} }
return false; return false;
} }
} }

View File

@@ -0,0 +1,220 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.MenuProvider;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.InteractionResult;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.item.context.UseOnContext;
@MethodsReturnNonnullByDefault
@ParametersAreNonnullByDefault
public abstract class AbstractRandomizerBagItem extends Item {
private static long currentSeed = 1337;
private static final Random rand = new Random(currentSeed);
public AbstractRandomizerBagItem() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
public abstract int getInventorySize();
public abstract MenuProvider getContainerProvider(ItemStack item);
/**
* Get the inventory of a randomizer bag by checking the capability.
*/
public IItemHandler getBagInventory(ItemStack bag) {
return bag.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).orElse(null);
}
/**
* Pick a random slot from the bag. Empty slots will never get chosen.
*/
public ItemStack pickRandomStack(IItemHandler bagInventory) {
//Find how many stacks are non-empty, and save them in a list
int nonempty = 0;
List<ItemStack> nonEmptyStacks = new ArrayList<>();
List<Integer> originalSlots = new ArrayList<>(getInventorySize());
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty()) {
nonempty++;
nonEmptyStacks.add(stack);
originalSlots.add(i);
}
}
if (nonEmptyStacks.size() != originalSlots.size())
throw new Error("NonEmptyStacks and OriginalSlots not same size");
if (nonempty == 0) return ItemStack.EMPTY;
//Pick random slot
int randomSlot = rand.nextInt(nonempty);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
int originalSlot = originalSlots.get(randomSlot);
if (originalSlot < 0 || originalSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
return bagInventory.getStackInSlot(originalSlot);
}
public ItemStack findStack(IItemHandler bagInventory, Item item) {
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == item) {
return stack;
}
}
return ItemStack.EMPTY;
}
public static void resetRandomness() {
rand.setSeed(currentSeed);
}
public static void renewRandomness() {
currentSeed = Calendar.getInstance().getTimeInMillis();
rand.setSeed(currentSeed);
}
@Override
public InteractionResult useOn(UseOnContext ctx) {
Player player = ctx.getPlayer();
Level world = ctx.getLevel();
BlockPos pos = ctx.getClickedPos();
Direction facing = ctx.getClickedFace();
ItemStack item = ctx.getItemInHand();
Vec3 hitVec = ctx.getClickLocation();
if (player == null) return InteractionResult.FAIL;
if (ctx.getPlayer() != null && ctx.getPlayer().isShiftKeyDown()) { //ctx.isPlacerSneaking()
if (world.isClientSide) return InteractionResult.SUCCESS;
//Open inventory
NetworkHooks.openScreen((ServerPlayer) player, getContainerProvider(item));
} else {
if (world.isClientSide) return InteractionResult.SUCCESS;
//Only place manually if in normal vanilla mode
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL || modifierSettings.doQuickReplace()) {
return InteractionResult.FAIL;
}
//Use item
//Get bag inventory
//TODO offhand support
ItemStack bag = player.getItemInHand(InteractionHand.MAIN_HAND);
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return InteractionResult.FAIL;
ItemStack toPlace = pickRandomStack(bagInventory);
if (toPlace.isEmpty()) return InteractionResult.FAIL;
//Previously: use onItemUse to place block (no synergy)
//bag.setItemDamage(toPlace.getMetadata());
//toPlace.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
//TODO replaceable
if (!world.getBlockState(pos).getBlock().canBeReplaced(world.getBlockState(pos), Fluids.EMPTY)) {
pos = pos.relative(facing);
}
BlockPlaceContext blockItemUseContext = new BlockPlaceContext(new UseOnContext(player, InteractionHand.MAIN_HAND, new BlockHitResult(hitVec, facing, pos, false)));
BlockState blockState = Block.byItem(toPlace.getItem()).getStateForPlacement(blockItemUseContext);
SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, hitVec, false, false, true);
//Synergy
//Works without calling
// BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, pos, blockState);
// BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
// Mirror.onBlockPlaced(placeEvent);
// Array.onBlockPlaced(placeEvent);
}
return InteractionResult.SUCCESS;
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
ItemStack bag = player.getItemInHand(hand);
if (player.isShiftKeyDown()) {
if (world.isClientSide) return new InteractionResultHolder<>(InteractionResult.SUCCESS, bag);
//Open inventory
NetworkHooks.openScreen((ServerPlayer) player, getContainerProvider(bag));
} else {
//Use item
//Get bag inventory
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return new InteractionResultHolder<>(InteractionResult.FAIL, bag);
ItemStack toUse = pickRandomStack(bagInventory);
if (toUse.isEmpty()) return new InteractionResultHolder<>(InteractionResult.FAIL, bag);
return toUse.use(world, player, hand);
}
return new InteractionResultHolder<>(InteractionResult.PASS, bag);
}
@Override
public int getUseDuration(ItemStack p_77626_1_) {
return 1;
}
@Nullable
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundTag nbt) {
return new ItemHandlerCapabilityProvider(getInventorySize());
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(Component.literal(ChatFormatting.BLUE + "Rightclick" + ChatFormatting.GRAY + " to place a random block"));
tooltip.add(Component.literal(ChatFormatting.BLUE + "Sneak + rightclick" + ChatFormatting.GRAY + " to open inventory"));
if (world != null && world.players().size() > 1) {
tooltip.add(Component.literal(ChatFormatting.YELLOW + "Experimental on servers: may lose inventory"));
}
}
}

View File

@@ -0,0 +1,45 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.network.chat.Component;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagContainer;
import javax.annotation.Nullable;
public class DiamondRandomizerBagItem extends AbstractRandomizerBagItem{
public static final int INV_SIZE = 27;
@Override
public int getInventorySize() {
return 27;
}
@Override
public MenuProvider getContainerProvider(ItemStack bag) {
return new ContainerProvider(bag);
}
public static class ContainerProvider implements MenuProvider {
private final ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public Component getDisplayName() {
return Component.translatable("effortlessbuilding:diamond_randomizer_bag");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new DiamondRandomizerBagContainer(containerId, playerInventory, ((AbstractRandomizerBagItem)bag.getItem()).getBagInventory(bag));
}
}
}

View File

@@ -0,0 +1,45 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.network.chat.Component;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagContainer;
import javax.annotation.Nullable;
public class GoldenRandomizerBagItem extends AbstractRandomizerBagItem{
public static final int INV_SIZE = 9;
@Override
public int getInventorySize() {
return 9;
}
@Override
public MenuProvider getContainerProvider(ItemStack bag) {
return new ContainerProvider(bag);
}
public static class ContainerProvider implements MenuProvider {
private final ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public Component getDisplayName() {
return Component.translatable("effortlessbuilding:golden_randomizer_bag");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new GoldenRandomizerBagContainer(containerId, playerInventory, ((AbstractRandomizerBagItem)bag.getItem()).getBagInventory(bag));
}
}
}

View File

@@ -1,245 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.*;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.util.*;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.World;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.fml.network.NetworkHooks;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.capability.ItemHandlerCapabilityProvider;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Random;
public class ItemRandomizerBag extends Item {
public static final int INV_SIZE = 5;
private static long currentSeed = 1337;
private static Random rand = new Random(currentSeed);
public ItemRandomizerBag() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "randomizer_bag");
}
@Override
public ActionResultType onItemUse(ItemUseContext ctx) {
PlayerEntity player = ctx.getPlayer();
World world = ctx.getWorld();
BlockPos pos = ctx.getPos();
Direction facing = ctx.getFace();
ItemStack item = ctx.getItem();
Vec3d hitVec = ctx.getHitVec();
if (player == null) return ActionResultType.FAIL;
if (ctx.func_225518_g_()) { //ctx.isPlacerSneaking()
if (world.isRemote) return ActionResultType.SUCCESS;
//Open inventory
NetworkHooks.openGui((ServerPlayerEntity) player, new ContainerProvider(item));
} else {
if (world.isRemote) return ActionResultType.SUCCESS;
//Only place manually if in normal vanilla mode
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
if (buildMode != BuildModes.BuildModeEnum.NORMAL || modifierSettings.doQuickReplace()) {
return ActionResultType.FAIL;
}
//Use item
//Get bag inventory
//TODO offhand support
ItemStack bag = player.getHeldItem(Hand.MAIN_HAND);
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return ActionResultType.FAIL;
ItemStack toPlace = pickRandomStack(bagInventory);
if (toPlace.isEmpty()) return ActionResultType.FAIL;
//Previously: use onItemUse to place block (no synergy)
//bag.setItemDamage(toPlace.getMetadata());
//toPlace.onItemUse(player, world, pos, hand, facing, hitX, hitY, hitZ);
//TODO replaceable
if (!world.getBlockState(pos).getBlock().getMaterial(world.getBlockState(pos)).isReplaceable()) {
pos = pos.offset(facing);
}
BlockItemUseContext blockItemUseContext = new BlockItemUseContext(new ItemUseContext(player, Hand.MAIN_HAND, new BlockRayTraceResult(hitVec, facing, pos, false)));
BlockState blockState = Block.getBlockFromItem(toPlace.getItem()).getStateForPlacement(blockItemUseContext);
SurvivalHelper.placeBlock(world, player, pos, blockState, toPlace, facing, hitVec, false, false, true);
//Synergy
//Works without calling
// BlockSnapshot blockSnapshot = new BlockSnapshot(player.world, pos, blockState);
// BlockEvent.PlaceEvent placeEvent = new BlockEvent.PlaceEvent(blockSnapshot, blockState, player, hand);
// Mirror.onBlockPlaced(placeEvent);
// Array.onBlockPlaced(placeEvent);
}
return ActionResultType.SUCCESS;
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
ItemStack bag = player.getHeldItem(hand);
if (player.isSneaking()) {
if (world.isRemote) return new ActionResult<>(ActionResultType.SUCCESS, bag);
//Open inventory
NetworkHooks.openGui((ServerPlayerEntity) player, new ContainerProvider(bag));
} else {
//Use item
//Get bag inventory
IItemHandler bagInventory = getBagInventory(bag);
if (bagInventory == null)
return new ActionResult<>(ActionResultType.FAIL, bag);
ItemStack toUse = pickRandomStack(bagInventory);
if (toUse.isEmpty()) return new ActionResult<>(ActionResultType.FAIL, bag);
return toUse.useItemRightClick(world, player, hand);
}
return new ActionResult<>(ActionResultType.PASS, bag);
}
/**
* Get the inventory of a randomizer bag by checking the capability.
*
* @param bag
* @return
*/
public static IItemHandler getBagInventory(ItemStack bag) {
return bag.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, null).orElse(null);
}
/**
* Pick a random slot from the bag. Empty slots will never get chosen.
*
* @param bagInventory
* @return
*/
public static ItemStack pickRandomStack(IItemHandler bagInventory) {
//Find how many stacks are non-empty, and save them in a list
int nonempty = 0;
List<ItemStack> nonEmptyStacks = new ArrayList<>(INV_SIZE);
List<Integer> originalSlots = new ArrayList<>(INV_SIZE);
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty()) {
nonempty++;
nonEmptyStacks.add(stack);
originalSlots.add(i);
}
}
if (nonEmptyStacks.size() != originalSlots.size())
throw new Error("NonEmptyStacks and OriginalSlots not same size");
if (nonempty == 0) return ItemStack.EMPTY;
//Pick random slot
int randomSlot = rand.nextInt(nonempty);
if (randomSlot < 0 || randomSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
int originalSlot = originalSlots.get(randomSlot);
if (originalSlot < 0 || originalSlot > bagInventory.getSlots()) return ItemStack.EMPTY;
return bagInventory.getStackInSlot(originalSlot);
}
public static ItemStack findStack(IItemHandler bagInventory, Item item) {
for (int i = 0; i < bagInventory.getSlots(); i++) {
ItemStack stack = bagInventory.getStackInSlot(i);
if (!stack.isEmpty() && stack.getItem() == item) {
return stack;
}
}
return ItemStack.EMPTY;
}
@Override
public int getUseDuration(ItemStack p_77626_1_) {
return 1;
}
@Nullable
@Override
public ICapabilityProvider initCapabilities(ItemStack stack, @Nullable CompoundNBT nbt) {
return new ItemHandlerCapabilityProvider();
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new StringTextComponent(TextFormatting.BLUE + "Rightclick" + TextFormatting.GRAY + " to place a random block"));
tooltip.add(new StringTextComponent(TextFormatting.BLUE + "Sneak + rightclick" + TextFormatting.GRAY + " to open inventory"));
if (world != null && world.getPlayers().size() > 1) {
tooltip.add(new StringTextComponent(TextFormatting.YELLOW + "Experimental on servers: may lose inventory"));
}
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
public static void resetRandomness() {
rand.setSeed(currentSeed);
}
public static void renewRandomness() {
currentSeed = Calendar.getInstance().getTimeInMillis();
rand.setSeed(currentSeed);
}
public static class ContainerProvider implements INamedContainerProvider{
private ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public ITextComponent getDisplayName() {
return new TranslationTextComponent("effortlessbuilding.screen.randomizer_bag");
}
@Nullable
@Override
public Container createMenu(int containerId, PlayerInventory playerInventory, PlayerEntity player) {
return new RandomizerBagContainer(containerId, playerInventory, ItemRandomizerBag.getBagInventory(bag));
}
}
}

View File

@@ -1,65 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade1 extends Item {
public ItemReachUpgrade1() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade1");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(ActionResultType.PASS, player.getHeldItem(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 0) {
modifierSettings.setReachUpgrade(1);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 0) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(ActionResultType.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel1.get()));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
}

View File

@@ -1,70 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade2 extends Item {
public ItemReachUpgrade2() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade2");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(ActionResultType.PASS, player.getHeldItem(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 1) {
modifierSettings.setReachUpgrade(2);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 1) {
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 1 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 1) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(ActionResultType.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel2.get()));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
}

View File

@@ -1,73 +0,0 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.*;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import java.util.List;
public class ItemReachUpgrade3 extends Item {
public ItemReachUpgrade3() {
super(new Item.Properties().group(ItemGroup.TOOLS).maxStackSize(1));
this.setRegistryName(EffortlessBuilding.MODID, "reach_upgrade3");
}
@Override
public ActionResult<ItemStack> onItemRightClick(World world, PlayerEntity player, Hand hand) {
if (player.isCreative()) {
if (world.isRemote) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isRemote) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new ActionResult<>(ActionResultType.PASS, player.getHeldItem(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 2) {
modifierSettings.setReachUpgrade(3);
if (world.isRemote) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setHeldItem(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 2) {
if (currentLevel == 0)
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 1 and 2 first.");
if (currentLevel == 1)
if (world.isRemote) EffortlessBuilding.log(player, "Use Reach Upgrade 2 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 2) {
if (world.isRemote) EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new ActionResult<>(ActionResultType.PASS, player.getHeldItem(hand));
}
@Override
public void addInformation(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Consume to increase reach to " + TextFormatting.BLUE + BuildConfig.reach.maxReachLevel3.get()));
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
@Override
public String getTranslationKey() {
return this.getRegistryName().toString();
}
}

View File

@@ -0,0 +1,45 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.network.chat.Component;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.inventory.AbstractContainerMenu;
import net.minecraft.world.item.ItemStack;
import nl.requios.effortlessbuilding.gui.RandomizerBagContainer;
import javax.annotation.Nullable;
public class RandomizerBagItem extends AbstractRandomizerBagItem {
public static final int INV_SIZE = 5;
@Override
public int getInventorySize() {
return 5;
}
@Override
public MenuProvider getContainerProvider(ItemStack bag) {
return new ContainerProvider(bag);
}
public static class ContainerProvider implements MenuProvider {
private final ItemStack bag;
public ContainerProvider(ItemStack bag) {
this.bag = bag;
}
@Override
public Component getDisplayName() {
return Component.translatable("effortlessbuilding:randomizer_bag");
}
@Nullable
@Override
public AbstractContainerMenu createMenu(int containerId, Inventory playerInventory, Player player) {
return new RandomizerBagContainer(containerId, playerInventory, ((AbstractRandomizerBagItem)bag.getItem()).getBagInventory(bag));
}
}
}

View File

@@ -0,0 +1,69 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ReachUpgrade1Item extends Item {
public ReachUpgrade1Item() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 0) {
modifierSettings.setReachUpgrade(1);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 0) {
if (world.isClientSide)
EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel1.get()));
}
}

View File

@@ -0,0 +1,74 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.awt.*;
import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ReachUpgrade2Item extends Item {
public ReachUpgrade2Item() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 1) {
modifierSettings.setReachUpgrade(2);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 1) {
if (world.isClientSide) EffortlessBuilding.log(player, "Use Reach Upgrade 1 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 1) {
if (world.isClientSide)
EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel2.get()));
tooltip.add(Component.literal(ChatFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
}

View File

@@ -0,0 +1,77 @@
package nl.requios.effortlessbuilding.item;
import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.network.chat.Component;
import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.helper.ReachHelper;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ReachUpgrade3Item extends Item {
public ReachUpgrade3Item() {
super(new Item.Properties().tab(CreativeModeTab.TAB_TOOLS).stacksTo(1));
}
@Override
public InteractionResultHolder<ItemStack> use(Level world, Player player, InteractionHand hand) {
if (player.isCreative()) {
if (world.isClientSide) EffortlessBuilding.log(player, "Reach upgrades are not necessary in creative.");
if (world.isClientSide) EffortlessBuilding.log(player, "Still want increased reach? Use the config.");
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
int currentLevel = modifierSettings.getReachUpgrade();
if (currentLevel == 2) {
modifierSettings.setReachUpgrade(3);
if (world.isClientSide) EffortlessBuilding.log(player, "Upgraded reach to " + ReachHelper.getMaxReach(player));
player.setItemInHand(hand, ItemStack.EMPTY);
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("entity.player.levelup"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel < 2) {
if (currentLevel == 0)
if (world.isClientSide) EffortlessBuilding.log(player, "Use Reach Upgrade 1 and 2 first.");
if (currentLevel == 1)
if (world.isClientSide) EffortlessBuilding.log(player, "Use Reach Upgrade 2 first.");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
} else if (currentLevel > 2) {
if (world.isClientSide)
EffortlessBuilding.log(player, "Already used this upgrade! Current reach is " + ReachHelper
.getMaxReach(player) + ".");
SoundEvent soundEvent = new SoundEvent(new ResourceLocation("item.armor.equip_leather"));
player.playSound(soundEvent, 1f, 1f);
}
return new InteractionResultHolder<>(InteractionResult.PASS, player.getItemInHand(hand));
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag flag) {
tooltip.add(Component.literal(ChatFormatting.GRAY + "Consume to increase reach to " + ChatFormatting.BLUE + BuildConfig.reach.maxReachLevel3.get()));
tooltip.add(Component.literal(ChatFormatting.GRAY + "Previous upgrades need to be consumed first"));
}
}

View File

@@ -1,16 +1,20 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.block.Block; import net.minecraft.world.level.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet; import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -19,69 +23,79 @@ import java.util.function.Supplier;
* Sends a message to the client asking to add a block to the undo stack. * Sends a message to the client asking to add a block to the undo stack.
*/ */
public class AddUndoMessage { public class AddUndoMessage {
private BlockPos coordinate; private final BlockPos coordinate;
private BlockState previousBlockState; private final BlockState previousBlockState;
private BlockState newBlockState; private final BlockState newBlockState;
public AddUndoMessage() { public AddUndoMessage() {
coordinate = BlockPos.ZERO; coordinate = BlockPos.ZERO;
previousBlockState = null; previousBlockState = null;
newBlockState = null; newBlockState = null;
} }
public AddUndoMessage(BlockPos coordinate, BlockState previousBlockState, BlockState newBlockState) { public AddUndoMessage(BlockPos coordinate, BlockState previousBlockState, BlockState newBlockState) {
this.coordinate = coordinate; this.coordinate = coordinate;
this.previousBlockState = previousBlockState; this.previousBlockState = previousBlockState;
this.newBlockState = newBlockState; this.newBlockState = newBlockState;
} }
public BlockPos getCoordinate() { public static void encode(AddUndoMessage message, FriendlyByteBuf buf) {
return coordinate; buf.writeInt(message.coordinate.getX());
} buf.writeInt(message.coordinate.getY());
buf.writeInt(message.coordinate.getZ());
buf.writeInt(Block.getId(message.previousBlockState));
buf.writeInt(Block.getId(message.newBlockState));
}
public BlockState getPreviousBlockState() { public static AddUndoMessage decode(FriendlyByteBuf buf) {
return previousBlockState; BlockPos coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
} BlockState previousBlockState = Block.stateById(buf.readInt());
BlockState newBlockState = Block.stateById(buf.readInt());
return new AddUndoMessage(coordinate, previousBlockState, newBlockState);
}
public BlockState getNewBlockState() { public BlockPos getCoordinate() {
return newBlockState; return coordinate;
} }
public static void encode(AddUndoMessage message, PacketBuffer buf) { public BlockState getPreviousBlockState() {
buf.writeInt(message.coordinate.getX()); return previousBlockState;
buf.writeInt(message.coordinate.getY()); }
buf.writeInt(message.coordinate.getZ());
buf.writeInt(Block.getStateId(message.previousBlockState));
buf.writeInt(Block.getStateId(message.newBlockState));
}
public static AddUndoMessage decode(PacketBuffer buf) { public BlockState getNewBlockState() {
BlockPos coordinate = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); return newBlockState;
BlockState previousBlockState = Block.getStateById(buf.readInt()); }
BlockState newBlockState = Block.getStateById(buf.readInt());
return new AddUndoMessage(coordinate, previousBlockState, newBlockState);
}
public static class Handler public static class Handler {
{ public static void handle(AddUndoMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(AddUndoMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
ctx.get().enqueueWork(() -> { //Received clientside
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ClientHandler.handle(message, ctx));
//Received clientside }
});
ctx.get().setPacketHandled(true);
}
}
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); @OnlyIn(Dist.CLIENT)
//Add to undo stack clientside public static class ClientHandler {
//Only the appropriate player that needs to add this to the undo stack gets this message public static void handle(AddUndoMessage message, Supplier<NetworkEvent.Context> ctx) {
UndoRedo.addUndo(player, new BlockSet( Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
new ArrayList<BlockPos>() {{add(message.getCoordinate());}}, //Add to undo stack clientside
new ArrayList<BlockState>() {{add(message.getPreviousBlockState());}}, //Only the appropriate player that needs to add this to the undo stack gets this message
new ArrayList<BlockState>() {{add(message.getNewBlockState());}}, UndoRedo.addUndo(player, new BlockSet(
new Vec3d(0,0,0), new ArrayList<BlockPos>() {{
message.getCoordinate(), message.getCoordinate())); add(message.getCoordinate());
} }},
}); new ArrayList<BlockState>() {{
ctx.get().setPacketHandled(true); add(message.getPreviousBlockState());
} }},
} new ArrayList<BlockState>() {{
add(message.getNewBlockState());
}},
new Vec3(0, 0, 0),
message.getCoordinate(), message.getCoordinate()));
}
}
} }

View File

@@ -1,14 +1,13 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.Direction; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.phys.HitResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -18,78 +17,76 @@ import java.util.function.Supplier;
*/ */
public class BlockBrokenMessage { public class BlockBrokenMessage {
private boolean blockHit; private final boolean blockHit;
private BlockPos blockPos; private final BlockPos blockPos;
private Direction sideHit; private final Direction sideHit;
private Vec3d hitVec; private final Vec3 hitVec;
public BlockBrokenMessage() { public BlockBrokenMessage() {
this.blockHit = false; this.blockHit = false;
this.blockPos = BlockPos.ZERO; this.blockPos = BlockPos.ZERO;
this.sideHit = Direction.UP; this.sideHit = Direction.UP;
this.hitVec = new Vec3d(0, 0, 0); this.hitVec = new Vec3(0, 0, 0);
} }
public BlockBrokenMessage(BlockRayTraceResult result) { public BlockBrokenMessage(BlockHitResult result) {
this.blockHit = result.getType() == RayTraceResult.Type.BLOCK; this.blockHit = result.getType() == HitResult.Type.BLOCK;
this.blockPos = result.getPos(); this.blockPos = result.getBlockPos();
this.sideHit = result.getFace(); this.sideHit = result.getDirection();
this.hitVec = result.getHitVec(); this.hitVec = result.getLocation();
} }
public BlockBrokenMessage(boolean blockHit, BlockPos blockPos, Direction sideHit, Vec3d hitVec) { public BlockBrokenMessage(boolean blockHit, BlockPos blockPos, Direction sideHit, Vec3 hitVec) {
this.blockHit = blockHit; this.blockHit = blockHit;
this.blockPos = blockPos; this.blockPos = blockPos;
this.sideHit = sideHit; this.sideHit = sideHit;
this.hitVec = hitVec; this.hitVec = hitVec;
} }
public boolean isBlockHit() { public static void encode(BlockBrokenMessage message, FriendlyByteBuf buf) {
return blockHit; buf.writeBoolean(message.blockHit);
} buf.writeInt(message.blockPos.getX());
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.get3DDataValue());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
}
public BlockPos getBlockPos() { public static BlockBrokenMessage decode(FriendlyByteBuf buf) {
return blockPos; boolean blockHit = buf.readBoolean();
} BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
Direction sideHit = Direction.from3DDataValue(buf.readInt());
Vec3 hitVec = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
return new BlockBrokenMessage(blockHit, blockPos, sideHit, hitVec);
}
public Direction getSideHit() { public boolean isBlockHit() {
return sideHit; return blockHit;
} }
public Vec3d getHitVec() { public BlockPos getBlockPos() {
return hitVec; return blockPos;
} }
public static void encode(BlockBrokenMessage message, PacketBuffer buf) { public Direction getSideHit() {
buf.writeBoolean(message.blockHit); return sideHit;
buf.writeInt(message.blockPos.getX()); }
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.getIndex());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
}
public static BlockBrokenMessage decode(PacketBuffer buf) { public Vec3 getHitVec() {
boolean blockHit = buf.readBoolean(); return hitVec;
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); }
Direction sideHit = Direction.byIndex(buf.readInt());
Vec3d hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
return new BlockBrokenMessage(blockHit, blockPos, sideHit, hitVec);
}
public static class Handler public static class Handler {
{ public static void handle(BlockBrokenMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(BlockBrokenMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ if (ctx.get().getDirection().getReceptionSide() == LogicalSide.SERVER) {
ctx.get().enqueueWork(() -> { //Received serverside
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.SERVER) { BuildModes.onBlockBrokenMessage(ctx.get().getSender(), message);
//Received serverside }
BuildModes.onBlockBrokenMessage(ctx.get().getSender(), message); });
} ctx.get().setPacketHandled(true);
}); }
ctx.get().setPacketHandled(true); }
}
}
} }

View File

@@ -1,14 +1,16 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.util.Direction; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.Direction;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.HitResult;
import net.minecraft.network.PacketBuffer; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer; import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
@@ -20,92 +22,97 @@ import java.util.function.Supplier;
*/ */
public class BlockPlacedMessage { public class BlockPlacedMessage {
private boolean blockHit; private final boolean blockHit;
private BlockPos blockPos; private final BlockPos blockPos;
private Direction sideHit; private final Direction sideHit;
private Vec3d hitVec; private final Vec3 hitVec;
private boolean placeStartPos; //prevent double placing in normal mode private final boolean placeStartPos; //prevent double placing in normal mode
public BlockPlacedMessage() { public BlockPlacedMessage() {
this.blockHit = false; this.blockHit = false;
this.blockPos = BlockPos.ZERO; this.blockPos = BlockPos.ZERO;
this.sideHit = Direction.UP; this.sideHit = Direction.UP;
this.hitVec = new Vec3d(0, 0, 0); this.hitVec = new Vec3(0, 0, 0);
this.placeStartPos = true; this.placeStartPos = true;
} }
public BlockPlacedMessage(BlockRayTraceResult result, boolean placeStartPos) { public BlockPlacedMessage(BlockHitResult result, boolean placeStartPos) {
this.blockHit = result.getType() == RayTraceResult.Type.BLOCK; this.blockHit = result.getType() == HitResult.Type.BLOCK;
this.blockPos = result.getPos(); this.blockPos = result.getBlockPos();
this.sideHit = result.getFace(); this.sideHit = result.getDirection();
this.hitVec = result.getHitVec(); this.hitVec = result.getLocation();
this.placeStartPos = placeStartPos; this.placeStartPos = placeStartPos;
} }
public BlockPlacedMessage(boolean blockHit, BlockPos blockPos, Direction sideHit, Vec3d hitVec, boolean placeStartPos) { public BlockPlacedMessage(boolean blockHit, BlockPos blockPos, Direction sideHit, Vec3 hitVec, boolean placeStartPos) {
this.blockHit = blockHit; this.blockHit = blockHit;
this.blockPos = blockPos; this.blockPos = blockPos;
this.sideHit = sideHit; this.sideHit = sideHit;
this.hitVec = hitVec; this.hitVec = hitVec;
this.placeStartPos = placeStartPos; this.placeStartPos = placeStartPos;
} }
public boolean isBlockHit() { public static void encode(BlockPlacedMessage message, FriendlyByteBuf buf) {
return blockHit; buf.writeBoolean(message.blockHit);
} buf.writeInt(message.blockPos.getX());
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.get3DDataValue());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
buf.writeBoolean(message.placeStartPos);
}
public BlockPos getBlockPos() { public static BlockPlacedMessage decode(FriendlyByteBuf buf) {
return blockPos; boolean blockHit = buf.readBoolean();
} BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
Direction sideHit = Direction.from3DDataValue(buf.readInt());
Vec3 hitVec = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean placeStartPos = buf.readBoolean();
return new BlockPlacedMessage(blockHit, blockPos, sideHit, hitVec, placeStartPos);
}
public Direction getSideHit() { public boolean isBlockHit() {
return sideHit; return blockHit;
} }
public Vec3d getHitVec() { public BlockPos getBlockPos() {
return hitVec; return blockPos;
} }
public boolean getPlaceStartPos() { public Direction getSideHit() {
return placeStartPos; return sideHit;
} }
public static void encode(BlockPlacedMessage message, PacketBuffer buf) { public Vec3 getHitVec() {
buf.writeBoolean(message.blockHit); return hitVec;
buf.writeInt(message.blockPos.getX()); }
buf.writeInt(message.blockPos.getY());
buf.writeInt(message.blockPos.getZ());
buf.writeInt(message.sideHit.getIndex());
buf.writeDouble(message.hitVec.x);
buf.writeDouble(message.hitVec.y);
buf.writeDouble(message.hitVec.z);
buf.writeBoolean(message.placeStartPos);
}
public static BlockPlacedMessage decode(PacketBuffer buf) { public boolean getPlaceStartPos() {
boolean blockHit = buf.readBoolean(); return placeStartPos;
BlockPos blockPos = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); }
Direction sideHit = Direction.byIndex(buf.readInt());
Vec3d hitVec = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean placeStartPos = buf.readBoolean();
return new BlockPlacedMessage(blockHit, blockPos, sideHit, hitVec, placeStartPos);
}
public static class Handler public static class Handler {
{ public static void handle(BlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(BlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
ctx.get().enqueueWork(() -> { //Received clientside
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ClientHandler.handle(message, ctx));
//Received clientside } else {
//Nod RenderHandler to do the dissolve shader effect //Received serverside
BlockPreviewRenderer.onBlocksPlaced(); BuildModes.onBlockPlacedMessage(ctx.get().getSender(), message);
} else { }
//Received serverside });
BuildModes.onBlockPlacedMessage(ctx.get().getSender(), message); ctx.get().setPacketHandled(true);
} }
}); }
ctx.get().setPacketHandled(true);
} @OnlyIn(Dist.CLIENT)
} public static class ClientHandler {
public static void handle(BlockPlacedMessage message, Supplier<NetworkEvent.Context> ctx) {
//Nod RenderHandler to do the dissolve shader effect
BlockPreviewRenderer.onBlocksPlaced();
}
}
} }

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
@@ -13,23 +13,21 @@ import java.util.function.Supplier;
*/ */
public class CancelModeMessage { public class CancelModeMessage {
public static void encode(CancelModeMessage message, PacketBuffer buf) { public static void encode(CancelModeMessage message, FriendlyByteBuf buf) {
} }
public static CancelModeMessage decode(PacketBuffer buf) { public static CancelModeMessage decode(FriendlyByteBuf buf) {
return new CancelModeMessage(); return new CancelModeMessage();
} }
public static class Handler public static class Handler {
{ public static void handle(CancelModeMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(CancelModeMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ctx.get().enqueueWork(() -> {
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
BuildModes.initializeMode(player); BuildModes.initializeMode(player);
}); });
ctx.get().setPacketHandled(true); ctx.get().setPacketHandled(true);
} }
} }
} }

View File

@@ -1,11 +1,15 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo; import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -14,31 +18,36 @@ import java.util.function.Supplier;
*/ */
public class ClearUndoMessage { public class ClearUndoMessage {
public ClearUndoMessage() { public ClearUndoMessage() {
} }
public static void encode(ClearUndoMessage message, PacketBuffer buf) { public static void encode(ClearUndoMessage message, FriendlyByteBuf buf) {
} }
public static ClearUndoMessage decode(PacketBuffer buf) { public static ClearUndoMessage decode(FriendlyByteBuf buf) {
return new ClearUndoMessage(); return new ClearUndoMessage();
} }
public static class Handler public static class Handler {
{ public static void handle(ClearUndoMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(ClearUndoMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
ctx.get().enqueueWork(() -> { //Received clientside
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ClientHandler.handle(message, ctx));
//Received clientside }
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); });
ctx.get().setPacketHandled(true);
}
}
//Add to undo stack clientside @OnlyIn(Dist.CLIENT)
UndoRedo.clear(player); public static class ClientHandler {
} public static void handle(ClearUndoMessage message, Supplier<NetworkEvent.Context> ctx) {
}); Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ctx.get().setPacketHandled(true);
} //Add to undo stack clientside
} UndoRedo.clear(player);
}
}
} }

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
@@ -13,34 +13,32 @@ import java.util.function.Supplier;
*/ */
public class ModeActionMessage { public class ModeActionMessage {
private ModeOptions.ActionEnum action; private ModeOptions.ActionEnum action;
public ModeActionMessage() { public ModeActionMessage() {
} }
public ModeActionMessage(ModeOptions.ActionEnum action) { public ModeActionMessage(ModeOptions.ActionEnum action) {
this.action = action; this.action = action;
} }
public static void encode(ModeActionMessage message, PacketBuffer buf) { public static void encode(ModeActionMessage message, FriendlyByteBuf buf) {
buf.writeInt(message.action.ordinal()); buf.writeInt(message.action.ordinal());
} }
public static ModeActionMessage decode(PacketBuffer buf) { public static ModeActionMessage decode(FriendlyByteBuf buf) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.values()[buf.readInt()]; ModeOptions.ActionEnum action = ModeOptions.ActionEnum.values()[buf.readInt()];
return new ModeActionMessage(action); return new ModeActionMessage(action);
} }
public static class Handler public static class Handler {
{ public static void handle(ModeActionMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(ModeActionMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ctx.get().enqueueWork(() -> {
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ModeOptions.performAction(player, message.action); ModeOptions.performAction(player, message.action);
}); });
ctx.get().setPacketHandled(true); ctx.get().setPacketHandled(true);
} }
} }
} }

View File

@@ -1,8 +1,8 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
@@ -15,38 +15,36 @@ import java.util.function.Supplier;
*/ */
public class ModeSettingsMessage { public class ModeSettingsMessage {
private ModeSettings modeSettings; private ModeSettings modeSettings;
public ModeSettingsMessage() { public ModeSettingsMessage() {
} }
public ModeSettingsMessage(ModeSettings modeSettings) { public ModeSettingsMessage(ModeSettings modeSettings) {
this.modeSettings = modeSettings; this.modeSettings = modeSettings;
} }
public static void encode(ModeSettingsMessage message, PacketBuffer buf) { public static void encode(ModeSettingsMessage message, FriendlyByteBuf buf) {
buf.writeInt(message.modeSettings.getBuildMode().ordinal()); buf.writeInt(message.modeSettings.getBuildMode().ordinal());
} }
public static ModeSettingsMessage decode(PacketBuffer buf) { public static ModeSettingsMessage decode(FriendlyByteBuf buf) {
BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()]; BuildModes.BuildModeEnum buildMode = BuildModes.BuildModeEnum.values()[buf.readInt()];
return new ModeSettingsMessage(new ModeSettings(buildMode)); return new ModeSettingsMessage(new ModeSettings(buildMode));
} }
public static class Handler public static class Handler {
{ public static void handle(ModeSettingsMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(ModeSettingsMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ctx.get().enqueueWork(() -> {
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize // Sanitize
ModeSettingsManager.sanitize(message.modeSettings, player); ModeSettingsManager.sanitize(message.modeSettings, player);
ModeSettingsManager.setModeSettings(player, message.modeSettings); ModeSettingsManager.setModeSettings(player, message.modeSettings);
}); });
ctx.get().setPacketHandled(true); ctx.get().setPacketHandled(true);
} }
} }
} }

View File

@@ -1,10 +1,10 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.math.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.Array; import nl.requios.effortlessbuilding.buildmodifier.Array;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
@@ -13,130 +13,128 @@ import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import java.util.function.Supplier; import java.util.function.Supplier;
import static nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.ModifierSettings;
/** /**
* Shares modifier settings (see ModifierSettingsManager) between server and client * Shares modifier settings (see ModifierSettingsManager) between server and client
*/ */
public class ModifierSettingsMessage { public class ModifierSettingsMessage {
private ModifierSettings modifierSettings; private ModifierSettings modifierSettings;
public ModifierSettingsMessage() { public ModifierSettingsMessage() {
} }
public ModifierSettingsMessage(ModifierSettings modifierSettings) { public ModifierSettingsMessage(ModifierSettings modifierSettings) {
this.modifierSettings = modifierSettings; this.modifierSettings = modifierSettings;
} }
public static void encode(ModifierSettingsMessage message, PacketBuffer buf) { public static void encode(ModifierSettingsMessage message, FriendlyByteBuf buf) {
//MIRROR //MIRROR
Mirror.MirrorSettings m = message.modifierSettings.getMirrorSettings(); Mirror.MirrorSettings m = message.modifierSettings.getMirrorSettings();
buf.writeBoolean(m != null); buf.writeBoolean(m != null);
if (m != null) { if (m != null) {
buf.writeBoolean(m.enabled); buf.writeBoolean(m.enabled);
buf.writeDouble(m.position.x); buf.writeDouble(m.position.x);
buf.writeDouble(m.position.y); buf.writeDouble(m.position.y);
buf.writeDouble(m.position.z); buf.writeDouble(m.position.z);
buf.writeBoolean(m.mirrorX); buf.writeBoolean(m.mirrorX);
buf.writeBoolean(m.mirrorY); buf.writeBoolean(m.mirrorY);
buf.writeBoolean(m.mirrorZ); buf.writeBoolean(m.mirrorZ);
buf.writeInt(m.radius); buf.writeInt(m.radius);
buf.writeBoolean(m.drawLines); buf.writeBoolean(m.drawLines);
buf.writeBoolean(m.drawPlanes); buf.writeBoolean(m.drawPlanes);
} }
//ARRAY //ARRAY
Array.ArraySettings a = message.modifierSettings.getArraySettings(); Array.ArraySettings a = message.modifierSettings.getArraySettings();
buf.writeBoolean(a != null); buf.writeBoolean(a != null);
if (a != null) { if (a != null) {
buf.writeBoolean(a.enabled); buf.writeBoolean(a.enabled);
buf.writeInt(a.offset.getX()); buf.writeInt(a.offset.getX());
buf.writeInt(a.offset.getY()); buf.writeInt(a.offset.getY());
buf.writeInt(a.offset.getZ()); buf.writeInt(a.offset.getZ());
buf.writeInt(a.count); buf.writeInt(a.count);
} }
buf.writeBoolean(message.modifierSettings.doQuickReplace()); buf.writeBoolean(message.modifierSettings.doQuickReplace());
buf.writeInt(message.modifierSettings.getReachUpgrade()); buf.writeInt(message.modifierSettings.getReachUpgrade());
//RADIAL MIRROR //RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = message.modifierSettings.getRadialMirrorSettings();
buf.writeBoolean(r != null); buf.writeBoolean(r != null);
if (r != null) { if (r != null) {
buf.writeBoolean(r.enabled); buf.writeBoolean(r.enabled);
buf.writeDouble(r.position.x); buf.writeDouble(r.position.x);
buf.writeDouble(r.position.y); buf.writeDouble(r.position.y);
buf.writeDouble(r.position.z); buf.writeDouble(r.position.z);
buf.writeInt(r.slices); buf.writeInt(r.slices);
buf.writeBoolean(r.alternate); buf.writeBoolean(r.alternate);
buf.writeInt(r.radius); buf.writeInt(r.radius);
buf.writeBoolean(r.drawLines); buf.writeBoolean(r.drawLines);
buf.writeBoolean(r.drawPlanes); buf.writeBoolean(r.drawPlanes);
} }
} }
public static ModifierSettingsMessage decode(PacketBuffer buf) { public static ModifierSettingsMessage decode(FriendlyByteBuf buf) {
//MIRROR //MIRROR
Mirror.MirrorSettings m = new Mirror.MirrorSettings(); Mirror.MirrorSettings m = new Mirror.MirrorSettings();
if (buf.readBoolean()) { if (buf.readBoolean()) {
boolean mirrorEnabled = buf.readBoolean(); boolean mirrorEnabled = buf.readBoolean();
Vec3d mirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); Vec3 mirrorPosition = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
boolean mirrorX = buf.readBoolean(); boolean mirrorX = buf.readBoolean();
boolean mirrorY = buf.readBoolean(); boolean mirrorY = buf.readBoolean();
boolean mirrorZ = buf.readBoolean(); boolean mirrorZ = buf.readBoolean();
int mirrorRadius = buf.readInt(); int mirrorRadius = buf.readInt();
boolean mirrorDrawLines = buf.readBoolean(); boolean mirrorDrawLines = buf.readBoolean();
boolean mirrorDrawPlanes = buf.readBoolean(); boolean mirrorDrawPlanes = buf.readBoolean();
m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius, m = new Mirror.MirrorSettings(mirrorEnabled, mirrorPosition, mirrorX, mirrorY, mirrorZ, mirrorRadius,
mirrorDrawLines, mirrorDrawPlanes); mirrorDrawLines, mirrorDrawPlanes);
} }
//ARRAY //ARRAY
Array.ArraySettings a = new Array.ArraySettings(); Array.ArraySettings a = new Array.ArraySettings();
if (buf.readBoolean()) { if (buf.readBoolean()) {
boolean arrayEnabled = buf.readBoolean(); boolean arrayEnabled = buf.readBoolean();
BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt()); BlockPos arrayOffset = new BlockPos(buf.readInt(), buf.readInt(), buf.readInt());
int arrayCount = buf.readInt(); int arrayCount = buf.readInt();
a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount); a = new Array.ArraySettings(arrayEnabled, arrayOffset, arrayCount);
} }
boolean quickReplace = buf.readBoolean(); boolean quickReplace = buf.readBoolean();
int reachUpgrade = buf.readInt(); int reachUpgrade = buf.readInt();
//RADIAL MIRROR //RADIAL MIRROR
RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = new RadialMirror.RadialMirrorSettings();
if (buf.readBoolean()) { if (buf.readBoolean()) {
boolean radialMirrorEnabled = buf.readBoolean(); boolean radialMirrorEnabled = buf.readBoolean();
Vec3d radialMirrorPosition = new Vec3d(buf.readDouble(), buf.readDouble(), buf.readDouble()); Vec3 radialMirrorPosition = new Vec3(buf.readDouble(), buf.readDouble(), buf.readDouble());
int radialMirrorSlices = buf.readInt(); int radialMirrorSlices = buf.readInt();
boolean radialMirrorAlternate = buf.readBoolean(); boolean radialMirrorAlternate = buf.readBoolean();
int radialMirrorRadius = buf.readInt(); int radialMirrorRadius = buf.readInt();
boolean radialMirrorDrawLines = buf.readBoolean(); boolean radialMirrorDrawLines = buf.readBoolean();
boolean radialMirrorDrawPlanes = buf.readBoolean(); boolean radialMirrorDrawPlanes = buf.readBoolean();
r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices, r = new RadialMirror.RadialMirrorSettings(radialMirrorEnabled, radialMirrorPosition, radialMirrorSlices,
radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes); radialMirrorAlternate, radialMirrorRadius, radialMirrorDrawLines, radialMirrorDrawPlanes);
} }
ModifierSettings modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade); ModifierSettings modifierSettings = new ModifierSettings(m, a, r, quickReplace, reachUpgrade);
return new ModifierSettingsMessage(modifierSettings); return new ModifierSettingsMessage(modifierSettings);
} }
public static class Handler public static class Handler {
{ public static void handle(ModifierSettingsMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(ModifierSettingsMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
ctx.get().enqueueWork(() -> {
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
// Sanitize // Sanitize
ModifierSettingsManager.sanitize(message.modifierSettings, player); ModifierSettingsManager.sanitize(message.modifierSettings, player);
ModifierSettingsManager.setModifierSettings(player, message.modifierSettings); ModifierSettingsManager.setModifierSettings(player, message.modifierSettings);
}); });
ctx.get().setPacketHandled(true); ctx.get().setPacketHandled(true);
} }
} }
} }

View File

@@ -1,32 +1,32 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.util.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.network.NetworkRegistry; import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel; import net.minecraftforge.network.simple.SimpleChannel;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
public class PacketHandler { public class PacketHandler {
private static final String PROTOCOL_VERSION = "1"; private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.ChannelBuilder public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
.named(new ResourceLocation(EffortlessBuilding.MODID, "main_channel")) new ResourceLocation(EffortlessBuilding.MODID, "main"),
.clientAcceptedVersions(PROTOCOL_VERSION::equals) () -> PROTOCOL_VERSION,
.serverAcceptedVersions(PROTOCOL_VERSION::equals) PROTOCOL_VERSION::equals,
.networkProtocolVersion(() -> PROTOCOL_VERSION) PROTOCOL_VERSION::equals
.simpleChannel(); );
public static void register() { public static void register() {
int id = 0; int id = 0;
INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode, ModifierSettingsMessage.Handler::handle); INSTANCE.registerMessage(id++, ModifierSettingsMessage.class, ModifierSettingsMessage::encode, ModifierSettingsMessage::decode, ModifierSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeSettingsMessage.class, ModeSettingsMessage::encode, ModeSettingsMessage::decode, ModeSettingsMessage.Handler::handle); INSTANCE.registerMessage(id++, ModeSettingsMessage.class, ModeSettingsMessage::encode, ModeSettingsMessage::decode, ModeSettingsMessage.Handler::handle);
INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode, ModeActionMessage.Handler::handle); INSTANCE.registerMessage(id++, ModeActionMessage.class, ModeActionMessage::encode, ModeActionMessage::decode, ModeActionMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockPlacedMessage.class, BlockPlacedMessage::encode, BlockPlacedMessage::decode, BlockPlacedMessage.Handler::handle); INSTANCE.registerMessage(id++, BlockPlacedMessage.class, BlockPlacedMessage::encode, BlockPlacedMessage::decode, BlockPlacedMessage.Handler::handle);
INSTANCE.registerMessage(id++, BlockBrokenMessage.class, BlockBrokenMessage::encode, BlockBrokenMessage::decode, BlockBrokenMessage.Handler::handle); INSTANCE.registerMessage(id++, BlockBrokenMessage.class, BlockBrokenMessage::encode, BlockBrokenMessage::decode, BlockBrokenMessage.Handler::handle);
INSTANCE.registerMessage(id++, CancelModeMessage.class, CancelModeMessage::encode, CancelModeMessage::decode, CancelModeMessage.Handler::handle); INSTANCE.registerMessage(id++, CancelModeMessage.class, CancelModeMessage::encode, CancelModeMessage::decode, CancelModeMessage.Handler::handle);
INSTANCE.registerMessage(id++, RequestLookAtMessage.class, RequestLookAtMessage::encode, RequestLookAtMessage::decode, RequestLookAtMessage.Handler::handle); INSTANCE.registerMessage(id++, RequestLookAtMessage.class, RequestLookAtMessage::encode, RequestLookAtMessage::decode, RequestLookAtMessage.Handler::handle);
INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode, AddUndoMessage.Handler::handle); INSTANCE.registerMessage(id++, AddUndoMessage.class, AddUndoMessage::encode, AddUndoMessage::decode, AddUndoMessage.Handler::handle);
INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode, ClearUndoMessage.Handler::handle); INSTANCE.registerMessage(id++, ClearUndoMessage.class, ClearUndoMessage::encode, ClearUndoMessage::decode, ClearUndoMessage.Handler::handle);
} }
} }

View File

@@ -1,13 +1,17 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.network.PacketBuffer; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.util.math.BlockRayTraceResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.phys.HitResult;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import nl.requios.effortlessbuilding.render.BlockPreviewRenderer;
import java.util.function.Supplier; import java.util.function.Supplier;
@@ -16,49 +20,54 @@ import java.util.function.Supplier;
* This is then sent back with a BlockPlacedMessage. * This is then sent back with a BlockPlacedMessage.
*/ */
public class RequestLookAtMessage { public class RequestLookAtMessage {
private boolean placeStartPos; private final boolean placeStartPos;
public RequestLookAtMessage() { public RequestLookAtMessage() {
placeStartPos = false; placeStartPos = false;
} }
public RequestLookAtMessage(boolean placeStartPos) { public RequestLookAtMessage(boolean placeStartPos) {
this.placeStartPos = placeStartPos; this.placeStartPos = placeStartPos;
} }
public boolean getPlaceStartPos() { public static void encode(RequestLookAtMessage message, FriendlyByteBuf buf) {
return placeStartPos; buf.writeBoolean(message.placeStartPos);
} }
public static void encode(RequestLookAtMessage message, PacketBuffer buf) { public static RequestLookAtMessage decode(FriendlyByteBuf buf) {
buf.writeBoolean(message.placeStartPos); boolean placeStartPos = buf.readBoolean();
} return new RequestLookAtMessage(placeStartPos);
}
public static RequestLookAtMessage decode(PacketBuffer buf) { public boolean getPlaceStartPos() {
boolean placeStartPos = buf.readBoolean(); return placeStartPos;
return new RequestLookAtMessage(placeStartPos); }
}
public static class Handler public static class Handler {
{ public static void handle(RequestLookAtMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(RequestLookAtMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
ctx.get().enqueueWork(() -> { //Received clientside
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) { DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> ClientHandler.handle(message, ctx));
//Received clientside }
//Send back your info });
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); ctx.get().setPacketHandled(true);
}
}
//Prevent double placing in normal mode with placeStartPos false @OnlyIn(Dist.CLIENT)
//Unless QuickReplace is on, then we do need to place start pos. public static class ClientHandler {
if (ClientProxy.previousLookAt.getType() == RayTraceResult.Type.BLOCK) { public static void handle(RequestLookAtMessage message, Supplier<NetworkEvent.Context> ctx) {
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage((BlockRayTraceResult) ClientProxy.previousLookAt, message.getPlaceStartPos())); //Send back your info
} else { Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage());
} //Prevent double placing in normal mode with placeStartPos false
} //Unless QuickReplace is on, then we do need to place start pos.
}); if (ClientProxy.previousLookAt.getType() == HitResult.Type.BLOCK) {
ctx.get().setPacketHandled(true); PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage((BlockHitResult) ClientProxy.previousLookAt, message.getPlaceStartPos()));
} } else {
} PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage());
}
}
}
} }

View File

@@ -1,79 +1,74 @@
package nl.requios.effortlessbuilding.network; package nl.requios.effortlessbuilding.network;
import net.minecraft.block.BlockState; import net.minecraft.world.entity.player.Player;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmodifier.BlockSet;
import nl.requios.effortlessbuilding.buildmodifier.UndoRedo;
import java.util.ArrayList;
import java.util.function.Supplier; import java.util.function.Supplier;
/**
* Send packet to client to translate and log the containing message
*/
public class TranslatedLogMessage { public class TranslatedLogMessage {
private String prefix; private final String prefix;
private String translationKey; private final String translationKey;
private String suffix; private final String suffix;
private boolean actionBar; private final boolean actionBar;
public TranslatedLogMessage(){ public TranslatedLogMessage() {
prefix = ""; prefix = "";
translationKey = ""; translationKey = "";
suffix = ""; suffix = "";
actionBar = false; actionBar = false;
} }
public TranslatedLogMessage(String prefix, String translationKey, String suffix, boolean actionBar) { public TranslatedLogMessage(String prefix, String translationKey, String suffix, boolean actionBar) {
this.prefix = prefix; this.prefix = prefix;
this.translationKey = translationKey; this.translationKey = translationKey;
this.suffix = suffix; this.suffix = suffix;
this.actionBar = actionBar; this.actionBar = actionBar;
} }
public String getPrefix() { public static void encode(TranslatedLogMessage message, FriendlyByteBuf buf) {
return prefix; buf.writeUtf(message.prefix);
} buf.writeUtf(message.translationKey);
buf.writeUtf(message.suffix);
buf.writeBoolean(message.actionBar);
}
public String getTranslationKey() { public static TranslatedLogMessage decode(FriendlyByteBuf buf) {
return translationKey; return new TranslatedLogMessage(buf.readUtf(), buf.readUtf(), buf.readUtf(), buf.readBoolean());
} }
public String getSuffix() { public String getPrefix() {
return suffix; return prefix;
} }
public boolean isActionBar() { public String getTranslationKey() {
return actionBar; return translationKey;
} }
public static void encode(TranslatedLogMessage message, PacketBuffer buf) { public String getSuffix() {
buf.writeString(message.prefix); return suffix;
buf.writeString(message.translationKey); }
buf.writeString(message.suffix);
buf.writeBoolean(message.actionBar);
}
public static TranslatedLogMessage decode(PacketBuffer buf) { public boolean isActionBar() {
return new TranslatedLogMessage(buf.readString(), buf.readString(), buf.readString(), buf.readBoolean()); return actionBar;
} }
public static class Handler public static class Handler {
{ public static void handle(TranslatedLogMessage message, Supplier<NetworkEvent.Context> ctx) {
public static void handle(TranslatedLogMessage message, Supplier<NetworkEvent.Context> ctx) ctx.get().enqueueWork(() -> {
{ if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
ctx.get().enqueueWork(() -> { //Received clientside
if (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT) {
//Received clientside
PlayerEntity player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx); Player player = EffortlessBuilding.proxy.getPlayerEntityFromContext(ctx);
EffortlessBuilding.logTranslate(player, message.prefix, message.translationKey, message.suffix, message.actionBar); EffortlessBuilding.logTranslate(player, message.prefix, message.translationKey, message.suffix, message.actionBar);
} }
}); });
ctx.get().setPacketHandled(true); ctx.get().setPacketHandled(true);
} }
} }
} }

View File

@@ -1,379 +1,334 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.block.BlockState; import net.minecraft.MethodsReturnNonnullByDefault;
import net.minecraft.block.SoundType; import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.gui.ScreenManager; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screen.Screen; import net.minecraft.client.resources.language.I18n;
import net.minecraft.client.renderer.texture.TextureAtlasSprite; import net.minecraft.client.KeyMapping;
import net.minecraft.client.resources.I18n; import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.world.entity.player.Player;
import net.minecraft.client.util.InputMappings; import net.minecraft.world.item.BlockItem;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.BlockItem; import net.minecraft.world.InteractionHand;
import net.minecraft.item.ItemStack; import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Hand; import net.minecraft.core.BlockPos;
import net.minecraft.util.ResourceLocation; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.SoundCategory; import net.minecraft.world.level.ClipContext;
import net.minecraft.util.math.*; import net.minecraft.world.phys.HitResult;
import net.minecraft.util.text.TextFormatting; import net.minecraft.world.phys.Vec3;
import net.minecraft.world.World; import net.minecraft.ChatFormatting;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.client.event.TextureStitchEvent; import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
import net.minecraftforge.client.event.ScreenEvent;
import net.minecraftforge.client.settings.KeyConflictContext; import net.minecraftforge.client.settings.KeyConflictContext;
import net.minecraftforge.client.settings.KeyModifier; import net.minecraftforge.client.settings.KeyModifier;
import net.minecraftforge.event.TickEvent; import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DeferredWorkQueue;
import net.minecraftforge.fml.LogicalSide; import net.minecraftforge.fml.LogicalSide;
import net.minecraftforge.fml.client.registry.ClientRegistry;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.BuildModes; import nl.requios.effortlessbuilding.buildmode.BuildModes;
import nl.requios.effortlessbuilding.buildmode.ModeOptions; import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.gui.DiamondRandomizerBagScreen;
import nl.requios.effortlessbuilding.gui.GoldenRandomizerBagScreen;
import nl.requios.effortlessbuilding.gui.RandomizerBagScreen; import nl.requios.effortlessbuilding.gui.RandomizerBagScreen;
import nl.requios.effortlessbuilding.gui.buildmode.PlayerSettingsGui; import nl.requios.effortlessbuilding.gui.buildmode.PlayerSettingsGui;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu; import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui; import nl.requios.effortlessbuilding.gui.buildmodifier.ModifierSettingsGui;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.network.*; import nl.requios.effortlessbuilding.network.*;
import nl.requios.effortlessbuilding.render.ShaderHandler;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.HashMap;
import java.util.function.Supplier; import java.util.function.Supplier;
@Mod.EventBusSubscriber(value = {Dist.CLIENT}) @Mod.EventBusSubscriber(value = {Dist.CLIENT})
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
public class ClientProxy implements IProxy { public class ClientProxy implements IProxy {
public static KeyBinding[] keyBindings; public static KeyMapping[] keyBindings;
public static RayTraceResult previousLookAt; public static HitResult previousLookAt;
public static RayTraceResult currentLookAt; public static HitResult currentLookAt;
private static int placeCooldown = 0; public static int ticksInGame = 0;
private static int breakCooldown = 0; private static int placeCooldown = 0;
private static boolean shadersInitialized = false; private static int breakCooldown = 0;
public static int ticksInGame = 0; @Override
public void setup(FMLCommonSetupEvent event) {
}
@Override @Override
public void setup(FMLCommonSetupEvent event) {} public void clientSetup(FMLClientSetupEvent event) {
//Keybindings are setup and registered in ModClientEventHandler
@Override MenuScreens.register(EffortlessBuilding.RANDOMIZER_BAG_CONTAINER.get(), RandomizerBagScreen::new);
public void clientSetup(FMLClientSetupEvent event) { MenuScreens.register(EffortlessBuilding.GOLDEN_RANDOMIZER_BAG_CONTAINER.get(), GoldenRandomizerBagScreen::new);
// register key bindings MenuScreens.register(EffortlessBuilding.DIAMOND_RANDOMIZER_BAG_CONTAINER.get(), DiamondRandomizerBagScreen::new);
keyBindings = new KeyBinding[7]; }
// instantiate the key bindings @SubscribeEvent
keyBindings[0] = new KeyBinding("key.effortlessbuilding.hud.desc", KeyConflictContext.UNIVERSAL, InputMappings.getInputByCode(GLFW.GLFW_KEY_KP_ADD, 0), "key.effortlessbuilding.category"); public static void onClientTick(TickEvent.ClientTickEvent event) {
keyBindings[1] = new KeyBinding("key.effortlessbuilding.replace.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_KP_SUBTRACT, 0), "key.effortlessbuilding.category");
keyBindings[2] = new KeyBinding("key.effortlessbuilding.creative.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_F4, 0), "key.effortlessbuilding.category");
keyBindings[3] = new KeyBinding("key.effortlessbuilding.mode.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_LEFT_ALT, 0), "key.effortlessbuilding.category") {
@Override
public boolean conflicts(KeyBinding other) {
//Does not conflict with Chisels and Bits radial menu
if (other.getKey().getKeyCode() == getKey().getKeyCode() && other.getKeyDescription().equals("mod.chiselsandbits.other.mode")) return false;
return super.conflicts(other);
}
};
keyBindings[4] = new KeyBinding("key.effortlessbuilding.undo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputMappings.getInputByCode(GLFW.GLFW_KEY_Z, 0), "key.effortlessbuilding.category");
keyBindings[5] = new KeyBinding("key.effortlessbuilding.redo.desc", KeyConflictContext.IN_GAME, KeyModifier.CONTROL, InputMappings.getInputByCode(GLFW.GLFW_KEY_Y, 0), "key.effortlessbuilding.category");
keyBindings[6] = new KeyBinding("key.effortlessbuilding.altplacement.desc", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_LEFT_CONTROL, 0), "key.effortlessbuilding.category");
//keyBindings[7] = new KeyBinding("Reload shaders", KeyConflictContext.UNIVERSAL, InputMappings.getInputByCode(GLFW.GLFW_KEY_TAB, 0), "key.effortlessbuilding.category");
// register all the key bindings if (event.phase == TickEvent.Phase.START) {
for (int i = 0; i < keyBindings.length; ++i) { onMouseInput();
ClientRegistry.registerKeyBinding(keyBindings[i]);
}
DeferredWorkQueue.runLater( () -> ScreenManager.registerFactory(EffortlessBuilding.RANDOMIZER_BAG_CONTAINER, RandomizerBagScreen::new)); //Update previousLookAt
} HitResult objectMouseOver = Minecraft.getInstance().hitResult;
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (objectMouseOver == null) return;
public PlayerEntity getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx){ if (currentLookAt == null) {
return (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT ? Minecraft.getInstance().player : ctx.get().getSender()); currentLookAt = objectMouseOver;
} previousLookAt = objectMouseOver;
return;
}
@SubscribeEvent if (objectMouseOver.getType() == HitResult.Type.BLOCK) {
public static void onClientTick(TickEvent.ClientTickEvent event) { if (currentLookAt.getType() != HitResult.Type.BLOCK) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (((BlockHitResult) currentLookAt).getBlockPos() != ((BlockHitResult) objectMouseOver).getBlockPos()) {
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
}
}
} else if (event.phase == TickEvent.Phase.END) {
Screen gui = Minecraft.getInstance().screen;
if (gui == null || !gui.isPauseScreen()) {
ticksInGame++;
}
}
if (event.phase == TickEvent.Phase.START) { }
onMouseInput();
//Update previousLookAt private static void onMouseInput() {
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver; Minecraft mc = Minecraft.getInstance();
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS) LocalPlayer player = mc.player;
if (objectMouseOver == null) return; if (player == null) return;
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (currentLookAt == null) { if (mc.screen != null ||
currentLookAt = objectMouseOver; buildMode == BuildModes.BuildModeEnum.NORMAL ||
previousLookAt = objectMouseOver; RadialMenu.instance.isVisible()) {
return; return;
} }
if (objectMouseOver.getType() == RayTraceResult.Type.BLOCK) { if (mc.options.keyUse.isDown()) {
if (currentLookAt.getType() != RayTraceResult.Type.BLOCK) {
currentLookAt = objectMouseOver;
previousLookAt = objectMouseOver;
} else {
if (((BlockRayTraceResult) currentLookAt).getPos() != ((BlockRayTraceResult) objectMouseOver).getPos()) {
previousLookAt = currentLookAt;
currentLookAt = objectMouseOver;
}
}
}
} else if (event.phase == TickEvent.Phase.END){ //KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false);
Screen gui = Minecraft.getInstance().currentScreen;
if(gui == null || !gui.isPauseScreen()) {
ticksInGame++;
}
//Init shaders in the first tick. Doing it anywhere before this seems to crash the game. if (placeCooldown <= 0) {
if (!shadersInitialized) { placeCooldown = 4;
ShaderHandler.init();
shadersInitialized = true;
}
}
} ItemStack currentItemStack = player.getItemInHand(InteractionHand.MAIN_HAND);
if (currentItemStack.getItem() instanceof BlockItem ||
(CompatHelper.isItemBlockProxy(currentItemStack) && !player.isShiftKeyDown())) {
private static void onMouseInput() { ItemStack itemStack = CompatHelper.getItemBlockFromStack(currentItemStack);
Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
if (player == null) return;
BuildModes.BuildModeEnum buildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (Minecraft.getInstance().currentScreen != null || //find position in distance
buildMode == BuildModes.BuildModeEnum.NORMAL || HitResult lookingAt = getLookingAt(player);
RadialMenu.instance.isVisible()) { if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
return; BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
}
if (mc.gameSettings.keyBindUseItem.isKeyDown()) { BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage(blockLookingAt, true));
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage(blockLookingAt, true));
//KeyBinding.setKeyBindState(mc.gameSettings.keyBindUseItem.getKeyCode(), false); //play sound if further than normal
if ((blockLookingAt.getLocation().subtract(player.getEyePosition(1f))).lengthSqr() > 25f &&
itemStack.getItem() instanceof BlockItem) {
if (placeCooldown <= 0) { BlockState state = ((BlockItem) itemStack.getItem()).getBlock().defaultBlockState();
placeCooldown = 4; BlockPos blockPos = blockLookingAt.getBlockPos();
SoundType soundType = state.getBlock().getSoundType(state, player.level, blockPos, player);
player.level.playSound(player, player.blockPosition(), soundType.getPlaceSound(), SoundSource.BLOCKS,
0.4f, soundType.getPitch());
player.swing(InteractionHand.MAIN_HAND);
}
} else {
BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage());
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage());
}
}
} else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
placeCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0;
}
} else {
placeCooldown = 0;
}
ItemStack currentItemStack = player.getHeldItem(Hand.MAIN_HAND); if (mc.options.keyAttack.isDown()) {
if (currentItemStack.getItem() instanceof BlockItem ||
(CompatHelper.isItemBlockProxy(currentItemStack) && !player.isSneaking())) {
ItemStack itemStack = CompatHelper.getItemBlockFromStack(currentItemStack); //Break block in distance in creative (or survival if enabled in config)
if (breakCooldown <= 0) {
breakCooldown = 4;
//find position in distance HitResult lookingAt = getLookingAt(player);
RayTraceResult lookingAt = getLookingAt(player); if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
if (lookingAt != null && lookingAt.getType() == RayTraceResult.Type.BLOCK) { BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
BlockRayTraceResult blockLookingAt = (BlockRayTraceResult) lookingAt;
BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage(blockLookingAt, true)); BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage(blockLookingAt));
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage(blockLookingAt, true)); PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage(blockLookingAt));
//play sound if further than normal //play sound if further than normal
if ((blockLookingAt.getHitVec().subtract(player.getEyePosition(1f))).lengthSquared() > 25f && if ((blockLookingAt.getLocation().subtract(player.getEyePosition(1f))).lengthSqr() > 25f) {
itemStack.getItem() instanceof BlockItem) {
BlockState state = ((BlockItem) itemStack.getItem()).getBlock().getDefaultState(); BlockPos blockPos = blockLookingAt.getBlockPos();
BlockPos blockPos = blockLookingAt.getPos(); BlockState state = player.level.getBlockState(blockPos);
SoundType soundType = state.getBlock().getSoundType(state, player.world, blockPos, player); SoundType soundtype = state.getBlock().getSoundType(state, player.level, blockPos, player);
player.world.playSound(player, player.getPosition(), soundType.getPlaceSound(), SoundCategory.BLOCKS, player.level.playSound(player, player.blockPosition(), soundtype.getBreakSound(), SoundSource.BLOCKS,
0.4f, soundType.getPitch() * 1f); 0.4f, soundtype.getPitch());
player.swingArm(Hand.MAIN_HAND); player.swing(InteractionHand.MAIN_HAND);
} }
} else { } else {
BuildModes.onBlockPlacedMessage(player, new BlockPlacedMessage()); BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage());
PacketHandler.INSTANCE.sendToServer(new BlockPlacedMessage()); PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage());
} }
} } else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
} breakCooldown--;
else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) { if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0;
placeCooldown--; }
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) placeCooldown = 0;
}
} else {
placeCooldown = 0;
}
if (mc.gameSettings.keyBindAttack.isKeyDown()) { //EffortlessBuilding.packetHandler.sendToServer(new CancelModeMessage());
//Break block in distance in creative (or survival if enabled in config) } else {
if (breakCooldown <= 0) { breakCooldown = 0;
breakCooldown = 4; }
}
//Early out if cant break far, coming from own mouse event (not block broken event) @SubscribeEvent(receiveCanceled = true)
//To make breaking blocks in survival possible like array public static void onKeyPress(InputEvent.Key event) {
//TODO this causes not being able to cancel placement in survival LocalPlayer player = Minecraft.getInstance().player;
// moving it to after buildmodes fixes that, but introduces this bug if (player == null)
if (!ReachHelper.canBreakFar(player)) return; return;
RayTraceResult lookingAt = getLookingAt(player); //Remember to send packet to server if necessary
if (lookingAt != null && lookingAt.getType() == RayTraceResult.Type.BLOCK) { //Show Modifier Settings GUI
BlockRayTraceResult blockLookingAt = (BlockRayTraceResult) lookingAt; if (keyBindings[0].consumeClick()) {
openModifierSettings();
}
BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage(blockLookingAt)); //QuickReplace toggle
PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage(blockLookingAt)); if (keyBindings[1].consumeClick()) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace());
EffortlessBuilding.log(player, "Set " + ChatFormatting.GOLD + "Quick Replace " + ChatFormatting.RESET + (
modifierSettings.doQuickReplace() ? "on" : "off"));
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings));
}
//play sound if further than normal //Radial menu
if ((blockLookingAt.getHitVec().subtract(player.getEyePosition(1f))).lengthSquared() > 25f) { if (keyBindings[2].isDown()) {
if (ReachHelper.getMaxReach(player) > 0) {
if (!RadialMenu.instance.isVisible()) {
Minecraft.getInstance().setScreen(RadialMenu.instance);
}
} else {
EffortlessBuilding.log(player, "Build modes are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
}
}
BlockPos blockPos = blockLookingAt.getPos(); //Undo (Ctrl+Z)
BlockState state = player.world.getBlockState(blockPos); if (keyBindings[3].consumeClick()) {
SoundType soundtype = state.getBlock().getSoundType(state, player.world, blockPos, player); ModeOptions.ActionEnum action = ModeOptions.ActionEnum.UNDO;
player.world.playSound(player, player.getPosition(), soundtype.getBreakSound(), SoundCategory.BLOCKS, ModeOptions.performAction(player, action);
0.4f, soundtype.getPitch() * 1f); PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
player.swingArm(Hand.MAIN_HAND); }
}
} else {
BuildModes.onBlockBrokenMessage(player, new BlockBrokenMessage());
PacketHandler.INSTANCE.sendToServer(new BlockBrokenMessage());
}
}
else if (buildMode == BuildModes.BuildModeEnum.NORMAL_PLUS) {
breakCooldown--;
if (ModeOptions.getBuildSpeed() == ModeOptions.ActionEnum.FAST_SPEED) breakCooldown = 0;
}
//EffortlessBuilding.packetHandler.sendToServer(new CancelModeMessage()); //Redo (Ctrl+Y)
if (keyBindings[4].consumeClick()) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.REDO;
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
} else { //Change placement mode
breakCooldown = 0; if (keyBindings[5].consumeClick()) {
} //Toggle between first two actions of the first option of the current build mode
} BuildModes.BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (currentBuildMode.options.length > 0) {
ModeOptions.OptionEnum option = currentBuildMode.options[0];
if (option.actions.length >= 2) {
if (ModeOptions.getOptionSetting(option) == option.actions[0]) {
ModeOptions.performAction(player, option.actions[1]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[1]));
} else {
ModeOptions.performAction(player, option.actions[0]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[0]));
}
}
}
}
@SubscribeEvent(receiveCanceled = true) }
public static void onKeyPress(InputEvent.KeyInputEvent event) {
ClientPlayerEntity player = Minecraft.getInstance().player;
//Remember to send packet to server if necessary public static void openModifierSettings() {
//Show Modifier Settings GUI Minecraft mc = Minecraft.getInstance();
if (keyBindings[0].isPressed()) { LocalPlayer player = mc.player;
openModifierSettings(); if (player == null) return;
}
//QuickReplace toggle //Disabled if max reach is 0, might be set in the config that way.
if (keyBindings[1].isPressed()) { if (ReachHelper.getMaxReach(player) == 0) {
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); EffortlessBuilding.log(player, "Build modifiers are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
modifierSettings.setQuickReplace(!modifierSettings.doQuickReplace()); } else {
EffortlessBuilding.log(player, "Set " + TextFormatting.GOLD + "Quick Replace " + TextFormatting.RESET + ( mc.setScreen(new ModifierSettingsGui());
modifierSettings.doQuickReplace() ? "on" : "off")); }
PacketHandler.INSTANCE.sendToServer(new ModifierSettingsMessage(modifierSettings)); }
}
//Creative/survival mode toggle public static void openPlayerSettings() {
if (keyBindings[2].isPressed()) { Minecraft mc = Minecraft.getInstance();
if (player.isCreative()) { mc.setScreen(new PlayerSettingsGui());
player.sendChatMessage("/gamemode survival"); }
} else {
player.sendChatMessage("/gamemode creative");
}
}
//Undo (Ctrl+Z) @SubscribeEvent
if (keyBindings[4].isPressed()) { public static void onGuiOpen(ScreenEvent event) {
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.UNDO; Player player = Minecraft.getInstance().player;
ModeOptions.performAction(player, action); if (player != null) {
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action)); BuildModes.initializeMode(player);
} }
}
//Redo (Ctrl+Y) public static boolean isKeybindDown(int keybindIndex) {
if (keyBindings[5].isPressed()) { return InputConstants.isKeyDown(
ModeOptions.ActionEnum action = ModeOptions.ActionEnum.REDO; Minecraft.getInstance().getWindow().getWindow(),
ModeOptions.performAction(player, action); ClientProxy.keyBindings[2].getKey().getValue());
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action)); }
}
//Change placement mode public static HitResult getLookingAt(Player player) {
if (keyBindings[6].isPressed()) { Level world = player.level;
//Toggle between first two actions of the first option of the current build mode
BuildModes.BuildModeEnum currentBuildMode = ModeSettingsManager.getModeSettings(player).getBuildMode();
if (currentBuildMode.options.length > 0) {
ModeOptions.OptionEnum option = currentBuildMode.options[0];
if (option.actions.length >= 2) {
if (ModeOptions.getOptionSetting(option) == option.actions[0]) {
ModeOptions.performAction(player, option.actions[1]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[1]));
} else {
ModeOptions.performAction(player, option.actions[0]);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(option.actions[0]));
}
}
}
}
//For shader development //base distance off of player ability (config)
if (keyBindings.length >= 8 && keyBindings[7].isPressed()) { float raytraceRange = ReachHelper.getPlacementReach(player);
ShaderHandler.init();
EffortlessBuilding.log(player, "Reloaded shaders");
}
} Vec3 look = player.getLookAngle();
Vec3 start = new Vec3(player.getX(), player.getY() + player.getEyeHeight(), player.getZ());
public static void openModifierSettings() { Vec3 end = new Vec3(player.getX() + look.x * raytraceRange, player.getY() + player.getEyeHeight() + look.y * raytraceRange, player.getZ() + look.z * raytraceRange);
Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
RadialMenu.instance.setVisibility(0f);
//Disabled if max reach is 0, might be set in the config that way.
if (ReachHelper.getMaxReach(player) == 0) {
EffortlessBuilding.log(player, "Build modifiers are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
} else {
if (mc.currentScreen == null) {
mc.displayGuiScreen(new ModifierSettingsGui());
} else {
player.closeScreen();
}
}
}
public static void openPlayerSettings() {
Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
RadialMenu.instance.setVisibility(0f);
//Disabled if max reach is 0, might be set in the config that way.
if (mc.currentScreen == null) {
mc.displayGuiScreen(new PlayerSettingsGui());
} else {
player.closeScreen();
}
}
@SubscribeEvent
public static void onGuiOpen(GuiOpenEvent event) {
PlayerEntity player = Minecraft.getInstance().player;
if (player != null) {
BuildModes.initializeMode(player);
}
}
@Nullable
public static RayTraceResult getLookingAt(PlayerEntity player) {
World world = player.world;
//base distance off of player ability (config)
float raytraceRange = ReachHelper.getPlacementReach(player);
Vec3d look = player.getLookVec();
Vec3d start = new Vec3d(player.getPosX(), player.getPosY() + player.getEyeHeight(), player.getPosZ());
Vec3d end = new Vec3d(player.getPosX() + look.x * raytraceRange, player.getPosY() + player.getEyeHeight() + look.y * raytraceRange, player.getPosZ() + look.z * raytraceRange);
// return player.rayTrace(raytraceRange, 1f, RayTraceFluidMode.NEVER); // return player.rayTrace(raytraceRange, 1f, RayTraceFluidMode.NEVER);
//TODO 1.14 check if correct //TODO 1.14 check if correct
return world.rayTraceBlocks(new RayTraceContext(start, end, RayTraceContext.BlockMode.COLLIDER, RayTraceContext.FluidMode.NONE, player)); return world.clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, player));
} }
@Override public Player getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx) {
public void logTranslate(PlayerEntity player, String prefix, String translationKey, String suffix, boolean actionBar) { return (ctx.get().getDirection().getReceptionSide() == LogicalSide.CLIENT ? Minecraft.getInstance().player : ctx.get().getSender());
EffortlessBuilding.log(Minecraft.getInstance().player, prefix + I18n.format(translationKey) + suffix, actionBar); }
}
@Override
public void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
EffortlessBuilding.log(Minecraft.getInstance().player, prefix + I18n.get(translationKey) + suffix, actionBar);
}
} }

View File

@@ -1,18 +1,18 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier; import java.util.function.Supplier;
public interface IProxy { public interface IProxy {
void setup(final FMLCommonSetupEvent event); void setup(final FMLCommonSetupEvent event);
void clientSetup(final FMLClientSetupEvent event); void clientSetup(final FMLClientSetupEvent event);
PlayerEntity getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx); Player getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx);
void logTranslate(PlayerEntity player, String prefix, String translationKey, String suffix, boolean actionBar); void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar);
} }

View File

@@ -1,32 +1,33 @@
package nl.requios.effortlessbuilding.proxy; package nl.requios.effortlessbuilding.proxy;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.entity.player.ServerPlayerEntity; import net.minecraft.server.level.ServerPlayer;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.network.NetworkEvent; import net.minecraftforge.network.NetworkEvent;
import net.minecraftforge.fml.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import nl.requios.effortlessbuilding.network.PacketHandler; import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.network.TranslatedLogMessage; import nl.requios.effortlessbuilding.network.TranslatedLogMessage;
import java.util.function.Supplier; import java.util.function.Supplier;
public class ServerProxy implements IProxy { public class ServerProxy implements IProxy {
//Only physical server! Singleplayer server is seen as clientproxy //Only physical server! Singleplayer server is seen as clientproxy
@Override @Override
public void setup(FMLCommonSetupEvent event) { public void setup(FMLCommonSetupEvent event) {
} }
@Override @Override
public void clientSetup(FMLClientSetupEvent event) {} public void clientSetup(FMLClientSetupEvent event) {
}
public PlayerEntity getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx){ public Player getPlayerEntityFromContext(Supplier<NetworkEvent.Context> ctx) {
return ctx.get().getSender(); return ctx.get().getSender();
} }
@Override @Override
public void logTranslate(PlayerEntity player, String prefix, String translationKey, String suffix, boolean actionBar) { public void logTranslate(Player player, String prefix, String translationKey, String suffix, boolean actionBar) {
PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), new TranslatedLogMessage(prefix, translationKey, suffix, actionBar)); PacketHandler.INSTANCE.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new TranslatedLogMessage(prefix, translationKey, suffix, actionBar));
} }
} }

View File

@@ -1,21 +1,23 @@
package nl.requios.effortlessbuilding.render; package nl.requios.effortlessbuilding.render;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.blaze3d.vertex.IVertexBuilder; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.block.BlockState; import net.minecraft.world.level.block.SoundType;
import net.minecraft.block.SoundType;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.BlockRendererDispatcher; import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.IRenderTypeBuffer; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.world.entity.player.Player;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.item.ItemStack;
import net.minecraft.item.ItemStack; import net.minecraft.core.Direction;
import net.minecraft.util.Direction; import net.minecraft.sounds.SoundSource;
import net.minecraft.util.SoundCategory; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.*; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.util.math.shapes.VoxelShape; import net.minecraft.util.Mth;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.BuildConfig; import nl.requios.effortlessbuilding.BuildConfig;
@@ -30,355 +32,353 @@ import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager.Modif
import nl.requios.effortlessbuilding.compatibility.CompatHelper; import nl.requios.effortlessbuilding.compatibility.CompatHelper;
import nl.requios.effortlessbuilding.helper.ReachHelper; import nl.requios.effortlessbuilding.helper.ReachHelper;
import nl.requios.effortlessbuilding.helper.SurvivalHelper; import nl.requios.effortlessbuilding.helper.SurvivalHelper;
import nl.requios.effortlessbuilding.item.ItemRandomizerBag; import nl.requios.effortlessbuilding.item.AbstractRandomizerBagItem;
import nl.requios.effortlessbuilding.proxy.ClientProxy; import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.*;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class BlockPreviewRenderer { public class BlockPreviewRenderer {
private static List<BlockPos> previousCoordinates; private static final List<PlacedData> placedDataList = new ArrayList<>();
private static List<BlockState> previousBlockStates; private static List<BlockPos> previousCoordinates;
private static List<ItemStack> previousItemStacks; private static List<BlockState> previousBlockStates;
private static BlockPos previousFirstPos; private static List<ItemStack> previousItemStacks;
private static BlockPos previousSecondPos; private static BlockPos previousFirstPos;
private static int soundTime = 0; private static BlockPos previousSecondPos;
private static int soundTime = 0;
static class PlacedData {
float time; public static void render(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Player player, ModifierSettings modifierSettings, ModeSettings modeSettings) {
List<BlockPos> coordinates;
List<BlockState> blockStates; //Render placed blocks with dissolve effect
List<ItemStack> itemStacks; //Use fancy shader if config allows, otherwise no dissolve
BlockPos firstPos; if (BuildConfig.visuals.useShaders.get()) {
BlockPos secondPos; for (int i = 0; i < placedDataList.size(); i++) {
boolean breaking; PlacedData placed = placedDataList.get(i);
if (placed.coordinates != null && !placed.coordinates.isEmpty()) {
public PlacedData(float time, List<BlockPos> coordinates, List<BlockState> blockStates,
List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) { double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
this.time = time; float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) totalTime;
this.coordinates = coordinates; renderBlockPreviews(matrixStack, renderTypeBuffer, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking);
this.blockStates = blockStates; }
this.itemStacks = itemStacks; }
this.firstPos = firstPos; }
this.secondPos = secondPos; //Expire
this.breaking = breaking; placedDataList.removeIf(placed -> {
} double totalTime = Mth.clampedLerp(30, 60, placed.firstPos.distSqr(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get();
} return placed.time + totalTime < ClientProxy.ticksInGame;
});
private static List<PlacedData> placedDataList = new ArrayList<>();
//Render block previews
public static void render(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, PlayerEntity player, ModifierSettings modifierSettings, ModeSettings modeSettings) { HitResult lookingAt = ClientProxy.getLookingAt(player);
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.NORMAL)
//Render placed blocks with dissolve effect lookingAt = Minecraft.getInstance().hitResult;
//Use fancy shader if config allows, otherwise no dissolve
if (BuildConfig.visuals.useShaders.get()) { ItemStack mainhand = player.getMainHandItem();
for (int i = 0; i < placedDataList.size(); i++) { boolean noBlockInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand));
PlacedData placed = placedDataList.get(i);
if (placed.coordinates != null && !placed.coordinates.isEmpty()) { BlockPos startPos = null;
Direction sideHit = null;
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get(); Vec3 hitVec = null;
float dissolve = (ClientProxy.ticksInGame - placed.time) / (float) totalTime;
renderBlockPreviews(matrixStack, renderTypeBuffer, placed.coordinates, placed.blockStates, placed.itemStacks, dissolve, placed.firstPos, placed.secondPos, false, placed.breaking); //Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
} if (lookingAt != null && lookingAt.getType() == HitResult.Type.BLOCK) {
} BlockHitResult blockLookingAt = (BlockHitResult) lookingAt;
} startPos = blockLookingAt.getBlockPos();
//Expire
placedDataList.removeIf(placed -> { //Check if tool (or none) in hand
double totalTime = MathHelper.clampedLerp(30, 60, placed.firstPos.distanceSq(placed.secondPos) / 100.0) * BuildConfig.visuals.dissolveTimeMultiplier.get(); //TODO 1.13 replaceable
return placed.time + totalTime < ClientProxy.ticksInGame; boolean replaceable = player.level.getBlockState(startPos).getMaterial().isReplaceable();
}); boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, blockLookingAt.getDirection());
if (!modifierSettings.doQuickReplace() && !noBlockInHand && !replaceable && !becomesDoubleSlab) {
//Render block previews startPos = startPos.relative(blockLookingAt.getDirection());
RayTraceResult lookingAt = ClientProxy.getLookingAt(player); }
if (modeSettings.getBuildMode() == BuildModes.BuildModeEnum.NORMAL) lookingAt = Minecraft.getInstance().objectMouseOver;
//Get under tall grass and other replaceable blocks
ItemStack mainhand = player.getHeldItemMainhand(); if (modifierSettings.doQuickReplace() && !noBlockInHand && replaceable) {
boolean toolInHand = !(!mainhand.isEmpty() && CompatHelper.isItemBlockProxy(mainhand)); startPos = startPos.below();
}
BlockPos startPos = null;
Direction sideHit = null; sideHit = blockLookingAt.getDirection();
Vec3d hitVec = null; hitVec = blockLookingAt.getLocation();
}
//Checking for null is necessary! Even in vanilla when looking down ladders it is occasionally null (instead of Type MISS)
if (lookingAt != null && lookingAt.getType() == RayTraceResult.Type.BLOCK) { //Dont render if in normal mode and modifiers are disabled
BlockRayTraceResult blockLookingAt = (BlockRayTraceResult) lookingAt; //Unless alwaysShowBlockPreview is true in config
startPos = blockLookingAt.getPos(); if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) {
//Check if tool (or none) in hand //Keep blockstate the same for every block in the buildmode
//TODO 1.13 replaceable //So dont rotate blocks when in the middle of placing wall etc.
boolean replaceable = player.world.getBlockState(startPos).getBlock().getMaterial(player.world.getBlockState(startPos)).isReplaceable(); if (BuildModes.isActive(player)) {
boolean becomesDoubleSlab = SurvivalHelper.doesBecomeDoubleSlab(player, startPos, blockLookingAt.getFace()); IBuildMode buildModeInstance = modeSettings.getBuildMode().instance;
if (!modifierSettings.doQuickReplace() && !toolInHand && !replaceable && !becomesDoubleSlab) { if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player);
startPos = startPos.offset(blockLookingAt.getFace()); if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player);
} }
//Get under tall grass and other replaceable blocks if (sideHit != null) {
if (modifierSettings.doQuickReplace() && !toolInHand && replaceable) {
startPos = startPos.down(); //Should be red?
} boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
sideHit = blockLookingAt.getFace(); //get coordinates
hitVec = blockLookingAt.getHitVec(); List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
}
//Remember first and last point for the shader
//Dont render if in normal mode and modifiers are disabled BlockPos firstPos = BlockPos.ZERO, secondPos = BlockPos.ZERO;
//Unless alwaysShowBlockPreview is true in config if (!startCoordinates.isEmpty()) {
if (doRenderBlockPreviews(modifierSettings, modeSettings, startPos)) { firstPos = startCoordinates.get(0);
secondPos = startCoordinates.get(startCoordinates.size() - 1);
//Keep blockstate the same for every block in the buildmode }
//So dont rotate blocks when in the middle of placing wall etc.
if (BuildModes.isActive(player)) { //Limit number of blocks you can place
IBuildMode buildModeInstance = modeSettings.getBuildMode().instance; int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player);
if (buildModeInstance.getSideHit(player) != null) sideHit = buildModeInstance.getSideHit(player); if (startCoordinates.size() > limit) {
if (buildModeInstance.getHitVec(player) != null) hitVec = buildModeInstance.getHitVec(player); startCoordinates = startCoordinates.subList(0, limit);
} }
if (sideHit != null) { List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates);
//Should be red? sortOnDistanceToPlayer(newCoordinates, player);
boolean breaking = BuildModes.currentlyBreakingClient.get(player) != null && BuildModes.currentlyBreakingClient.get(player);
hitVec = new Vec3(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)),
//get coordinates Math.abs(hitVec.z - ((int) hitVec.z)));
List<BlockPos> startCoordinates = BuildModes.findCoordinates(player, startPos, breaking || modifierSettings.doQuickReplace());
//Get blockstates
//Remember first and last point for the shader List<ItemStack> itemStacks = new ArrayList<>();
BlockPos firstPos = BlockPos.ZERO, secondPos = BlockPos.ZERO; List<BlockState> blockStates = new ArrayList<>();
if (!startCoordinates.isEmpty()) { if (breaking) {
firstPos = startCoordinates.get(0); //Find blockstate of world
secondPos = startCoordinates.get(startCoordinates.size() - 1); for (BlockPos coordinate : newCoordinates) {
} blockStates.add(player.level.getBlockState(coordinate));
}
//Limit number of blocks you can place } else {
int limit = ReachHelper.getMaxBlocksPlacedAtOnce(player); blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks);
if (startCoordinates.size() > limit) { }
startCoordinates = startCoordinates.subList(0, limit);
}
//Check if they are different from previous
List<BlockPos> newCoordinates = BuildModifiers.findCoordinates(player, startCoordinates); //TODO fix triggering when moving player
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) {
sortOnDistanceToPlayer(newCoordinates, player); previousCoordinates = newCoordinates;
//remember the rest for placed blocks
hitVec = new Vec3d(Math.abs(hitVec.x - ((int) hitVec.x)), Math.abs(hitVec.y - ((int) hitVec.y)), previousBlockStates = blockStates;
Math.abs(hitVec.z - ((int) hitVec.z))); previousItemStacks = itemStacks;
previousFirstPos = firstPos;
//Get blockstates previousSecondPos = secondPos;
List<ItemStack> itemStacks = new ArrayList<>();
List<BlockState> blockStates = new ArrayList<>(); //if so, renew randomness of randomizer bag
if (breaking) { AbstractRandomizerBagItem.renewRandomness();
//Find blockstate of world //and play sound (max once every tick)
for (BlockPos coordinate : newCoordinates) { if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) {
blockStates.add(player.world.getBlockState(coordinate)); soundTime = ClientProxy.ticksInGame;
}
} else { if (blockStates.get(0) != null) {
blockStates = BuildModifiers.findBlockStates(player, startCoordinates, hitVec, sideHit, itemStacks); SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.level,
} newCoordinates.get(0), player);
player.level.playSound(player, player.blockPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(),
SoundSource.BLOCKS, 0.3f, 0.8f);
//Check if they are different from previous }
//TODO fix triggering when moving player }
if (!BuildModifiers.compareCoordinates(previousCoordinates, newCoordinates)) { }
previousCoordinates = newCoordinates;
//remember the rest for placed blocks //Render block previews
previousBlockStates = blockStates; if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
previousItemStacks = itemStacks; int blockCount;
previousFirstPos = firstPos;
previousSecondPos = secondPos; //Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
//if so, renew randomness of randomizer bag blockCount = renderBlockPreviews(matrixStack, renderTypeBuffer, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking);
ItemRandomizerBag.renewRandomness(); } else {
//and play sound (max once every tick) VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
if (newCoordinates.size() > 1 && blockStates.size() > 1 && soundTime < ClientProxy.ticksInGame - 0) {
soundTime = ClientProxy.ticksInGame; Vec3 color = new Vec3(1f, 1f, 1f);
if (breaking) color = new Vec3(1f, 0f, 0f);
if (blockStates.get(0) != null) {
SoundType soundType = blockStates.get(0).getBlock().getSoundType(blockStates.get(0), player.world, for (int i = newCoordinates.size() - 1; i >= 0; i--) {
newCoordinates.get(0), player); VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.level, newCoordinates.get(i));
player.world.playSound(player, player.getPosition(), breaking ? soundType.getBreakSound() : soundType.getPlaceSound(), RenderHandler.renderBlockOutline(matrixStack, buffer, newCoordinates.get(i), collisionShape, color);
SoundCategory.BLOCKS, 0.3f, 0.8f); }
}
} RenderHandler.endLines(renderTypeBuffer);
}
blockCount = newCoordinates.size();
//Render block previews }
if (blockStates.size() != 0 && newCoordinates.size() == blockStates.size()) {
int blockCount; //Display block count and dimensions in actionbar
if (BuildModes.isActive(player)) {
//Use fancy shader if config allows, otherwise outlines
if (BuildConfig.visuals.useShaders.get() && newCoordinates.size() < BuildConfig.visuals.shaderTreshold.get()) { //Find min and max values (not simply firstPos and secondPos because that doesn't work with circles)
blockCount = renderBlockPreviews(matrixStack, renderTypeBuffer, newCoordinates, blockStates, itemStacks, 0f, firstPos, secondPos, !breaking, breaking); int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE;
} else { int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
IVertexBuilder buffer = RenderHandler.beginLines(renderTypeBuffer); int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
for (BlockPos pos : startCoordinates) {
Vec3d color = new Vec3d(1f, 1f, 1f); if (pos.getX() < minX) minX = pos.getX();
if (breaking) color = new Vec3d(1f, 0f, 0f); if (pos.getX() > maxX) maxX = pos.getX();
if (pos.getY() < minY) minY = pos.getY();
for (int i = newCoordinates.size() - 1; i >= 0; i--) { if (pos.getY() > maxY) maxY = pos.getY();
VoxelShape collisionShape = blockStates.get(i).getCollisionShape(player.world, newCoordinates.get(i)); if (pos.getZ() < minZ) minZ = pos.getZ();
RenderHandler.renderBlockOutline(matrixStack, buffer, newCoordinates.get(i), collisionShape, color); if (pos.getZ() > maxZ) maxZ = pos.getZ();
} }
BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
RenderHandler.endLines(renderTypeBuffer);
String dimensions = "(";
blockCount = newCoordinates.size(); if (dim.getX() > 1) dimensions += dim.getX() + "x";
} if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
if (dim.getY() > 1) dimensions += dim.getY() + "x";
//Display block count and dimensions in actionbar dimensions = dimensions.substring(0, dimensions.length() - 1);
if (BuildModes.isActive(player)) { if (dimensions.length() > 1) dimensions += ")";
//Find min and max values (not simply firstPos and secondPos because that doesn't work with circles) EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE; }
int minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE; }
int minZ = Integer.MAX_VALUE, maxZ = Integer.MIN_VALUE;
for (BlockPos pos : startCoordinates) {
if (pos.getX() < minX) minX = pos.getX(); }
if (pos.getX() > maxX) maxX = pos.getX();
if (pos.getY() < minY) minY = pos.getY(); //Draw outlines if no block in hand
if (pos.getY() > maxY) maxY = pos.getY(); //Find proper raytrace: either normal range or increased range depending on canBreakFar
if (pos.getZ() < minZ) minZ = pos.getZ(); VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
if (pos.getZ() > maxZ) maxZ = pos.getZ(); HitResult objectMouseOver = Minecraft.getInstance().hitResult;
} HitResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver;
BlockPos dim = new BlockPos(maxX - minX + 1, maxY - minY + 1, maxZ - minZ + 1);
if (player.isCreative() && noBlockInHand && breakingRaytrace != null && breakingRaytrace.getType() == HitResult.Type.BLOCK) {
String dimensions = "("; BlockHitResult blockBreakingRaytrace = (BlockHitResult) breakingRaytrace;
if (dim.getX() > 1) dimensions += dim.getX() + "x"; List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getBlockPos());
if (dim.getZ() > 1) dimensions += dim.getZ() + "x";
if (dim.getY() > 1) dimensions += dim.getY() + "x"; //Only render first outline if further than normal reach
dimensions = dimensions.substring(0, dimensions.length() - 1); boolean excludeFirst = objectMouseOver != null && objectMouseOver.getType() == HitResult.Type.BLOCK;
if (dimensions.length() > 1) dimensions += ")"; for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) {
BlockPos coordinate = breakCoordinates.get(i);
EffortlessBuilding.log(player, blockCount + " blocks " + dimensions, true);
} BlockState blockState = player.level.getBlockState(coordinate);
} if (!blockState.isAir()) {
if (SurvivalHelper.canBreak(player.level, player, coordinate) || i == 0) {
VoxelShape collisionShape = blockState.getCollisionShape(player.level, coordinate);
} RenderHandler.renderBlockOutline(matrixStack, buffer, coordinate, collisionShape, new Vec3(0f, 0f, 0f));
}
IVertexBuilder buffer = RenderHandler.beginLines(renderTypeBuffer); }
//Draw outlines if tool in hand }
//Find proper raytrace: either normal range or increased range depending on canBreakFar }
RayTraceResult objectMouseOver = Minecraft.getInstance().objectMouseOver; RenderHandler.endLines(renderTypeBuffer);
RayTraceResult breakingRaytrace = ReachHelper.canBreakFar(player) ? lookingAt : objectMouseOver; }
if (toolInHand && breakingRaytrace != null && breakingRaytrace.getType() == RayTraceResult.Type.BLOCK) { }
BlockRayTraceResult blockBreakingRaytrace = (BlockRayTraceResult) breakingRaytrace;
List<BlockPos> breakCoordinates = BuildModifiers.findCoordinates(player, blockBreakingRaytrace.getPos()); //Whether to draw any block previews or outlines
public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) {
//Only render first outline if further than normal reach return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.NORMAL ||
boolean excludeFirst = objectMouseOver != null && objectMouseOver.getType() == RayTraceResult.Type.BLOCK; (startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
for (int i = excludeFirst ? 1 : 0; i < breakCoordinates.size(); i++) { BuildConfig.visuals.alwaysShowBlockPreview.get();
BlockPos coordinate = breakCoordinates.get(i); }
BlockState blockState = player.world.getBlockState(coordinate); protected static int renderBlockPreviews(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, List<BlockPos> coordinates, List<BlockState> blockStates,
if (!blockState.getBlock().isAir(blockState, player.world, coordinate)) { List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
if (SurvivalHelper.canBreak(player.world, player, coordinate) || i == 0) { BlockPos secondPos, boolean checkCanPlace, boolean red) {
VoxelShape collisionShape = blockState.getCollisionShape(player.world, coordinate); Player player = Minecraft.getInstance().player;
RenderHandler.renderBlockOutline(matrixStack, buffer, coordinate, collisionShape, new Vec3d(0f, 0f, 0f)); ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
} BlockRenderDispatcher dispatcher = Minecraft.getInstance().getBlockRenderer();
} int blocksValid = 0;
}
} if (coordinates.isEmpty()) return blocksValid;
RenderHandler.endLines(renderTypeBuffer);
} for (int i = coordinates.size() - 1; i >= 0; i--) {
} BlockPos blockPos = coordinates.get(i);
BlockState blockState = blockStates.get(i);
//Whether to draw any block previews or outlines ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i);
public static boolean doRenderBlockPreviews(ModifierSettings modifierSettings, ModeSettings modeSettings, BlockPos startPos) { if (CompatHelper.isItemBlockProxy(itemstack))
return modeSettings.getBuildMode() != BuildModes.BuildModeEnum.NORMAL || itemstack = CompatHelper.getItemBlockByState(itemstack, blockState);
(startPos != null && BuildModifiers.isEnabled(modifierSettings, startPos)) ||
BuildConfig.visuals.alwaysShowBlockPreview.get(); //Check if can place
} //If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks the breaking shader)
protected static int renderBlockPreviews(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, List<BlockPos> coordinates, List<BlockState> blockStates, SurvivalHelper.canPlace(player.level, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP)) {
List<ItemStack> itemStacks, float dissolve, BlockPos firstPos,
BlockPos secondPos, boolean checkCanPlace, boolean red) { RenderHandler.renderBlockPreview(matrixStack, renderTypeBuffer, dispatcher, blockPos, blockState, dissolve, firstPos, secondPos, red);
PlayerEntity player = Minecraft.getInstance().player; blocksValid++;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); }
BlockRendererDispatcher dispatcher = Minecraft.getInstance().getBlockRendererDispatcher(); }
int blocksValid = 0; return blocksValid;
}
if (coordinates.isEmpty()) return blocksValid;
public static void onBlocksPlaced() {
for (int i = coordinates.size() - 1; i >= 0; i--) { onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
BlockPos blockPos = coordinates.get(i); }
BlockState blockState = blockStates.get(i);
ItemStack itemstack = itemStacks.isEmpty() ? ItemStack.EMPTY : itemStacks.get(i); public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates,
if (CompatHelper.isItemBlockProxy(itemstack)) BlockPos firstPos, BlockPos secondPos) {
itemstack = CompatHelper.getItemBlockByState(itemstack, blockState); LocalPlayer player = Minecraft.getInstance().player;
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
//Check if can place ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//If check is turned off, check if blockstate is the same (for dissolve effect)
if ((!checkCanPlace /*&& player.world.getNewBlockState(blockPos) == blockState*/) || //TODO enable (breaks the breaking shader) //Check if block previews are enabled
SurvivalHelper.canPlace(player.world, player, blockPos, blockState, itemstack, modifierSettings.doQuickReplace(), Direction.UP)) { if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
RenderHandler.renderBlockPreview(matrixStack, renderTypeBuffer, dispatcher, blockPos, blockState, dissolve, firstPos, secondPos, red); //Save current coordinates, blockstates and itemstacks
blocksValid++; if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
} coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
}
return blocksValid; placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
} itemStacks, firstPos, secondPos, false));
}
public static void onBlocksPlaced() { }
onBlocksPlaced(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
} }
public static void onBlocksPlaced(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates, public static void onBlocksBroken() {
BlockPos firstPos, BlockPos secondPos) { onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos);
ClientPlayerEntity player = Minecraft.getInstance().player; }
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates,
BlockPos firstPos, BlockPos secondPos) {
//Check if block previews are enabled LocalPlayer player = Minecraft.getInstance().player;
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) { ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
//Save current coordinates, blockstates and itemstacks
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() && //Check if block previews are enabled
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold.get()) { if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) {
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates, //Save current coordinates, blockstates and itemstacks
itemStacks, firstPos, secondPos, false)); if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
} coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderThreshold.get()) {
}
sortOnDistanceToPlayer(coordinates, player);
}
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates,
public static void onBlocksBroken() { itemStacks, firstPos, secondPos, true));
onBlocksBroken(previousCoordinates, previousItemStacks, previousBlockStates, previousFirstPos, previousSecondPos); }
} }
public static void onBlocksBroken(List<BlockPos> coordinates, List<ItemStack> itemStacks, List<BlockState> blockStates, }
BlockPos firstPos, BlockPos secondPos) {
ClientPlayerEntity player = Minecraft.getInstance().player; private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, Player player) {
ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); Collections.sort(coordinates, (lhs, rhs) -> {
// -1 - less than, 1 - greater than, 0 - equal
//Check if block previews are enabled double lhsDistanceToPlayer = Vec3.atLowerCornerOf(lhs).subtract(player.getEyePosition(1f)).lengthSqr();
if (doRenderBlockPreviews(modifierSettings, modeSettings, firstPos)) { double rhsDistanceToPlayer = Vec3.atLowerCornerOf(rhs).subtract(player.getEyePosition(1f)).lengthSqr();
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer);
//Save current coordinates, blockstates and itemstacks });
if (!coordinates.isEmpty() && blockStates.size() == coordinates.size() &&
coordinates.size() > 1 && coordinates.size() < BuildConfig.visuals.shaderTreshold.get()) { }
sortOnDistanceToPlayer(coordinates, player); static class PlacedData {
float time;
placedDataList.add(new PlacedData(ClientProxy.ticksInGame, coordinates, blockStates, List<BlockPos> coordinates;
itemStacks, firstPos, secondPos, true)); List<BlockState> blockStates;
} List<ItemStack> itemStacks;
} BlockPos firstPos;
BlockPos secondPos;
} boolean breaking;
public PlacedData(float time, List<BlockPos> coordinates, List<BlockState> blockStates,
private static void sortOnDistanceToPlayer(List<BlockPos> coordinates, PlayerEntity player) { List<ItemStack> itemStacks, BlockPos firstPos, BlockPos secondPos, boolean breaking) {
this.time = time;
Collections.sort(coordinates, (lhs, rhs) -> { this.coordinates = coordinates;
// -1 - less than, 1 - greater than, 0 - equal this.blockStates = blockStates;
double lhsDistanceToPlayer = new Vec3d(lhs).subtract(player.getEyePosition(1f)).lengthSquared(); this.itemStacks = itemStacks;
double rhsDistanceToPlayer = new Vec3d(rhs).subtract(player.getEyePosition(1f)).lengthSquared(); this.firstPos = firstPos;
return (int) Math.signum(lhsDistanceToPlayer - rhsDistanceToPlayer); this.secondPos = secondPos;
}); this.breaking = breaking;
}
} }
} }

View File

@@ -1,245 +1,132 @@
package nl.requios.effortlessbuilding.render; package nl.requios.effortlessbuilding.render;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.shaders.Uniform;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft; import com.mojang.blaze3d.vertex.DefaultVertexFormat;
import net.minecraft.client.renderer.RenderState; import com.mojang.blaze3d.vertex.VertexFormat;
import net.minecraft.client.renderer.RenderStateShard;
import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.AtlasTexture; import net.minecraft.client.renderer.ShaderInstance;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.core.BlockPos;
import net.minecraft.util.math.BlockPos; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.math.Vec3d; import net.minecraft.world.phys.Vec3;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import org.lwjgl.opengl.*;
import java.util.OptionalDouble; import java.util.OptionalDouble;
import java.util.function.Consumer;
public class BuildRenderTypes {
public static final RenderState.TransparencyState TRANSLUCENT_TRANSPARENCY;
public static final RenderState.TransparencyState NO_TRANSPARENCY;
public static final RenderState.DiffuseLightingState DIFFUSE_LIGHTING_ENABLED;
public static final RenderState.DiffuseLightingState DIFFUSE_LIGHTING_DISABLED;
public static final RenderState.LayerState PROJECTION_LAYERING;
public static final RenderState.CullState CULL_DISABLED;
public static final RenderState.AlphaState DEFAULT_ALPHA;
public static final RenderState.WriteMaskState WRITE_TO_DEPTH_AND_COLOR;
public static final RenderState.WriteMaskState COLOR_WRITE;
public static final RenderType LINES;
public static final RenderType PLANES;
private static final int primaryTextureUnit = 0;
private static final int secondaryTextureUnit = 2;
static {
TRANSLUCENT_TRANSPARENCY = ObfuscationReflectionHelper.getPrivateValue(RenderState.class, null, "field_228515_g_");
NO_TRANSPARENCY = ObfuscationReflectionHelper.getPrivateValue(RenderState.class, null, "field_228510_b_");
DIFFUSE_LIGHTING_ENABLED = new RenderState.DiffuseLightingState(true);
DIFFUSE_LIGHTING_DISABLED = new RenderState.DiffuseLightingState(false);
PROJECTION_LAYERING = ObfuscationReflectionHelper.getPrivateValue(RenderState.class, null, "field_228500_J_");
CULL_DISABLED = new RenderState.CullState(false);
DEFAULT_ALPHA = new RenderState.AlphaState(0.003921569F);
final boolean ENABLE_DEPTH_WRITING = true;
final boolean ENABLE_COLOUR_COMPONENTS_WRITING = true;
WRITE_TO_DEPTH_AND_COLOR = new RenderState.WriteMaskState(ENABLE_COLOUR_COMPONENTS_WRITING, ENABLE_DEPTH_WRITING);
COLOR_WRITE = new RenderState.WriteMaskState(true, false);
final int INITIAL_BUFFER_SIZE = 128;
RenderType.State renderState;
//LINES
// RenderSystem.pushLightingAttributes();
// RenderSystem.pushTextureAttributes();
// RenderSystem.disableCull();
// RenderSystem.disableLighting();
// RenderSystem.disableTexture();
//
// RenderSystem.enableBlend();
// RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
//
// RenderSystem.lineWidth(2);
renderState = RenderType.State.getBuilder()
.line(new RenderState.LineState(OptionalDouble.of(2)))
.layer(PROJECTION_LAYERING)
.transparency(TRANSLUCENT_TRANSPARENCY)
.writeMask(WRITE_TO_DEPTH_AND_COLOR)
.cull(CULL_DISABLED)
.build(false);
LINES = RenderType.makeType("eb_lines",
DefaultVertexFormats.POSITION_COLOR, GL11.GL_LINES, INITIAL_BUFFER_SIZE, renderState);
renderState = RenderType.State.getBuilder()
.line(new RenderState.LineState(OptionalDouble.of(2)))
.layer(PROJECTION_LAYERING)
.transparency(TRANSLUCENT_TRANSPARENCY)
.writeMask(COLOR_WRITE)
.cull(CULL_DISABLED)
.build(false);
PLANES = RenderType.makeType("eb_planes",
DefaultVertexFormats.POSITION_COLOR, GL11.GL_TRIANGLE_STRIP, INITIAL_BUFFER_SIZE, renderState);
}
private class ShaderInfo {
float dissolve;
Vec3d blockPos;
Vec3d firstPos;
Vec3d secondPos;
boolean red;
public ShaderInfo(float dissolve, Vec3d blockPos, Vec3d firstPos, Vec3d secondPos, boolean red) {
this.dissolve = dissolve;
this.blockPos = blockPos;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.red = red;
}
}
public static RenderType getBlockPreviewRenderType(float dissolve, BlockPos blockPos, BlockPos firstPos,
BlockPos secondPos, boolean red) {
// RenderSystem.pushLightingAttributes();
// RenderSystem.pushTextureAttributes();
// RenderSystem.enableCull();
// RenderSystem.enableTexture();
// Minecraft.getInstance().textureManager.bindTexture(ShaderHandler.shaderMaskTextureLocation);
//
// RenderSystem.enableBlend();
// RenderSystem.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA);
// RenderSystem.blendColor(1f, 1f, 1f, 0.8f);
//end
// ShaderHandler.releaseShader();
//highjacking texturing state (which does nothing by default) to do my own things
String stateName = "eb_texturing_" + dissolve + "_" + blockPos + "_" + firstPos + "_" + secondPos + "_" + red;
RenderState.TexturingState MY_TEXTURING = new RenderState.TexturingState(stateName, () -> {
// RenderSystem.pushLightingAttributes();
// RenderSystem.pushTextureAttributes();
ShaderHandler.useShader(ShaderHandler.dissolve, generateShaderCallback(dissolve, new Vec3d(blockPos), new Vec3d(firstPos), new Vec3d(secondPos), blockPos == secondPos, red));
RenderSystem.blendColor(1f, 1f, 1f, 0.8f);
}, () -> {
ShaderHandler.releaseShader();
});
RenderType.State renderState = RenderType.State.getBuilder()
.texture(new RenderState.TextureState(ShaderHandler.shaderMaskTextureLocation, false, false))
.texturing(MY_TEXTURING)
.transparency(TRANSLUCENT_TRANSPARENCY)
.diffuseLighting(DIFFUSE_LIGHTING_DISABLED)
.alpha(DEFAULT_ALPHA)
.cull(new RenderState.CullState(true))
.lightmap(new RenderState.LightmapState(false))
.overlay(new RenderState.OverlayState(false))
.build(true);
//Unique name for every combination, otherwise it will reuse the previous one
String name = "eb_block_previews_" + dissolve + "_" + blockPos + "_" + firstPos + "_" + secondPos + "_" + red;
return RenderType.makeType(name,
DefaultVertexFormats.BLOCK, GL11.GL_QUADS, 256, true, true, renderState);
}
private static Consumer<Integer> generateShaderCallback(final float dissolve, final Vec3d blockpos, public class BuildRenderTypes extends RenderType {
final Vec3d firstpos, final Vec3d secondpos, public static ResourceLocation shaderMaskTextureLocation = new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png");
final boolean highlight, final boolean red) {
Minecraft mc = Minecraft.getInstance();
return (Integer shader) -> {
int percentileUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "dissolve");
int highlightUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "highlight");
int redUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "red");
int blockposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "blockpos");
int firstposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "firstpos");
int secondposUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "secondpos");
int imageUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "image");
int maskUniform = ARBShaderObjects.glGetUniformLocationARB(shader, "mask");
RenderSystem.enableTexture(); public static final RenderType LINES;
GL11.glGetInteger(GL11.GL_TEXTURE_BINDING_2D); public static final RenderType PLANES;
//mask public static ShaderInstance dissolveShaderInstance;
ARBShaderObjects.glUniform1iARB(maskUniform, secondaryTextureUnit); private static final ShaderStateShard RENDERTYPE_DISSOLVE_SHADER = new ShaderStateShard(() -> dissolveShaderInstance);
glActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + secondaryTextureUnit);
mc.getTextureManager().bindTexture(ShaderHandler.shaderMaskTextureLocation);//getTexture(ShaderHandler.shaderMaskTextureLocation).bindTexture();
//GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getTextureManager().getTexture(ShaderHandler.shaderMaskTextureLocation).getGlTextureId());
//image //Between 0 and 7, but dont override vanilla textures
ARBShaderObjects.glUniform1iARB(imageUniform, primaryTextureUnit); //Also update dissolve.fsh SamplerX
glActiveTexture(ARBMultitexture.GL_TEXTURE0_ARB + primaryTextureUnit); private static final int maskTextureIndex = 2;
mc.getTextureManager().bindTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE);//.getTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE).bindTexture();
//GL11.glBindTexture(GL11.GL_TEXTURE_2D, mc.getTextureManager().getTexture(AtlasTexture.LOCATION_BLOCKS_TEXTURE).getGlTextureId());
//blockpos static {
ARBShaderObjects.glUniform3fARB(blockposUniform, (float) blockpos.x, (float) blockpos.y, (float) blockpos.z); final LineStateShard LINE = new LineStateShard(OptionalDouble.of(2.0));
ARBShaderObjects.glUniform3fARB(firstposUniform, (float) firstpos.x, (float) firstpos.y, (float) firstpos.z); final int INITIAL_BUFFER_SIZE = 128;
ARBShaderObjects.glUniform3fARB(secondposUniform, (float) secondpos.x, (float) secondpos.y, (float) secondpos.z); RenderType.CompositeState renderState;
//dissolve //LINES
ARBShaderObjects.glUniform1fARB(percentileUniform, dissolve); renderState = CompositeState.builder()
//highlight .setLineState(LINE)
ARBShaderObjects.glUniform1iARB(highlightUniform, highlight ? 1 : 0); .setShaderState(RenderStateShard.RENDERTYPE_LINES_SHADER)
//red .setLayeringState(VIEW_OFFSET_Z_LAYERING)
ARBShaderObjects.glUniform1iARB(redUniform, red ? 1 : 0); .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
}; .setTextureState(RenderStateShard.NO_TEXTURE)
} .setDepthTestState(RenderStateShard.NO_DEPTH_TEST)
.setLightmapState(RenderStateShard.NO_LIGHTMAP)
.setWriteMaskState(COLOR_DEPTH_WRITE)
.setCullState(RenderStateShard.NO_CULL)
.createCompositeState(false);
LINES = RenderType.create("eb_lines",
DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.LINES, INITIAL_BUFFER_SIZE, false, false, renderState);
public static void glActiveTexture(int texture) { //PLANES
if (GL.getCapabilities().GL_ARB_multitexture && !GL.getCapabilities().OpenGL13) { renderState = CompositeState.builder()
ARBMultitexture.glActiveTextureARB(texture); .setLineState(LINE)
} else { .setShaderState(RenderStateShard.RENDERTYPE_LINES_SHADER)
GL13.glActiveTexture(texture); .setLayeringState(VIEW_OFFSET_Z_LAYERING)
} .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
.setTextureState(RenderStateShard.NO_TEXTURE)
.setDepthTestState(RenderStateShard.NO_DEPTH_TEST)
.setLightmapState(RenderStateShard.NO_LIGHTMAP)
.setWriteMaskState(COLOR_WRITE)
.setCullState(RenderStateShard.NO_CULL)
.createCompositeState(false);
PLANES = RenderType.create("eb_planes",
DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.TRIANGLE_STRIP, INITIAL_BUFFER_SIZE, false, false, renderState);
}
}
// public static class MyTexturingState extends RenderState.TexturingState { // Dummy constructor needed to make java happy
// public BuildRenderTypes(String p_173178_, VertexFormat p_173179_, VertexFormat.Mode p_173180_, int p_173181_, boolean p_173182_, boolean p_173183_, Runnable p_173184_, Runnable p_173185_) {
// public float dissolve; super(p_173178_, p_173179_, p_173180_, p_173181_, p_173182_, p_173183_, p_173184_, p_173185_);
// public Vec3d blockPos; }
// public Vec3d firstPos;
// public Vec3d secondPos; public static RenderType getBlockPreviewRenderType(float dissolve, BlockPos blockPos, BlockPos firstPos, BlockPos secondPos, boolean red) {
// public boolean highlight;
// public boolean red; String stateName = "eb_texturing_" + dissolve + "_" + blockPos + "_" + firstPos + "_" + secondPos + "_" + red;
// TexturingStateShard MY_TEXTURING = new TexturingStateShard(stateName, () -> {
// public MyTexturingState(String p_i225989_1_, float dissolve, Vec3d blockPos, Vec3d firstPos, setShaderParameters(dissolveShaderInstance, dissolve, Vec3.atLowerCornerOf(blockPos), Vec3.atLowerCornerOf(firstPos), Vec3.atLowerCornerOf(secondPos), blockPos == secondPos, red);
// Vec3d secondPos, boolean highlight, boolean red, Runnable p_i225989_2_, Runnable p_i225989_3_) { RenderSystem.setShaderColor(1f, 1f, 1f, 0.8f);
// super(p_i225989_1_, p_i225989_2_, p_i225989_3_); }, () -> {});
// this.dissolve = dissolve;
// this.blockPos = blockPos; RenderType.CompositeState renderState = RenderType.CompositeState.builder()
// this.firstPos = firstPos; .setShaderState(RENDERTYPE_DISSOLVE_SHADER)
// this.secondPos = secondPos; .setTexturingState(MY_TEXTURING)
// this.highlight = highlight; .setTextureState(RenderStateShard.BLOCK_SHEET_MIPPED)
// this.red = red; .setTransparencyState(TRANSLUCENT_TRANSPARENCY)
// } .setLightmapState(RenderStateShard.NO_LIGHTMAP)
// .setCullState(RenderStateShard.CULL)
// @Override .setOutputState(RenderStateShard.TRANSLUCENT_TARGET)
// public boolean equals(Object p_equals_1_) { .createCompositeState(true);
// if (this == p_equals_1_) { //Unique name for every combination, otherwise it will reuse the previous one
// return true; String name = "eb_block_previews_" + dissolve + "_" + blockPos + "_" + firstPos + "_" + secondPos + "_" + red;
// } else if (p_equals_1_ != null && this.getClass() == p_equals_1_.getClass()) { return RenderType.create(name,
// MyTexturingState other = (MyTexturingState)p_equals_1_; DefaultVertexFormat.BLOCK, VertexFormat.Mode.QUADS, 2097152, true, true, renderState);
// return this.dissolve == other.dissolve && this.blockPos == other.blockPos && this.firstPos == other.firstPos }
// && this.secondPos == other.secondPos && this.highlight == other.highlight && this.red == other.red;
// } else { private static void setShaderParameters(ShaderInstance shader, final float dissolve, final Vec3 blockpos,
// return false; final Vec3 firstpos, final Vec3 secondpos,
// } final boolean highlight, final boolean red) {
// } Uniform percentileUniform = shader.getUniform("dissolve");
// Uniform highlightUniform = shader.getUniform("highlight");
// @Override Uniform redUniform = shader.getUniform("red");
// public int hashCode() { Uniform blockposUniform = shader.getUniform("blockpos");
// Uniform firstposUniform = shader.getUniform("firstpos");
// } Uniform secondposUniform = shader.getUniform("secondpos");
// }
RenderSystem.setShaderTexture(maskTextureIndex, shaderMaskTextureLocation);
if (percentileUniform != null) percentileUniform.set(dissolve); else EffortlessBuilding.log("percentileUniform is null");
if (highlightUniform != null) highlightUniform.set(highlight ? 1 : 0); else EffortlessBuilding.log("highlightUniform is null");
if (redUniform != null) redUniform.set(red ? 1 : 0); else EffortlessBuilding.log("redUniform is null");
if (blockposUniform != null) blockposUniform.set((float) blockpos.x, (float) blockpos.y, (float) blockpos.z); else EffortlessBuilding.log("blockposUniform is null");
if (firstposUniform != null) firstposUniform.set((float) firstpos.x, (float) firstpos.y, (float) firstpos.z); else EffortlessBuilding.log("firstposUniform is null");
if (secondposUniform != null) secondposUniform.set((float) secondpos.x, (float) secondpos.y, (float) secondpos.z); else EffortlessBuilding.log("secondposUniform is null");
}
private class ShaderInfo {
float dissolve;
Vec3 blockPos;
Vec3 firstPos;
Vec3 secondPos;
boolean red;
public ShaderInfo(float dissolve, Vec3 blockPos, Vec3 firstPos, Vec3 secondPos, boolean red) {
this.dissolve = dissolve;
this.blockPos = blockPos;
this.firstPos = firstPos;
this.secondPos = secondPos;
this.red = red;
}
}
} }

View File

@@ -1,177 +1,167 @@
package nl.requios.effortlessbuilding.render; package nl.requios.effortlessbuilding.render;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.IVertexBuilder; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.IRenderTypeBuffer; import com.mojang.math.Matrix4f;
import net.minecraft.client.renderer.Matrix4f; import net.minecraft.world.phys.Vec3;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.Vec3d;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import nl.requios.effortlessbuilding.buildmodifier.Mirror; import nl.requios.effortlessbuilding.buildmodifier.Mirror;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.RadialMirror; import nl.requios.effortlessbuilding.buildmodifier.RadialMirror;
import org.lwjgl.opengl.GL11;
import java.awt.*; import java.awt.*;
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public class ModifierRenderer { public class ModifierRenderer {
protected static final Color colorX = new Color(255, 72, 52); protected static final Color colorX = new Color(255, 72, 52);
protected static final Color colorY = new Color(67, 204, 51); protected static final Color colorY = new Color(67, 204, 51);
protected static final Color colorZ = new Color(52, 247, 255); protected static final Color colorZ = new Color(52, 247, 255);
protected static final Color colorRadial = new Color(52, 247, 255); protected static final Color colorRadial = new Color(52, 247, 255);
protected static final int lineAlpha = 200; protected static final int lineAlpha = 200;
protected static final int planeAlpha = 75; protected static final int planeAlpha = 50;
protected static final Vec3d epsilon = new Vec3d(0.001, 0.001, 0.001); //prevents z-fighting protected static final Vec3 epsilon = new Vec3(0.001, 0.001, 0.001); //prevents z-fighting
public static void render(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, ModifierSettingsManager.ModifierSettings modifierSettings) { public static void render(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, ModifierSettingsManager.ModifierSettings modifierSettings) {
//Mirror lines and areas //Mirror lines and areas
Mirror.MirrorSettings m = modifierSettings.getMirrorSettings(); Mirror.MirrorSettings m = modifierSettings.getMirrorSettings();
if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ)) if (m != null && m.enabled && (m.mirrorX || m.mirrorY || m.mirrorZ)) {
{ Vec3 pos = m.position.add(epsilon);
Vec3d pos = m.position.add(epsilon); int radius = m.radius;
int radius = m.radius;
if (m.mirrorX) if (m.mirrorX) {
{ Vec3 posA = new Vec3(pos.x, pos.y - radius, pos.z - radius);
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z - radius); Vec3 posB = new Vec3(pos.x, pos.y + radius, pos.z + radius);
Vec3d posB = new Vec3d(pos.x, pos.y + radius, pos.z + radius);
drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorX, m.drawLines, m.drawPlanes, true); drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorX, m.drawLines, m.drawPlanes, true);
} }
if (m.mirrorY) if (m.mirrorY) {
{ Vec3 posA = new Vec3(pos.x - radius, pos.y, pos.z - radius);
Vec3d posA = new Vec3d(pos.x - radius, pos.y, pos.z - radius); Vec3 posB = new Vec3(pos.x + radius, pos.y, pos.z + radius);
Vec3d posB = new Vec3d(pos.x + radius, pos.y, pos.z + radius);
drawMirrorPlaneY(matrixStack, renderTypeBuffer, posA, posB, colorY, m.drawLines, m.drawPlanes); drawMirrorPlaneY(matrixStack, renderTypeBuffer, posA, posB, colorY, m.drawLines, m.drawPlanes);
} }
if (m.mirrorZ) if (m.mirrorZ) {
{ Vec3 posA = new Vec3(pos.x - radius, pos.y - radius, pos.z);
Vec3d posA = new Vec3d(pos.x - radius, pos.y - radius, pos.z); Vec3 posB = new Vec3(pos.x + radius, pos.y + radius, pos.z);
Vec3d posB = new Vec3d(pos.x + radius, pos.y + radius, pos.z);
drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorZ, m.drawLines, m.drawPlanes, true); drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorZ, m.drawLines, m.drawPlanes, true);
} }
//Draw axis coordinated colors if two or more axes are enabled //Draw axis coordinated colors if two or more axes are enabled
//(If only one is enabled the lines are that planes color) //(If only one is enabled the lines are that planes color)
if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) if (m.drawLines && ((m.mirrorX && m.mirrorY) || (m.mirrorX && m.mirrorZ) || (m.mirrorY && m.mirrorZ))) {
{ drawMirrorLines(matrixStack, renderTypeBuffer, m);
drawMirrorLines(matrixStack, renderTypeBuffer, m); }
} }
}
//Radial mirror lines and areas //Radial mirror lines and areas
RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings(); RadialMirror.RadialMirrorSettings r = modifierSettings.getRadialMirrorSettings();
if (r != null && r.enabled) if (r != null && r.enabled) {
{ Vec3 pos = r.position.add(epsilon);
Vec3d pos = r.position.add(epsilon); int radius = r.radius;
int radius = r.radius;
float angle = 2f * ((float) Math.PI) / r.slices; float angle = 2f * ((float) Math.PI) / r.slices;
Vec3d relStartVec = new Vec3d(radius, 0, 0); Vec3 relStartVec = new Vec3(radius, 0, 0);
if (r.slices%4 == 2) relStartVec = relStartVec.rotateYaw(angle / 2f); if (r.slices % 4 == 2) relStartVec = relStartVec.yRot(angle / 2f);
for (int i = 0; i < r.slices; i++) { for (int i = 0; i < r.slices; i++) {
Vec3d relNewVec = relStartVec.rotateYaw(angle * i); Vec3 relNewVec = relStartVec.yRot(angle * i);
Vec3d newVec = pos.add(relNewVec); Vec3 newVec = pos.add(relNewVec);
Vec3d posA = new Vec3d(pos.x, pos.y - radius, pos.z); Vec3 posA = new Vec3(pos.x, pos.y - radius, pos.z);
Vec3d posB = new Vec3d(newVec.x, pos.y + radius, newVec.z); Vec3 posB = new Vec3(newVec.x, pos.y + radius, newVec.z);
drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorRadial, r.drawLines, r.drawPlanes, false); drawMirrorPlane(matrixStack, renderTypeBuffer, posA, posB, colorRadial, r.drawLines, r.drawPlanes, false);
} }
} }
} }
//----Mirror---- //----Mirror----
protected static void drawMirrorPlane(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) { protected static void drawMirrorPlane(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Vec3 posA, Vec3 posB, Color c, boolean drawLines, boolean drawPlanes, boolean drawVerticalLines) {
// GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha); // GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha);
Matrix4f matrixPos = matrixStack.getLast().getMatrix(); Matrix4f matrixPos = matrixStack.last().pose();
if (drawPlanes) { if (drawPlanes) {
IVertexBuilder buffer = RenderHandler.beginPlanes(renderTypeBuffer); VertexConsumer buffer = RenderHandler.beginPlanes(renderTypeBuffer);
buffer.pos(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posA.x, (float) posB.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posB.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posB.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posB.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posB.x, (float) posB.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posB.x, (float) posB.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
//backface (using triangle strip) //backface (using triangle strip)
buffer.pos(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posA.x, (float) posB.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posB.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
RenderHandler.endPlanes(renderTypeBuffer); RenderHandler.endPlanes(renderTypeBuffer);
} }
if (drawLines) { if (drawLines) {
IVertexBuilder buffer = RenderHandler.beginLines(renderTypeBuffer); VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
Vec3d middle = posA.add(posB).scale(0.5); Vec3 middle = posA.add(posB).scale(0.5);
buffer.pos(matrixPos, (float) posA.x, (float) middle.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) middle.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) posB.x, (float) middle.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) posB.x, (float) middle.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
if (drawVerticalLines) { if (drawVerticalLines) {
buffer.pos(matrixPos, (float) middle.x, (float) posA.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) middle.x, (float) posA.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) middle.x, (float) posB.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) middle.x, (float) posB.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
} }
RenderHandler.endLines(renderTypeBuffer); RenderHandler.endLines(renderTypeBuffer);
} }
} }
protected static void drawMirrorPlaneY(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, Vec3d posA, Vec3d posB, Color c, boolean drawLines, boolean drawPlanes) { protected static void drawMirrorPlaneY(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Vec3 posA, Vec3 posB, Color c, boolean drawLines, boolean drawPlanes) {
// GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha()); // GL11.glColor4d(c.getRed(), c.getGreen(), c.getBlue(), c.getAlpha());
Matrix4f matrixPos = matrixStack.getLast().getMatrix(); Matrix4f matrixPos = matrixStack.last().pose();
if (drawPlanes) { if (drawPlanes) {
IVertexBuilder buffer = RenderHandler.beginPlanes(renderTypeBuffer); VertexConsumer buffer = RenderHandler.beginPlanes(renderTypeBuffer);
buffer.pos(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posA.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posB.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posB.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posB.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posB.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
//backface (using triangle strip) //backface (using triangle strip)
buffer.pos(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
buffer.pos(matrixPos, (float) posA.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) posA.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), planeAlpha).endVertex();
RenderHandler.endPlanes(renderTypeBuffer); RenderHandler.endPlanes(renderTypeBuffer);
} }
if (drawLines) { if (drawLines) {
IVertexBuilder buffer = RenderHandler.beginLines(renderTypeBuffer); VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
Vec3d middle = posA.add(posB).scale(0.5); Vec3 middle = posA.add(posB).scale(0.5);
buffer.pos(matrixPos, (float) middle.x, (float) middle.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) middle.x, (float) middle.y, (float) posA.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) middle.x, (float) middle.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) middle.x, (float) middle.y, (float) posB.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) posA.x, (float) middle.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) posA.x, (float) middle.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) posB.x, (float) middle.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) posB.x, (float) middle.y, (float) middle.z).color(c.getRed(), c.getGreen(), c.getBlue(), lineAlpha).endVertex();
RenderHandler.endLines(renderTypeBuffer); RenderHandler.endLines(renderTypeBuffer);
} }
} }
protected static void drawMirrorLines(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, Mirror.MirrorSettings m) { protected static void drawMirrorLines(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, Mirror.MirrorSettings m) {
// GL11.glColor4d(100, 100, 100, 255); // GL11.glColor4d(100, 100, 100, 255);
IVertexBuilder buffer = RenderHandler.beginLines(renderTypeBuffer); VertexConsumer buffer = RenderHandler.beginLines(renderTypeBuffer);
Matrix4f matrixPos = matrixStack.getLast().getMatrix(); Matrix4f matrixPos = matrixStack.last().pose();
Vec3d pos = m.position.add(epsilon); Vec3 pos = m.position.add(epsilon);
buffer.pos(matrixPos, (float) pos.x - m.radius, (float) pos.y, (float) pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) pos.x - m.radius, (float) pos.y, (float) pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) pos.x + m.radius, (float) pos.y, (float) pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) pos.x + m.radius, (float) pos.y, (float) pos.z).color(colorX.getRed(), colorX.getGreen(), colorX.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) pos.x, (float) pos.y - m.radius, (float) pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) pos.x, (float) pos.y - m.radius, (float) pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) pos.x, (float) pos.y + m.radius, (float) pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) pos.x, (float) pos.y + m.radius, (float) pos.z).color(colorY.getRed(), colorY.getGreen(), colorY.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) pos.x, (float) pos.y, (float) pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) pos.x, (float) pos.y, (float) pos.z - m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
buffer.pos(matrixPos, (float) pos.x, (float) pos.y, (float) pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex(); buffer.vertex(matrixPos, (float) pos.x, (float) pos.y, (float) pos.z + m.radius).color(colorZ.getRed(), colorZ.getGreen(), colorZ.getBlue(), lineAlpha).endVertex();
RenderHandler.endLines(renderTypeBuffer); RenderHandler.endLines(renderTypeBuffer);
} }
} }

View File

@@ -1,47 +1,34 @@
package nl.requios.effortlessbuilding.render; package nl.requios.effortlessbuilding.render;
import com.mojang.blaze3d.matrix.MatrixStack; import com.mojang.blaze3d.vertex.BufferBuilder;
import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.Tesselator;
import com.mojang.blaze3d.vertex.IVertexBuilder; import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SimpleSound; import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.entity.player.ClientPlayerEntity; import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.model.IBakedModel; import net.minecraft.client.renderer.Sheets;
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.client.resources.I18n; import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.core.BlockPos;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.world.entity.player.Player;
import net.minecraft.server.MinecraftServer; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.util.SoundCategory; import net.minecraft.world.phys.AABB;
import net.minecraft.util.SoundEvents; import net.minecraft.world.phys.Vec3;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderGameOverlayEvent; import net.minecraftforge.client.event.RenderLevelStageEvent;
import net.minecraftforge.client.event.RenderWorldLastEvent; import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import nl.requios.effortlessbuilding.EffortlessBuilding; import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.buildmode.ModeOptions;
import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager; import nl.requios.effortlessbuilding.buildmode.ModeSettingsManager;
import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager; import nl.requios.effortlessbuilding.buildmodifier.ModifierSettingsManager;
import nl.requios.effortlessbuilding.gui.buildmode.RadialMenu;
import nl.requios.effortlessbuilding.helper.ReachHelper; import static net.minecraftforge.client.event.RenderLevelStageEvent.Stage.AFTER_PARTICLES;
import nl.requios.effortlessbuilding.network.ModeActionMessage;
import nl.requios.effortlessbuilding.network.ModeSettingsMessage;
import nl.requios.effortlessbuilding.network.PacketHandler;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.lwjgl.opengl.GL11;
/*** /***
* Main render class for Effortless Building * Main render class for Effortless Building
@@ -49,193 +36,104 @@ import org.lwjgl.opengl.GL11;
@Mod.EventBusSubscriber(value = Dist.CLIENT) @Mod.EventBusSubscriber(value = Dist.CLIENT)
public class RenderHandler { public class RenderHandler {
@SubscribeEvent @SubscribeEvent
public static void onRender(RenderWorldLastEvent event) { public static void onRender(RenderLevelStageEvent event) {
if(event.getPhase() != EventPriority.NORMAL) if (event.getPhase() != EventPriority.NORMAL || event.getStage() != AFTER_PARTICLES)
return; return;
MatrixStack matrixStack = event.getMatrixStack(); PoseStack matrixStack = event.getPoseStack();
BufferBuilder bufferBuilder = Tessellator.getInstance().getBuffer(); BufferBuilder bufferBuilder = Tesselator.getInstance().getBuilder();
IRenderTypeBuffer.Impl renderTypeBuffer = IRenderTypeBuffer.getImpl(bufferBuilder); MultiBufferSource.BufferSource renderTypeBuffer = MultiBufferSource.immediate(bufferBuilder);
PlayerEntity player = Minecraft.getInstance().player; Player player = Minecraft.getInstance().player;
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player); ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player); ModifierSettingsManager.ModifierSettings modifierSettings = ModifierSettingsManager.getModifierSettings(player);
Vec3d projectedView = Minecraft.getInstance().gameRenderer.getActiveRenderInfo().getProjectedView(); Vec3 projectedView = Minecraft.getInstance().gameRenderer.getMainCamera().getPosition();
matrixStack.push(); matrixStack.pushPose();
matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z); matrixStack.translate(-projectedView.x, -projectedView.y, -projectedView.z);
//Mirror and radial mirror lines and areas //Mirror and radial mirror lines and areas
ModifierRenderer.render(matrixStack, renderTypeBuffer, modifierSettings); ModifierRenderer.render(matrixStack, renderTypeBuffer, modifierSettings);
//Render block previews //Render block previews
BlockPreviewRenderer.render(matrixStack, renderTypeBuffer, player, modifierSettings, modeSettings); BlockPreviewRenderer.render(matrixStack, renderTypeBuffer, player, modifierSettings, modeSettings);
matrixStack.pop(); matrixStack.popPose();
} }
@SubscribeEvent protected static VertexConsumer beginLines(MultiBufferSource.BufferSource renderTypeBuffer) {
//Display Radial Menu return renderTypeBuffer.getBuffer(BuildRenderTypes.LINES);
public static void onRenderGameOverlay(final RenderGameOverlayEvent.Post event) { }
Minecraft mc = Minecraft.getInstance();
ClientPlayerEntity player = mc.player;
//check if chisel and bits tool in hand (and has menu) protected static void endLines(MultiBufferSource.BufferSource renderTypeBuffer) {
// final boolean hasChiselInHand = CompatHelper.chiselsAndBitsProxy.isHoldingChiselTool(EnumHand.MAIN_HAND); renderTypeBuffer.endBatch();
}
final RenderGameOverlayEvent.ElementType type = event.getType(); protected static VertexConsumer beginPlanes(MultiBufferSource.BufferSource renderTypeBuffer) {
//TODO 1.13 compatibility return renderTypeBuffer.getBuffer(BuildRenderTypes.PLANES);
if (type == RenderGameOverlayEvent.ElementType.ALL /*&& !hasChiselInHand*/) { }
final boolean wasVisible = RadialMenu.instance.isVisible();
if (ClientProxy.keyBindings[3].isKeyDown()) { protected static void endPlanes(MultiBufferSource.BufferSource renderTypeBuffer) {
if (ReachHelper.getMaxReach(player) > 0) { renderTypeBuffer.endBatch();
RadialMenu.instance.actionUsed = false; }
RadialMenu.instance.raiseVisibility();
} else if (ClientProxy.keyBindings[3].isPressed()) {
EffortlessBuilding.log(player, "Build modes are disabled until your reach has increased. Increase your reach with craftable reach upgrades.");
}
} else {
if (!RadialMenu.instance.actionUsed) {
ModeSettingsManager.ModeSettings modeSettings = ModeSettingsManager.getModeSettings(player);
if (RadialMenu.instance.switchTo != null) { protected static void renderBlockPreview(PoseStack matrixStack, MultiBufferSource.BufferSource renderTypeBuffer, BlockRenderDispatcher dispatcher,
playRadialMenuSound(); BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean red) {
modeSettings.setBuildMode(RadialMenu.instance.switchTo); if (blockState == null) return;
ModeSettingsManager.setModeSettings(player, modeSettings);
PacketHandler.INSTANCE.sendToServer(new ModeSettingsMessage(modeSettings));
EffortlessBuilding.log(player, I18n.format(modeSettings.getBuildMode().name), true); matrixStack.pushPose();
} matrixStack.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ());
//Perform button action
ModeOptions.ActionEnum action = RadialMenu.instance.doAction;
if (action != null) {
ModeOptions.performAction(player, action);
PacketHandler.INSTANCE.sendToServer(new ModeActionMessage(action));
}
playRadialMenuSound();
}
RadialMenu.instance.actionUsed = true;
RadialMenu.instance.decreaseVisibility();
}
if (RadialMenu.instance.isVisible()) {
int scaledWidth = mc.getMainWindow().getScaledWidth();
int scaledHeight = mc.getMainWindow().getScaledHeight();
RadialMenu.instance.configure(scaledWidth, scaledHeight);
if (!wasVisible) {
mc.mouseHelper.ungrabMouse();
}
if (mc.mouseHelper.isMouseGrabbed()) {
KeyBinding.unPressAllKeys();
}
final int mouseX = ((int) mc.mouseHelper.getMouseX()) * scaledWidth / mc.getMainWindow().getFramebufferWidth();
final int mouseY = scaledHeight - ((int) mc.mouseHelper.getMouseY()) * scaledHeight / mc.getMainWindow().getFramebufferHeight() - 1;
net.minecraftforge.client.ForgeHooksClient.drawScreen(RadialMenu.instance, mouseX, mouseY, event.getPartialTicks());
} else {
if (wasVisible &&
RadialMenu.instance.doAction != ModeOptions.ActionEnum.OPEN_MODIFIER_SETTINGS &&
RadialMenu.instance.doAction != ModeOptions.ActionEnum.OPEN_PLAYER_SETTINGS) {
mc.mouseHelper.grabMouse();
}
}
}
}
public static void playRadialMenuSound() {
final float volume = 0.1f;
if (volume >= 0.0001f) {
SimpleSound sound = new SimpleSound(SoundEvents.UI_BUTTON_CLICK, SoundCategory.MASTER, volume, 1.0f, Minecraft.getInstance().player.getPosition());
Minecraft.getInstance().getSoundHandler().play(sound);
}
}
protected static IVertexBuilder beginLines(IRenderTypeBuffer.Impl renderTypeBuffer) {
return renderTypeBuffer.getBuffer(BuildRenderTypes.LINES);
}
protected static void endLines(IRenderTypeBuffer.Impl renderTypeBuffer) {
renderTypeBuffer.finish();
}
protected static IVertexBuilder beginPlanes(IRenderTypeBuffer.Impl renderTypeBuffer){
return renderTypeBuffer.getBuffer(BuildRenderTypes.PLANES);
}
protected static void endPlanes(IRenderTypeBuffer.Impl renderTypeBuffer){
renderTypeBuffer.finish();
}
protected static void renderBlockPreview(MatrixStack matrixStack, IRenderTypeBuffer.Impl renderTypeBuffer, BlockRendererDispatcher dispatcher,
BlockPos blockPos, BlockState blockState, float dissolve, BlockPos firstPos, BlockPos secondPos, boolean red) {
if (blockState == null) return;
matrixStack.push();
matrixStack.translate(blockPos.getX(), blockPos.getY(), blockPos.getZ());
// matrixStack.rotate(Vector3f.YP.rotationDegrees(-90f)); // matrixStack.rotate(Vector3f.YP.rotationDegrees(-90f));
matrixStack.translate(-0.01f, -0.01f, -0.01f); matrixStack.translate(-0.01f, -0.01f, -0.01f);
matrixStack.scale(1.02f, 1.02f, 1.02f); matrixStack.scale(1.02f, 1.02f, 1.02f);
//Begin block preview rendering //Begin block preview rendering
RenderType blockPreviewRenderType = BuildRenderTypes.getBlockPreviewRenderType(dissolve, blockPos, firstPos, secondPos, red); RenderType blockPreviewRenderType = BuildRenderTypes.getBlockPreviewRenderType(dissolve, blockPos, firstPos, secondPos, red);
IVertexBuilder buffer = renderTypeBuffer.getBuffer(blockPreviewRenderType); VertexConsumer buffer = renderTypeBuffer.getBuffer(blockPreviewRenderType);
// MinecraftServer server = Minecraft.getInstance().getIntegratedServer(); try {
// World world = DimensionManager.getWorld(server, DimensionType.OVERWORLD, false, true); BakedModel model = dispatcher.getBlockModel(blockState);
dispatcher.getModelRenderer().renderModel(matrixStack.last(), buffer, blockState, model,
1f, 1f, 1f, 0, OverlayTexture.NO_OVERLAY, ModelData.EMPTY, blockPreviewRenderType);
} catch (NullPointerException e) {
EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString());
try { //Render outline as backup, escape out of the current renderstack
IBakedModel model = dispatcher.getModelForState(blockState); matrixStack.popPose();
dispatcher.getBlockModelRenderer().renderModelBrightnessColor(matrixStack.getLast(), buffer, renderTypeBuffer.endBatch();
blockState, model, 1f, 1f, 1f, 0, OverlayTexture.NO_OVERLAY); VertexConsumer lineBuffer = beginLines(renderTypeBuffer);
// blockRendererDispatcher.getBlockModelRenderer().renderModel(world, blockRendererDispatcher.getModelForState(blockState), renderBlockOutline(matrixStack, lineBuffer, blockPos, new Vec3(1f, 1f, 1f));
// blockState, logicPos, matrixStack, renderTypeBuffer.getBuffer(renderType), true, new Random(), blockState.getPositionRandom(logicPos), i); endLines(renderTypeBuffer);
} catch (NullPointerException e) { buffer = renderTypeBuffer.getBuffer(Sheets.translucentCullBlockSheet()); //any type will do, as long as we have something on the stack
EffortlessBuilding.logger.warn("RenderHandler::renderBlockPreview cannot render " + blockState.getBlock().toString()); matrixStack.pushPose();
}
//Render outline as backup, escape out of the current renderstack renderTypeBuffer.endBatch();
matrixStack.pop(); matrixStack.popPose();
renderTypeBuffer.finish(); }
IVertexBuilder lineBuffer = beginLines(renderTypeBuffer);
renderBlockOutline(matrixStack, lineBuffer, blockPos, new Vec3d(1f, 1f, 1f));
endLines(renderTypeBuffer);
buffer = renderTypeBuffer.getBuffer(Atlases.getTranslucentBlockType()); //any type will do, as long as we have something on the stack
matrixStack.push();
}
renderTypeBuffer.finish(); protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, Vec3 color) {
matrixStack.pop(); renderBlockOutline(matrixStack, buffer, pos, pos, color);
} }
protected static void renderBlockOutline(MatrixStack matrixStack, IVertexBuilder buffer, BlockPos pos, Vec3d color) { //Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z
renderBlockOutline(matrixStack, buffer, pos, pos, color); protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos1, BlockPos pos2, Vec3 color) {
} AABB aabb = new AABB(pos1, pos2.offset(1, 1, 1)).inflate(0.0020000000949949026);
//Renders outline. Pos1 has to be minimal x,y,z and pos2 maximal x,y,z LevelRenderer.renderLineBox(matrixStack, buffer, aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
protected static void renderBlockOutline(MatrixStack matrixStack, IVertexBuilder buffer, BlockPos pos1, BlockPos pos2, Vec3d color) {
AxisAlignedBB aabb = new AxisAlignedBB(pos1, pos2.add(1, 1, 1)).grow(0.0020000000949949026);
WorldRenderer.drawBoundingBox(matrixStack, buffer, aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
// WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f); // WorldRenderer.drawSelectionBoundingBox(aabb, (float) color.x, (float) color.y, (float) color.z, 0.4f);
} }
//Renders outline with given bounding box //Renders outline with given bounding box
protected static void renderBlockOutline(MatrixStack matrixStack, IVertexBuilder buffer, BlockPos pos, VoxelShape collisionShape, Vec3d color) { protected static void renderBlockOutline(PoseStack matrixStack, VertexConsumer buffer, BlockPos pos, VoxelShape collisionShape, Vec3 color) {
// WorldRenderer.drawShape(collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f); // WorldRenderer.drawShape(collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f);
WorldRenderer.drawVoxelShapeParts(matrixStack, buffer, collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f); LevelRenderer.renderVoxelShape(matrixStack, buffer, collisionShape, pos.getX(), pos.getY(), pos.getZ(), (float) color.x, (float) color.y, (float) color.z, 0.4f);
} }
//TODO 1.14 //TODO
//Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken //Sends breaking progress for all coordinates to renderglobal, so all blocks get visually broken
// @Override // @Override
// public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { // public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) {
// Minecraft mc = Minecraft.getInstance(); // Minecraft mc = Minecraft.getInstance();

View File

@@ -1,202 +0,0 @@
/**
* This class was created by <Vazkii>. It's distributed as
* part of the Botania Mod. Get the Source Code in github:
* https://github.com/Vazkii/Botania
*
* Modified by Requios
*
* Botania is Open Source and distributed under the
* Botania License: http://botaniamod.net/license.php
*
* File Created @ [Apr 9, 2014, 11:20:26 PM (GMT)]
*/
package nl.requios.effortlessbuilding.render;
import net.minecraft.util.ResourceLocation;
import nl.requios.effortlessbuilding.BuildConfig;
import nl.requios.effortlessbuilding.EffortlessBuilding;
import nl.requios.effortlessbuilding.proxy.ClientProxy;
import org.apache.logging.log4j.Level;
import org.lwjgl.opengl.*;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.function.Consumer;
public final class ShaderHandler {
private static final int VERT_ST = ARBVertexShader.GL_VERTEX_SHADER_ARB;
private static final int FRAG_ST = ARBFragmentShader.GL_FRAGMENT_SHADER_ARB;
private static final int VERT = 1;
private static final int FRAG = 2;
private static final String VERT_EXTENSION = ".vert";
private static final String FRAG_EXTENSION = ".frag";
public static int rawColor;
public static int dissolve;
public static ResourceLocation shaderMaskTextureLocation = new ResourceLocation(EffortlessBuilding.MODID, "textures/shader_mask.png");
public static void init() {
if(!doUseShaders())
return;
// rawColor = createProgram("/assets/effortlessbuilding/shaders/raw_color", FRAG);
dissolve = createProgram("/assets/effortlessbuilding/shaders/dissolve", VERT + FRAG);
}
public static void useShader(int shader, Consumer<Integer> callback) {
if(!doUseShaders())
return;
ARBShaderObjects.glUseProgramObjectARB(shader);
if(shader != 0) {
int time = ARBShaderObjects.glGetUniformLocationARB(shader, "time");
ARBShaderObjects.glUniform1iARB(time, ClientProxy.ticksInGame);
if(callback != null)
callback.accept(shader);
}
}
public static void useShader(int shader) {
useShader(shader, null);
}
public static void releaseShader() {
useShader(0);
}
public static boolean doUseShaders() {
//Extracted from OpenGLHelper in 1.13 and earlier
//Can probably be simplified
GLCapabilities glcapabilities = GL.getCapabilities();
boolean openGL14 = glcapabilities.OpenGL14 || glcapabilities.GL_EXT_blend_func_separate;
boolean openGL21 = glcapabilities.OpenGL21;
boolean framebufferSupported = openGL14 && (glcapabilities.GL_ARB_framebuffer_object || glcapabilities.GL_EXT_framebuffer_object || glcapabilities.OpenGL30);
boolean shadersAvailable = openGL21 || glcapabilities.GL_ARB_vertex_shader && glcapabilities.GL_ARB_fragment_shader && glcapabilities.GL_ARB_shader_objects;
boolean shadersSupported = framebufferSupported && shadersAvailable;
return BuildConfig.visuals.useShaders.get() && shadersSupported;
}
private static int createProgram(String s, int sides) {
boolean vert = (sides & VERT) != 0;
boolean frag = (sides & FRAG) != 0;
return createProgram(vert ? s + VERT_EXTENSION : null, frag ? s + FRAG_EXTENSION : null);
}
// Most of the code taken from the LWJGL wiki
// http://lwjgl.org/wiki/index.php?title=GLSL_Shaders_with_LWJGL
private static int createProgram(String vert, String frag) {
int vertId = 0, fragId = 0, program;
if(vert != null)
vertId = createShader(vert, VERT_ST);
if(frag != null)
fragId = createShader(frag, FRAG_ST);
program = ARBShaderObjects.glCreateProgramObjectARB();
if(program == 0)
return 0;
if(vert != null)
ARBShaderObjects.glAttachObjectARB(program, vertId);
if(frag != null)
ARBShaderObjects.glAttachObjectARB(program, fragId);
ARBShaderObjects.glLinkProgramARB(program);
if(ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_LINK_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
ARBShaderObjects.glValidateProgramARB(program);
if (ARBShaderObjects.glGetObjectParameteriARB(program, ARBShaderObjects.GL_OBJECT_VALIDATE_STATUS_ARB) == GL11.GL_FALSE) {
EffortlessBuilding.logger.log(Level.ERROR, getLogInfo(program));
return 0;
}
return program;
}
private static int createShader(String filename, int shaderType){
int shader = 0;
try {
shader = ARBShaderObjects.glCreateShaderObjectARB(shaderType);
if(shader == 0)
return 0;
ARBShaderObjects.glShaderSourceARB(shader, readFileAsString(filename));
ARBShaderObjects.glCompileShaderARB(shader);
if (ARBShaderObjects.glGetObjectParameteriARB(shader, ARBShaderObjects.GL_OBJECT_COMPILE_STATUS_ARB) == GL11.GL_FALSE)
throw new RuntimeException("Error creating shader: " + getLogInfo(shader));
return shader;
}
catch(Exception e) {
ARBShaderObjects.glDeleteObjectARB(shader);
e.printStackTrace();
return -1;
}
}
private static String getLogInfo(int obj) {
return ARBShaderObjects.glGetInfoLogARB(obj, ARBShaderObjects.glGetObjectParameteriARB(obj, ARBShaderObjects.GL_OBJECT_INFO_LOG_LENGTH_ARB));
}
private static String readFileAsString(String filename) throws Exception {
StringBuilder source = new StringBuilder();
InputStream in = ShaderHandler.class.getResourceAsStream(filename);
Exception exception = null;
BufferedReader reader;
if(in == null)
return "";
try {
reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
Exception innerExc= null;
try {
String line;
while((line = reader.readLine()) != null)
source.append(line).append('\n');
} catch(Exception exc) {
exception = exc;
} finally {
try {
reader.close();
} catch(Exception exc) {
innerExc = exc;
}
}
if(innerExc != null)
throw innerExc;
} catch(Exception exc) {
exception = exc;
} finally {
try {
in.close();
} catch(Exception exc) {
if(exception == null)
exception = exc;
else exc.printStackTrace();
}
if(exception != null)
throw exception;
}
return source.toString();
}
}

View File

@@ -0,0 +1,3 @@
public net.minecraft.client.gui.components.AbstractSelectionList f_93398_ # renderHeader
public net.minecraft.client.gui.Font m_92803_(Ljava/lang/String;FFILcom/mojang/math/Matrix4f;ZZ)I # renderString
public net.minecraft.world.inventory.MenuType m_39988_(Ljava/lang/String;Lnet/minecraft/world/inventory/MenuType$MenuSupplier;)Lnet/minecraft/world/inventory/MenuType; # register

Some files were not shown because too many files have changed in this diff Show More