Compare commits

..

30 commits

Author SHA1 Message Date
a03b83a8c4 fix: 1-block previews on consecutive placements 2023-03-24 23:33:28 +01:00
ab75971728 fix: remove playerPos function 2023-03-24 22:08:53 +01:00
bc12017774 bump version to 2.10 2023-03-24 01:38:52 +01:00
e1baa81ac0
Merge pull request #71 from Heimdallr-1/patch-1
Create ru_ru.json
2023-03-24 01:36:39 +01:00
aeb6dd562e fix: JEI wand info showing raw translation key 2023-03-24 01:30:52 +01:00
Heimdallr-1
09173b053e
Create ru_ru.json
The necessary information such as Stone wand, iron wand or infinity wand is not displayed in the key "construction and.description.and": "%1$s
2023-03-21 23:36:29 +05:00
fcd2307db8 update jei dependency 2023-02-15 21:31:46 +01:00
c53845ced9 fix: wands not breaking when out of durability 2023-02-12 17:47:50 +01:00
91c6901706 fix: replace deprecated CapabilityItemHandler 2023-02-12 17:15:42 +01:00
36de8df509 update Forge, fix compatibility with 1.19 Botania API 2023-02-12 17:07:04 +01:00
05658450c8 Merge pull request #59 from buff-mango/patch-1 2022-11-27 17:56:26 +01:00
f47273b0db
Merge pull request #57 from FITFC/1.19
added pt_br.json
2022-11-27 17:48:11 +01:00
mango_buff
00e621da71
Create zh_cn.json 2022-11-24 09:53:40 +08:00
FITFC
379285dbfe
added pt_br.json 2022-10-29 17:19:59 -05:00
61a95fcd1e add explaination to notes 2022-08-09 20:46:11 +02:00
44f1b531ec add notes 2022-08-09 20:39:54 +02:00
312d7597f9 Revert "update minecraft to 1.19.2"
This reverts commit 373be90a2e.
2022-08-09 20:28:52 +02:00
de61ff8fd6 fix dedicated server crash 2022-08-09 20:22:47 +02:00
373be90a2e update minecraft to 1.19.2 2022-08-09 20:21:07 +02:00
24eca43bb3 update minecraft to 1.19.1 2022-08-09 20:15:07 +02:00
4b04a9300e bump version to 2.8 2022-08-09 19:38:07 +02:00
f70347159e Merge branch '1.18.2' of github.com:Theta-Dev/ConstructionWand into 1.19 2022-08-09 19:37:29 +02:00
06d2488c6c fix config access before server start 2022-08-09 19:36:51 +02:00
f400310b59 fix text components 2022-08-09 18:40:44 +02:00
3a1316ce0f ported to Minecraft 1.19 2022-08-09 13:43:38 +02:00
28e97eca26
Merge pull request #50 from gjeodnd12165/patch-1
Korean Localization
2022-04-22 16:25:08 +02:00
gjeodnd12165
058cabe327
Create ko_kr.json 2022-04-18 17:17:01 +09:00
83d880cb2e update Botania integration for MC1.18.2 2022-03-26 00:28:07 +01:00
5f0cc62dbc remove superfluous inventory checks 2022-03-26 00:24:18 +01:00
Mrbysco
fc20293906 Port to 1.18.2
Convert item registering to DeferredRegister as vanilla freezes the registry which instantiating them outside of the RegistryEvent or DeferredRegister will result in an error.
2022-03-15 03:15:54 +01:00
36 changed files with 402 additions and 334 deletions

2
.gitignore vendored
View file

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

View file

@ -4,7 +4,7 @@ With a Construction Wand you can place multiple blocks (up to 1024) at once, ext
facing. If that's not enough: you can upgrade your wand with additional cores, allowing you to place a block behind the facing. If that's not enough: you can upgrade your wand with additional cores, allowing you to place a block behind the
block you are facing, conjure blocks in mid air or destroy lots of blocks very fast. block you are facing, conjure blocks in mid air or destroy lots of blocks very fast.
![](images/wands.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/wands.png)
**Note:** These are the instructions for ConstructionWand version 2.0+, which introduced some new features. **Note:** These are the instructions for ConstructionWand version 2.0+, which introduced some new features.
If you are still using version 1.x, refer to [those](https://github.com/Theta-Dev/ConstructionWand/tree/1.16.2-1.7) If you are still using version 1.x, refer to [those](https://github.com/Theta-Dev/ConstructionWand/tree/1.16.2-1.7)
@ -23,12 +23,12 @@ and last longer. These properties can be changed in the config.
| Infinity | Unbreakable | 1024 | Yes | 8 | 81 | | Infinity | Unbreakable | 1024 | Yes | 8 | 81 |
## Crafting ## Crafting
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting1.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/crafting1.png)
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting2.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/crafting2.png)
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting3.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/crafting3.png)
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting4.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/crafting4.png)
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting5.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/crafting5.png)
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting6.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/crafting6.png)
## Keybindings ## Keybindings
@ -69,7 +69,7 @@ you can use the undo feature if you've made a mistake.
## Options ## Options
SNEAK+OPTKEY+Right clicking empty space opens the option screen of your wand. SNEAK+OPTKEY+Right clicking empty space opens the option screen of your wand.
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/options.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/options.png)
**Restriction:** If restriction is enabled the wand will only place blocks in one row or column **Restriction:** If restriction is enabled the wand will only place blocks in one row or column
(choose between North/South, East/West on a horizontal plane and Horizontal, Vertical on a vertical plane). (choose between North/South, East/West on a horizontal plane and Horizontal, Vertical on a vertical plane).
@ -79,7 +79,7 @@ has no effect if the angel core is enabled.
**Direction:** If set to "Player" the wand places blocks in the same direction as if they were placed by yourself. **Direction:** If set to "Player" the wand places blocks in the same direction as if they were placed by yourself.
Target mode places the blocks in the same direction as their supporting block. See the picture below: Target mode places the blocks in the same direction as their supporting block. See the picture below:
![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/placedir.png) ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.19/images/placedir.png)
**Replacement:** Enables/disables the replacement of replaceable blocks (Fluids, snow, tallgrass). **Replacement:** Enables/disables the replacement of replaceable blocks (Fluids, snow, tallgrass).
@ -122,7 +122,7 @@ for TileEntities in CW Version 1.7. Chisels&Bits blocks are blacklisted by defau
There are probably a few other tile entities from other mods out there which may cause issues as well. There are probably a few other tile entities from other mods out there which may cause issues as well.
If you find some of them you can tell me by creating If you find some of them you can tell me by creating
an issue, commenting on Curse or editing the default blacklist yourself an issue, commenting on Curse or editing the default blacklist yourself
(it is located at https://github.com/Theta-Dev/ConstructionWand/blob/1.16.2/src/main/java/thetadev/constructionwand/basics/ConfigServer.java#L28) (it is located at https://github.com/Theta-Dev/ConstructionWand/blob/1.19/src/main/java/thetadev/constructionwand/basics/ConfigServer.java#L25)
and making a PR. and making a PR.
## Contributions and #Hacktoberfest ## Contributions and #Hacktoberfest

View file

@ -16,8 +16,10 @@ version = "${mcversion}-${version_major}.${version_minor}"
group = "${author}.${modid}" group = "${author}.${modid}"
archivesBaseName = "${modid}" archivesBaseName = "${modid}"
// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17.
java.toolchain.languageVersion = JavaLanguageVersion.of(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 {
mappings channel: project.mcp_channel, version: project.mcp_mappings mappings channel: project.mcp_channel, version: project.mcp_mappings
@ -31,6 +33,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', modid
mods { mods {
constructionwand { constructionwand {
source sourceSets.main source sourceSets.main
@ -47,6 +52,8 @@ 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'
// property 'forge.enabledGameTestNamespaces', modid
mods { mods {
constructionwand { constructionwand {
source sourceSets.main source sourceSets.main
@ -54,6 +61,25 @@ minecraft {
} }
} }
// 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', modid
mods {
examplemod {
source sourceSets.main
}
}
}
data { data {
workingDirectory project.file("run/client").canonicalPath workingDirectory project.file("run/client").canonicalPath
@ -101,8 +127,9 @@ dependencies {
version: "${project.mcversion}-${project.forgeversion}" version: "${project.mcversion}-${project.forgeversion}"
]) ])
compileOnly fg.deobf("mezz.jei:${jei_version}:api") compileOnly fg.deobf("mezz.jei:jei-${mcversion}-common-api:${jei_version}")
runtimeOnly fg.deobf("mezz.jei:${jei_version}") compileOnly fg.deobf("mezz.jei:jei-${mcversion}-forge-api:${jei_version}")
runtimeOnly fg.deobf("mezz.jei:jei-${mcversion}-forge:${jei_version}")
compileOnly fg.deobf([ compileOnly fg.deobf([
group: "vazkii.botania", group: "vazkii.botania",
@ -144,3 +171,7 @@ publishing {
} }
} }
} }
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}

View file

@ -4,15 +4,15 @@ org.gradle.daemon=false
author=thetadev author=thetadev
modid=constructionwand modid=constructionwand
mcversion=1.18.1 mcversion=1.19.2
forgeversion=39.1.0 forgeversion=43.2.4
mcp_channel=official mcp_channel=official
mcp_mappings=1.18.1 mcp_mappings=1.19.2
# Source: https://maven.blamejared.com/vazkii/botania/Botania/ # Source: https://maven.blamejared.com/vazkii/botania/Botania/
botania=1.18.1-429 botania=1.19.2-437-FORGE
# Source: https://dvs1.progwml6.com/files/maven/mezz/jei/ # Source: https://dvs1.progwml6.com/files/maven/mezz/jei/
jei_version=jei-1.18.1:9.1.0.41 jei_version=11.5.2.1007
version_major=2 version_major=2
version_minor=11 version_minor=10

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 distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

269
gradlew vendored
View file

@ -1,7 +1,7 @@
#!/usr/bin/env sh #!/bin/sh
# #
# Copyright 2015 the original author or authors. # Copyright © 2015-2021 the original authors.
# #
# Licensed under the Apache License, Version 2.0 (the "License"); # Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License. # you may not use this file except in compliance with the License.
@ -17,67 +17,101 @@
# #
############################################################################## ##############################################################################
## #
## 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 «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# 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='"-Xmx64m" "-Xms64m"' 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
;;
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
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
@ -98,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
@ -106,80 +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 or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; 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=`expr $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" )
JAVACMD=$( cygpath --unix "$JAVACMD" )
# 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
# 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" "$@"

13
notes/Builds.md Normal file
View file

@ -0,0 +1,13 @@
# Builds
Overview of all builds of ConstructionWand and their properties.
| Build | Java version | Supported MC versions |
|--------|--------------|-----------------------|
| 1.14.4 | 8 | 1.14.4 |
| 1.15.2 | 8 | 1.15.2 |
| 1.16.1 | 8 | 1.16.1 |
| 1.16.5 | 8 | 1.16.2 - 1.16.5 |
| 1.17.1 | 16 | 1.17.1 |
| 1.18 | 17 | 1.18 |
| 1.19 | 17 | 1.19 - 1.19.2 |

11
notes/test_command.md Normal file
View file

@ -0,0 +1,11 @@
# Testing item containers
- Install the toolbelt mod (https://www.curseforge.com/minecraft/mc-mods/tool-belt)
- Place a chest on top of a command block and enter this command:
- Get a toolbeld with 2 stacks of diamond blocks in it
The reason for this hack is that the toolbelt mod gets updated very quickly and is available for almost every
MC version supported by ConstructionWand.
```
data merge block ~ ~1 ~ {Items: [{Slot: 0, id: "toolbelt:belt", Count: 1, tag: {Items: [{Slot: 0, id: "minecraft:diamond_block", Count: 64}, {Slot: 1, id: "minecraft:diamond_block", Count: 64}]}}]}
```

6
settings.gradle Normal file
View file

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

View file

@ -15,7 +15,6 @@ import org.apache.logging.log4j.Logger;
import thetadev.constructionwand.basics.ConfigClient; import thetadev.constructionwand.basics.ConfigClient;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.ModStats; import thetadev.constructionwand.basics.ModStats;
import thetadev.constructionwand.basics.ReplacementRegistry;
import thetadev.constructionwand.client.ClientEvents; import thetadev.constructionwand.client.ClientEvents;
import thetadev.constructionwand.client.RenderBlockPreview; import thetadev.constructionwand.client.RenderBlockPreview;
import thetadev.constructionwand.containers.ContainerManager; import thetadev.constructionwand.containers.ContainerManager;
@ -74,9 +73,6 @@ public class ConstructionWand
// Container registry // Container registry
ContainerRegistrar.register(); ContainerRegistrar.register();
//Replacement registry
ReplacementRegistry.init();
// Stats // Stats
ModStats.register(); ModStats.register();
} }
@ -87,7 +83,6 @@ public class ConstructionWand
MinecraftForge.EVENT_BUS.register(new ClientEvents()); MinecraftForge.EVENT_BUS.register(new ClientEvents());
event.enqueueWork(ModItems::registerModelProperties); event.enqueueWork(ModItems::registerModelProperties);
event.enqueueWork(ModItems::registerItemColors);
} }
public static ResourceLocation loc(String name) { public static ResourceLocation loc(String name) {

View file

@ -2,6 +2,7 @@ package thetadev.constructionwand.basics;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.event.server.ServerStartingEvent;
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 thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
@ -9,9 +10,14 @@ import thetadev.constructionwand.ConstructionWand;
@Mod.EventBusSubscriber(modid = ConstructionWand.MODID) @Mod.EventBusSubscriber(modid = ConstructionWand.MODID)
public class CommonEvents public class CommonEvents
{ {
@SubscribeEvent
public static void serverStarting(ServerStartingEvent e) {
ReplacementRegistry.init();
}
@SubscribeEvent @SubscribeEvent
public static void logOut(PlayerEvent.PlayerLoggedOutEvent e) { public static void logOut(PlayerEvent.PlayerLoggedOutEvent e) {
Player player = e.getPlayer(); Player player = e.getEntity();
if(player.level.isClientSide) return; if(player.level.isClientSide) return;
ConstructionWand.instance.undoHistory.removePlayer(player); ConstructionWand.instance.undoHistory.removePlayer(player);
} }

View file

@ -4,6 +4,7 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.Tiers; import net.minecraft.world.item.Tiers;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.items.ModItems;
@ -13,7 +14,7 @@ import java.util.List;
public class ConfigServer public class ConfigServer
{ {
private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); public static final ForgeConfigSpec SPEC;
public static final ForgeConfigSpec.IntValue LIMIT_CREATIVE; public static final ForgeConfigSpec.IntValue LIMIT_CREATIVE;
public static final ForgeConfigSpec.IntValue MAX_RANGE; public static final ForgeConfigSpec.IntValue MAX_RANGE;
@ -32,7 +33,7 @@ public class ConfigServer
private static final HashMap<ResourceLocation, WandProperties> wandProperties = new HashMap<>(); private static final HashMap<ResourceLocation, WandProperties> wandProperties = new HashMap<>();
public static WandProperties getWandProperties(Item wand) { public static WandProperties getWandProperties(Item wand) {
return wandProperties.getOrDefault(wand.getRegistryName(), WandProperties.DEFAULT); return wandProperties.getOrDefault(ForgeRegistries.ITEMS.getKey(wand), WandProperties.DEFAULT);
} }
public static class WandProperties public static class WandProperties
@ -100,39 +101,41 @@ public class ConfigServer
} }
static { static {
BUILDER.comment("This is the Server config for ConstructionWand.", final var builder = new ForgeConfigSpec.Builder();
builder.comment("This is the Server config for ConstructionWand.",
"If you're not familiar with Forge's new split client/server config, let me explain:", "If you're not familiar with Forge's new split client/server config, let me explain:",
"Client config is stored in the /config folder and only contains client specific settings like graphics and keybinds.", "Client config is stored in the /config folder and only contains client specific settings like graphics and keybinds.",
"Mod behavior is configured in the Server config, which is world-specific and thus located", "Mod behavior is configured in the Server config, which is world-specific and thus located",
"in the /saves/myworld/serverconfig folder. If you want to change the serverconfig for all", "in the /saves/myworld/serverconfig folder. If you want to change the serverconfig for all",
"new worlds, copy the config files in the /defaultconfigs folder."); "new worlds, copy the config files in the /defaultconfigs folder.");
new WandProperties(BUILDER, ModItems.WAND_STONE, Tiers.STONE.getUses(), 9, 0, 0, false); new WandProperties(builder, ModItems.WAND_STONE, Tiers.STONE.getUses(), 9, 0, 0, false);
new WandProperties(BUILDER, ModItems.WAND_IRON, Tiers.IRON.getUses(), 27, 2, 9, true); new WandProperties(builder, ModItems.WAND_IRON, Tiers.IRON.getUses(), 27, 2, 9, true);
new WandProperties(BUILDER, ModItems.WAND_DIAMOND, Tiers.DIAMOND.getUses(), 128, 8, 25, true); new WandProperties(builder, ModItems.WAND_DIAMOND, Tiers.DIAMOND.getUses(), 128, 8, 25, true);
new WandProperties(BUILDER, ModItems.WAND_INFINITY, 0, 1024, 16, 81, true); new WandProperties(builder, ModItems.WAND_INFINITY, 0, 1024, 16, 81, true);
BUILDER.push("misc"); builder.push("misc");
BUILDER.comment("Block limit for Infinity Wand used in creative mode"); builder.comment("Block limit for Infinity Wand used in creative mode");
LIMIT_CREATIVE = BUILDER.defineInRange("InfinityWandCreative", 2048, 1, Integer.MAX_VALUE); LIMIT_CREATIVE = builder.defineInRange("InfinityWandCreative", 2048, 1, Integer.MAX_VALUE);
BUILDER.comment("Maximum placement range (0: unlimited). Affects all wands and is meant for lag prevention, not game balancing."); builder.comment("Maximum placement range (0: unlimited). Affects all wands and is meant for lag prevention, not game balancing.");
MAX_RANGE = BUILDER.defineInRange("MaxRange", 100, 0, Integer.MAX_VALUE); MAX_RANGE = builder.defineInRange("MaxRange", 100, 0, Integer.MAX_VALUE);
BUILDER.comment("Number of operations that can be undone"); builder.comment("Number of operations that can be undone");
UNDO_HISTORY = BUILDER.defineInRange("UndoHistory", 3, 0, Integer.MAX_VALUE); UNDO_HISTORY = builder.defineInRange("UndoHistory", 3, 0, Integer.MAX_VALUE);
BUILDER.comment("Place blocks below you while falling > 10 blocks with angel core (Can be used to save you from drops/the void)"); builder.comment("Place blocks below you while falling > 10 blocks with angel core (Can be used to save you from drops/the void)");
ANGEL_FALLING = BUILDER.define("AngelFalling", false); ANGEL_FALLING = builder.define("AngelFalling", false);
BUILDER.comment("Blocks to treat equally when in Similar mode. Enter block IDs seperated by ;"); builder.comment("Blocks to treat equally when in Similar mode. Enter block IDs seperated by ;");
SIMILAR_BLOCKS = BUILDER.defineList("SimilarBlocks", Arrays.asList(SIMILAR_BLOCKS_DEFAULT), obj -> true); SIMILAR_BLOCKS = builder.defineList("SimilarBlocks", Arrays.asList(SIMILAR_BLOCKS_DEFAULT), obj -> true);
BUILDER.pop(); builder.pop();
BUILDER.push("tileentity"); builder.push("tileentity");
BUILDER.comment("White/Blacklist for Tile Entities. Allow/Prevent blocks with TEs from being placed by wand.", builder.comment("White/Blacklist for Tile Entities. Allow/Prevent blocks with TEs from being placed by wand.",
"You can either add block ids like minecraft:chest or mod ids like minecraft"); "You can either add block ids like minecraft:chest or mod ids like minecraft");
TE_LIST = BUILDER.defineList("TEList", Arrays.asList(TE_LIST_DEFAULT), obj -> true); TE_LIST = builder.defineList("TEList", Arrays.asList(TE_LIST_DEFAULT), obj -> true);
BUILDER.comment("If set to TRUE, treat TEList as a whitelist, otherwise blacklist"); builder.comment("If set to TRUE, treat TEList as a whitelist, otherwise blacklist");
TE_WHITELIST = BUILDER.define("TEWhitelist", false); TE_WHITELIST = builder.define("TEWhitelist", false);
BUILDER.pop(); builder.pop();
}
public static final ForgeConfigSpec SPEC = BUILDER.build(); SPEC = builder.build();
}
} }

View file

@ -16,6 +16,8 @@ public class ReplacementRegistry
private static final HashSet<HashSet<Item>> replacements = new HashSet<>(); private static final HashSet<HashSet<Item>> replacements = new HashSet<>();
public static void init() { public static void init() {
replacements.clear();
for(Object key : ConfigServer.SIMILAR_BLOCKS.get()) { for(Object key : ConfigServer.SIMILAR_BLOCKS.get()) {
if(!(key instanceof String)) continue; if(!(key instanceof String)) continue;
HashSet<Item> set = new HashSet<>(); HashSet<Item> set = new HashSet<>();

View file

@ -20,7 +20,8 @@ import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.registries.ForgeRegistries;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.containers.ContainerManager; import thetadev.constructionwand.containers.ContainerManager;
import thetadev.constructionwand.items.wand.ItemWand; import thetadev.constructionwand.items.wand.ItemWand;
@ -52,10 +53,6 @@ public class WandUtil
return null; return null;
} }
public static BlockPos playerPos(Player player) {
return new BlockPos(player.position());
}
public static Vec3 entityPositionVec(Entity entity) { public static Vec3 entityPositionVec(Entity entity) {
return new Vec3(entity.getX(), entity.getY() - entity.getMyRidingOffset() + entity.getBbHeight() / 2, entity.getZ()); return new Vec3(entity.getX(), entity.getY() - entity.getMyRidingOffset() + entity.getBbHeight() / 2, entity.getZ());
} }
@ -91,7 +88,7 @@ public class WandUtil
public static boolean isTEAllowed(BlockState state) { public static boolean isTEAllowed(BlockState state) {
if(!state.hasBlockEntity()) return true; if(!state.hasBlockEntity()) return true;
ResourceLocation name = state.getBlock().getRegistryName(); ResourceLocation name = ForgeRegistries.BLOCKS.getKey(state.getBlock());
if(name == null) return false; if(name == null) return false;
String fullId = name.toString(); String fullId = name.toString();

View file

@ -1,17 +1,18 @@
package thetadev.constructionwand.basics.pool; package thetadev.constructionwand.basics.pool;
import net.minecraft.util.RandomSource;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Random;
public class RandomPool<T> implements IPool<T> public class RandomPool<T> implements IPool<T>
{ {
private final Random rng; private final RandomSource rng;
private final HashMap<T, Integer> elements; private final HashMap<T, Integer> elements;
private HashSet<T> pool; private HashSet<T> pool;
public RandomPool(Random rng) { public RandomPool(RandomSource rng) {
this.rng = rng; this.rng = rng;
elements = new HashMap<>(); elements = new HashMap<>();
reset(); reset();

View file

@ -26,7 +26,7 @@ public class ClientEvents
// Send state of OPT key to server // Send state of OPT key to server
@SubscribeEvent @SubscribeEvent
public void KeyEvent(InputEvent.KeyInputEvent event) { public void KeyEvent(InputEvent.Key event) {
Player player = Minecraft.getInstance().player; Player player = Minecraft.getInstance().player;
if(player == null) return; if(player == null) return;
if(WandUtil.holdingWand(player) == null) return; if(WandUtil.holdingWand(player) == null) return;
@ -42,7 +42,7 @@ public class ClientEvents
// Sneak+(OPT)+Scroll to change direction lock // Sneak+(OPT)+Scroll to change direction lock
@SubscribeEvent(priority = EventPriority.HIGHEST) @SubscribeEvent(priority = EventPriority.HIGHEST)
public void MouseScrollEvent(InputEvent.MouseScrollEvent event) { public void MouseScrollEvent(InputEvent.MouseScrollingEvent event) {
Player player = Minecraft.getInstance().player; Player player = Minecraft.getInstance().player;
double scroll = event.getScrollDelta(); double scroll = event.getScrollDelta();
@ -60,7 +60,7 @@ public class ClientEvents
// Sneak+(OPT)+Left click wand to change core // Sneak+(OPT)+Left click wand to change core
@SubscribeEvent @SubscribeEvent
public void onLeftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) { public void onLeftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) {
Player player = event.getPlayer(); Player player = event.getEntity();
if(player == null || !modeKeyCombDown(player)) return; if(player == null || !modeKeyCombDown(player)) return;
@ -77,7 +77,7 @@ public class ClientEvents
public void onRightClickItem(PlayerInteractEvent.RightClickItem event) { public void onRightClickItem(PlayerInteractEvent.RightClickItem event) {
if(event.getSide().isServer()) return; if(event.getSide().isServer()) return;
Player player = event.getPlayer(); Player player = event.getEntity();
if(player == null || !guiKeyCombDown(player)) return; if(player == null || !guiKeyCombDown(player)) return;
ItemStack wand = event.getItemStack(); ItemStack wand = event.getItemStack();

View file

@ -12,7 +12,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.HitResult;
import net.minecraftforge.client.event.DrawSelectionEvent; import net.minecraftforge.client.event.RenderHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.items.wand.ItemWand; import thetadev.constructionwand.items.wand.ItemWand;
@ -26,7 +26,7 @@ public class RenderBlockPreview
public Set<BlockPos> undoBlocks; public Set<BlockPos> undoBlocks;
@SubscribeEvent @SubscribeEvent
public void renderBlockHighlight(DrawSelectionEvent.HighlightBlock event) { public void renderBlockHighlight(RenderHighlightEvent.Block event) {
if(event.getTarget().getType() != HitResult.Type.BLOCK) return; if(event.getTarget().getType() != HitResult.Type.BLOCK) return;
BlockHitResult rtr = event.getTarget(); BlockHitResult rtr = event.getTarget();
@ -59,7 +59,7 @@ public class RenderBlockPreview
MultiBufferSource buffer = event.getMultiBufferSource(); MultiBufferSource buffer = event.getMultiBufferSource();
VertexConsumer lineBuilder = buffer.getBuffer(RenderType.LINES); VertexConsumer lineBuilder = buffer.getBuffer(RenderType.LINES);
double partialTicks = event.getPartialTicks(); double partialTicks = event.getPartialTick();
double d0 = player.xOld + (player.getX() - player.xOld) * partialTicks; double d0 = player.xOld + (player.getX() - player.xOld) * partialTicks;
double d1 = player.yOld + player.getEyeHeight() + (player.getY() - player.yOld) * partialTicks; double d1 = player.yOld + player.getEyeHeight() + (player.getY() - player.yOld) * partialTicks;
double d2 = player.zOld + (player.getZ() - player.zOld) * partialTicks; double d2 = player.zOld + (player.getZ() - player.zOld) * partialTicks;
@ -72,6 +72,10 @@ public class RenderBlockPreview
event.setCanceled(true); event.setCanceled(true);
} }
public void reset() {
wandJob = null;
}
private static boolean compareRTR(BlockHitResult rtr1, BlockHitResult rtr2) { private static boolean compareRTR(BlockHitResult rtr1, BlockHitResult rtr2) {
return rtr1.getBlockPos().equals(rtr2.getBlockPos()) && rtr1.getDirection().equals(rtr2.getDirection()); return rtr1.getBlockPos().equals(rtr2.getBlockPos()) && rtr1.getDirection().equals(rtr2.getDirection());
} }

View file

@ -5,8 +5,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.option.IOption; import thetadev.constructionwand.basics.option.IOption;
@ -31,7 +29,7 @@ public class ScreenWand extends Screen
private static final int FIELD_HEIGHT = N_ROWS * (BUTTON_HEIGHT + SPACING_HEIGHT) - SPACING_HEIGHT; private static final int FIELD_HEIGHT = N_ROWS * (BUTTON_HEIGHT + SPACING_HEIGHT) - SPACING_HEIGHT;
public ScreenWand(ItemStack wand) { public ScreenWand(ItemStack wand) {
super(new TextComponent("ScreenWand")); super(Component.literal("ScreenWand"));
this.wand = wand; this.wand = wand;
wandOptions = new WandOptions(wand); wandOptions = new WandOptions(wand);
} }
@ -58,13 +56,15 @@ public class ScreenWand extends Screen
if(Minecraft.getInstance().options.keyInventory.matches(keyCode, scanCode)) { if(Minecraft.getInstance().options.keyInventory.matches(keyCode, scanCode)) {
this.onClose(); this.onClose();
return true; return true;
} else { }
else {
return super.keyPressed(keyCode, scanCode, modifiers); return super.keyPressed(keyCode, scanCode, modifiers);
} }
} }
private void createButton(int cx, int cy, IOption<?> option) { private void createButton(int cx, int cy, IOption<?> option) {
Button button = new Button(getX(cx), getY(cy), BUTTON_WIDTH, BUTTON_HEIGHT, getButtonLabel(option), bt -> clickButton(bt, option), (bt, ms, x, y) -> drawTooltip(ms, x, y, option)); Button button = new Button(getX(cx), getY(cy), BUTTON_WIDTH, BUTTON_HEIGHT,
getButtonLabel(option), bt -> clickButton(bt, option), (bt, ms, x, y) -> drawTooltip(ms, x, y, option));
button.active = option.isEnabled(); button.active = option.isEnabled();
addRenderableWidget(button); addRenderableWidget(button);
} }
@ -77,7 +77,7 @@ public class ScreenWand extends Screen
private void drawTooltip(PoseStack matrixStack, int mouseX, int mouseY, IOption<?> option) { private void drawTooltip(PoseStack matrixStack, int mouseX, int mouseY, IOption<?> option) {
if(isMouseOver(mouseX, mouseY)) { if(isMouseOver(mouseX, mouseY)) {
renderTooltip(matrixStack, new TranslatableComponent(option.getDescTranslation()), mouseX, mouseY); renderTooltip(matrixStack, Component.translatable(option.getDescTranslation()), mouseX, mouseY);
} }
} }
@ -90,6 +90,6 @@ public class ScreenWand extends Screen
} }
private Component getButtonLabel(IOption<?> option) { private Component getButtonLabel(IOption<?> option) {
return new TranslatableComponent(option.getKeyTranslation()).append(new TranslatableComponent(option.getValueTranslation())); return Component.translatable(option.getKeyTranslation()).append(Component.translatable(option.getValueTranslation()));
} }
} }

View file

@ -5,7 +5,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Block;
import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.api.IContainerHandler;
import vazkii.botania.api.BotaniaForgeCapabilities; import vazkii.botania.api.BotaniaForgeCapabilities;
import vazkii.botania.api.item.IBlockProvider; import vazkii.botania.api.item.BlockProvider;
import java.util.Optional; import java.util.Optional;
@ -18,10 +18,10 @@ public class HandlerBotania implements IContainerHandler
@Override @Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
Optional<IBlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve(); Optional<BlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve();
if(provOptional.isEmpty()) return 0; if(provOptional.isEmpty()) return 0;
IBlockProvider prov = provOptional.get(); BlockProvider prov = provOptional.get();
int provCount = prov.getBlockCount(player, inventoryStack, Block.byItem(itemStack.getItem())); int provCount = prov.getBlockCount(player, inventoryStack, Block.byItem(itemStack.getItem()));
if(provCount == -1) if(provCount == -1)
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
@ -30,10 +30,10 @@ public class HandlerBotania implements IContainerHandler
@Override @Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
Optional<IBlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve(); Optional<BlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve();
if(provOptional.isEmpty()) return 0; if(provOptional.isEmpty()) return 0;
IBlockProvider prov = provOptional.get(); BlockProvider prov = provOptional.get();
if(prov.provideBlock(player, inventoryStack, Block.byItem(itemStack.getItem()), true)) if(prov.provideBlock(player, inventoryStack, Block.byItem(itemStack.getItem()), true))
return 0; return 0;
return count; return count;

View file

@ -2,7 +2,7 @@ package thetadev.constructionwand.containers.handlers;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.common.capabilities.ForgeCapabilities;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.api.IContainerHandler;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
@ -13,12 +13,12 @@ public class HandlerCapability implements IContainerHandler
{ {
@Override @Override
public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) {
return inventoryStack != null && inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).isPresent(); return inventoryStack != null && inventoryStack.getCapability(ForgeCapabilities.ITEM_HANDLER).isPresent();
} }
@Override @Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve(); Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve();
if(itemHandlerOptional.isEmpty()) return 0; if(itemHandlerOptional.isEmpty()) return 0;
int total = 0; int total = 0;
@ -36,7 +36,7 @@ public class HandlerCapability implements IContainerHandler
@Override @Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve(); Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(ForgeCapabilities.ITEM_HANDLER).resolve();
if(itemHandlerOptional.isEmpty()) return 0; if(itemHandlerOptional.isEmpty()) return 0;
IItemHandler itemHandler = itemHandlerOptional.get(); IItemHandler itemHandler = itemHandlerOptional.get();

View file

@ -1,10 +1,11 @@
package thetadev.constructionwand.data; package thetadev.constructionwand.data;
import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.critereon.ItemPredicate;
import net.minecraft.tags.Tag; import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.ItemLike;
import net.minecraftforge.registries.ForgeRegistries;
public class Inp public class Inp
{ {
@ -19,10 +20,10 @@ public class Inp
} }
public static Inp fromItem(ItemLike in) { public static Inp fromItem(ItemLike in) {
return new Inp(in.asItem().getRegistryName().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build()); return new Inp(ForgeRegistries.ITEMS.getKey(in.asItem()).getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build());
} }
public static Inp fromTag(Tag.Named<Item> in) { public static Inp fromTag(TagKey<Item> in) {
return new Inp(in.getName().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build()); return new Inp(in.location().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build());
} }
} }

View file

@ -5,6 +5,7 @@ import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraftforge.client.model.generators.ItemModelProvider; import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.items.ModItems;
@ -21,7 +22,7 @@ public class ItemModelGenerator extends ItemModelProvider
protected void registerModels() { protected void registerModels() {
for(RegistryObject<Item> itemObject : ModItems.ITEMS.getEntries()) { for(RegistryObject<Item> itemObject : ModItems.ITEMS.getEntries()) {
Item item = itemObject.get(); Item item = itemObject.get();
String name = item.getRegistryName().getPath(); String name = ForgeRegistries.ITEMS.getKey(item).getPath();
if(item instanceof ICustomItemModel) if(item instanceof ICustomItemModel)
((ICustomItemModel) item).generateCustomItemModel(this, name); ((ICustomItemModel) item).generateCustomItemModel(this, name);

View file

@ -2,9 +2,9 @@ package thetadev.constructionwand.data;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.data.event.GatherDataEvent;
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.forge.event.lifecycle.GatherDataEvent;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class ModData public class ModData
@ -15,11 +15,11 @@ public class ModData
ExistingFileHelper fileHelper = event.getExistingFileHelper(); ExistingFileHelper fileHelper = event.getExistingFileHelper();
if(event.includeServer()) { if(event.includeServer()) {
generator.addProvider(new RecipeGenerator(generator)); generator.addProvider(true, new RecipeGenerator(generator));
} }
if(event.includeClient()) { if(event.includeClient()) {
generator.addProvider(new ItemModelGenerator(generator, fileHelper)); generator.addProvider(true, new ItemModelGenerator(generator, fileHelper));
} }
} }
} }

View file

@ -7,11 +7,12 @@ import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.registration.IRecipeRegistration; import mezz.jei.api.registration.IRecipeRegistration;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject; import net.minecraftforge.registries.RegistryObject;
import org.jetbrains.annotations.NotNull;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.ConfigClient; import thetadev.constructionwand.basics.ConfigClient;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
@ -34,12 +35,12 @@ public class ConstructionWandJeiPlugin implements IModPlugin
private Component keyComboComponent(boolean shiftOpt, Component optkeyComponent) { private Component keyComboComponent(boolean shiftOpt, Component optkeyComponent) {
String key = shiftOpt ? "sneak_opt" : "sneak"; String key = shiftOpt ? "sneak_opt" : "sneak";
return new TranslatableComponent(baseKey + "key." + key, optkeyComponent).withStyle(ChatFormatting.BLUE); return Component.translatable(baseKey + "key." + key, optkeyComponent).withStyle(ChatFormatting.BLUE);
} }
@Override @Override
public void registerRecipes(IRecipeRegistration registration) { public void registerRecipes(@NotNull IRecipeRegistration registration) {
Component optkeyComponent = new TranslatableComponent(InputConstants.getKey(ConfigClient.OPT_KEY.get(), -1).getName()) Component optkeyComponent = Component.translatable(InputConstants.getKey(ConfigClient.OPT_KEY.get(), -1).getName())
.withStyle(ChatFormatting.BLUE); .withStyle(ChatFormatting.BLUE);
Component wandModeComponent = keyComboComponent(ConfigClient.SHIFTOPT_MODE.get(), optkeyComponent); Component wandModeComponent = keyComboComponent(ConfigClient.SHIFTOPT_MODE.get(), optkeyComponent);
Component wandGuiComponent = keyComboComponent(ConfigClient.SHIFTOPT_GUI.get(), optkeyComponent); Component wandGuiComponent = keyComboComponent(ConfigClient.SHIFTOPT_GUI.get(), optkeyComponent);
@ -49,21 +50,21 @@ public class ConstructionWandJeiPlugin implements IModPlugin
ConfigServer.WandProperties wandProperties = ConfigServer.getWandProperties(wand); ConfigServer.WandProperties wandProperties = ConfigServer.getWandProperties(wand);
String durabilityKey = wand == ModItems.WAND_INFINITY.get() ? "unlimited" : "limited"; String durabilityKey = wand == ModItems.WAND_INFINITY.get() ? "unlimited" : "limited";
Component durabilityComponent = new TranslatableComponent(baseKey + "durability." + durabilityKey, wandProperties.getDurability()); Component durabilityComponent = Component.translatable(baseKey + "durability." + durabilityKey, wandProperties.getDurability());
registration.addIngredientInfo(new ItemStack(wand), VanillaTypes.ITEM, registration.addIngredientInfo(new ItemStack(wand), VanillaTypes.ITEM_STACK,
new TranslatableComponent(baseKey + "wand", Component.translatable(baseKey + "wand",
new TranslatableComponent(baseKeyItem + wand.getRegistryName().getPath()), Component.translatable(baseKeyItem + ForgeRegistries.ITEMS.getKey(wand).getPath()),
wandProperties.getLimit(), durabilityComponent, wandProperties.getLimit(), durabilityComponent, optkeyComponent, wandModeComponent, wandGuiComponent)
optkeyComponent, wandModeComponent, wandGuiComponent)
); );
} }
for(RegistryObject<Item> coreSupplier : ModItems.CORES) { for(RegistryObject<Item> coreSupplier : ModItems.CORES) {
Item core = coreSupplier.get(); Item core = coreSupplier.get();
registration.addIngredientInfo(new ItemStack(core), VanillaTypes.ITEM, registration.addIngredientInfo(new ItemStack(core), VanillaTypes.ITEM_STACK,
new TranslatableComponent(baseKey + core.getRegistryName().getPath()), Component.translatable(baseKey + ForgeRegistries.ITEMS.getKey(core).getPath())
new TranslatableComponent(baseKey + "core", wandModeComponent) .append("\n\n")
.append(Component.translatable(baseKey + "core", wandModeComponent))
); );
} }
} }

View file

@ -1,18 +1,18 @@
package thetadev.constructionwand.items; package thetadev.constructionwand.items;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.Tiers; import net.minecraft.world.item.Tiers;
import net.minecraft.world.item.crafting.RecipeSerializer;
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.event.RegistryEvent; import net.minecraftforge.client.event.RegisterColorHandlersEvent;
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.registries.*; import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent;
import net.minecraftforge.registries.RegistryObject;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.crafting.RecipeWandUpgrade; import thetadev.constructionwand.crafting.RecipeWandUpgrade;
@ -50,9 +50,10 @@ public class ModItems
} }
@SubscribeEvent @SubscribeEvent
public static void registerRecipeSerializers(RegistryEvent.Register<RecipeSerializer<?>> event) { public static void registerRecipeSerializers(RegisterEvent event) {
IForgeRegistry<RecipeSerializer<?>> r = event.getRegistry(); event.register(ForgeRegistries.Keys.RECIPE_SERIALIZERS, registry -> {
register(r, "wand_upgrade", RecipeWandUpgrade.SERIALIZER); registry.register("wand_upgrade", RecipeWandUpgrade.SERIALIZER);
});
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
@ -68,17 +69,12 @@ public class ModItems
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public static void registerItemColors() { @SubscribeEvent
ItemColors colors = Minecraft.getInstance().getItemColors(); public static void registerItemColors(RegisterColorHandlersEvent.Item event) {
for(RegistryObject<Item> itemSupplier : WANDS) { for(RegistryObject<Item> itemSupplier : WANDS) {
Item item = itemSupplier.get(); Item item = itemSupplier.get();
colors.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ? event.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ?
new WandOptions(stack).cores.get().getColor() : -1, item); new WandOptions(stack).cores.get().getColor() : -1, item);
} }
} }
private static <V extends IForgeRegistryEntry<V>> void register(IForgeRegistry<V> reg, String name, IForgeRegistryEntry<V> thing) {
reg.register(thing.setRegistryName(ConstructionWand.loc(name)));
}
} }

View file

@ -2,7 +2,6 @@ package thetadev.constructionwand.items.core;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.TooltipFlag;
@ -23,9 +22,12 @@ public abstract class ItemCore extends Item implements IWandCore
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void appendHoverText(@Nonnull ItemStack itemstack, Level worldIn, @Nonnull List<Component> lines, @Nonnull TooltipFlag extraInfo) { public void appendHoverText(@Nonnull ItemStack itemstack, Level worldIn, @Nonnull List<Component> lines, @Nonnull TooltipFlag extraInfo) {
lines.add(new TranslatableComponent(ConstructionWand.MODID + ".option.cores." + getRegistryName().toString() + ".desc") lines.add(
.withStyle(ChatFormatting.GRAY)); Component.translatable(ConstructionWand.MODID + ".option.cores." + getRegistryName().toString() + ".desc")
lines.add(new TranslatableComponent(ConstructionWand.MODID + ".tooltip.core_tip") .withStyle(ChatFormatting.GRAY)
.withStyle(ChatFormatting.AQUA)); );
lines.add(
Component.translatable(ConstructionWand.MODID + ".tooltip.core_tip").withStyle(ChatFormatting.AQUA)
);
} }
} }

View file

@ -1,5 +1,7 @@
package thetadev.constructionwand.items.core; package thetadev.constructionwand.items.core;
import net.minecraft.resources.ResourceLocation;
import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.wand.action.ActionAngel; import thetadev.constructionwand.wand.action.ActionAngel;
@ -18,4 +20,9 @@ public class ItemCoreAngel extends ItemCore
public IWandAction getWandAction() { public IWandAction getWandAction() {
return new ActionAngel(); return new ActionAngel();
} }
@Override
public ResourceLocation getRegistryName() {
return ConstructionWand.loc("core_angel");
}
} }

View file

@ -1,5 +1,7 @@
package thetadev.constructionwand.items.core; package thetadev.constructionwand.items.core;
import net.minecraft.resources.ResourceLocation;
import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.wand.action.ActionDestruction; import thetadev.constructionwand.wand.action.ActionDestruction;
@ -18,4 +20,9 @@ public class ItemCoreDestruction extends ItemCore
public IWandAction getWandAction() { public IWandAction getWandAction() {
return new ActionDestruction(); return new ActionDestruction();
} }
@Override
public ResourceLocation getRegistryName() {
return ConstructionWand.loc("core_destruction");
}
} }

View file

@ -3,8 +3,6 @@ package thetadev.constructionwand.items.wand;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult; import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.InteractionResultHolder;
@ -68,7 +66,7 @@ public abstract class ItemWand extends Item implements ICustomItemModel
// Right click: Place angel block // Right click: Place angel block
WandJob job = getWandJob(player, world, BlockHitResult.miss(player.getLookAngle(), WandJob job = getWandJob(player, world, BlockHitResult.miss(player.getLookAngle(),
WandUtil.fromVector(player.getLookAngle()), WandUtil.playerPos(player)), stack); WandUtil.fromVector(player.getLookAngle()), player.blockPosition()), stack);
return job.doIt() ? InteractionResultHolder.success(stack) : InteractionResultHolder.fail(stack); return job.doIt() ? InteractionResultHolder.success(stack) : InteractionResultHolder.fail(stack);
} }
return InteractionResultHolder.fail(stack); return InteractionResultHolder.fail(stack);
@ -107,35 +105,35 @@ public abstract class ItemWand extends Item implements ICustomItemModel
if(Screen.hasShiftDown()) { if(Screen.hasShiftDown()) {
for(int i = 1; i < options.allOptions.length; i++) { for(int i = 1; i < options.allOptions.length; i++) {
IOption<?> opt = options.allOptions[i]; IOption<?> opt = options.allOptions[i];
lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA) lines.add(Component.translatable(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.GRAY)) .append(Component.translatable(opt.getValueTranslation()).withStyle(ChatFormatting.GRAY))
); );
} }
if(!options.cores.getUpgrades().isEmpty()) { if(!options.cores.getUpgrades().isEmpty()) {
lines.add(new TextComponent("")); lines.add(Component.literal(""));
lines.add(new TranslatableComponent(langTooltip + "cores").withStyle(ChatFormatting.GRAY)); lines.add(Component.translatable(langTooltip + "cores").withStyle(ChatFormatting.GRAY));
for(IWandCore core : options.cores.getUpgrades()) { for(IWandCore core : options.cores.getUpgrades()) {
lines.add(new TranslatableComponent(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString())); lines.add(Component.translatable(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString()));
} }
} }
} }
// Default tooltip: show block limit + active wand core // Default tooltip: show block limit + active wand core
else { else {
IOption<?> opt = options.allOptions[0]; IOption<?> opt = options.allOptions[0];
lines.add(new TranslatableComponent(langTooltip + "blocks", limit).withStyle(ChatFormatting.GRAY)); lines.add(Component.translatable(langTooltip + "blocks", limit).withStyle(ChatFormatting.GRAY));
lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA) lines.add(Component.translatable(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.WHITE))); .append(Component.translatable(opt.getValueTranslation()).withStyle(ChatFormatting.WHITE)));
lines.add(new TranslatableComponent(langTooltip + "shift").withStyle(ChatFormatting.AQUA)); lines.add(Component.translatable(langTooltip + "shift").withStyle(ChatFormatting.AQUA));
} }
} }
public static void optionMessage(Player player, IOption<?> option) { public static void optionMessage(Player player, IOption<?> option) {
player.displayClientMessage( player.displayClientMessage(
new TranslatableComponent(option.getKeyTranslation()).withStyle(ChatFormatting.AQUA) Component.translatable(option.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(new TranslatableComponent(option.getValueTranslation()).withStyle(ChatFormatting.WHITE)) .append(Component.translatable(option.getValueTranslation()).withStyle(ChatFormatting.WHITE))
.append(new TextComponent(" - ").withStyle(ChatFormatting.GRAY)) .append(Component.literal(" - ").withStyle(ChatFormatting.GRAY))
.append(new TranslatableComponent(option.getDescTranslation()).withStyle(ChatFormatting.WHITE)) .append(Component.translatable(option.getDescTranslation()).withStyle(ChatFormatting.WHITE))
, true); , true);
} }

View file

@ -16,7 +16,6 @@ import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.ModStats; import thetadev.constructionwand.basics.ModStats;
import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.items.ModItems;
import thetadev.constructionwand.items.wand.ItemWand; import thetadev.constructionwand.items.wand.ItemWand;
@ -119,7 +118,7 @@ public class WandJob
// Play place sound // Play place sound
if(!placeSnapshots.isEmpty()) { if(!placeSnapshots.isEmpty()) {
SoundType sound = placeSnapshots.get(0).getBlockState().getSoundType(); SoundType sound = placeSnapshots.get(0).getBlockState().getSoundType();
world.playSound(null, WandUtil.playerPos(player), sound.getPlaceSound(), SoundSource.BLOCKS, sound.volume, sound.pitch); world.playSound(null, player.blockPosition(), sound.getPlaceSound(), SoundSource.BLOCKS, sound.volume, sound.pitch);
// Add to job history for undo // Add to job history for undo
ConstructionWand.instance.undoHistory.add(player, world, placeSnapshots); ConstructionWand.instance.undoHistory.add(player, world, placeSnapshots);

View file

@ -6,6 +6,8 @@ import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.Property;
@ -98,7 +100,7 @@ public class PlaceSnapshot implements ISnapshot
// Can block be placed? // Can block be placed?
BlockState blockState = item.getBlock().getStateForPlacement(ctx); BlockState blockState = item.getBlock().getStateForPlacement(ctx);
if(blockState == null || !blockState.canSurvive(world, pos)) return null; if(blockState == null) return null;
// Forbidden Tile Entity? // Forbidden Tile Entity?
if(!WandUtil.isTEAllowed(blockState)) return null; if(!WandUtil.isTEAllowed(blockState)) return null;
@ -106,6 +108,11 @@ public class PlaceSnapshot implements ISnapshot
// No entities colliding? // No entities colliding?
if(WandUtil.entitiesCollidingWithBlock(world, blockState, pos)) return null; if(WandUtil.entitiesCollidingWithBlock(world, blockState, pos)) return null;
// Adjust blockstate to neighbors
// TODO: verify that
blockState = Block.updateFromNeighbourShapes(blockState, world, pos);
if(blockState.getBlock() == Blocks.AIR || !blockState.canSurvive(world, pos)) return null;
// Copy block properties from supporting block // Copy block properties from supporting block
if(targetMode && supportingBlock != null) { if(targetMode && supportingBlock != null) {
// Block properties to be copied (alignment/rotation properties) // Block properties to be copied (alignment/rotation properties)

View file

@ -11,7 +11,6 @@ import net.minecraft.world.level.Level;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.network.PacketDistributor;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.network.PacketUndoBlocks; import thetadev.constructionwand.network.PacketUndoBlocks;
import java.util.*; import java.util.*;
@ -142,7 +141,7 @@ public class UndoHistory
// Play teleport sound // Play teleport sound
SoundEvent sound = SoundEvents.CHORUS_FRUIT_TELEPORT; SoundEvent sound = SoundEvents.CHORUS_FRUIT_TELEPORT;
world.playSound(null, WandUtil.playerPos(player), sound, SoundSource.PLAYERS, 1.0F, 1.0F); world.playSound(null, player.blockPosition(), sound, SoundSource.PLAYERS, 1.0F, 1.0F);
return true; return true;
} }

View file

@ -1,5 +1,5 @@
modLoader = "javafml" modLoader = "javafml"
loaderVersion = "[38,)" loaderVersion = "[41,)"
license = "MIT License" license = "MIT License"
[[mods]] [[mods]]
modId="constructionwand" modId="constructionwand"
@ -20,12 +20,12 @@ This is my first minecraft mod. May the odds be ever in your favor.
[[dependencies.constructionwand]] [[dependencies.constructionwand]]
modId="forge" modId="forge"
mandatory = true mandatory = true
versionRange = "[38,)" versionRange = "[41,)"
ordering = "NONE" ordering = "NONE"
side="BOTH" side="BOTH"
[[dependencies.constructionwand]] [[dependencies.constructionwand]]
modId="minecraft" modId="minecraft"
mandatory = true mandatory = true
versionRange = "[1.18, 1.19)" versionRange = "[1.19, 1.20)"
ordering = "NONE" ordering = "NONE"
side="BOTH" side="BOTH"

View file

@ -1,70 +0,0 @@
{
"item.constructionwand.stone_wand": "Taş Asa",
"item.constructionwand.iron_wand": "Demir Asa",
"item.constructionwand.diamond_wand": "Elmas Asa",
"item.constructionwand.infinity_wand": "Sonsuzluk Asası",
"item.constructionwand.core_angel": "Melek Asa Çekirdeği",
"item.constructionwand.core_destruction": "Yıkım Asa Çekirdeği",
"constructionwand.tooltip.blocks": "Maks. %d blok",
"constructionwand.tooltip.shift": "[SHIFT] bas",
"constructionwand.tooltip.cores": "Asa çekirdekleri:",
"constructionwand.tooltip.core_tip": "Çekirdeği asanızla birlikte üretim ızgarasında birleştirin",
"constructionwand.option.cores": "",
"constructionwand.option.cores.constructionwand:default": "İnşa Çekirdeği",
"constructionwand.option.cores.constructionwand:default.desc": "Yapınızın size bakan tarafını uzatır",
"constructionwand.option.cores.constructionwand:core_angel": "§6Melek Çekirdeği",
"constructionwand.option.cores.constructionwand:core_angel.desc": "Blokların arkasına ve havaya yerleştirir",
"constructionwand.option.cores.constructionwand:core_destruction": "§cYıkım Çekirdeği",
"constructionwand.option.cores.constructionwand:core_destruction.desc": "Size bakan taraftaki blokları yok eder",
"constructionwand.option.lock": "Sınırlama: ",
"constructionwand.option.lock.horizontal": "§aSol/Sağ",
"constructionwand.option.lock.horizontal.desc": "Orijinal bloğun önüne yatay bir sütun oluşturur",
"constructionwand.option.lock.vertical": "§aYukarı/Aşağı",
"constructionwand.option.lock.vertical.desc": "Orijinal bloğun önünde dikey bir sütun oluşturur",
"constructionwand.option.lock.northsouth": "§6Kuzey/Güney",
"constructionwand.option.lock.northsouth.desc": "Orijinal bloğun üstüne K/G yönünde bir sıra oluşturun",
"constructionwand.option.lock.eastwest": "§6Doğu/Batı",
"constructionwand.option.lock.eastwest.desc": "Orijinal bloğun üstüne D/B yönünde bir sıra oluşturur",
"constructionwand.option.lock.nolock": "§cYok",
"constructionwand.option.lock.nolock.desc": "Orijinal bloğun herhangi bir tarafından uzatır",
"constructionwand.option.direction": "Yön: ",
"constructionwand.option.direction.target": "§6Hedef",
"constructionwand.option.direction.target.desc": "Blokları hedef blokla aynı yönde yerleştirir",
"constructionwand.option.direction.player": "§aOyuncu",
"constructionwand.option.direction.player.desc": "Blokları oyuncuya bakacak şekilde yerleştirir",
"constructionwand.option.replace": "Değiştirme: ",
"constructionwand.option.replace.yes": "§aEvet",
"constructionwand.option.replace.yes.desc": "Sıvılar, kar ve uzun otlar gibi belirli blokları değiştirir",
"constructionwand.option.replace.no": "§cHayır",
"constructionwand.option.replace.no.desc": "Blokları değiştirmez",
"constructionwand.option.match": "Eşleşen: ",
"constructionwand.option.match.exact": "§aAynı",
"constructionwand.option.match.exact.desc": "Yalnızca tamamen aynı olan blokları uzatır",
"constructionwand.option.match.similar": "§6Benzer",
"constructionwand.option.match.similar.desc": "Benzer bloklara (toprak/çimen türleri) eşit davranır",
"constructionwand.option.match.any": "§cHerhangi",
"constructionwand.option.match.any.desc": "Herhangi bir bloğu uzatır",
"constructionwand.option.random": "Rastgele: ",
"constructionwand.option.random.yes": "§aEvet",
"constructionwand.option.random.yes.desc": "Hotbar'ınızdan rastgele bloklar yerleştirir",
"constructionwand.option.random.no": "§cHayır",
"constructionwand.option.random.no.desc": "Yerleştirilen blokları rastgeleleştirmez",
"constructionwand.description.wand": "%1$s, bir yapının size bakan tarafına en fazla %2$d blok yerleştirebilir ve %3$s dayanıklılığı vardır.\n\n%5$s tuşunu basılı tutun ve yerleştirme sınırlamasını değiştirmek için kaydırın (Yatay, Dikey, Kuzey/Güney, Doğu/Batı, Kilitsiz).\n\n%6$s§9+Sağ tıklama ile seçenek ekranınıın§0.\n\n§5§nGERİ ALMA§0§r\nBir bloğa bakarken §9Eğil+§0%4$s tuşunu basılı tuttuğunuzda, yerleştirdiğiniz son bloklar, çevresinde yeşil bir çerçeveyle gösterilecektir. §9Eğil+§0%4$s§9+Bunlardan herhangi birine sağ tıklama§0 işlemi geri alacak ve tüm öğeleri size geri verecektir. Yıkım çekirdeğini kullandıysanız blokları geri koyacaktır.\n\n§5§nKONTEYNERLER§0§r\nShulker kutuları, paketler ve diğer modlardan birçok konteyner, asa için yapı taşları sağlar.\n\n§5§nBOŞTAKİ EL ÖNCELİĞݧ0§r\nBoştaki elinizde blok olduğunda, baktığınız blok yerine boştaki elinizdekini yerleştirirsiniz.",
"constructionwand.description.durability.limited": "%d blok için",
"constructionwand.description.durability.unlimited": "sonsuza kadar",
"constructionwand.description.key.sneak": "Eğil",
"constructionwand.description.key.sneak_opt": "Eğil+%s",
"constructionwand.description.core": "§5§nKURULUM§0§r\nTakmak için yeni çekirdeğinizi asanızla birlikte bir üretim ızgarasına koyun. Çekirdekler arasında geçiş yapmak için %s tuşunu basılı tutun ve asanızla boş alana sol tıklayın veya seçenek ekranını kullanın",
"constructionwand.description.core_angel": "Melek çekirdeği, karşı karşıya olduğunuz bloğun (veya blok sırasının) karşı tarafına bir blok yerleştirir. Maksimum mesafe asa seviyesine bağlıdır. Havada bir blok yerleştirmek için boş alana sağ tıklayın. Bunu yapmak için, yerleştirmek istediğiniz bloğu boştaki elinize almalısınız.",
"constructionwand.description.core_destruction": "Yıkım çekirdeği, size bakan taraftaki blokları (tile entities haricinde) yok eder. Maksimum blok sayısı asa seviyesine bağlıdır. Yok edilen bloklar boşluğa kaybolur, hata yaptıysanız geri alma özelliğini kullanabilirsiniz.",
"stat.constructionwand.use_wand": "Asa kullanılarak yerleştirilen bloklar"
}

View file

@ -1,6 +1,8 @@
{ {
"pack": { "pack": {
"description": "ConstructionWand resources", "description": "ConstructionWand resources",
"pack_format": 8 "pack_format": 9,
"forge:resource_pack_format": 9,
"forge:data_pack_format": 10
} }
} }