diff --git a/.gitignore b/.gitignore index faba627..aa70068 100644 --- a/.gitignore +++ b/.gitignore @@ -24,5 +24,4 @@ run # Files from Forge MDK forge*changelog.txt -.cache -logs \ No newline at end of file +.cache \ No newline at end of file diff --git a/LICENSE b/LICENSE deleted file mode 100644 index b33b4c3..0000000 --- a/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -Copyright (c) 2021 ThetaDev -MIT LICENSE - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index a1263e3..c50c77f 100644 --- a/README.md +++ b/README.md @@ -1,134 +1,53 @@ # Construction Wand +With a Construction Wand you can place multiple blocks (up to 1024) at once, extending your build on the side you're facing. +Sneak+Right click to activate angel mode which allows you to place a block at the opposite side of the block facing you. +If you concentrate enough, you can even conjure a block in mid air! -With a Construction Wand you can place multiple blocks (up to 1024) at once, extending your build on the side you're -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. - -![](images/wands.png) - -**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) -instructions. +![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/wands.png) ## Wands +There are basic wands made from stone, iron and diamond and the Infinity wand. -There are basic wands made from stone, iron and diamond and the Infinity wand. Wands from higher tiers are more powerful -and last longer. These properties can be changed in the config. - -| Wand | Durability | Max. Blocks | Upgradeable | Angel distance | Max. Blocks (Destroy) | -|----------|-------------|-------------|-------------|----------------|-----------------------| -| Stone | 131 | 9 | No | - | - | -| Iron | 250 | 27 | Yes | 1 | 9 | -| Diamond | 1561 | 128 | Yes | 4 | 25 | -| Infinity | Unbreakable | 1024 | Yes | 8 | 81 | +| Wand | Durability | Max. Blocks | Angel distance | +|----------|-------------|-------------|----------------| +| Stone | 131 | 9 | No angel mode | +| Iron | 250 | 27 | 1 | +| Diamond | 1561 | 128 | 4 | +| Infinity | Unbreakable | 1024 | 8 | ## Crafting -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting1.png) -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting2.png) -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting3.png) -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting4.png) -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting5.png) -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.16.2/images/crafting6.png) +![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/crafting1.png) +![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/crafting2.png) +![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/crafting3.png) +![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/crafting4.png) -## Keybindings +## Modes +There are four wand tiers: Stone, Iron, Diamond and Infinity. -To change a wand's core and options or undo your placement you need to hold down the wand option key -(refered as OPTKEY). By default, this is CTRL, but it can be changed in the client config file. To prevent unwanted -changes to your options, you can configure that you have to hold down SNEAK as well to change options or open up the -GUI. +**Default mode:** Extends your build on the side facing you. Maximum number of blocks depends on wand tier. SHIFT+scroll to change the placement mode (Horizontal, Vertical, North/South, East/West, No lock). -## Wand cores - -Wand cores are magical gemstones that make your wand do its thing. - -Every wand comes with a Construction core. You can make your wand even better by putting -aditional cores into it. Put your new core together with your wand in a -crafting grid to install it. To switch between cores, hold down OPTKEY and left click empty space -with your wand. -Stone wands can't be upgraded. - -**Construction core** - -Extend your build on the side facing you. Maximum number of blocks depends on wand tier. -Hold down OPTKEY and scroll to change placement restriction -(Horizontal, Vertical, North/South, East/West, No lock). - -**Angel core** - -Place a block on the opposite side of the block (or row of blocks) you are facing. Maximum distance depends -on wand tier. Right click empty space to place a block in midair (similar to angel blocks, hence the name). -To do that, you'll need to have the block you want to place in your offhand. You can't place a block in midair -if you've fallen more than 10 blocks deep (no easy rescue tool from falling into the void). - -**Destruction core** - -Destroy blocks (no tile entities) on the side facing you. Maximum number of blocks depends on wand tier. -Restrictions work just like with the Construction core. Destroyed blocks disappear into the void, -you can use the undo feature if you've made a mistake. +**Angel mode:** Places a block on the opposite side of the block (or row of blocks) you are facing. Maximum distance depends on wand tier. Right click empty space to place a block in midair (similar to angel blocks, hence the name). To do that, you'll need to have the block you want to place in your offhand. You can't place a block in midair if you've fallen more than 10 blocks deep (no easy rescue tool from falling into the void). ## Options -SNEAK+OPTKEY+Right clicking empty space opens the option screen of your wand. +**Direction lock:** To change the direction lock, hold down SHIFT and scroll. With active direction lock 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). If the direction lock is switched off, the wand will extend the entire face of the building it's pointed at. This option has no effect in Angel mode. -![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/options.png) +Every wand has two additional options that can be changed using keys. (Standard: N / SHIFT+N) -**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). -If the direction lock is switched off, the wand will extend the entire face of the building it's pointed at. This option -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. -Target mode places the blocks in the same direction as their supporting block. See the picture below: +**Placement 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: ![](https://raw.githubusercontent.com/Theta-Dev/ConstructionWand/1.15/images/placedir.png) -**Replacement:** Enables/disables the replacement of replaceable blocks (Fluids, snow, tallgrass). - -**Matching:** Select which blocks are extended by the wand. If set to "EXACT" it will only extend blocks that -are exactly the same as the selected block.
-"SIMILAR" will treat similar blocks equally (e.g. extend dirt and grass blocks).
-"ANY" will extend any block on the face of the building you're looking at. - -**Random:** If random mode is enabled, the wand places random blocks from your hotbar.
-~~Shamelessly stolen~~ Inspired by the Trowel from Quark. - -## Undo - -Holding down Sneak+OPTKEY while looking at a block will show you the last blocks you placed with a green border around -them. Sneak+OPTKEY+Right clicking any of them will undo the operation, giving you all the items back. If you used the -Destruction core, it will restore the blocks. +**Replacement:** Enables/disables the replacement of replaceable blocks (snow, tallgrass and fluids). ## Additional features +- If you have shulker boxes in your inventory filled with blocks, the wand can pull them out and place them -- Shulker boxes, bundles (MC 1.17+) and many containers from other mods can provide building blocks for the wand +- Botania compatibility: The Black Hole Talisman can supply blocks just like shulker boxes can. Having a Rod of the Lands / Rod of the Depths in your inventory will provide you with infinite dirt/cobble at the cost of Mana. -- Botania compatibility: The Black Hole Talisman can supply blocks just like shulker boxes can. Having a Rod of the - Lands / Rod of the Depths in your inventory will provide you with infinite dirt/cobble at the cost of Mana. +- Holding down SHIFT+CTRL while looking at a blocks will show you the last blocks you placed with a green border around them. SHIFT+CTRL+Right clickking any of them will undo the operation, giving you all the items back. - Having blocks in your offhand will place them instead of the block you're looking at - Look at your statisics to see how many blocks you have placed using your wand -- **1.16+ only:** The Infinity Wand won't burn in lava just like netherite gear. - -- Ingame documentation with Just Enough Items (JEI) - -## TileEntity Blacklist - -Some modded TileEntitys can cause issues when placed using a wand. They may turn into invisible and -unremovable ghost blocks, become unbreakable or cause other unwanted effects. - -That's why I've included a Black/Whitelist system -for TileEntities in CW Version 1.7. Chisels&Bits blocks are blacklisted by default. -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 -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) -and making a PR. - -## Contributions and #Hacktoberfest - -As #Hacktoberfest now requires repo owners to opt in, I added the tag to this repository. - -I'd really appreciate translations. Currently, ConstructionWand is available in English, German and Swedish. -If you speak any other language you can help translate the mod and add a new language file -under `src/main/resources/assets/constructionwand/lang/`. +- **1.16 only:** The Infinity Wand won't burn in lava just like netherite gear. diff --git a/build.gradle b/build.gradle index 546e606..f3f91d4 100644 --- a/build.gradle +++ b/build.gradle @@ -1,10 +1,11 @@ buildscript { repositories { - maven { url = 'https://maven.minecraftforge.net' } + maven { url = 'https://files.minecraftforge.net/maven' } + jcenter() mavenCentral() } dependencies { - classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '3.+', changing: true } } apply plugin: 'net.minecraftforge.gradle' @@ -12,15 +13,25 @@ apply plugin: 'net.minecraftforge.gradle' apply plugin: 'eclipse' apply plugin: 'maven-publish' -version = "${mcversion}-${version_major}.${version_minor}" -group = "${author}.${modid}" -archivesBaseName = "${modid}" +version = '1.14-1.2' +group = 'thetadev.constructionwand' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'constructionwand' -java.toolchain.languageVersion = JavaLanguageVersion.of(17) +sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly. minecraft { - mappings channel: project.mcp_channel, version: project.mcp_mappings + // The mappings can be changed at any time, and must be in the following format. + // snapshot_YYYYMMDD Snapshot are built nightly. + // stable_# Stables are built at the discretion of the MCP team. + // Use non-default mappings at your own risk. they may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'snapshot', version: '20190719-1.14.3' + // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable. + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. runs { client { workingDirectory project.file("run/client").canonicalPath @@ -88,39 +99,27 @@ repositories { maven { url = "https://maven.theillusivec4.top/" } - maven { - name = "JEI Maven" - url "https://dvs1.progwml6.com/files/maven" - } } dependencies { - minecraft([ - group : "net.minecraftforge", - name : "forge", - version: "${project.mcversion}-${project.forgeversion}" - ]) + minecraft 'net.minecraftforge:forge:1.14.4-28.2.23' - compileOnly fg.deobf("mezz.jei:${jei_version}:api") - runtimeOnly fg.deobf("mezz.jei:${jei_version}") + runtimeOnly fg.deobf("vazkii.patchouli:Patchouli:1.14.4-1.1-25.135") + runtimeOnly fg.deobf("top.theillusivec4.curios:curios:FORGE-1.14.4-1.0.6.1") - compileOnly fg.deobf([ - group: "vazkii.botania", - name: "Botania", - version: "${project.botania}", - classifier: "api" - ]) + compileOnly fg.deobf("vazkii.botania:Botania:r1.11-379.354:api") + runtimeOnly fg.deobf("vazkii.botania:Botania:r1.11-379.354") } jar { manifest { attributes([ "Specification-Title": archivesBaseName, - "Specification-Vendor": "${author}", + "Specification-Vendor": "thetadev", "Specification-Version": "1", // We are version 1 of ourselves "Implementation-Title": archivesBaseName, "Implementation-Version": "${version}", - "Implementation-Vendor" :"${author}", + "Implementation-Vendor" : "thetadev", "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") ]) } diff --git a/gradle.properties b/gradle.properties index 1d83096..878bf1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,18 +1,4 @@ +# Sets default memory used for gradle commands. Can be overridden by user or command line properties. +# This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false - -author=thetadev -modid=constructionwand - -mcversion=1.18.1 -forgeversion=39.1.0 -mcp_channel=official -mcp_mappings=1.18.1 - -# Source: https://maven.blamejared.com/vazkii/botania/Botania/ -botania=1.18.1-429 -# Source: https://dvs1.progwml6.com/files/maven/mezz/jei/ -jei_version=jei-1.18.1:9.1.0.41 - -version_major=2 -version_minor=11 \ No newline at end of file +org.gradle.daemon=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 7454180..7a3265e 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e750102..1d5b29f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-bin.zip diff --git a/gradlew b/gradlew index 744e882..cccdd3d 100644 --- a/gradlew +++ b/gradlew @@ -1,21 +1,5 @@ #!/usr/bin/env sh -# -# Copyright 2015 the original author or 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 @@ -44,7 +28,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +DEFAULT_JVM_OPTS="" # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -72,7 +56,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MSYS* | MINGW* ) + MINGW* ) msys=true ;; NONSTOP* ) @@ -82,7 +66,6 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar - # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -126,11 +109,10 @@ 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 +# 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 @@ -156,19 +138,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then else eval `echo args$i`="\"$arg\"" fi - i=`expr $i + 1` + 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" ;; + (0) set -- ;; + (1) set -- "$args0" ;; + (2) set -- "$args0" "$args1" ;; + (3) set -- "$args0" "$args1" "$args2" ;; + (4) set -- "$args0" "$args1" "$args2" "$args3" ;; + (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -177,9 +159,14 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=`save "$@"` +APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong +if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then + cd "$(dirname "$0")" +fi + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index 107acd3..f955316 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,19 +1,3 @@ -@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 @rem ########################################################################## @rem @@ -29,18 +13,15 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 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. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" +set DEFAULT_JVM_OPTS= @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if "%ERRORLEVEL%" == "0" goto init echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +35,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto execute +if exist "%JAVA_EXE%" goto init echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,14 +45,28 @@ echo location of your Java installation. goto fail +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% :end @rem End local scope for the variables with windows NT shell diff --git a/images/crafting5.png b/images/crafting5.png deleted file mode 100644 index 8b51b86..0000000 Binary files a/images/crafting5.png and /dev/null differ diff --git a/images/crafting6.png b/images/crafting6.png deleted file mode 100644 index f9bc286..0000000 Binary files a/images/crafting6.png and /dev/null differ diff --git a/images/options.png b/images/options.png deleted file mode 100644 index 9adb38b..0000000 Binary files a/images/options.png and /dev/null differ diff --git a/images/textures/core_angel.png b/images/textures/core_angel.png deleted file mode 100644 index 4869087..0000000 Binary files a/images/textures/core_angel.png and /dev/null differ diff --git a/images/textures/core_destruction.png b/images/textures/core_destruction.png deleted file mode 100644 index 987968a..0000000 Binary files a/images/textures/core_destruction.png and /dev/null differ diff --git a/images/textures/core_overlay.png b/images/textures/core_overlay.png deleted file mode 100644 index b70e745..0000000 Binary files a/images/textures/core_overlay.png and /dev/null differ diff --git a/images/textures/diamond_wand.xcf b/images/textures/diamond_wand.xcf index 297d55e..0281a91 100644 Binary files a/images/textures/diamond_wand.xcf and b/images/textures/diamond_wand.xcf differ diff --git a/images/textures/wand_core.xcf b/images/textures/wand_core.xcf deleted file mode 100644 index 01f206b..0000000 Binary files a/images/textures/wand_core.xcf and /dev/null differ diff --git a/images/textures_old/ConstructionWand.xcf b/images/textures_old/ConstructionWand.xcf new file mode 100644 index 0000000..6fe835e Binary files /dev/null and b/images/textures_old/ConstructionWand.xcf differ diff --git a/images/textures_old/diamond_wand.png b/images/textures_old/diamond_wand.png new file mode 100644 index 0000000..1059b8f Binary files /dev/null and b/images/textures_old/diamond_wand.png differ diff --git a/images/textures_old/infinity_wand.png b/images/textures_old/infinity_wand.png new file mode 100644 index 0000000..fd04119 Binary files /dev/null and b/images/textures_old/infinity_wand.png differ diff --git a/images/textures_old/iron_wand.png b/images/textures_old/iron_wand.png new file mode 100644 index 0000000..c8c93d6 Binary files /dev/null and b/images/textures_old/iron_wand.png differ diff --git a/images/textures_old/stone_wand.png b/images/textures_old/stone_wand.png new file mode 100644 index 0000000..9bd11ea Binary files /dev/null and b/images/textures_old/stone_wand.png differ diff --git a/src/generated/resources/assets/constructionwand/models/item/core_angel.json b/src/generated/resources/assets/constructionwand/models/item/core_angel.json deleted file mode 100644 index 8dd551e..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/core_angel.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "constructionwand:item/core_angel" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/core_destruction.json b/src/generated/resources/assets/constructionwand/models/item/core_destruction.json deleted file mode 100644 index e47d329..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/core_destruction.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "parent": "minecraft:item/generated", - "textures": { - "layer0": "constructionwand:item/core_destruction" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/diamond_wand.json b/src/generated/resources/assets/constructionwand/models/item/diamond_wand.json deleted file mode 100644 index e9d1d77..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/diamond_wand.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/diamond_wand" - }, - "overrides": [ - { - "predicate": { - "constructionwand:using_core": 1.0 - }, - "model": "constructionwand:item/diamond_wand_core" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/diamond_wand_core.json b/src/generated/resources/assets/constructionwand/models/item/diamond_wand_core.json deleted file mode 100644 index e762bfb..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/diamond_wand_core.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/diamond_wand", - "layer1": "constructionwand:item/overlay_core" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/infinity_wand.json b/src/generated/resources/assets/constructionwand/models/item/infinity_wand.json deleted file mode 100644 index 9edbd2d..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/infinity_wand.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/infinity_wand" - }, - "overrides": [ - { - "predicate": { - "constructionwand:using_core": 1.0 - }, - "model": "constructionwand:item/infinity_wand_core" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/infinity_wand_core.json b/src/generated/resources/assets/constructionwand/models/item/infinity_wand_core.json deleted file mode 100644 index c16345c..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/infinity_wand_core.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/infinity_wand", - "layer1": "constructionwand:item/overlay_core" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/iron_wand.json b/src/generated/resources/assets/constructionwand/models/item/iron_wand.json deleted file mode 100644 index 71e224d..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/iron_wand.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/iron_wand" - }, - "overrides": [ - { - "predicate": { - "constructionwand:using_core": 1.0 - }, - "model": "constructionwand:item/iron_wand_core" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/iron_wand_core.json b/src/generated/resources/assets/constructionwand/models/item/iron_wand_core.json deleted file mode 100644 index 6533e05..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/iron_wand_core.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/iron_wand", - "layer1": "constructionwand:item/overlay_core" - } -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/stone_wand.json b/src/generated/resources/assets/constructionwand/models/item/stone_wand.json deleted file mode 100644 index 6958a75..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/stone_wand.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/stone_wand" - }, - "overrides": [ - { - "predicate": { - "constructionwand:using_core": 1.0 - }, - "model": "constructionwand:item/stone_wand_core" - } - ] -} \ No newline at end of file diff --git a/src/generated/resources/assets/constructionwand/models/item/stone_wand_core.json b/src/generated/resources/assets/constructionwand/models/item/stone_wand_core.json deleted file mode 100644 index 18f0d78..0000000 --- a/src/generated/resources/assets/constructionwand/models/item/stone_wand_core.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "parent": "minecraft:item/handheld", - "textures": { - "layer0": "constructionwand:item/stone_wand", - "layer1": "constructionwand:item/overlay_core" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/constructionwand/advancements/recipes/misc/core_angel.json b/src/generated/resources/data/constructionwand/advancements/recipes/misc/core_angel.json deleted file mode 100644 index b6be2fb..0000000 --- a/src/generated/resources/data/constructionwand/advancements/recipes/misc/core_angel.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "rewards": { - "recipes": [ - "constructionwand:core_angel" - ] - }, - "criteria": { - "has_item": { - "trigger": "minecraft:inventory_changed", - "conditions": { - "items": [ - { - "tag": "forge:feathers" - } - ] - } - }, - "has_the_recipe": { - "trigger": "minecraft:recipe_unlocked", - "conditions": { - "recipe": "constructionwand:core_angel" - } - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/constructionwand/advancements/recipes/misc/core_destruction.json b/src/generated/resources/data/constructionwand/advancements/recipes/misc/core_destruction.json deleted file mode 100644 index 0fee178..0000000 --- a/src/generated/resources/data/constructionwand/advancements/recipes/misc/core_destruction.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "parent": "minecraft:recipes/root", - "rewards": { - "recipes": [ - "constructionwand:core_destruction" - ] - }, - "criteria": { - "has_item": { - "trigger": "minecraft:inventory_changed", - "conditions": { - "items": [ - { - "tag": "forge:storage_blocks/diamond" - } - ] - } - }, - "has_the_recipe": { - "trigger": "minecraft:recipe_unlocked", - "conditions": { - "recipe": "constructionwand:core_destruction" - } - } - }, - "requirements": [ - [ - "has_item", - "has_the_recipe" - ] - ] -} \ No newline at end of file diff --git a/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json b/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json index c31aa4d..5b07428 100644 --- a/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json +++ b/src/generated/resources/data/constructionwand/advancements/recipes/tools/stone_wand.json @@ -11,7 +11,7 @@ "conditions": { "items": [ { - "tag": "minecraft:stone_tool_materials" + "tag": "forge:cobblestone" } ] } diff --git a/src/generated/resources/data/constructionwand/recipes/core_angel.json b/src/generated/resources/data/constructionwand/recipes/core_angel.json deleted file mode 100644 index a501405..0000000 --- a/src/generated/resources/data/constructionwand/recipes/core_angel.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "pattern": [ - " #X", - "#O#", - "X# " - ], - "key": { - "O": { - "tag": "forge:feathers" - }, - "X": { - "tag": "forge:ingots/gold" - }, - "#": { - "tag": "forge:glass_panes" - } - }, - "result": { - "item": "constructionwand:core_angel" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/constructionwand/recipes/core_destruction.json b/src/generated/resources/data/constructionwand/recipes/core_destruction.json deleted file mode 100644 index 2dff73c..0000000 --- a/src/generated/resources/data/constructionwand/recipes/core_destruction.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "type": "minecraft:crafting_shaped", - "pattern": [ - " #X", - "#O#", - "X# " - ], - "key": { - "O": { - "tag": "forge:storage_blocks/diamond" - }, - "X": { - "item": "minecraft:diamond_pickaxe" - }, - "#": { - "tag": "forge:glass_panes" - } - }, - "result": { - "item": "constructionwand:core_destruction" - } -} \ No newline at end of file diff --git a/src/generated/resources/data/constructionwand/recipes/dynamic/wand_upgrade.json b/src/generated/resources/data/constructionwand/recipes/dynamic/wand_upgrade.json deleted file mode 100644 index e164828..0000000 --- a/src/generated/resources/data/constructionwand/recipes/dynamic/wand_upgrade.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "constructionwand:wand_upgrade" -} \ No newline at end of file diff --git a/src/generated/resources/data/constructionwand/recipes/stone_wand.json b/src/generated/resources/data/constructionwand/recipes/stone_wand.json index b4448d5..114881e 100644 --- a/src/generated/resources/data/constructionwand/recipes/stone_wand.json +++ b/src/generated/resources/data/constructionwand/recipes/stone_wand.json @@ -7,7 +7,7 @@ ], "key": { "X": { - "tag": "minecraft:stone_tool_materials" + "tag": "forge:cobblestone" }, "#": { "tag": "forge:rods/wooden" diff --git a/src/main/java/thetadev/constructionwand/ConstructionWand.java b/src/main/java/thetadev/constructionwand/ConstructionWand.java index c5b9f76..370ebcf 100644 --- a/src/main/java/thetadev/constructionwand/ConstructionWand.java +++ b/src/main/java/thetadev/constructionwand/ConstructionWand.java @@ -1,6 +1,6 @@ package thetadev.constructionwand; -import net.minecraft.resources.ResourceLocation; +import net.minecraft.util.ResourceLocation; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.common.Mod; @@ -8,89 +8,72 @@ import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; +import net.minecraftforge.fml.network.NetworkRegistry; +import net.minecraftforge.fml.network.simple.SimpleChannel; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import thetadev.constructionwand.basics.ConfigClient; -import thetadev.constructionwand.basics.ConfigServer; +import thetadev.constructionwand.basics.ConfigHandler; import thetadev.constructionwand.basics.ModStats; -import thetadev.constructionwand.basics.ReplacementRegistry; -import thetadev.constructionwand.client.ClientEvents; +import thetadev.constructionwand.client.KeyEvents; import thetadev.constructionwand.client.RenderBlockPreview; import thetadev.constructionwand.containers.ContainerManager; import thetadev.constructionwand.containers.ContainerRegistrar; -import thetadev.constructionwand.items.ModItems; +import thetadev.constructionwand.job.JobHistory; import thetadev.constructionwand.network.PacketQueryUndo; import thetadev.constructionwand.network.PacketUndoBlocks; import thetadev.constructionwand.network.PacketWandOption; -import thetadev.constructionwand.wand.undo.UndoHistory; @Mod(ConstructionWand.MODID) public class ConstructionWand { public static final String MODID = "constructionwand"; - public static final String MODNAME = "ConstructionWand"; - public static ConstructionWand instance; public static final Logger LOGGER = LogManager.getLogger(); private static final String PROTOCOL_VERSION = "1"; public SimpleChannel HANDLER; public ContainerManager containerManager; - public UndoHistory undoHistory; + public JobHistory jobHistory; public RenderBlockPreview renderBlockPreview; public ConstructionWand() { instance = this; containerManager = new ContainerManager(); - undoHistory = new UndoHistory(); + jobHistory = new JobHistory(); // Register setup methods for modloading FMLJavaModLoadingContext.get().getModEventBus().addListener(this::commonSetup); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); MinecraftForge.EVENT_BUS.register(this); - // Register Item DeferredRegister - ModItems.ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus()); - // Config setup - ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ConfigServer.SPEC); - ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigClient.SPEC); + ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ConfigHandler.SPEC, MODID + ".toml"); } - private void commonSetup(final FMLCommonSetupEvent event) { + private void commonSetup(final FMLCommonSetupEvent event) + { LOGGER.info("ConstructionWand says hello - may the odds be ever in your favor."); // Register packets - HANDLER = NetworkRegistry.newSimpleChannel(new ResourceLocation(MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals); + HANDLER = NetworkRegistry.newSimpleChannel(new ResourceLocation(MODID, "main"), ()->PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals); int packetIndex = 0; HANDLER.registerMessage(packetIndex++, PacketUndoBlocks.class, PacketUndoBlocks::encode, PacketUndoBlocks::decode, PacketUndoBlocks.Handler::handle); HANDLER.registerMessage(packetIndex++, PacketQueryUndo.class, PacketQueryUndo::encode, PacketQueryUndo::decode, PacketQueryUndo.Handler::handle); - HANDLER.registerMessage(packetIndex, PacketWandOption.class, PacketWandOption::encode, PacketWandOption::decode, PacketWandOption.Handler::handle); + HANDLER.registerMessage(packetIndex++, PacketWandOption.class, PacketWandOption::encode, PacketWandOption::decode, PacketWandOption.Handler::handle); // Container registry ContainerRegistrar.register(); - //Replacement registry - ReplacementRegistry.init(); - // Stats ModStats.register(); } - private void clientSetup(final FMLClientSetupEvent event) { + private void clientSetup(final FMLClientSetupEvent event) + { renderBlockPreview = new RenderBlockPreview(); MinecraftForge.EVENT_BUS.register(renderBlockPreview); - MinecraftForge.EVENT_BUS.register(new ClientEvents()); - - event.enqueueWork(ModItems::registerModelProperties); - event.enqueueWork(ModItems::registerItemColors); - } - - public static ResourceLocation loc(String name) { - return new ResourceLocation(MODID, name); + MinecraftForge.EVENT_BUS.register(new KeyEvents()); } } diff --git a/src/main/java/thetadev/constructionwand/api/IContainerHandler.java b/src/main/java/thetadev/constructionwand/api/IContainerHandler.java index befd8d5..31006b7 100644 --- a/src/main/java/thetadev/constructionwand/api/IContainerHandler.java +++ b/src/main/java/thetadev/constructionwand/api/IContainerHandler.java @@ -1,13 +1,14 @@ package thetadev.constructionwand.api; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +/** + * Created by james on 28/12/16. + */ public interface IContainerHandler { - boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack); - - int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack); - - int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count); + boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack); + int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack); + int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count); } diff --git a/src/main/java/thetadev/constructionwand/api/IWandAction.java b/src/main/java/thetadev/constructionwand/api/IWandAction.java deleted file mode 100644 index beac255..0000000 --- a/src/main/java/thetadev/constructionwand/api/IWandAction.java +++ /dev/null @@ -1,24 +0,0 @@ -package thetadev.constructionwand.api; - -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.wand.undo.ISnapshot; - -import javax.annotation.Nonnull; -import java.util.List; - -public interface IWandAction -{ - int getLimit(ItemStack wand); - - @Nonnull - List getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit); - - @Nonnull - List getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit); -} diff --git a/src/main/java/thetadev/constructionwand/api/IWandCore.java b/src/main/java/thetadev/constructionwand/api/IWandCore.java deleted file mode 100644 index 371d190..0000000 --- a/src/main/java/thetadev/constructionwand/api/IWandCore.java +++ /dev/null @@ -1,8 +0,0 @@ -package thetadev.constructionwand.api; - -public interface IWandCore extends IWandUpgrade -{ - int getColor(); - - IWandAction getWandAction(); -} diff --git a/src/main/java/thetadev/constructionwand/api/IWandSupplier.java b/src/main/java/thetadev/constructionwand/api/IWandSupplier.java deleted file mode 100644 index 8578ba6..0000000 --- a/src/main/java/thetadev/constructionwand/api/IWandSupplier.java +++ /dev/null @@ -1,30 +0,0 @@ -package thetadev.constructionwand.api; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.wand.undo.PlaceSnapshot; - -import javax.annotation.Nullable; - -public interface IWandSupplier -{ - void getSupply(@Nullable BlockItem target); - - /** - * Tries to create a new PlaceSnapshot at the specified position. - * Returns null if there aren't any blocks available that can be placed - * in that position. - */ - @Nullable - PlaceSnapshot getPlaceSnapshot(Level world, BlockPos pos, BlockHitResult rayTraceResult, - @Nullable BlockState supportingBlock); - - /** - * Consumes an item stack if the placement was successful - */ - int takeItemStack(ItemStack stack); -} diff --git a/src/main/java/thetadev/constructionwand/api/IWandUpgrade.java b/src/main/java/thetadev/constructionwand/api/IWandUpgrade.java deleted file mode 100644 index 7aab489..0000000 --- a/src/main/java/thetadev/constructionwand/api/IWandUpgrade.java +++ /dev/null @@ -1,8 +0,0 @@ -package thetadev.constructionwand.api; - -import net.minecraft.resources.ResourceLocation; - -public interface IWandUpgrade -{ - ResourceLocation getRegistryName(); -} diff --git a/src/main/java/thetadev/constructionwand/basics/CommonEvents.java b/src/main/java/thetadev/constructionwand/basics/CommonEvents.java index 77a9071..f248eee 100644 --- a/src/main/java/thetadev/constructionwand/basics/CommonEvents.java +++ b/src/main/java/thetadev/constructionwand/basics/CommonEvents.java @@ -1,6 +1,6 @@ package thetadev.constructionwand.basics; -import net.minecraft.world.entity.player.Player; +import net.minecraft.entity.player.PlayerEntity; import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; @@ -9,10 +9,10 @@ import thetadev.constructionwand.ConstructionWand; @Mod.EventBusSubscriber(modid = ConstructionWand.MODID) public class CommonEvents { - @SubscribeEvent - public static void logOut(PlayerEvent.PlayerLoggedOutEvent e) { - Player player = e.getPlayer(); - if(player.level.isClientSide) return; - ConstructionWand.instance.undoHistory.removePlayer(player); - } + @SubscribeEvent + public static void logOut(PlayerEvent.PlayerLoggedOutEvent e) { + PlayerEntity player = e.getPlayer(); + if(player.getEntityWorld().isRemote) return; + ConstructionWand.instance.jobHistory.removePlayer(player); + } } diff --git a/src/main/java/thetadev/constructionwand/basics/ConfigClient.java b/src/main/java/thetadev/constructionwand/basics/ConfigClient.java deleted file mode 100644 index d623360..0000000 --- a/src/main/java/thetadev/constructionwand/basics/ConfigClient.java +++ /dev/null @@ -1,32 +0,0 @@ -package thetadev.constructionwand.basics; - -import net.minecraftforge.common.ForgeConfigSpec; - -public class ConfigClient -{ - private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); - - public static final ForgeConfigSpec.IntValue OPT_KEY; - public static final ForgeConfigSpec.BooleanValue SHIFTOPT_MODE; - public static final ForgeConfigSpec.BooleanValue SHIFTOPT_GUI; - - static { - BUILDER.comment("This is the Client config for ConstructionWand.", - "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.", - "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", - "new worlds, copy the config files in the /defaultconfigs folder."); - - BUILDER.push("keys"); - BUILDER.comment("Key code of OPTKEY (Default: Left Control). Look up key codes under https://www.glfw.org/docs/3.3/group__keys.html"); - OPT_KEY = BUILDER.defineInRange("OptKey", 341, 0, 350); - BUILDER.comment("Press SNEAK+OPTKEY instead of SNEAK for changing wand mode/direction lock"); - SHIFTOPT_MODE = BUILDER.define("ShiftOpt", false); - BUILDER.comment("Press SNEAK+OPTKEY instead of SNEAK for opening wand GUI"); - SHIFTOPT_GUI = BUILDER.define("ShiftOptGUI", true); - BUILDER.pop(); - } - - public static final ForgeConfigSpec SPEC = BUILDER.build(); -} diff --git a/src/main/java/thetadev/constructionwand/basics/ConfigHandler.java b/src/main/java/thetadev/constructionwand/basics/ConfigHandler.java new file mode 100644 index 0000000..91c05fa --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/ConfigHandler.java @@ -0,0 +1,69 @@ +package thetadev.constructionwand.basics; + +import net.minecraft.item.Item; +import net.minecraft.item.ItemTier; +import net.minecraft.item.Items; +import net.minecraftforge.common.ForgeConfigSpec; + +import java.util.Arrays; +import java.util.List; + +public class ConfigHandler +{ + private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); + + // Durability + public static final ForgeConfigSpec.IntValue DURABILITY_STONE; + public static final ForgeConfigSpec.IntValue DURABILITY_IRON; + public static final ForgeConfigSpec.IntValue DURABILITY_DIAMOND; + + public static final ForgeConfigSpec.IntValue LIMIT_STONE; + public static final ForgeConfigSpec.IntValue LIMIT_IRON; + public static final ForgeConfigSpec.IntValue LIMIT_DIAMOND; + public static final ForgeConfigSpec.IntValue LIMIT_INFINITY; + public static final ForgeConfigSpec.IntValue LIMIT_CREATIVE; + + public static final ForgeConfigSpec.IntValue ANGEL_STONE; + public static final ForgeConfigSpec.IntValue ANGEL_IRON; + public static final ForgeConfigSpec.IntValue ANGEL_DIAMOND; + public static final ForgeConfigSpec.IntValue ANGEL_INFINITY; + + public static final ForgeConfigSpec.IntValue UNDO_HISTORY; + public static final ForgeConfigSpec.BooleanValue ANGEL_FALLING; + + static { + BUILDER.comment("Wand durability"); + BUILDER.push("durability"); + DURABILITY_STONE = BUILDER.defineInRange("StoneWand", ItemTier.STONE.getMaxUses(), 1, Integer.MAX_VALUE); + DURABILITY_IRON = BUILDER.defineInRange("IronWand", ItemTier.IRON.getMaxUses(), 1, Integer.MAX_VALUE); + DURABILITY_DIAMOND = BUILDER.defineInRange("DiamondWand", ItemTier.DIAMOND.getMaxUses(), 1, Integer.MAX_VALUE); + BUILDER.pop(); + + BUILDER.comment("Wand block limit"); + BUILDER.push("block_limit"); + LIMIT_STONE = BUILDER.defineInRange("StoneWand", 9, 1, Integer.MAX_VALUE); + LIMIT_IRON = BUILDER.defineInRange("IronWand", 27, 1, Integer.MAX_VALUE); + LIMIT_DIAMOND = BUILDER.defineInRange("DiamondWand", 128, 1, Integer.MAX_VALUE); + LIMIT_INFINITY = BUILDER.defineInRange("InfinityWand", 1024, 1, Integer.MAX_VALUE); + BUILDER.comment("Infinity Wand used in creative mode"); + LIMIT_CREATIVE = BUILDER.defineInRange("InfinityWandCreative", 2048, 1, Integer.MAX_VALUE); + BUILDER.pop(); + + BUILDER.comment("Max placement distance with angel mode (0 to disable angel mode)"); + BUILDER.push("angel_distance"); + ANGEL_STONE = BUILDER.defineInRange("StoneWand", 0, 0, Integer.MAX_VALUE); + ANGEL_IRON = BUILDER.defineInRange("IronWand", 1, 0, Integer.MAX_VALUE); + ANGEL_DIAMOND = BUILDER.defineInRange("DiamondWand", 4, 0, Integer.MAX_VALUE); + ANGEL_INFINITY = BUILDER.defineInRange("InfinityWand", 8, 0, Integer.MAX_VALUE); + BUILDER.pop(); + + BUILDER.push("misc"); + BUILDER.comment("Number of operations that can be undone"); + UNDO_HISTORY = BUILDER.defineInRange("UndoHistory", 3, 0, Integer.MAX_VALUE); + BUILDER.comment("Place blocks below you while falling > 10 blocks with angel mode (Can be used to save you from drops/the void)"); + ANGEL_FALLING = BUILDER.define("AngelFalling", false); + BUILDER.pop(); + } + + public static final ForgeConfigSpec SPEC = BUILDER.build(); +} diff --git a/src/main/java/thetadev/constructionwand/basics/ConfigServer.java b/src/main/java/thetadev/constructionwand/basics/ConfigServer.java deleted file mode 100644 index 6fc0de9..0000000 --- a/src/main/java/thetadev/constructionwand/basics/ConfigServer.java +++ /dev/null @@ -1,138 +0,0 @@ -package thetadev.constructionwand.basics; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Tiers; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.registries.RegistryObject; -import thetadev.constructionwand.items.ModItems; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; - -public class ConfigServer -{ - private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); - - public static final ForgeConfigSpec.IntValue LIMIT_CREATIVE; - public static final ForgeConfigSpec.IntValue MAX_RANGE; - public static final ForgeConfigSpec.IntValue UNDO_HISTORY; - public static final ForgeConfigSpec.BooleanValue ANGEL_FALLING; - - public static final ForgeConfigSpec.ConfigValue> SIMILAR_BLOCKS; - private static final String[] SIMILAR_BLOCKS_DEFAULT = { - "minecraft:dirt;minecraft:grass_block;minecraft:coarse_dirt;minecraft:podzol;minecraft:mycelium;minecraft:farmland;minecraft:dirt_path;minecraft:rooted_dirt" - }; - - public static final ForgeConfigSpec.BooleanValue TE_WHITELIST; - public static final ForgeConfigSpec.ConfigValue> TE_LIST; - private static final String[] TE_LIST_DEFAULT = {"chiselsandbits"}; - - private static final HashMap wandProperties = new HashMap<>(); - - public static WandProperties getWandProperties(Item wand) { - return wandProperties.getOrDefault(wand.getRegistryName(), WandProperties.DEFAULT); - } - - public static class WandProperties - { - public static final WandProperties DEFAULT = new WandProperties(null, null, null, null, null); - - private final ForgeConfigSpec.IntValue durability; - private final ForgeConfigSpec.IntValue limit; - private final ForgeConfigSpec.IntValue angel; - private final ForgeConfigSpec.IntValue destruction; - private final ForgeConfigSpec.BooleanValue upgradeable; - - private WandProperties(ForgeConfigSpec.IntValue durability, ForgeConfigSpec.IntValue limit, - ForgeConfigSpec.IntValue angel, ForgeConfigSpec.IntValue destruction, - ForgeConfigSpec.BooleanValue upgradeable) { - this.durability = durability; - this.limit = limit; - this.angel = angel; - this.destruction = destruction; - this.upgradeable = upgradeable; - } - - public WandProperties(ForgeConfigSpec.Builder builder, RegistryObject wandSupplier, int defDurability, int defLimit, - int defAngel, int defDestruction, boolean defUpgradeable) { - ResourceLocation registryName = wandSupplier.getId(); - builder.push(registryName.getPath()); - - if(defDurability > 0) { - builder.comment("Wand durability"); - durability = builder.defineInRange("durability", defDurability, 1, Integer.MAX_VALUE); - } - else durability = null; - builder.comment("Wand block limit"); - limit = builder.defineInRange("limit", defLimit, 1, Integer.MAX_VALUE); - builder.comment("Max placement distance with angel core (0 to disable angel core)"); - angel = builder.defineInRange("angel", defAngel, 0, Integer.MAX_VALUE); - builder.comment("Wand destruction block limit (0 to disable destruction core)"); - destruction = builder.defineInRange("destruction", defDestruction, 0, Integer.MAX_VALUE); - builder.comment("Allow wand upgrading by putting the wand together with a wand core in a crafting grid."); - upgradeable = builder.define("upgradeable", defUpgradeable); - builder.pop(); - - wandProperties.put(registryName, this); - } - - public int getDurability() { - return durability == null ? -1 : durability.get(); - } - - public int getLimit() { - return limit == null ? 0 : limit.get(); - } - - public int getAngel() { - return angel == null ? 0 : angel.get(); - } - - public int getDestruction() { - return destruction == null ? 0 : destruction.get(); - } - - public boolean isUpgradeable() { - return upgradeable != null && upgradeable.get(); - } - } - - static { - 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:", - "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", - "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 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_DIAMOND, Tiers.DIAMOND.getUses(), 128, 8, 25, true); - new WandProperties(BUILDER, ModItems.WAND_INFINITY, 0, 1024, 16, 81, true); - - BUILDER.push("misc"); - BUILDER.comment("Block limit for Infinity Wand used in creative mode"); - 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."); - MAX_RANGE = BUILDER.defineInRange("MaxRange", 100, 0, Integer.MAX_VALUE); - BUILDER.comment("Number of operations that can be undone"); - 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)"); - ANGEL_FALLING = BUILDER.define("AngelFalling", false); - 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); - BUILDER.pop(); - - BUILDER.push("tileentity"); - 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"); - 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"); - TE_WHITELIST = BUILDER.define("TEWhitelist", false); - BUILDER.pop(); - } - - public static final ForgeConfigSpec SPEC = BUILDER.build(); -} diff --git a/src/main/java/thetadev/constructionwand/basics/ModStats.java b/src/main/java/thetadev/constructionwand/basics/ModStats.java index ccfa739..e37e587 100644 --- a/src/main/java/thetadev/constructionwand/basics/ModStats.java +++ b/src/main/java/thetadev/constructionwand/basics/ModStats.java @@ -1,22 +1,22 @@ package thetadev.constructionwand.basics; -import net.minecraft.core.Registry; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.stats.StatFormatter; +import net.minecraft.stats.IStatFormatter; import net.minecraft.stats.Stats; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.registry.Registry; import thetadev.constructionwand.ConstructionWand; public class ModStats { - public static final ResourceLocation USE_WAND = new ResourceLocation(ConstructionWand.MODID, "use_wand"); + public static final ResourceLocation USE_WAND = new ResourceLocation(ConstructionWand.MODID, "use_wand"); - public static void register() { - registerStat(USE_WAND); - } + public static void register() { + registerStat(USE_WAND); + } - private static void registerStat(ResourceLocation registryName) { - // Compare with net.minecraft.stats.Stats#registerCustom - Registry.register(Registry.CUSTOM_STAT, registryName.getPath(), registryName); - Stats.CUSTOM.get(registryName, StatFormatter.DEFAULT); - } + private static void registerStat(ResourceLocation registryName) { + // Compare with net.minecraft.stats.Stats#registerCustom + Registry.register(Registry.CUSTOM_STAT, registryName.getPath(), registryName); + Stats.CUSTOM.get(registryName, IStatFormatter.DEFAULT); + } } diff --git a/src/main/java/thetadev/constructionwand/basics/ReplacementRegistry.java b/src/main/java/thetadev/constructionwand/basics/ReplacementRegistry.java deleted file mode 100644 index 3677d09..0000000 --- a/src/main/java/thetadev/constructionwand/basics/ReplacementRegistry.java +++ /dev/null @@ -1,54 +0,0 @@ -package thetadev.constructionwand.basics; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraftforge.registries.ForgeRegistries; -import thetadev.constructionwand.ConstructionWand; - -import java.util.HashSet; -import java.util.Set; - -public class ReplacementRegistry -{ - private static final HashSet> replacements = new HashSet<>(); - - public static void init() { - for(Object key : ConfigServer.SIMILAR_BLOCKS.get()) { - if(!(key instanceof String)) continue; - HashSet set = new HashSet<>(); - - for(String id : ((String) key).split(";")) { - Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(id)); - if(item == null || item == Items.AIR) { - ConstructionWand.LOGGER.warn("Replacement Registry: Could not find item " + id); - continue; - } - set.add(item); - } - if(!set.isEmpty()) replacements.add(set); - } - } - - public static Set getMatchingSet(Item item) { - HashSet res = new HashSet<>(); - - for(HashSet set : replacements) { - if(set.contains(item)) res.addAll(set); - } - res.remove(item); - return res; - } - - public static boolean matchBlocks(Block b1, Block b2) { - if(b1 == b2) return true; - if(b1 == Blocks.AIR || b2 == Blocks.AIR) return false; - - for(HashSet set : replacements) { - if(set.contains(b1.asItem()) && set.contains(b2.asItem())) return true; - } - return false; - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/WandUtil.java b/src/main/java/thetadev/constructionwand/basics/WandUtil.java index aa98cbe..c4e05a1 100644 --- a/src/main/java/thetadev/constructionwand/basics/WandUtil.java +++ b/src/main/java/thetadev/constructionwand/basics/WandUtil.java @@ -1,233 +1,46 @@ package thetadev.constructionwand.basics; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import net.minecraft.world.phys.shapes.VoxelShape; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.util.BlockSnapshot; -import net.minecraftforge.event.world.BlockEvent; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.containers.ContainerManager; -import thetadev.constructionwand.items.wand.ItemWand; -import thetadev.constructionwand.wand.WandItemUseContext; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.function.Predicate; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.tags.ItemTags; +import net.minecraft.util.Hand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import thetadev.constructionwand.basics.options.EnumMode; +import thetadev.constructionwand.basics.options.IEnumOption; +import thetadev.constructionwand.basics.options.WandOptions; +import thetadev.constructionwand.items.ItemWand; +import thetadev.constructionwand.job.ConstructionJob; +import thetadev.constructionwand.job.TransductionJob; +import thetadev.constructionwand.job.WandJob; public class WandUtil { - public static boolean stackEquals(ItemStack stackA, ItemStack stackB) { - return ItemStack.isSameItemSameTags(stackA, stackB); - } + public static boolean stackEquals(ItemStack stackA, ItemStack stackB) { + return ItemStack.areItemsEqual(stackA, stackB) && ItemStack.areItemStackTagsEqual(stackA, stackB); + } - public static boolean stackEquals(ItemStack stackA, Item item) { - ItemStack stackB = new ItemStack(item); - return stackEquals(stackA, stackB); - } + public static boolean stackEquals(ItemStack stackA, Item item) { + ItemStack stackB = new ItemStack(item); + return stackEquals(stackA, stackB); + } - public static ItemStack holdingWand(Player player) { - if(player.getItemInHand(InteractionHand.MAIN_HAND) != ItemStack.EMPTY && player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof ItemWand) { - return player.getItemInHand(InteractionHand.MAIN_HAND); - } - else if(player.getItemInHand(InteractionHand.OFF_HAND) != ItemStack.EMPTY && player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof ItemWand) { - return player.getItemInHand(InteractionHand.OFF_HAND); - } - return null; - } + public static ItemStack holdingWand(PlayerEntity player) { + if(player.getHeldItem(Hand.MAIN_HAND) != ItemStack.EMPTY && player.getHeldItem(Hand.MAIN_HAND).getItem() instanceof ItemWand) { + return player.getHeldItem(Hand.MAIN_HAND); + } + else if(player.getHeldItem(Hand.OFF_HAND) != ItemStack.EMPTY && player.getHeldItem(Hand.OFF_HAND).getItem() instanceof ItemWand) { + return player.getHeldItem(Hand.OFF_HAND); + } + return null; + } - public static BlockPos playerPos(Player player) { - return new BlockPos(player.position()); - } - - public static Vec3 entityPositionVec(Entity entity) { - return new Vec3(entity.getX(), entity.getY() - entity.getMyRidingOffset() + entity.getBbHeight() / 2, entity.getZ()); - } - - public static Vec3 blockPosVec(BlockPos pos) { - return new Vec3(pos.getX(), pos.getY(), pos.getZ()); - } - - public static List getHotbar(Player player) { - return player.getInventory().items.subList(0, 9); - } - - public static List getHotbarWithOffhand(Player player) { - ArrayList inventory = new ArrayList<>(player.getInventory().items.subList(0, 9)); - inventory.addAll(player.getInventory().offhand); - return inventory; - } - - public static List getMainInv(Player player) { - return player.getInventory().items.subList(9, player.getInventory().items.size()); - } - - public static List getFullInv(Player player) { - ArrayList inventory = new ArrayList<>(player.getInventory().offhand); - inventory.addAll(player.getInventory().items); - return inventory; - } - - public static int blockDistance(BlockPos p1, BlockPos p2) { - return Math.max(Math.abs(p1.getX() - p2.getX()), Math.abs(p1.getZ() - p2.getZ())); - } - - public static boolean isTEAllowed(BlockState state) { - if(!state.hasBlockEntity()) return true; - - ResourceLocation name = state.getBlock().getRegistryName(); - if(name == null) return false; - - String fullId = name.toString(); - String modId = name.getNamespace(); - - boolean inList = ConfigServer.TE_LIST.get().contains(fullId) || ConfigServer.TE_LIST.get().contains(modId); - boolean isWhitelist = ConfigServer.TE_WHITELIST.get(); - - return isWhitelist == inList; - } - - public static boolean placeBlock(Level world, Player player, BlockState block, BlockPos pos, @Nullable BlockItem item) { - if(!world.setBlockAndUpdate(pos, block)) { - ConstructionWand.LOGGER.info("Block could not be placed"); - return false; - } - - // Remove block if placeEvent is canceled - BlockSnapshot snapshot = BlockSnapshot.create(world.dimension(), world, pos); - BlockEvent.EntityPlaceEvent placeEvent = new BlockEvent.EntityPlaceEvent(snapshot, block, player); - MinecraftForge.EVENT_BUS.post(placeEvent); - if(placeEvent.isCanceled()) { - world.removeBlock(pos, false); - return false; - } - - ItemStack stack; - if(item == null) stack = new ItemStack(block.getBlock().asItem()); - else { - stack = new ItemStack(item); - player.awardStat(Stats.ITEM_USED.get(item)); - } - - // Call OnBlockPlaced method - block.getBlock().setPlacedBy(world, pos, block, player, stack); - - return true; - } - - public static boolean removeBlock(Level world, Player player, @Nullable BlockState block, BlockPos pos) { - BlockState currentBlock = world.getBlockState(pos); - - if(!world.mayInteract(player, pos)) return false; - - if(!player.isCreative()) { - if(currentBlock.getDestroySpeed(world, pos) <= -1 || world.getBlockEntity(pos) != null) return false; - - if(block != null) - if(!ReplacementRegistry.matchBlocks(currentBlock.getBlock(), block.getBlock())) return false; - } - - BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(world, pos, currentBlock, player); - MinecraftForge.EVENT_BUS.post(breakEvent); - if(breakEvent.isCanceled()) return false; - - world.removeBlock(pos, false); - return true; - } - - public static int countItem(Player player, Item item) { - if(player.getInventory().items == null) return 0; - if(player.isCreative()) return Integer.MAX_VALUE; - - int total = 0; - ContainerManager containerManager = ConstructionWand.instance.containerManager; - List inventory = WandUtil.getFullInv(player); - - for(ItemStack stack : inventory) { - if(stack == null || stack.isEmpty()) continue; - - if(WandUtil.stackEquals(stack, item)) { - total += stack.getCount(); - } - else { - int amount = containerManager.countItems(player, new ItemStack(item), stack); - if(amount == Integer.MAX_VALUE) return Integer.MAX_VALUE; - total += amount; - } - } - return total; - } - - private static boolean isPositionModifiable(Level world, Player player, BlockPos pos) { - // Is position out of world? - if(!world.isInWorldBounds(pos)) return false; - - // Is block modifiable? - if(!world.mayInteract(player, pos)) return false; - - // Limit range - if(ConfigServer.MAX_RANGE.get() > 0 && - WandUtil.blockDistance(player.blockPosition(), pos) > ConfigServer.MAX_RANGE.get()) return false; - - return true; - } - - /** - * Tests if a wand can place a block at a certain position. - * This check is independent of the used block. - */ - public static boolean isPositionPlaceable(Level world, Player player, BlockPos pos, boolean replace) { - if(!isPositionModifiable(world, player, pos)) return false; - - // If replace mode is off, target has to be air - if(world.isEmptyBlock(pos)) return true; - - // Otherwise, check if the block can be replaced by a generic block - return replace && world.getBlockState(pos).canBeReplaced( - new WandItemUseContext(world, player, - new BlockHitResult(new Vec3(0, 0, 0), Direction.DOWN, pos, false), - pos, (BlockItem) Items.STONE)); - } - - public static boolean isBlockRemovable(Level world, Player player, BlockPos pos) { - if(!isPositionModifiable(world, player, pos)) return false; - - if(!player.isCreative()) { - return !(world.getBlockState(pos).getDestroySpeed(world, pos) <= -1) && world.getBlockEntity(pos) == null; - } - return true; - } - - public static boolean isBlockPermeable(Level world, BlockPos pos) { - return world.isEmptyBlock(pos) || world.getBlockState(pos).getCollisionShape(world, pos).isEmpty(); - } - - public static boolean entitiesCollidingWithBlock(Level world, BlockState blockState, BlockPos pos) { - VoxelShape shape = blockState.getCollisionShape(world, pos); - if(!shape.isEmpty()) { - AABB blockBB = shape.bounds().move(pos); - return !world.getEntitiesOfClass(LivingEntity.class, blockBB, Predicate.not(Entity::isSpectator)).isEmpty(); - } - return false; - } - - public static Direction fromVector(Vec3 vector) { - return Direction.getNearest(vector.x, vector.y, vector.z); - } + public static Vec3d entityPositionVec(Entity entity) { + return new Vec3d(entity.posX, entity.posY - entity.getYOffset() + entity.getHeight()/2, entity.posZ); + } } diff --git a/src/main/java/thetadev/constructionwand/basics/option/IOption.java b/src/main/java/thetadev/constructionwand/basics/option/IOption.java deleted file mode 100644 index e35365e..0000000 --- a/src/main/java/thetadev/constructionwand/basics/option/IOption.java +++ /dev/null @@ -1,36 +0,0 @@ -package thetadev.constructionwand.basics.option; - -import thetadev.constructionwand.ConstructionWand; - -public interface IOption -{ - String getKey(); - - String getValueString(); - - void setValueString(String val); - - default String getKeyTranslation() { - return ConstructionWand.MODID + ".option." + getKey(); - } - - default String getValueTranslation() { - return ConstructionWand.MODID + ".option." + getKey() + "." + getValueString(); - } - - default String getDescTranslation() { - return ConstructionWand.MODID + ".option." + getKey() + "." + getValueString() + ".desc"; - } - - boolean isEnabled(); - - void set(T val); - - T get(); - - T next(boolean dir); - - default T next() { - return next(true); - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/option/OptionBoolean.java b/src/main/java/thetadev/constructionwand/basics/option/OptionBoolean.java deleted file mode 100644 index 6823509..0000000 --- a/src/main/java/thetadev/constructionwand/basics/option/OptionBoolean.java +++ /dev/null @@ -1,62 +0,0 @@ -package thetadev.constructionwand.basics.option; - -import net.minecraft.nbt.CompoundTag; - -public class OptionBoolean implements IOption -{ - private final CompoundTag tag; - private final String key; - private final boolean enabled; - private boolean value; - - public OptionBoolean(CompoundTag tag, String key, boolean dval, boolean enabled) { - this.tag = tag; - this.key = key; - this.enabled = enabled; - - if(tag.contains(key)) value = tag.getBoolean(key); - else value = dval; - } - - public OptionBoolean(CompoundTag tag, String key, boolean dval) { - this(tag, key, dval, true); - } - - @Override - public String getKey() { - return key; - } - - @Override - public String getValueString() { - return value ? "yes" : "no"; - } - - @Override - public void setValueString(String val) { - set(val.equals("yes")); - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void set(Boolean val) { - if(!enabled) return; - value = val; - tag.putBoolean(key, value); - } - - @Override - public Boolean get() { - return value; - } - - @Override - public Boolean next(boolean dir) { - set(!value); - return value; - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/option/OptionEnum.java b/src/main/java/thetadev/constructionwand/basics/option/OptionEnum.java deleted file mode 100644 index 5c79dcd..0000000 --- a/src/main/java/thetadev/constructionwand/basics/option/OptionEnum.java +++ /dev/null @@ -1,69 +0,0 @@ -package thetadev.constructionwand.basics.option; - -import com.google.common.base.Enums; -import net.minecraft.nbt.CompoundTag; - -public class OptionEnum> implements IOption -{ - private final CompoundTag tag; - private final String key; - private final Class enumClass; - private final boolean enabled; - private final E dval; - private E value; - - public OptionEnum(CompoundTag tag, String key, Class enumClass, E dval, boolean enabled) { - this.tag = tag; - this.key = key; - this.enumClass = enumClass; - this.enabled = enabled; - this.dval = dval; - - value = Enums.getIfPresent(enumClass, tag.getString(key).toUpperCase()).or(dval); - } - - public OptionEnum(CompoundTag tag, String key, Class enumClass, E dval) { - this(tag, key, enumClass, dval, true); - } - - @Override - public String getKey() { - return key; - } - - @Override - public String getValueString() { - return value.name().toLowerCase(); - } - - @Override - public void setValueString(String val) { - set(Enums.getIfPresent(enumClass, val.toUpperCase()).or(dval)); - } - - @Override - public boolean isEnabled() { - return enabled; - } - - @Override - public void set(E val) { - if(!enabled) return; - value = val; - tag.putString(key, getValueString()); - } - - @Override - public E get() { - return value; - } - - @Override - public E next(boolean dir) { - E[] enumValues = enumClass.getEnumConstants(); - int i = value.ordinal() + (dir ? 1 : -1); - if(i < 0) i += enumValues.length; - set(enumValues[i % enumValues.length]); - return value; - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java b/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java deleted file mode 100644 index 2a9b39e..0000000 --- a/src/main/java/thetadev/constructionwand/basics/option/WandOptions.java +++ /dev/null @@ -1,100 +0,0 @@ -package thetadev.constructionwand.basics.option; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import thetadev.constructionwand.api.IWandCore; -import thetadev.constructionwand.api.IWandUpgrade; -import thetadev.constructionwand.basics.ReplacementRegistry; -import thetadev.constructionwand.items.core.CoreDefault; - -import javax.annotation.Nullable; - -public class WandOptions -{ - public final CompoundTag tag; - - private static final String TAG_ROOT = "wand_options"; - - public enum LOCK - { - HORIZONTAL, - VERTICAL, - NORTHSOUTH, - EASTWEST, - NOLOCK - } - - public enum DIRECTION - { - TARGET, - PLAYER - } - - public enum MATCH - { - EXACT, - SIMILAR, - ANY - } - - public final WandUpgradesSelectable cores; - - public final OptionEnum lock; - public final OptionEnum direction; - public final OptionBoolean replace; - public final OptionEnum match; - public final OptionBoolean random; - - public final IOption[] allOptions; - - public WandOptions(ItemStack wandStack) { - tag = wandStack.getOrCreateTagElement(TAG_ROOT); - - cores = new WandUpgradesSelectable<>(tag, "cores", new CoreDefault()); - - lock = new OptionEnum<>(tag, "lock", LOCK.class, LOCK.NOLOCK); - direction = new OptionEnum<>(tag, "direction", DIRECTION.class, DIRECTION.TARGET); - replace = new OptionBoolean(tag, "replace", true); - match = new OptionEnum<>(tag, "match", MATCH.class, MATCH.SIMILAR); - random = new OptionBoolean(tag, "random", false); - - allOptions = new IOption[]{cores, lock, direction, replace, match, random}; - } - - @Nullable - public IOption get(String key) { - for(IOption option : allOptions) { - if(option.getKey().equals(key)) return option; - } - return null; - } - - public boolean testLock(LOCK l) { - if(lock.get() == LOCK.NOLOCK) return true; - return lock.get() == l; - } - - public boolean matchBlocks(Block b1, Block b2) { - switch(match.get()) { - case EXACT: - return b1 == b2; - case SIMILAR: - return ReplacementRegistry.matchBlocks(b1, b2); - case ANY: - return b1 != Blocks.AIR && b2 != Blocks.AIR; - } - return false; - } - - public boolean hasUpgrade(IWandUpgrade upgrade) { - if(upgrade instanceof IWandCore) return cores.hasUpgrade((IWandCore) upgrade); - return false; - } - - public boolean addUpgrade(IWandUpgrade upgrade) { - if(upgrade instanceof IWandCore) return cores.addUpgrade((IWandCore) upgrade); - return false; - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/option/WandUpgrades.java b/src/main/java/thetadev/constructionwand/basics/option/WandUpgrades.java deleted file mode 100644 index 5b7f83b..0000000 --- a/src/main/java/thetadev/constructionwand/basics/option/WandUpgrades.java +++ /dev/null @@ -1,79 +0,0 @@ -package thetadev.constructionwand.basics.option; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.nbt.Tag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraftforge.registries.ForgeRegistries; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.api.IWandUpgrade; - -import java.util.ArrayList; - -public class WandUpgrades -{ - protected final CompoundTag tag; - protected final String key; - protected final ArrayList upgrades; - protected final T dval; - - public WandUpgrades(CompoundTag tag, String key, T dval) { - this.tag = tag; - this.key = key; - this.dval = dval; - - upgrades = new ArrayList<>(); - if(dval != null) upgrades.add(0, dval); - - deserialize(); - } - - protected void deserialize() { - ListTag listnbt = tag.getList(key, Tag.TAG_STRING); - boolean require_fix = false; - - for(int i = 0; i < listnbt.size(); i++) { - String str = listnbt.getString(i); - Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(str)); - - T data; - try { - //noinspection unchecked - data = (T) item; - upgrades.add(data); - } catch(ClassCastException e) { - ConstructionWand.LOGGER.warn("Invalid wand upgrade: " + str); - require_fix = true; - } - } - if(require_fix) serialize(); - } - - protected void serialize() { - ListTag listnbt = new ListTag(); - - for(T item : upgrades) { - if(item == dval) continue; - listnbt.add(StringTag.valueOf(item.getRegistryName().toString())); - } - tag.put(key, listnbt); - } - - public boolean addUpgrade(T upgrade) { - if(hasUpgrade(upgrade)) return false; - - upgrades.add(upgrade); - serialize(); - return true; - } - - public boolean hasUpgrade(T upgrade) { - return upgrades.contains(upgrade); - } - - public ArrayList getUpgrades() { - return upgrades; - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/option/WandUpgradesSelectable.java b/src/main/java/thetadev/constructionwand/basics/option/WandUpgradesSelectable.java deleted file mode 100644 index 3fec9a6..0000000 --- a/src/main/java/thetadev/constructionwand/basics/option/WandUpgradesSelectable.java +++ /dev/null @@ -1,83 +0,0 @@ -package thetadev.constructionwand.basics.option; - -import net.minecraft.nbt.CompoundTag; -import thetadev.constructionwand.api.IWandUpgrade; - -public class WandUpgradesSelectable extends WandUpgrades implements IOption -{ - private byte selector; - - public WandUpgradesSelectable(CompoundTag tag, String key, T dval) { - super(tag, key, dval); - } - - @Override - public String getKey() { - return key; - } - - @Override - public String getValueString() { - return get().getRegistryName().toString(); - } - - @Override - public void setValueString(String val) { - for(byte i = 0; i < upgrades.size(); i++) { - if(upgrades.get(i).getRegistryName().toString().equals(val)) { - selector = i; - serializeSelector(); - return; - } - } - } - - @Override - public boolean isEnabled() { - return upgrades.size() > 1; - } - - @Override - public void set(T val) { - selector = (byte) upgrades.indexOf(val); - fixSelector(); - serializeSelector(); - } - - @Override - public T get() { - fixSelector(); - return upgrades.get(selector); - } - - @Override - public T next(boolean dir) { - selector++; - fixSelector(); - serializeSelector(); - return get(); - } - - private void fixSelector() { - if(selector < 0 || selector >= upgrades.size()) selector = 0; - } - - @Override - protected void deserialize() { - super.deserialize(); - - selector = tag.getByte(key + "_sel"); - fixSelector(); - } - - @Override - protected void serialize() { - super.serialize(); - - serializeSelector(); - } - - private void serializeSelector() { - tag.putByte(key + "_sel", selector); - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/options/EnumDirection.java b/src/main/java/thetadev/constructionwand/basics/options/EnumDirection.java new file mode 100644 index 0000000..f06d2ac --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/options/EnumDirection.java @@ -0,0 +1,34 @@ +package thetadev.constructionwand.basics.options; + +import com.google.common.base.Enums; + +public enum EnumDirection implements IEnumOption +{ + TARGET, + PLAYER; + + private static EnumDirection[] vals = values(); + + public IEnumOption fromName(String name) { + return Enums.getIfPresent(EnumDirection.class, name.toUpperCase()).or(this); + } + + public EnumDirection next(boolean dir) { + int i = this.ordinal() + (dir ? 1:-1); + if(i < 0) i += vals.length; + + return vals[i % vals.length]; + } + + public int getOrdinal() { + return ordinal(); + } + + public String getOptionKey() { + return "direction"; + } + + public String getValue() { + return this.name().toLowerCase(); + } +} diff --git a/src/main/java/thetadev/constructionwand/basics/options/EnumLock.java b/src/main/java/thetadev/constructionwand/basics/options/EnumLock.java new file mode 100644 index 0000000..3bb7e83 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/options/EnumLock.java @@ -0,0 +1,42 @@ +package thetadev.constructionwand.basics.options; + +import com.google.common.base.Enums; + +public enum EnumLock implements IEnumOption +{ + HORIZONTAL, + VERTICAL, + NORTHSOUTH, + EASTWEST, + NOLOCK; + + private static EnumLock[] vals = values(); + + public IEnumOption fromName(String name) { + return Enums.getIfPresent(EnumLock.class, name.toUpperCase()).or(this); + } + + public EnumLock next(boolean dir) { + int i = this.ordinal() + (dir ? 1:-1); + if(i < 0) i += vals.length; + + return vals[i % vals.length]; + } + + public int getOrdinal() { + return ordinal(); + } + + public String getOptionKey() { + return "lock"; + } + + public String getValue() { + return this.name().toLowerCase(); + } + + public boolean test(EnumLock lock) { + if(this == NOLOCK) return true; + return this == lock; + } +} diff --git a/src/main/java/thetadev/constructionwand/basics/options/EnumMode.java b/src/main/java/thetadev/constructionwand/basics/options/EnumMode.java new file mode 100644 index 0000000..aa6f072 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/options/EnumMode.java @@ -0,0 +1,34 @@ +package thetadev.constructionwand.basics.options; + +import com.google.common.base.Enums; + +public enum EnumMode implements IEnumOption +{ + DEFAULT, + ANGEL; + + private static EnumMode[] vals = values(); + + public IEnumOption fromName(String name) { + return Enums.getIfPresent(EnumMode.class, name.toUpperCase()).or(this); + } + + public EnumMode next(boolean dir) { + int i = this.ordinal() + (dir ? 1:-1); + if(i < 0) i += vals.length; + + return vals[i % vals.length]; + } + + public int getOrdinal() { + return ordinal(); + } + + public String getOptionKey() { + return "mode"; + } + + public String getValue() { + return this.name().toLowerCase(); + } +} diff --git a/src/main/java/thetadev/constructionwand/basics/options/EnumReplace.java b/src/main/java/thetadev/constructionwand/basics/options/EnumReplace.java new file mode 100644 index 0000000..b9e9a10 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/options/EnumReplace.java @@ -0,0 +1,34 @@ +package thetadev.constructionwand.basics.options; + +import com.google.common.base.Enums; + +public enum EnumReplace implements IEnumOption +{ + YES, + NO; + + private static EnumReplace[] vals = values(); + + public IEnumOption fromName(String name) { + return Enums.getIfPresent(EnumReplace.class, name.toUpperCase()).or(this); + } + + public EnumReplace next(boolean dir) { + int i = this.ordinal() + (dir ? 1:-1); + if(i < 0) i += vals.length; + + return vals[i % vals.length]; + } + + public int getOrdinal() { + return ordinal(); + } + + public String getOptionKey() { + return "replace"; + } + + public String getValue() { + return this.name().toLowerCase(); + } +} diff --git a/src/main/java/thetadev/constructionwand/basics/options/IEnumOption.java b/src/main/java/thetadev/constructionwand/basics/options/IEnumOption.java new file mode 100644 index 0000000..8a39b20 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/options/IEnumOption.java @@ -0,0 +1,13 @@ +package thetadev.constructionwand.basics.options; + +public interface IEnumOption +{ + public int getOrdinal(); + public String getOptionKey(); + public String getValue(); + default String getTranslationKey() { + return getOptionKey() + "." + getValue(); + } + public IEnumOption next(boolean dir); + public IEnumOption fromName(String name); +} diff --git a/src/main/java/thetadev/constructionwand/basics/options/WandOptions.java b/src/main/java/thetadev/constructionwand/basics/options/WandOptions.java new file mode 100644 index 0000000..2001eac --- /dev/null +++ b/src/main/java/thetadev/constructionwand/basics/options/WandOptions.java @@ -0,0 +1,44 @@ +package thetadev.constructionwand.basics.options; + +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import thetadev.constructionwand.items.ItemWand; + +public class WandOptions +{ + private ItemWand item; + private CompoundNBT tag; + + private final String TAG_ROOT = "wand_options"; + + public static final IEnumOption[] options = { + EnumMode.DEFAULT, + EnumLock.NOLOCK, + EnumDirection.TARGET, + EnumReplace.YES + }; + + public WandOptions(ItemStack stack) { + this.item = (ItemWand) stack.getItem(); + this.tag = stack.getOrCreateChildTag(TAG_ROOT); + } + + public IEnumOption getOption(IEnumOption option) { + return option.fromName(tag.getString(option.getOptionKey())); + } + + public void setOption(IEnumOption option) { + tag.putString(option.getOptionKey(), option.getValue()); + } + + public IEnumOption nextOption(IEnumOption option, boolean dir) { + IEnumOption nextOption = getOption(option).next(dir); + if(nextOption == EnumMode.ANGEL && item.angelDistance == 0) nextOption = EnumMode.DEFAULT; + setOption(nextOption); + return nextOption; + } + + public IEnumOption nextOption(IEnumOption option) { + return nextOption(option, true); + } +} diff --git a/src/main/java/thetadev/constructionwand/basics/pool/IPool.java b/src/main/java/thetadev/constructionwand/basics/pool/IPool.java deleted file mode 100644 index 3b64df0..0000000 --- a/src/main/java/thetadev/constructionwand/basics/pool/IPool.java +++ /dev/null @@ -1,15 +0,0 @@ -package thetadev.constructionwand.basics.pool; - -import javax.annotation.Nullable; - -public interface IPool -{ - void add(T element); - - void remove(T element); - - @Nullable - T draw(); - - void reset(); -} diff --git a/src/main/java/thetadev/constructionwand/basics/pool/OrderedPool.java b/src/main/java/thetadev/constructionwand/basics/pool/OrderedPool.java deleted file mode 100644 index cf21358..0000000 --- a/src/main/java/thetadev/constructionwand/basics/pool/OrderedPool.java +++ /dev/null @@ -1,39 +0,0 @@ -package thetadev.constructionwand.basics.pool; - -import javax.annotation.Nullable; -import java.util.ArrayList; - -public class OrderedPool implements IPool -{ - private final ArrayList elements; - private int index; - - public OrderedPool() { - elements = new ArrayList<>(); - reset(); - } - - @Override - public void add(T element) { - elements.add(element); - } - - @Override - public void remove(T element) { - elements.remove(element); - } - - @Nullable - @Override - public T draw() { - if(index >= elements.size()) return null; - T e = elements.get(index); - index++; - return e; - } - - @Override - public void reset() { - index = 0; - } -} diff --git a/src/main/java/thetadev/constructionwand/basics/pool/RandomPool.java b/src/main/java/thetadev/constructionwand/basics/pool/RandomPool.java deleted file mode 100644 index 8e80d9d..0000000 --- a/src/main/java/thetadev/constructionwand/basics/pool/RandomPool.java +++ /dev/null @@ -1,60 +0,0 @@ -package thetadev.constructionwand.basics.pool; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Random; - -public class RandomPool implements IPool -{ - private final Random rng; - private final HashMap elements; - private HashSet pool; - - public RandomPool(Random rng) { - this.rng = rng; - elements = new HashMap<>(); - reset(); - } - - @Override - public void add(T element) { - addWithWeight(element, 1); - } - - @Override - public void remove(T element) { - elements.remove(element); - pool.remove(element); - } - - public void addWithWeight(T element, int weight) { - if(weight < 1) return; - elements.merge(element, weight, Integer::sum); - pool.add(element); - } - - @Nullable - @Override - public T draw() { - int allWeights = pool.stream().reduce(0, (partialRes, e) -> partialRes + elements.get(e), Integer::sum); - if(allWeights < 1) return null; - - int random = rng.nextInt(allWeights); - int accWeight = 0; - - for(T e : pool) { - accWeight += elements.get(e); - if(random < accWeight) { - pool.remove(e); - return e; - } - } - return null; - } - - @Override - public void reset() { - pool = new HashSet<>(elements.keySet()); - } -} diff --git a/src/main/java/thetadev/constructionwand/client/ClientEvents.java b/src/main/java/thetadev/constructionwand/client/ClientEvents.java deleted file mode 100644 index a92bca2..0000000 --- a/src/main/java/thetadev/constructionwand/client/ClientEvents.java +++ /dev/null @@ -1,105 +0,0 @@ -package thetadev.constructionwand.client; - -import com.mojang.blaze3d.platform.InputConstants; -import net.minecraft.client.Minecraft; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.client.event.InputEvent; -import net.minecraftforge.event.entity.player.PlayerInteractEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.basics.ConfigClient; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.items.wand.ItemWand; -import thetadev.constructionwand.network.PacketQueryUndo; -import thetadev.constructionwand.network.PacketWandOption; - -public class ClientEvents -{ - private boolean optPressed; - - public ClientEvents() { - optPressed = false; - } - - // Send state of OPT key to server - @SubscribeEvent - public void KeyEvent(InputEvent.KeyInputEvent event) { - Player player = Minecraft.getInstance().player; - if(player == null) return; - if(WandUtil.holdingWand(player) == null) return; - - boolean optState = isOptKeyDown(); - if(optPressed != optState) { - optPressed = optState; - PacketQueryUndo packet = new PacketQueryUndo(optPressed); - ConstructionWand.instance.HANDLER.sendToServer(packet); - //ConstructionWand.LOGGER.debug("OPT key update: " + optPressed); - } - } - - // Sneak+(OPT)+Scroll to change direction lock - @SubscribeEvent(priority = EventPriority.HIGHEST) - public void MouseScrollEvent(InputEvent.MouseScrollEvent event) { - Player player = Minecraft.getInstance().player; - double scroll = event.getScrollDelta(); - - if(player == null || !modeKeyCombDown(player) || scroll == 0) return; - - ItemStack wand = WandUtil.holdingWand(player); - if(wand == null) return; - - WandOptions wandOptions = new WandOptions(wand); - wandOptions.lock.next(scroll < 0); - ConstructionWand.instance.HANDLER.sendToServer(new PacketWandOption(wandOptions.lock, true)); - event.setCanceled(true); - } - - // Sneak+(OPT)+Left click wand to change core - @SubscribeEvent - public void onLeftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) { - Player player = event.getPlayer(); - - if(player == null || !modeKeyCombDown(player)) return; - - ItemStack wand = event.getItemStack(); - if(!(wand.getItem() instanceof ItemWand)) return; - - WandOptions wandOptions = new WandOptions(wand); - wandOptions.cores.next(); - ConstructionWand.instance.HANDLER.sendToServer(new PacketWandOption(wandOptions.cores, true)); - } - - // Sneak+(OPT)+Right click wand to open GUI - @SubscribeEvent - public void onRightClickItem(PlayerInteractEvent.RightClickItem event) { - if(event.getSide().isServer()) return; - - Player player = event.getPlayer(); - if(player == null || !guiKeyCombDown(player)) return; - - ItemStack wand = event.getItemStack(); - if(!(wand.getItem() instanceof ItemWand)) return; - - Minecraft.getInstance().setScreen(new ScreenWand(wand)); - event.setCanceled(true); - } - - private static boolean isKeyDown(int id) { - return InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), id); - } - - public static boolean isOptKeyDown() { - return isKeyDown(ConfigClient.OPT_KEY.get()); - } - - public static boolean modeKeyCombDown(Player player) { - return player.isCrouching() && (isOptKeyDown() || !ConfigClient.SHIFTOPT_MODE.get()); - } - - public static boolean guiKeyCombDown(Player player) { - return player.isCrouching() && (isOptKeyDown() || !ConfigClient.SHIFTOPT_GUI.get()); - } -} diff --git a/src/main/java/thetadev/constructionwand/client/KeyEvents.java b/src/main/java/thetadev/constructionwand/client/KeyEvents.java new file mode 100644 index 0000000..14e2a2b --- /dev/null +++ b/src/main/java/thetadev/constructionwand/client/KeyEvents.java @@ -0,0 +1,88 @@ +package thetadev.constructionwand.client; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +import net.minecraft.client.settings.KeyBinding; +import net.minecraft.client.util.InputMappings; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraftforge.client.event.InputEvent; +import net.minecraftforge.client.event.InputUpdateEvent; +import net.minecraftforge.client.settings.KeyConflictContext; +import net.minecraftforge.client.settings.KeyModifier; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import net.minecraftforge.eventbus.api.EventPriority; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.client.registry.ClientRegistry; +import org.lwjgl.glfw.GLFW; +import thetadev.constructionwand.ConstructionWand; +import thetadev.constructionwand.basics.*; +import thetadev.constructionwand.basics.options.EnumDirection; +import thetadev.constructionwand.basics.options.EnumReplace; +import thetadev.constructionwand.basics.options.EnumLock; +import thetadev.constructionwand.basics.options.IEnumOption; +import thetadev.constructionwand.network.PacketQueryUndo; +import thetadev.constructionwand.network.PacketWandOption; + + +public class KeyEvents +{ + private final String langPrefix = ConstructionWand.MODID + ".key."; + private final String langCategory = langPrefix + "category"; + + public final KeyBinding WAND_KEY = new KeyBinding(langPrefix+"wand", KeyConflictContext.IN_GAME, InputMappings.getInputByCode(GLFW.GLFW_KEY_N, 0), langCategory); + + public static final KeyModifier[] keyModifiers = { + KeyModifier.NONE, + KeyModifier.SHIFT + }; + + public static final IEnumOption[] keyOptions = { + EnumDirection.TARGET, + EnumReplace.YES + }; + + private boolean ctrlPressed; + + public KeyEvents() { + ClientRegistry.registerKeyBinding(WAND_KEY); + ctrlPressed = false; + } + + @SubscribeEvent + public void KeyEvent(InputEvent.KeyInputEvent e) { + PlayerEntity player = Minecraft.getInstance().player; + if(player == null) return; + if(WandUtil.holdingWand(player) == null) return; + + if(WAND_KEY.isPressed()) { + for(int i=0; i undoBlocks; + public WandJob wandJob; + public LinkedList undoBlocks; - @SubscribeEvent - public void renderBlockHighlight(DrawSelectionEvent.HighlightBlock event) { - if(event.getTarget().getType() != HitResult.Type.BLOCK) return; + @SubscribeEvent + public void renderBlockHighlight(DrawBlockHighlightEvent event) + { + if(event.getTarget().getType() != RayTraceResult.Type.BLOCK) return; - BlockHitResult rtr = event.getTarget(); - Entity entity = event.getCamera().getEntity(); - if(!(entity instanceof Player player)) return; - Set blocks; - float colorR = 0, colorG = 0, colorB = 0; + BlockRayTraceResult rtr = (BlockRayTraceResult) event.getTarget(); + Entity entity = event.getInfo().getRenderViewEntity(); + if(!(entity instanceof PlayerEntity)) return; + PlayerEntity player = (PlayerEntity) entity; + LinkedList blocks; + float colorR=0, colorG=0, colorB=0; - ItemStack wand = WandUtil.holdingWand(player); - if(wand == null) return; + ItemStack wand = WandUtil.holdingWand(player); + if(wand == null) return; - if(!(player.isCrouching() && ClientEvents.isOptKeyDown())) { - // Use cached wandJob for previews of the same target pos/dir - // Exception: always update if blockCount < 2 to prevent 1-block previews when block updates - // from the last placement are lagging - if(wandJob == null || !compareRTR(wandJob.rayTraceResult, rtr) || !(wandJob.wand.equals(wand)) - || wandJob.blockCount() < 2) { - wandJob = ItemWand.getWandJob(player, player.level, rtr, wand); - } - blocks = wandJob.getBlockPositions(); - } - else { - blocks = undoBlocks; - colorG = 1; - } + if(!(player.isSneaking() && Screen.hasControlDown())) { + if(wandJob == null || !(wandJob.getRayTraceResult().equals(rtr)) || !(wandJob.getWand().equals(wand))) { + wandJob = WandJob.getJob(player, player.getEntityWorld(), rtr, wand); + } - if(blocks == null || blocks.isEmpty()) return; + blocks = wandJob.getBlockPositions(); + } + else { + blocks = undoBlocks; + colorG = 1; + } - PoseStack ms = event.getPoseStack(); - MultiBufferSource buffer = event.getMultiBufferSource(); - VertexConsumer lineBuilder = buffer.getBuffer(RenderType.LINES); + if(blocks == null || blocks.isEmpty()) return; - double partialTicks = event.getPartialTicks(); - double d0 = player.xOld + (player.getX() - player.xOld) * partialTicks; - double d1 = player.yOld + player.getEyeHeight() + (player.getY() - player.yOld) * partialTicks; - double d2 = player.zOld + (player.getZ() - player.zOld) * partialTicks; + for(BlockPos block : blocks) { - for(BlockPos block : blocks) { - AABB aabb = new AABB(block).move(-d0, -d1, -d2); - LevelRenderer.renderLineBox(ms, lineBuilder, aabb, colorR, colorG, colorB, 0.4F); - } + double partialTicks = event.getPartialTicks(); + double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * partialTicks; + double d1 = player.lastTickPosY + player.getEyeHeight() + (player.posY - player.lastTickPosY) * partialTicks; + double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * partialTicks; - event.setCanceled(true); - } + AxisAlignedBB aabb = new AxisAlignedBB(block).offset(-d0, -d1, -d2); + //WorldRenderer.drawSelectionBoundingBox(aabb, colorR, colorG, colorB, 0.4F); + drawBoundingBox(aabb, colorR, colorG, colorB, 0.4F); + } - private static boolean compareRTR(BlockHitResult rtr1, BlockHitResult rtr2) { - return rtr1.getBlockPos().equals(rtr2.getBlockPos()) && rtr1.getDirection().equals(rtr2.getDirection()); - } + event.setCanceled(true); + } + + private static void drawBoundingBox(AxisAlignedBB box, float red, float green, float blue, float alpha) { + Tessellator tessellator = Tessellator.getInstance(); + BufferBuilder buffer = tessellator.getBuffer(); + buffer.begin(3, DefaultVertexFormats.POSITION_COLOR); + + //Base + buffer.pos(box.minX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + //Side1 + buffer.pos(box.minX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + //Side2 + buffer.pos(box.minX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.maxZ).color(red, green, blue, alpha).endVertex(); + //Side3 + buffer.pos(box.maxX, box.maxY, box.maxZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.maxX, box.minY, box.minZ).color(red, green, blue, alpha).endVertex(); + //Side4 + buffer.pos(box.maxX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + buffer.pos(box.minX, box.maxY, box.minZ).color(red, green, blue, alpha).endVertex(); + + tessellator.draw(); + } } diff --git a/src/main/java/thetadev/constructionwand/client/ScreenWand.java b/src/main/java/thetadev/constructionwand/client/ScreenWand.java deleted file mode 100644 index d665e83..0000000 --- a/src/main/java/thetadev/constructionwand/client/ScreenWand.java +++ /dev/null @@ -1,95 +0,0 @@ -package thetadev.constructionwand.client; - -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.components.Button; -import net.minecraft.client.gui.screens.Screen; -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 thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.basics.option.IOption; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.network.PacketWandOption; - -import javax.annotation.Nonnull; - -public class ScreenWand extends Screen -{ - private final ItemStack wand; - private final WandOptions wandOptions; - - private static final int BUTTON_WIDTH = 160; - private static final int BUTTON_HEIGHT = 20; - private static final int SPACING_WIDTH = 50; - private static final int SPACING_HEIGHT = 30; - private static final int N_COLS = 2; - private static final int N_ROWS = 3; - - private static final int FIELD_WIDTH = N_COLS * (BUTTON_WIDTH + SPACING_WIDTH) - SPACING_WIDTH; - private static final int FIELD_HEIGHT = N_ROWS * (BUTTON_HEIGHT + SPACING_HEIGHT) - SPACING_HEIGHT; - - public ScreenWand(ItemStack wand) { - super(new TextComponent("ScreenWand")); - this.wand = wand; - wandOptions = new WandOptions(wand); - } - - @Override - protected void init() { - createButton(0, 0, wandOptions.cores); - createButton(0, 1, wandOptions.lock); - createButton(0, 2, wandOptions.direction); - createButton(1, 0, wandOptions.replace); - createButton(1, 1, wandOptions.match); - createButton(1, 2, wandOptions.random); - } - - @Override - public void render(@Nonnull PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { - renderBackground(matrixStack); - drawCenteredString(matrixStack, font, wand.getDisplayName(), width / 2, height / 2 - FIELD_HEIGHT / 2 - SPACING_HEIGHT, 16777215); - super.render(matrixStack, mouseX, mouseY, partialTicks); - } - - @Override - public boolean keyPressed(int keyCode, int scanCode, int modifiers) { - if (Minecraft.getInstance().options.keyInventory.matches(keyCode, scanCode)) { - this.onClose(); - return true; - } else { - return super.keyPressed(keyCode, scanCode, modifiers); - } - } - - 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.active = option.isEnabled(); - addRenderableWidget(button); - } - - private void clickButton(Button button, IOption option) { - option.next(); - ConstructionWand.instance.HANDLER.sendToServer(new PacketWandOption(option, false)); - button.setMessage(getButtonLabel(option)); - } - - private void drawTooltip(PoseStack matrixStack, int mouseX, int mouseY, IOption option) { - if(isMouseOver(mouseX, mouseY)) { - renderTooltip(matrixStack, new TranslatableComponent(option.getDescTranslation()), mouseX, mouseY); - } - } - - private int getX(int n) { - return width / 2 - FIELD_WIDTH / 2 + n * (BUTTON_WIDTH + SPACING_WIDTH); - } - - private int getY(int n) { - return height / 2 - FIELD_HEIGHT / 2 + n * (BUTTON_HEIGHT + SPACING_HEIGHT); - } - - private Component getButtonLabel(IOption option) { - return new TranslatableComponent(option.getKeyTranslation()).append(new TranslatableComponent(option.getValueTranslation())); - } -} diff --git a/src/main/java/thetadev/constructionwand/containers/ContainerManager.java b/src/main/java/thetadev/constructionwand/containers/ContainerManager.java index ab2ee9a..d9f10a7 100644 --- a/src/main/java/thetadev/constructionwand/containers/ContainerManager.java +++ b/src/main/java/thetadev/constructionwand/containers/ContainerManager.java @@ -1,38 +1,37 @@ package thetadev.constructionwand.containers; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import thetadev.constructionwand.api.IContainerHandler; import java.util.ArrayList; -public class ContainerManager -{ - private final ArrayList handlers; +public class ContainerManager { + private ArrayList handlers; - public ContainerManager() { - handlers = new ArrayList(); - } + public ContainerManager() { + handlers = new ArrayList(); + } - public boolean register(IContainerHandler handler) { - return handlers.add(handler); - } + public boolean register(IContainerHandler handler) { + return handlers.add(handler); + } - public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { - for(IContainerHandler handler : handlers) { - if(handler.matches(player, itemStack, inventoryStack)) { - return handler.countItems(player, itemStack, inventoryStack); - } - } - return 0; - } + public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) { + for(IContainerHandler handler : handlers) { + if(handler.matches(player, itemStack, inventoryStack)) { + return handler.countItems(player,itemStack, inventoryStack); + } + } + return 0; + } - public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { - for(IContainerHandler handler : handlers) { - if(handler.matches(player, itemStack, inventoryStack)) { - return handler.useItems(player, itemStack, inventoryStack, count); - } - } - return count; - } + public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) { + for(IContainerHandler handler : handlers) { + if(handler.matches(player, itemStack, inventoryStack)) { + return handler.useItems(player, itemStack, inventoryStack, count); + } + } + return count; + } } \ No newline at end of file diff --git a/src/main/java/thetadev/constructionwand/containers/ContainerRegistrar.java b/src/main/java/thetadev/constructionwand/containers/ContainerRegistrar.java index e9e87f6..64c2e6d 100644 --- a/src/main/java/thetadev/constructionwand/containers/ContainerRegistrar.java +++ b/src/main/java/thetadev/constructionwand/containers/ContainerRegistrar.java @@ -2,21 +2,17 @@ package thetadev.constructionwand.containers; import net.minecraftforge.fml.ModList; import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.containers.handlers.HandlerBotania; -import thetadev.constructionwand.containers.handlers.HandlerBundle; -import thetadev.constructionwand.containers.handlers.HandlerCapability; -import thetadev.constructionwand.containers.handlers.HandlerShulkerbox; +import thetadev.constructionwand.containers.handlers.*; public class ContainerRegistrar { - public static void register() { - ConstructionWand.instance.containerManager.register(new HandlerCapability()); - ConstructionWand.instance.containerManager.register(new HandlerShulkerbox()); - ConstructionWand.instance.containerManager.register(new HandlerBundle()); + public static void register() { + ConstructionWand.instance.containerManager.register(new HandlerCapability()); + ConstructionWand.instance.containerManager.register(new HandlerShulkerbox()); - if(ModList.get().isLoaded("botania")) { - ConstructionWand.instance.containerManager.register(new HandlerBotania()); - ConstructionWand.LOGGER.info("Botania integration added"); - } - } + if(ModList.get().isLoaded("botania")) { + ConstructionWand.instance.containerManager.register(new HandlerBotania()); + ConstructionWand.LOGGER.info("Botania integration added"); + } + } } diff --git a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBotania.java b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBotania.java index 8ffb651..359cb67 100644 --- a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBotania.java +++ b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBotania.java @@ -1,41 +1,35 @@ package thetadev.constructionwand.containers.handlers; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; +import net.minecraft.block.Block; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; import thetadev.constructionwand.api.IContainerHandler; -import vazkii.botania.api.BotaniaForgeCapabilities; import vazkii.botania.api.item.IBlockProvider; -import java.util.Optional; - +/** + * Created by james on 28/12/16. + */ public class HandlerBotania implements IContainerHandler { @Override - public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { - return inventoryStack != null && inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).isPresent(); + public boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) { + return inventoryStack != null && inventoryStack.getCount() == 1 && inventoryStack.getItem() instanceof IBlockProvider; } @Override - public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { - Optional provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve(); - if(provOptional.isEmpty()) return 0; - - IBlockProvider prov = provOptional.get(); - int provCount = prov.getBlockCount(player, inventoryStack, Block.byItem(itemStack.getItem())); + public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) { + IBlockProvider prov = (IBlockProvider) inventoryStack.getItem(); + int provCount = prov.getBlockCount(player, itemStack, inventoryStack, Block.getBlockFromItem(itemStack.getItem())); if(provCount == -1) return Integer.MAX_VALUE; return provCount; } @Override - public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { - Optional provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve(); - if(provOptional.isEmpty()) return 0; - - IBlockProvider prov = provOptional.get(); - if(prov.provideBlock(player, inventoryStack, Block.byItem(itemStack.getItem()), true)) + public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) { + IBlockProvider prov = (IBlockProvider) inventoryStack.getItem(); + if(prov.provideBlock(player, itemStack, inventoryStack, Block.getBlockFromItem(itemStack.getItem()), true)) return 0; return count; } -} \ No newline at end of file +} diff --git a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBundle.java b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBundle.java deleted file mode 100644 index 27e5989..0000000 --- a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerBundle.java +++ /dev/null @@ -1,68 +0,0 @@ -package thetadev.constructionwand.containers.handlers; - -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import thetadev.constructionwand.api.IContainerHandler; -import thetadev.constructionwand.basics.WandUtil; - -import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Stream; - -public class HandlerBundle implements IContainerHandler -{ - @Override - public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { - return inventoryStack != null && inventoryStack.getCount() == 1 && inventoryStack.getItem() == Items.BUNDLE; - } - - @Override - public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { - return getContents(inventoryStack).filter((stack) -> WandUtil.stackEquals(stack, itemStack)) - .map(ItemStack::getCount).reduce(0, Integer::sum); - } - - @Override - public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { - AtomicInteger newCount = new AtomicInteger(count); - - List itemStacks = getContents(inventoryStack).filter((stack -> { - if(WandUtil.stackEquals(stack, itemStack)) { - int toTake = Math.min(newCount.get(), stack.getCount()); - stack.shrink(toTake); - newCount.set(newCount.get() - toTake); - } - return !stack.isEmpty(); - })).toList(); - - setItemList(inventoryStack, itemStacks); - - return newCount.get(); - } - - private Stream getContents(ItemStack bundleStack) { - CompoundTag compoundtag = bundleStack.getTag(); - if(compoundtag == null) { - return Stream.empty(); - } - else { - ListTag listtag = compoundtag.getList("Items", 10); - return listtag.stream().map(CompoundTag.class::cast).map(ItemStack::of); - } - } - - private void setItemList(ItemStack itemStack, List itemStacks) { - CompoundTag rootTag = itemStack.getOrCreateTag(); - ListTag listTag = new ListTag(); - rootTag.put("Items", listTag); - - for(ItemStack stack : itemStacks) { - CompoundTag itemTag = new CompoundTag(); - stack.save(itemTag); - listTag.add(itemTag); - } - } -} diff --git a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerCapability.java b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerCapability.java index d67ae0e..aaa08ce 100644 --- a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerCapability.java +++ b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerCapability.java @@ -1,52 +1,61 @@ package thetadev.constructionwand.containers.handlers; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraftforge.common.util.LazyOptional; import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.IItemHandler; import thetadev.constructionwand.api.IContainerHandler; -import thetadev.constructionwand.basics.WandUtil; - -import java.util.Optional; +/** + * Created by james on 28/12/16. + */ public class HandlerCapability implements IContainerHandler { @Override - public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { + public boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) { return inventoryStack != null && inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).isPresent(); } @Override - public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { - Optional itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve(); - if(itemHandlerOptional.isEmpty()) return 0; + public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) { + LazyOptional itemHandlerLazyOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + if(!itemHandlerLazyOptional.isPresent()) return 0; int total = 0; - IItemHandler itemHandler = itemHandlerOptional.get(); + IItemHandler itemHandler = itemHandlerLazyOptional.orElse(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getDefaultInstance()); - for(int i = 0; i < itemHandler.getSlots(); i++) { + for (int i = 0; i < itemHandler.getSlots(); i++) { ItemStack containerStack = itemHandler.getStackInSlot(i); - if(WandUtil.stackEquals(itemStack, containerStack)) { + if (containerStack != null && itemStack.isItemEqual(containerStack)) { total += Math.max(0, containerStack.getCount()); } + + // Already in a container. Don't inception this thing. } return total; } @Override - public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { - Optional itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve(); - if(itemHandlerOptional.isEmpty()) return 0; + public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) { + int toUse = itemStack.getCount(); - IItemHandler itemHandler = itemHandlerOptional.get(); + LazyOptional itemHandlerLazyOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY); + if(!itemHandlerLazyOptional.isPresent()) return 0; - for(int i = 0; i < itemHandler.getSlots(); i++) { + IItemHandler itemHandler = itemHandlerLazyOptional.orElse(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY.getDefaultInstance()); + + for (int i = 0; i < itemHandler.getSlots(); i++) { ItemStack handlerStack = itemHandler.getStackInSlot(i); - if(WandUtil.stackEquals(itemStack, handlerStack)) { + if(handlerStack != null && handlerStack.isItemEqual(itemStack)) { ItemStack extracted = itemHandler.extractItem(i, count, false); - count -= extracted.getCount(); - if(count <= 0) break; + if(extracted != null) { + count -= extracted.getCount(); + } + if(count <= 0) { + break; + } } } return count; diff --git a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerShulkerbox.java b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerShulkerbox.java index c4881bd..86bfad6 100644 --- a/src/main/java/thetadev/constructionwand/containers/handlers/HandlerShulkerbox.java +++ b/src/main/java/thetadev/constructionwand/containers/handlers/HandlerShulkerbox.java @@ -1,75 +1,78 @@ package thetadev.constructionwand.containers.handlers; -import net.minecraft.core.NonNullList; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.Tag; -import net.minecraft.world.ContainerHelper; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.ShulkerBoxBlock; +import net.minecraft.block.Block; +import net.minecraft.block.ShulkerBoxBlock; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.ItemStackHelper; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.CompoundNBT; +import net.minecraft.util.NonNullList; +import net.minecraftforge.common.util.Constants; import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.basics.WandUtil; public class HandlerShulkerbox implements IContainerHandler { - private final int SLOTS = 27; + private final int SLOTS = 27; - @Override - public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { - return inventoryStack != null && inventoryStack.getCount() == 1 && Block.byItem(inventoryStack.getItem()) instanceof ShulkerBoxBlock; - } + @Override + public boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) + { + return inventoryStack != null && inventoryStack.getCount() == 1 && Block.getBlockFromItem(inventoryStack.getItem()) instanceof ShulkerBoxBlock; + } - @Override - public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { - int count = 0; + @Override + public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) + { + int count = 0; - for(ItemStack stack : getItemList(inventoryStack)) { - if(WandUtil.stackEquals(stack, itemStack)) count += stack.getCount(); - } + for(ItemStack stack : getItemList(inventoryStack)) { + if(WandUtil.stackEquals(stack, itemStack)) count += stack.getCount(); + } - return count; - } + return count; + } - @Override - public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { - NonNullList itemList = getItemList(inventoryStack); - boolean changed = false; + @Override + public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) + { + NonNullList itemList = getItemList(inventoryStack); + boolean changed = false; - for(ItemStack stack : itemList) { - if(WandUtil.stackEquals(stack, itemStack)) { - int toTake = Math.min(count, stack.getCount()); - stack.shrink(toTake); - count -= toTake; - changed = true; - if(count == 0) break; - } - } - if(changed) { - setItemList(inventoryStack, itemList); - player.getInventory().setChanged(); - } + for(ItemStack stack : itemList) { + if(WandUtil.stackEquals(stack, itemStack)) { + int toTake = Math.min(count, stack.getCount()); + stack.shrink(toTake); + count -= toTake; + changed = true; + if(count == 0) break; + } + } + if(changed) { + setItemList(inventoryStack, itemList); + player.inventory.markDirty(); + } - return count; - } + return count; + } - private NonNullList getItemList(ItemStack itemStack) { - NonNullList itemStacks = NonNullList.withSize(SLOTS, ItemStack.EMPTY); - CompoundTag rootTag = itemStack.getTag(); - if(rootTag != null && rootTag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) { - CompoundTag entityTag = rootTag.getCompound("BlockEntityTag"); - if(entityTag.contains("Items", Tag.TAG_LIST)) { - ContainerHelper.loadAllItems(entityTag, itemStacks); - } - } - return itemStacks; - } + private NonNullList getItemList(ItemStack itemStack) { + NonNullList itemStacks = NonNullList.withSize(SLOTS, ItemStack.EMPTY); + CompoundNBT rootTag = itemStack.getTag(); + if (rootTag != null && rootTag.contains("BlockEntityTag", Constants.NBT.TAG_COMPOUND)) { + CompoundNBT entityTag = rootTag.getCompound("BlockEntityTag"); + if (entityTag.contains("Items", Constants.NBT.TAG_LIST)) { + ItemStackHelper.loadAllItems(entityTag, itemStacks); + } + } + return itemStacks; + } - private void setItemList(ItemStack itemStack, NonNullList itemStacks) { - CompoundTag rootTag = itemStack.getOrCreateTag(); - if(!rootTag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) { - rootTag.put("BlockEntityTag", new CompoundTag()); - } - ContainerHelper.saveAllItems(rootTag.getCompound("BlockEntityTag"), itemStacks); - } + private void setItemList(ItemStack itemStack, NonNullList itemStacks) { + CompoundNBT rootTag = itemStack.getOrCreateTag(); + if (!rootTag.contains("BlockEntityTag", Constants.NBT.TAG_COMPOUND)) { + rootTag.put("BlockEntityTag", new CompoundNBT()); + } + ItemStackHelper.saveAllItems(rootTag.getCompound("BlockEntityTag"), itemStacks); + } } diff --git a/src/main/java/thetadev/constructionwand/crafting/RecipeWandUpgrade.java b/src/main/java/thetadev/constructionwand/crafting/RecipeWandUpgrade.java deleted file mode 100644 index 7fafdaf..0000000 --- a/src/main/java/thetadev/constructionwand/crafting/RecipeWandUpgrade.java +++ /dev/null @@ -1,75 +0,0 @@ -package thetadev.constructionwand.crafting; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.inventory.CraftingContainer; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CustomRecipe; -import net.minecraft.world.item.crafting.RecipeSerializer; -import net.minecraft.world.item.crafting.SimpleRecipeSerializer; -import net.minecraft.world.level.Level; -import thetadev.constructionwand.api.IWandUpgrade; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.items.wand.ItemWand; - -import javax.annotation.Nonnull; - -public class RecipeWandUpgrade extends CustomRecipe -{ - public static final SimpleRecipeSerializer SERIALIZER = new SimpleRecipeSerializer<>(RecipeWandUpgrade::new); - - public RecipeWandUpgrade(ResourceLocation resourceLocation) { - super(resourceLocation); - } - - @Override - public boolean matches(@Nonnull CraftingContainer inv, @Nonnull Level worldIn) { - ItemStack wand = null; - IWandUpgrade upgrade = null; - - for(int i = 0; i < inv.getContainerSize(); i++) { - ItemStack stack = inv.getItem(i); - if(!stack.isEmpty()) { - if(wand == null && stack.getItem() instanceof ItemWand) wand = stack; - else if(upgrade == null && stack.getItem() instanceof IWandUpgrade) - upgrade = (IWandUpgrade) stack.getItem(); - else return false; - } - } - - if(wand == null || upgrade == null) return false; - return !new WandOptions(wand).hasUpgrade(upgrade) && ConfigServer.getWandProperties(wand.getItem()).isUpgradeable(); - } - - @Nonnull - @Override - public ItemStack assemble(@Nonnull CraftingContainer inv) { - ItemStack wand = null; - IWandUpgrade upgrade = null; - - for(int i = 0; i < inv.getContainerSize(); i++) { - ItemStack stack = inv.getItem(i); - if(!stack.isEmpty()) { - if(stack.getItem() instanceof ItemWand) wand = stack; - else if(stack.getItem() instanceof IWandUpgrade) upgrade = (IWandUpgrade) stack.getItem(); - } - } - - if(wand == null || upgrade == null) return ItemStack.EMPTY; - - ItemStack newWand = wand.copy(); - new WandOptions(newWand).addUpgrade(upgrade); - return newWand; - } - - @Override - public boolean canCraftInDimensions(int width, int height) { - return width * height >= 2; - } - - @Nonnull - @Override - public RecipeSerializer getSerializer() { - return SERIALIZER; - } -} diff --git a/src/main/java/thetadev/constructionwand/data/ICustomItemModel.java b/src/main/java/thetadev/constructionwand/data/ICustomItemModel.java deleted file mode 100644 index 6d7d3e2..0000000 --- a/src/main/java/thetadev/constructionwand/data/ICustomItemModel.java +++ /dev/null @@ -1,6 +0,0 @@ -package thetadev.constructionwand.data; - -public interface ICustomItemModel -{ - void generateCustomItemModel(ItemModelGenerator generator, String name); -} diff --git a/src/main/java/thetadev/constructionwand/data/INoItemBlock.java b/src/main/java/thetadev/constructionwand/data/INoItemBlock.java deleted file mode 100644 index 65935f2..0000000 --- a/src/main/java/thetadev/constructionwand/data/INoItemBlock.java +++ /dev/null @@ -1,5 +0,0 @@ -package thetadev.constructionwand.data; - -public interface INoItemBlock -{ -} diff --git a/src/main/java/thetadev/constructionwand/data/Inp.java b/src/main/java/thetadev/constructionwand/data/Inp.java index d85270a..4b52641 100644 --- a/src/main/java/thetadev/constructionwand/data/Inp.java +++ b/src/main/java/thetadev/constructionwand/data/Inp.java @@ -1,28 +1,27 @@ package thetadev.constructionwand.data; -import net.minecraft.advancements.critereon.ItemPredicate; +import net.minecraft.advancements.criterion.ItemPredicate; +import net.minecraft.item.Item; +import net.minecraft.item.crafting.Ingredient; import net.minecraft.tags.Tag; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.crafting.Ingredient; -import net.minecraft.world.level.ItemLike; +import net.minecraft.util.IItemProvider; public class Inp { - public final String name; - public final Ingredient ingredient; - public final ItemPredicate predicate; + public final String name; + public final Ingredient ingredient; + public final ItemPredicate predicate; - public Inp(String name, Ingredient ingredient, ItemPredicate predicate) { - this.name = name; - this.ingredient = ingredient; - this.predicate = predicate; - } + public Inp(String name, Ingredient ingredient, ItemPredicate predicate) { + this.name = name; + this.ingredient = ingredient; + this.predicate = predicate; + } - public static Inp fromItem(ItemLike in) { - return new Inp(in.asItem().getRegistryName().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build()); - } - - public static Inp fromTag(Tag.Named in) { - return new Inp(in.getName().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build()); - } + public static Inp fromItem(IItemProvider in) { + return new Inp(in.asItem().getRegistryName().getPath(), Ingredient.fromItems(in), ItemPredicate.Builder.create().item(in).build()); + } + public static Inp fromTag(Tag in) { + return new Inp(in.getId().getPath(), Ingredient.fromTag(in), ItemPredicate.Builder.create().tag(in).build()); + } } \ No newline at end of file diff --git a/src/main/java/thetadev/constructionwand/data/ItemModelGenerator.java b/src/main/java/thetadev/constructionwand/data/ItemModelGenerator.java deleted file mode 100644 index c007b70..0000000 --- a/src/main/java/thetadev/constructionwand/data/ItemModelGenerator.java +++ /dev/null @@ -1,39 +0,0 @@ -package thetadev.constructionwand.data; - -import net.minecraft.data.DataGenerator; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraftforge.client.model.generators.ItemModelProvider; -import net.minecraftforge.common.data.ExistingFileHelper; -import net.minecraftforge.registries.RegistryObject; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.items.ModItems; - -import javax.annotation.Nonnull; - -public class ItemModelGenerator extends ItemModelProvider -{ - public ItemModelGenerator(DataGenerator generator, ExistingFileHelper existingFileHelper) { - super(generator, ConstructionWand.MODID, existingFileHelper); - } - - @Override - protected void registerModels() { - for(RegistryObject itemObject : ModItems.ITEMS.getEntries()) { - Item item = itemObject.get(); - String name = item.getRegistryName().getPath(); - - if(item instanceof ICustomItemModel) - ((ICustomItemModel) item).generateCustomItemModel(this, name); - else if(item instanceof BlockItem) - withExistingParent(name, modLoc("block/" + name)); - else withExistingParent(name, "item/generated").texture("layer0", "item/" + name); - } - } - - @Nonnull - @Override - public String getName() { - return ConstructionWand.MODNAME + " item models"; - } -} diff --git a/src/main/java/thetadev/constructionwand/data/ModData.java b/src/main/java/thetadev/constructionwand/data/ModData.java index e389e41..e8819df 100644 --- a/src/main/java/thetadev/constructionwand/data/ModData.java +++ b/src/main/java/thetadev/constructionwand/data/ModData.java @@ -1,25 +1,21 @@ package thetadev.constructionwand.data; import net.minecraft.data.DataGenerator; -import net.minecraftforge.common.data.ExistingFileHelper; +import net.minecraftforge.client.model.generators.ExistingFileHelper; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.forge.event.lifecycle.GatherDataEvent; +import net.minecraftforge.fml.event.lifecycle.GatherDataEvent; @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public class ModData { - @SubscribeEvent - public static void gatherData(GatherDataEvent event) { - DataGenerator generator = event.getGenerator(); - ExistingFileHelper fileHelper = event.getExistingFileHelper(); + @SubscribeEvent + public static void gatherData(GatherDataEvent event) { + DataGenerator generator = event.getGenerator(); + ExistingFileHelper fileHelper = event.getExistingFileHelper(); - if(event.includeServer()) { - generator.addProvider(new RecipeGenerator(generator)); - } - - if(event.includeClient()) { - generator.addProvider(new ItemModelGenerator(generator, fileHelper)); - } - } + if(event.includeServer()) { + generator.addProvider(new RecipeGenerator(generator)); + } + } } diff --git a/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java b/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java index aaff00c..900d683 100644 --- a/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java +++ b/src/main/java/thetadev/constructionwand/data/RecipeGenerator.java @@ -1,74 +1,43 @@ package thetadev.constructionwand.data; import net.minecraft.data.DataGenerator; -import net.minecraft.data.recipes.FinishedRecipe; -import net.minecraft.data.recipes.RecipeProvider; -import net.minecraft.data.recipes.ShapedRecipeBuilder; -import net.minecraft.data.recipes.SpecialRecipeBuilder; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.ItemTags; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.SimpleRecipeSerializer; -import net.minecraft.world.level.ItemLike; +import net.minecraft.data.IFinishedRecipe; +import net.minecraft.data.RecipeProvider; +import net.minecraft.data.ShapedRecipeBuilder; +import net.minecraft.util.IItemProvider; import net.minecraftforge.common.Tags; -import net.minecraftforge.registries.ForgeRegistries; import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.crafting.RecipeWandUpgrade; import thetadev.constructionwand.items.ModItems; -import javax.annotation.Nonnull; import java.util.function.Consumer; public class RecipeGenerator extends RecipeProvider { - public RecipeGenerator(DataGenerator generatorIn) { - super(generatorIn); - } + public RecipeGenerator(DataGenerator generatorIn) { + super(generatorIn); + } - @Override - protected void buildCraftingRecipes(@Nonnull Consumer consumer) { - wandRecipe(consumer, ModItems.WAND_STONE.get(), Inp.fromTag(ItemTags.STONE_TOOL_MATERIALS)); - wandRecipe(consumer, ModItems.WAND_IRON.get(), Inp.fromTag(Tags.Items.INGOTS_IRON)); - wandRecipe(consumer, ModItems.WAND_DIAMOND.get(), Inp.fromTag(Tags.Items.GEMS_DIAMOND)); - wandRecipe(consumer, ModItems.WAND_INFINITY.get(), Inp.fromTag(Tags.Items.NETHER_STARS)); + @Override + protected void registerRecipes(Consumer consumer) { + wandRecipe(consumer, ModItems.WAND_STONE, Inp.fromTag(Tags.Items.COBBLESTONE)); + wandRecipe(consumer, ModItems.WAND_IRON, Inp.fromTag(Tags.Items.INGOTS_IRON)); + wandRecipe(consumer, ModItems.WAND_DIAMOND, Inp.fromTag(Tags.Items.GEMS_DIAMOND)); + wandRecipe(consumer, ModItems.WAND_INFINITY, Inp.fromTag(Tags.Items.NETHER_STARS)); + } - coreRecipe(consumer, ModItems.CORE_ANGEL.get(), Inp.fromTag(Tags.Items.FEATHERS), Inp.fromTag(Tags.Items.INGOTS_GOLD)); - coreRecipe(consumer, ModItems.CORE_DESTRUCTION.get(), Inp.fromTag(Tags.Items.STORAGE_BLOCKS_DIAMOND), Inp.fromItem(Items.DIAMOND_PICKAXE)); + private void wandRecipe(Consumer consumer, IItemProvider wand, Inp material) { + ShapedRecipeBuilder.shapedRecipe(wand) + .key('X', material.ingredient) + .key('#', Tags.Items.RODS_WOODEN) + .patternLine(" X") + .patternLine(" # ") + .patternLine("# ") + .addCriterion("has_item", hasItem(material.predicate)) + .build(consumer); + } - specialRecipe(consumer, RecipeWandUpgrade.SERIALIZER); - } - - private void wandRecipe(Consumer consumer, ItemLike wand, Inp material) { - ShapedRecipeBuilder.shaped(wand) - .define('X', material.ingredient) - .define('#', Tags.Items.RODS_WOODEN) - .pattern(" X") - .pattern(" # ") - .pattern("# ") - .unlockedBy("has_item", inventoryTrigger(material.predicate)) - .save(consumer); - } - - private void coreRecipe(Consumer consumer, ItemLike core, Inp item1, Inp item2) { - ShapedRecipeBuilder.shaped(core) - .define('O', item1.ingredient) - .define('X', item2.ingredient) - .define('#', Tags.Items.GLASS_PANES) - .pattern(" #X") - .pattern("#O#") - .pattern("X# ") - .unlockedBy("has_item", inventoryTrigger(item1.predicate)) - .save(consumer); - } - - private void specialRecipe(Consumer consumer, SimpleRecipeSerializer serializer) { - ResourceLocation name = ForgeRegistries.RECIPE_SERIALIZERS.getKey(serializer); - SpecialRecipeBuilder.special(serializer).save(consumer, ConstructionWand.loc("dynamic/" + name.getPath()).toString()); - } - - @Nonnull - @Override - public String getName() { - return ConstructionWand.MODID + " crafting recipes"; - } + @Override + public String getName() { + return ConstructionWand.MODID + " crafting recipes"; + } } \ No newline at end of file diff --git a/src/main/java/thetadev/constructionwand/integrations/jei/ConstructionWandJeiPlugin.java b/src/main/java/thetadev/constructionwand/integrations/jei/ConstructionWandJeiPlugin.java deleted file mode 100644 index ed0ca4d..0000000 --- a/src/main/java/thetadev/constructionwand/integrations/jei/ConstructionWandJeiPlugin.java +++ /dev/null @@ -1,70 +0,0 @@ -package thetadev.constructionwand.integrations.jei; - -import com.mojang.blaze3d.platform.InputConstants; -import mezz.jei.api.IModPlugin; -import mezz.jei.api.JeiPlugin; -import mezz.jei.api.constants.VanillaTypes; -import mezz.jei.api.registration.IRecipeRegistration; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.registries.RegistryObject; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.basics.ConfigClient; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.items.ModItems; - -import javax.annotation.Nonnull; - -@JeiPlugin -public class ConstructionWandJeiPlugin implements IModPlugin -{ - private static final ResourceLocation pluginId = new ResourceLocation(ConstructionWand.MODID, ConstructionWand.MODID); - private static final String baseKey = ConstructionWand.MODID + ".description."; - private static final String baseKeyItem = "item." + ConstructionWand.MODID + "."; - - @Nonnull - @Override - public ResourceLocation getPluginUid() { - return pluginId; - } - - private Component keyComboComponent(boolean shiftOpt, Component optkeyComponent) { - String key = shiftOpt ? "sneak_opt" : "sneak"; - return new TranslatableComponent(baseKey + "key." + key, optkeyComponent).withStyle(ChatFormatting.BLUE); - } - - @Override - public void registerRecipes(IRecipeRegistration registration) { - Component optkeyComponent = new TranslatableComponent(InputConstants.getKey(ConfigClient.OPT_KEY.get(), -1).getName()) - .withStyle(ChatFormatting.BLUE); - Component wandModeComponent = keyComboComponent(ConfigClient.SHIFTOPT_MODE.get(), optkeyComponent); - Component wandGuiComponent = keyComboComponent(ConfigClient.SHIFTOPT_GUI.get(), optkeyComponent); - - for(RegistryObject wandSupplier : ModItems.WANDS) { - Item wand = wandSupplier.get(); - ConfigServer.WandProperties wandProperties = ConfigServer.getWandProperties(wand); - - String durabilityKey = wand == ModItems.WAND_INFINITY.get() ? "unlimited" : "limited"; - Component durabilityComponent = new TranslatableComponent(baseKey + "durability." + durabilityKey, wandProperties.getDurability()); - - registration.addIngredientInfo(new ItemStack(wand), VanillaTypes.ITEM, - new TranslatableComponent(baseKey + "wand", - new TranslatableComponent(baseKeyItem + wand.getRegistryName().getPath()), - wandProperties.getLimit(), durabilityComponent, - optkeyComponent, wandModeComponent, wandGuiComponent) - ); - } - - for(RegistryObject coreSupplier : ModItems.CORES) { - Item core = coreSupplier.get(); - registration.addIngredientInfo(new ItemStack(core), VanillaTypes.ITEM, - new TranslatableComponent(baseKey + core.getRegistryName().getPath()), - new TranslatableComponent(baseKey + "core", wandModeComponent) - ); - } - } -} diff --git a/src/main/java/thetadev/constructionwand/items/ItemWand.java b/src/main/java/thetadev/constructionwand/items/ItemWand.java new file mode 100644 index 0000000..e13f2fd --- /dev/null +++ b/src/main/java/thetadev/constructionwand/items/ItemWand.java @@ -0,0 +1,154 @@ +package thetadev.constructionwand.items; + +import net.minecraft.block.BlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screen.Screen; +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.item.ItemUseContext; +import net.minecraft.item.crafting.Ingredient; +import net.minecraft.util.ActionResult; +import net.minecraft.util.ActionResultType; +import net.minecraft.util.Hand; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockRayTraceResult; +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.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import thetadev.constructionwand.ConstructionWand; +import thetadev.constructionwand.basics.*; +import thetadev.constructionwand.basics.options.EnumLock; +import thetadev.constructionwand.basics.options.EnumMode; +import thetadev.constructionwand.basics.options.IEnumOption; +import thetadev.constructionwand.basics.options.WandOptions; +import thetadev.constructionwand.job.AngelJob; +import thetadev.constructionwand.job.JobHistory; +import thetadev.constructionwand.job.WandJob; + +import java.util.List; + +public abstract class ItemWand extends Item +{ + public final int maxBlocks; + public final int angelDistance; + + public ItemWand(Item.Properties properties, int maxBlocks, int angelDistance) { + super(properties.group(ItemGroup.TOOLS)); + this.maxBlocks = maxBlocks; + this.angelDistance = angelDistance; + addPropertyOverride(new ResourceLocation(ConstructionWand.MODID, "wand_mode"), + (stack, worldIn, entityIn) -> getWandMode(stack)); + } + + @Override + public ActionResultType onItemUse(ItemUseContext context) + { + PlayerEntity player = context.getPlayer(); + Hand hand = context.getHand(); + World world = context.getWorld(); + + if(world.isRemote || player == null) return ActionResultType.FAIL; + + ItemStack stack = player.getHeldItem(hand); + + if(player.isSneaking() && ConstructionWand.instance.jobHistory.isUndoActive(player)) { + WandJob job = ConstructionWand.instance.jobHistory.getForUndo(player, world, context.getPos()); + if(job == null) return ActionResultType.FAIL; + //ConstructionWand.LOGGER.debug("Starting Undo"); + return job.undo() ? ActionResultType.SUCCESS : ActionResultType.FAIL; + } + else { + WandJob job = WandJob.getJob(player, world, new BlockRayTraceResult(context.getHitVec(), context.getFace(), context.getPos(), false), stack); + return job.doIt() ? ActionResultType.SUCCESS : ActionResultType.FAIL; + } + } + + @Override + public ActionResult onItemRightClick(World world, PlayerEntity player, Hand hand) { + ItemStack stack = player.getHeldItem(hand); + + if(world.isRemote) return new ActionResult<>(ActionResultType.FAIL, stack); + + if(player.isSneaking()) { + // SHIFT + Right click: Change wand mode + WandOptions options = new WandOptions(stack); + IEnumOption opt = EnumMode.DEFAULT; + opt = options.nextOption(opt); + + //ConstructionWand.LOGGER.debug("Wand mode: " + options.getOption(EnumLock.NOLOCK)); + + optionMessage(player, opt); + + player.inventory.markDirty(); + return new ActionResult<>(ActionResultType.SUCCESS, stack); + } + else { + // Right click: Place angel block + //ConstructionWand.LOGGER.debug("Place angel block"); + WandJob job = new AngelJob(player, world, stack); + return new ActionResult<>(job.doIt() ? ActionResultType.SUCCESS : ActionResultType.FAIL, stack); + } + } + + @Override + public boolean canHarvestBlock(BlockState blockIn) { + return false; + } + + @Override + public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) { + return false; + } + + public int getLimit(PlayerEntity player, ItemStack stack) { + return maxBlocks; + } + + public static int getWandMode(ItemStack stack) { + WandOptions options = new WandOptions(stack); + return options.getOption(EnumMode.DEFAULT).getOrdinal(); + } + + @OnlyIn(Dist.CLIENT) + public void addInformation(ItemStack itemstack, World worldIn, List lines, ITooltipFlag extraInfo) { + ItemWand wand = (ItemWand) itemstack.getItem(); + WandOptions options = new WandOptions(itemstack); + + String langPrefix = ConstructionWand.MODID + ".option."; + String langTooltip = ConstructionWand.MODID + ".tooltip."; + + if(Screen.hasShiftDown()) { + for(int i=1; i ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ConstructionWand.MODID); + public static final Item WAND_STONE = new ItemWandBasic(ItemTier.STONE, ConfigHandler.DURABILITY_STONE.get(), ConfigHandler.LIMIT_STONE.get(), ConfigHandler.ANGEL_STONE.get()); + public static final Item WAND_IRON = new ItemWandBasic(ItemTier.IRON, ConfigHandler.DURABILITY_IRON.get(), ConfigHandler.LIMIT_IRON.get(), ConfigHandler.ANGEL_IRON.get()); + public static final Item WAND_DIAMOND = new ItemWandBasic(ItemTier.DIAMOND, ConfigHandler.DURABILITY_DIAMOND.get(), ConfigHandler.LIMIT_DIAMOND.get(), ConfigHandler.ANGEL_DIAMOND.get()); + public static final Item WAND_INFINITY = new ItemWandInfinity(ConfigHandler.LIMIT_INFINITY.get(), ConfigHandler.ANGEL_INFINITY.get()); - // Wands - public static final RegistryObject WAND_STONE = ITEMS.register("stone_wand", () -> new ItemWandBasic(propWand(), Tiers.STONE)); - public static final RegistryObject WAND_IRON = ITEMS.register("iron_wand", () -> new ItemWandBasic(propWand(), Tiers.IRON)); - public static final RegistryObject WAND_DIAMOND = ITEMS.register("diamond_wand", () -> new ItemWandBasic(propWand(), Tiers.DIAMOND)); - public static final RegistryObject WAND_INFINITY = ITEMS.register("infinity_wand", () -> new ItemWandInfinity(propWand())); + @SubscribeEvent + public static void onRegisterItems(RegistryEvent.Register event) + { + event.getRegistry().registerAll( + register(WAND_STONE, "stone_wand"), + register(WAND_IRON, "iron_wand"), + register(WAND_DIAMOND, "diamond_wand"), + register(WAND_INFINITY, "infinity_wand") + ); + } - // Cores - public static final RegistryObject CORE_ANGEL = ITEMS.register("core_angel", () -> new ItemCoreAngel(propUpgrade())); - public static final RegistryObject CORE_DESTRUCTION = ITEMS.register("core_destruction", () -> new ItemCoreDestruction(propUpgrade())); + public static > T register(final T entry, final String name) { + return register(entry, new ResourceLocation(ConstructionWand.MODID, name)); + } - // Collections - public static final RegistryObject[] WANDS = new RegistryObject[] {WAND_STONE, WAND_IRON, WAND_DIAMOND, WAND_INFINITY}; - public static final RegistryObject[] CORES = new RegistryObject[] {CORE_ANGEL, CORE_DESTRUCTION}; - - public static Item.Properties propWand() { - return new Item.Properties().tab(CreativeModeTab.TAB_TOOLS); - } - - private static Item.Properties propUpgrade() { - return new Item.Properties().tab(CreativeModeTab.TAB_MISC).stacksTo(1); - } - - @SubscribeEvent - public static void registerRecipeSerializers(RegistryEvent.Register> event) { - IForgeRegistry> r = event.getRegistry(); - register(r, "wand_upgrade", RecipeWandUpgrade.SERIALIZER); - } - - @OnlyIn(Dist.CLIENT) - public static void registerModelProperties() { - for(RegistryObject itemSupplier : WANDS) { - Item item = itemSupplier.get(); - ItemProperties.register( - item, ConstructionWand.loc("using_core"), - (stack, world, entity, n) -> entity == null || !(stack.getItem() instanceof ItemWand) ? 0 : - new WandOptions(stack).cores.get().getColor() > -1 ? 1 : 0 - ); - } - } - - @OnlyIn(Dist.CLIENT) - public static void registerItemColors() { - ItemColors colors = Minecraft.getInstance().getItemColors(); - - for(RegistryObject itemSupplier : WANDS) { - Item item = itemSupplier.get(); - colors.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ? - new WandOptions(stack).cores.get().getColor() : -1, item); - } - } - - private static > void register(IForgeRegistry reg, String name, IForgeRegistryEntry thing) { - reg.register(thing.setRegistryName(ConstructionWand.loc(name))); - } + public static > T register(final T entry, final ResourceLocation registryName) { + entry.setRegistryName(registryName); + return entry; + } } diff --git a/src/main/java/thetadev/constructionwand/items/core/CoreDefault.java b/src/main/java/thetadev/constructionwand/items/core/CoreDefault.java deleted file mode 100644 index 02924af..0000000 --- a/src/main/java/thetadev/constructionwand/items/core/CoreDefault.java +++ /dev/null @@ -1,25 +0,0 @@ -package thetadev.constructionwand.items.core; - -import net.minecraft.resources.ResourceLocation; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.api.IWandCore; -import thetadev.constructionwand.wand.action.ActionConstruction; - -public class CoreDefault implements IWandCore -{ - @Override - public int getColor() { - return -1; - } - - @Override - public IWandAction getWandAction() { - return new ActionConstruction(); - } - - @Override - public ResourceLocation getRegistryName() { - return ConstructionWand.loc("default"); - } -} diff --git a/src/main/java/thetadev/constructionwand/items/core/ItemCore.java b/src/main/java/thetadev/constructionwand/items/core/ItemCore.java deleted file mode 100644 index 6b3362c..0000000 --- a/src/main/java/thetadev/constructionwand/items/core/ItemCore.java +++ /dev/null @@ -1,31 +0,0 @@ -package thetadev.constructionwand.items.core; - -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.TranslatableComponent; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.api.IWandCore; - -import javax.annotation.Nonnull; -import java.util.List; - -public abstract class ItemCore extends Item implements IWandCore -{ - public ItemCore(Properties properties) { - super(properties); - } - - @OnlyIn(Dist.CLIENT) - public void appendHoverText(@Nonnull ItemStack itemstack, Level worldIn, @Nonnull List lines, @Nonnull TooltipFlag extraInfo) { - lines.add(new TranslatableComponent(ConstructionWand.MODID + ".option.cores." + getRegistryName().toString() + ".desc") - .withStyle(ChatFormatting.GRAY)); - lines.add(new TranslatableComponent(ConstructionWand.MODID + ".tooltip.core_tip") - .withStyle(ChatFormatting.AQUA)); - } -} diff --git a/src/main/java/thetadev/constructionwand/items/core/ItemCoreAngel.java b/src/main/java/thetadev/constructionwand/items/core/ItemCoreAngel.java deleted file mode 100644 index 5062761..0000000 --- a/src/main/java/thetadev/constructionwand/items/core/ItemCoreAngel.java +++ /dev/null @@ -1,21 +0,0 @@ -package thetadev.constructionwand.items.core; - -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.wand.action.ActionAngel; - -public class ItemCoreAngel extends ItemCore -{ - public ItemCoreAngel(Properties properties) { - super(properties); - } - - @Override - public int getColor() { - return 0xE9B115; - } - - @Override - public IWandAction getWandAction() { - return new ActionAngel(); - } -} diff --git a/src/main/java/thetadev/constructionwand/items/core/ItemCoreDestruction.java b/src/main/java/thetadev/constructionwand/items/core/ItemCoreDestruction.java deleted file mode 100644 index bb2b5d3..0000000 --- a/src/main/java/thetadev/constructionwand/items/core/ItemCoreDestruction.java +++ /dev/null @@ -1,21 +0,0 @@ -package thetadev.constructionwand.items.core; - -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.wand.action.ActionDestruction; - -public class ItemCoreDestruction extends ItemCore -{ - public ItemCoreDestruction(Properties properties) { - super(properties); - } - - @Override - public int getColor() { - return 0xFF0000; - } - - @Override - public IWandAction getWandAction() { - return new ActionDestruction(); - } -} diff --git a/src/main/java/thetadev/constructionwand/items/wand/ItemWand.java b/src/main/java/thetadev/constructionwand/items/wand/ItemWand.java deleted file mode 100644 index 4fa3529..0000000 --- a/src/main/java/thetadev/constructionwand/items/wand/ItemWand.java +++ /dev/null @@ -1,155 +0,0 @@ -package thetadev.constructionwand.items.wand; - -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.screens.Screen; -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.InteractionResult; -import net.minecraft.world.InteractionResultHolder; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.model.generators.ModelFile; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.api.IWandCore; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.IOption; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.data.ICustomItemModel; -import thetadev.constructionwand.data.ItemModelGenerator; -import thetadev.constructionwand.wand.WandJob; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; - -public abstract class ItemWand extends Item implements ICustomItemModel -{ - public ItemWand(Properties properties) { - super(properties); - } - - @Nonnull - @Override - public InteractionResult useOn(UseOnContext context) { - Player player = context.getPlayer(); - InteractionHand hand = context.getHand(); - Level world = context.getLevel(); - - if(world.isClientSide || player == null) return InteractionResult.FAIL; - - ItemStack stack = player.getItemInHand(hand); - - if(player.isCrouching() && ConstructionWand.instance.undoHistory.isUndoActive(player)) { - return ConstructionWand.instance.undoHistory.undo(player, world, context.getClickedPos()) ? InteractionResult.SUCCESS : InteractionResult.FAIL; - } - else { - WandJob job = getWandJob(player, world, new BlockHitResult(context.getClickLocation(), context.getClickedFace(), context.getClickedPos(), false), stack); - return job.doIt() ? InteractionResult.SUCCESS : InteractionResult.FAIL; - } - } - - @Nonnull - @Override - public InteractionResultHolder use(@Nonnull Level world, Player player, @Nonnull InteractionHand hand) { - ItemStack stack = player.getItemInHand(hand); - - if(!player.isCrouching()) { - if(world.isClientSide) return InteractionResultHolder.fail(stack); - - // Right click: Place angel block - WandJob job = getWandJob(player, world, BlockHitResult.miss(player.getLookAngle(), - WandUtil.fromVector(player.getLookAngle()), WandUtil.playerPos(player)), stack); - return job.doIt() ? InteractionResultHolder.success(stack) : InteractionResultHolder.fail(stack); - } - return InteractionResultHolder.fail(stack); - } - - public static WandJob getWandJob(Player player, Level world, @Nullable BlockHitResult rayTraceResult, ItemStack wand) { - WandJob wandJob = new WandJob(player, world, rayTraceResult, wand); - wandJob.getSnapshots(); - - return wandJob; - } - - @Override - public boolean isCorrectToolForDrops(@Nonnull BlockState blockIn) { - return false; - } - - @Override - public boolean isValidRepairItem(@Nonnull ItemStack toRepair, @Nonnull ItemStack repair) { - return false; - } - - public int remainingDurability(ItemStack stack) { - return Integer.MAX_VALUE; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void appendHoverText(@Nonnull ItemStack itemstack, Level worldIn, @Nonnull List lines, @Nonnull TooltipFlag extraInfo) { - WandOptions options = new WandOptions(itemstack); - int limit = options.cores.get().getWandAction().getLimit(itemstack); - - String langTooltip = ConstructionWand.MODID + ".tooltip."; - - // +SHIFT tooltip: show all options + installed cores - if(Screen.hasShiftDown()) { - for(int i = 1; i < options.allOptions.length; i++) { - IOption opt = options.allOptions[i]; - lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA) - .append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.GRAY)) - ); - } - if(!options.cores.getUpgrades().isEmpty()) { - lines.add(new TextComponent("")); - lines.add(new TranslatableComponent(langTooltip + "cores").withStyle(ChatFormatting.GRAY)); - - for(IWandCore core : options.cores.getUpgrades()) { - lines.add(new TranslatableComponent(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString())); - } - } - } - // Default tooltip: show block limit + active wand core - else { - IOption opt = options.allOptions[0]; - lines.add(new TranslatableComponent(langTooltip + "blocks", limit).withStyle(ChatFormatting.GRAY)); - lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA) - .append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.WHITE))); - lines.add(new TranslatableComponent(langTooltip + "shift").withStyle(ChatFormatting.AQUA)); - } - } - - public static void optionMessage(Player player, IOption option) { - player.displayClientMessage( - new TranslatableComponent(option.getKeyTranslation()).withStyle(ChatFormatting.AQUA) - .append(new TranslatableComponent(option.getValueTranslation()).withStyle(ChatFormatting.WHITE)) - .append(new TextComponent(" - ").withStyle(ChatFormatting.GRAY)) - .append(new TranslatableComponent(option.getDescTranslation()).withStyle(ChatFormatting.WHITE)) - , true); - } - - @Override - public void generateCustomItemModel(ItemModelGenerator generator, String name) { - ModelFile wandWithCore = generator.withExistingParent(name + "_core", "item/handheld") - .texture("layer0", generator.modLoc("item/" + name)) - .texture("layer1", generator.modLoc("item/overlay_core")); - - generator.withExistingParent(name, "item/handheld") - .texture("layer0", generator.modLoc("item/" + name)) - .override() - .predicate(generator.modLoc("using_core"), 1) - .model(wandWithCore).end(); - - } -} diff --git a/src/main/java/thetadev/constructionwand/items/wand/ItemWandBasic.java b/src/main/java/thetadev/constructionwand/items/wand/ItemWandBasic.java deleted file mode 100644 index 3db9d28..0000000 --- a/src/main/java/thetadev/constructionwand/items/wand/ItemWandBasic.java +++ /dev/null @@ -1,32 +0,0 @@ -package thetadev.constructionwand.items.wand; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Tier; -import thetadev.constructionwand.basics.ConfigServer; - -import javax.annotation.Nonnull; - -public class ItemWandBasic extends ItemWand -{ - private final Tier tier; - - public ItemWandBasic(Properties properties, Tier tier) { - super(properties.durability(tier.getUses())); - this.tier = tier; - } - - @Override - public int getMaxDamage(ItemStack stack) { - return ConfigServer.getWandProperties(this).getDurability(); - } - - @Override - public int remainingDurability(ItemStack stack) { - return stack.getMaxDamage() - stack.getDamageValue(); - } - - @Override - public boolean isValidRepairItem(@Nonnull ItemStack toRepair, @Nonnull ItemStack repair) { - return this.tier.getRepairIngredient().test(repair); - } -} diff --git a/src/main/java/thetadev/constructionwand/items/wand/ItemWandInfinity.java b/src/main/java/thetadev/constructionwand/items/wand/ItemWandInfinity.java deleted file mode 100644 index 16bcc8a..0000000 --- a/src/main/java/thetadev/constructionwand/items/wand/ItemWandInfinity.java +++ /dev/null @@ -1,9 +0,0 @@ -package thetadev.constructionwand.items.wand; - - -public class ItemWandInfinity extends ItemWand -{ - public ItemWandInfinity(Properties properties) { - super(properties.stacksTo(1).fireResistant()); - } -} diff --git a/src/main/java/thetadev/constructionwand/job/AngelJob.java b/src/main/java/thetadev/constructionwand/job/AngelJob.java new file mode 100644 index 0000000..87b3db1 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/job/AngelJob.java @@ -0,0 +1,40 @@ +package thetadev.constructionwand.job; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; +import thetadev.constructionwand.basics.ConfigHandler; +import thetadev.constructionwand.basics.WandUtil; +import thetadev.constructionwand.basics.options.EnumMode; + +public class AngelJob extends WandJob +{ + public AngelJob(PlayerEntity player, World world, ItemStack wand) { + super(player, world, new BlockRayTraceResult(player.getLookVec(), fromVector(player.getLookVec()), player.getPosition(), false), wand); + } + + private static Direction fromVector(Vec3d vector) { + return Direction.getFacingFromVector(vector.x, vector.y, vector.z); + } + + @Override + protected void getBlockPositionList() { + if(options.getOption(EnumMode.DEFAULT) != EnumMode.ANGEL || wandItem.angelDistance == 0) return; + + if(!player.isCreative() && !ConfigHandler.ANGEL_FALLING.get() && player.fallDistance > 10) return; + + Vec3d playerVec = WandUtil.entityPositionVec(player); + Vec3d lookVec = player.getLookVec().mul(2, 2, 2); + Vec3d placeVec = playerVec.add(lookVec); + + BlockPos currentPos = new BlockPos(placeVec); + + if(canPlace(currentPos)) { + placeSnapshots.add(new PlaceSnapshot(currentPos, placeItem.getBlock().getDefaultState())); + } + } +} diff --git a/src/main/java/thetadev/constructionwand/job/ConstructionJob.java b/src/main/java/thetadev/constructionwand/job/ConstructionJob.java new file mode 100644 index 0000000..a760288 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/job/ConstructionJob.java @@ -0,0 +1,110 @@ +package thetadev.constructionwand.job; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.world.World; +import thetadev.constructionwand.ConstructionWand; +import thetadev.constructionwand.basics.options.EnumLock; + +import java.util.HashSet; +import java.util.LinkedList; + +public class ConstructionJob extends WandJob +{ + public ConstructionJob(PlayerEntity player, World world, BlockRayTraceResult rayTraceResult, ItemStack itemStack) { + super(player, world, rayTraceResult, itemStack); + } + + @Override + protected void getBlockPositionList() { + EnumLock lock = (EnumLock) options.getOption(EnumLock.NOLOCK); + + LinkedList candidates = new LinkedList<>(); + HashSet allCandidates = new HashSet<>(); + + Direction placeDirection = rayTraceResult.getFace(); + BlockState targetBlock = world.getBlockState(rayTraceResult.getPos()); + BlockPos startingPoint = rayTraceResult.getPos().offset(placeDirection); + + // Is place direction allowed by lock? + if(placeDirection == Direction.UP || placeDirection == Direction.DOWN) { + if(lock.test(EnumLock.NORTHSOUTH) || lock.test(EnumLock.EASTWEST)) candidates.add(startingPoint); + } + else if(lock.test(EnumLock.HORIZONTAL) || lock.test(EnumLock.VERTICAL)) candidates.add(startingPoint); + + while(!candidates.isEmpty() && placeSnapshots.size() < maxBlocks) + { + BlockPos currentCandidate = candidates.removeFirst(); + try { + BlockPos supportingPoint = currentCandidate.offset(placeDirection.getOpposite()); + BlockState candidateSupportingBlock = world.getBlockState(supportingPoint); + + if (targetBlock.getBlock().equals(candidateSupportingBlock.getBlock()) && canPlace(currentCandidate) && allCandidates.add(currentCandidate)) { + placeSnapshots.add(new PlaceSnapshot(currentCandidate, candidateSupportingBlock)); + + switch(placeDirection) { + case DOWN: + case UP: + if(lock.test(EnumLock.NORTHSOUTH)) { + candidates.add(currentCandidate.offset(Direction.NORTH)); + candidates.add(currentCandidate.offset(Direction.SOUTH)); + } + if(lock.test(EnumLock.EASTWEST)) { + candidates.add(currentCandidate.offset(Direction.EAST)); + candidates.add(currentCandidate.offset(Direction.WEST)); + } + if(lock.test(EnumLock.NORTHSOUTH) && lock.test(EnumLock.EASTWEST)) { + candidates.add(currentCandidate.offset(Direction.NORTH).offset(Direction.EAST)); + candidates.add(currentCandidate.offset(Direction.NORTH).offset(Direction.WEST)); + candidates.add(currentCandidate.offset(Direction.SOUTH).offset(Direction.EAST)); + candidates.add(currentCandidate.offset(Direction.SOUTH).offset(Direction.WEST)); + } + break; + case NORTH: + case SOUTH: + if(lock.test(EnumLock.HORIZONTAL)) { + candidates.add(currentCandidate.offset(Direction.EAST)); + candidates.add(currentCandidate.offset(Direction.WEST)); + } + if(lock.test(EnumLock.VERTICAL)) { + candidates.add(currentCandidate.offset(Direction.UP)); + candidates.add(currentCandidate.offset(Direction.DOWN)); + } + if(lock.test(EnumLock.HORIZONTAL) && lock.test(EnumLock.VERTICAL)) { + candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.EAST)); + candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.WEST)); + candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.EAST)); + candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.WEST)); + } + break; + case EAST: + case WEST: + if(lock.test(EnumLock.HORIZONTAL)) { + candidates.add(currentCandidate.offset(Direction.NORTH)); + candidates.add(currentCandidate.offset(Direction.SOUTH)); + } + if(lock.test(EnumLock.VERTICAL)) { + candidates.add(currentCandidate.offset(Direction.UP)); + candidates.add(currentCandidate.offset(Direction.DOWN)); + } + if(lock.test(EnumLock.HORIZONTAL) && lock.test(EnumLock.VERTICAL)) { + candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.NORTH)); + candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.SOUTH)); + candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.NORTH)); + candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.SOUTH)); + } + break; + } + } + } + catch(Exception e) { + // Can't do anything, could be anything. + // Skip if anything goes wrong. + } + } + } +} diff --git a/src/main/java/thetadev/constructionwand/job/JobHistory.java b/src/main/java/thetadev/constructionwand/job/JobHistory.java new file mode 100644 index 0000000..2b64eee --- /dev/null +++ b/src/main/java/thetadev/constructionwand/job/JobHistory.java @@ -0,0 +1,100 @@ +package thetadev.constructionwand.job; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraftforge.fml.network.PacketDistributor; +import thetadev.constructionwand.basics.ConfigHandler; +import thetadev.constructionwand.ConstructionWand; +import thetadev.constructionwand.network.PacketUndoBlocks; + +import java.util.HashMap; +import java.util.LinkedList; +import java.util.UUID; + +public class JobHistory +{ + private final HashMap history; + + public JobHistory() { + history = new HashMap<>(); + } + + private HistoryEntry getEntryFromPlayer(PlayerEntity player) { + return history.computeIfAbsent(player.getUniqueID(), k -> new HistoryEntry()); + } + + private LinkedList getJobsFromPlayer(PlayerEntity player) { + return getEntryFromPlayer(player).jobs; + } + + public void add(WandJob job) { + LinkedList list = getJobsFromPlayer(job.getPlayer()); + list.add(job); + while(list.size() > ConfigHandler.UNDO_HISTORY.get()) list.removeFirst(); + } + + public void removePlayer(PlayerEntity player) { + history.remove(player.getUniqueID()); + } + + public void updateClient(PlayerEntity player, boolean ctrlDown) { + World world = player.getEntityWorld(); + if(world.isRemote) return; + + // Set state of CTRL key + HistoryEntry entry = getEntryFromPlayer(player); + entry.undoActive = ctrlDown; + + LinkedList jobs = entry.jobs; + LinkedList positions; + + // Send block positions of most recent job to client + if(jobs.isEmpty()) positions = new LinkedList<>(); + else { + WandJob job = jobs.getLast(); + if(job == null || !job.getWorld().equals(world)) positions = new LinkedList<>(); + else positions = job.getBlockPositions(); + } + + PacketUndoBlocks packet = new PacketUndoBlocks(positions); + ConstructionWand.instance.HANDLER.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), packet); + } + + public boolean isUndoActive(PlayerEntity player) { + return getEntryFromPlayer(player).undoActive; + } + + public WandJob getForUndo(PlayerEntity player, World world, BlockPos pos) { + // If CTRL key is not pressed, return + HistoryEntry entry = getEntryFromPlayer(player); + if(!entry.undoActive) return null; + + // Get the most recent job for undo + LinkedList jobs = entry.jobs; + if(jobs.isEmpty()) return null; + WandJob job = jobs.getLast(); + + if(job.getWorld().equals(world) && job.getBlockPositions().contains(pos)) { + // Update job player entity, they could have changed by rejoin/respawn + job.setPlayer(player); + + // Remove undo job, sent update to client and return it + jobs.remove(job); + updateClient(player, true); + return job; + } + return null; + } + + private static class HistoryEntry { + public LinkedList jobs; + public boolean undoActive; + + public HistoryEntry() { + jobs = new LinkedList<>(); + undoActive = false; + } + } +} diff --git a/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java b/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java new file mode 100644 index 0000000..590acad --- /dev/null +++ b/src/main/java/thetadev/constructionwand/job/PlaceSnapshot.java @@ -0,0 +1,19 @@ +package thetadev.constructionwand.job; + +import net.minecraft.block.BlockState; +import net.minecraft.item.Item; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +public class PlaceSnapshot +{ + public BlockState block; + public BlockState supportingBlock; + public BlockPos pos; + + public PlaceSnapshot(BlockPos pos, BlockState supportingBlock) + { + this.pos = pos; + this.supportingBlock = supportingBlock; + } +} diff --git a/src/main/java/thetadev/constructionwand/job/TransductionJob.java b/src/main/java/thetadev/constructionwand/job/TransductionJob.java new file mode 100644 index 0000000..0418e16 --- /dev/null +++ b/src/main/java/thetadev/constructionwand/job/TransductionJob.java @@ -0,0 +1,32 @@ +package thetadev.constructionwand.job; + +import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.util.Direction; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.BlockRayTraceResult; +import net.minecraft.world.World; +import thetadev.constructionwand.items.ItemWand; + +public class TransductionJob extends WandJob +{ + public TransductionJob(PlayerEntity player, World world, BlockRayTraceResult rayTraceResult, ItemStack wand) { + super(player, world, rayTraceResult, wand); + } + + @Override + protected void getBlockPositionList() { + Direction placeDirection = rayTraceResult.getFace(); + BlockPos currentPos = rayTraceResult.getPos(); + BlockState supportingBlock = world.getBlockState(currentPos); + + for(int i=0; i placeSnapshots; + + public WandJob(PlayerEntity player, World world, BlockRayTraceResult rayTraceResult, ItemStack wand) + { + this.player = player; + this.world = world; + this.rayTraceResult = rayTraceResult; + placeSnapshots = new LinkedList<>(); + + // Get wand + if(wand == null || wand == ItemStack.EMPTY || !(wand.getItem() instanceof ItemWand)) return; + this.wand = wand; + + wandItem = (ItemWand) wand.getItem(); + + // Get options + options = new WandOptions(wand); + doReplace = options.getOption(EnumReplace.YES) == EnumReplace.YES; + targetDirection = options.getOption(EnumDirection.TARGET) == EnumDirection.TARGET; + + BlockPos targetPos = rayTraceResult.getPos(); + BlockState targetState = world.getBlockState(targetPos); + Block targetBlock = targetState.getBlock(); + ItemStack offhandStack = player.getHeldItem(Hand.OFF_HAND); + + // Get place item + Item item; + if(!offhandStack.isEmpty() && offhandStack.getItem() instanceof BlockItem) item = offhandStack.getItem(); + else { + //item = targetBlock.getBlock().getItem(world, targetPos, targetState).getItem(); + item = targetBlock.getPickBlock(targetState, rayTraceResult, world, targetPos, player).getItem(); + } + if(!(item instanceof BlockItem)) return; + placeItem = (BlockItem) item; + + // Get inventory supply + maxBlocks = Math.min(countItems(), wandItem.getLimit(player, wand)); + if(maxBlocks == 0) return; + + getBlockPositionList(); + } + + public static WandJob getJob(PlayerEntity player, World world, BlockRayTraceResult rayTraceResult, ItemStack itemStack) { + IEnumOption mode = new WandOptions(itemStack).getOption(EnumMode.DEFAULT); + + if(mode == EnumMode.ANGEL) return new TransductionJob(player, world, rayTraceResult, itemStack); + else return new ConstructionJob(player, world, rayTraceResult, itemStack); + } + + public LinkedList getBlockPositions() { + LinkedList res = new LinkedList<>(); + + for(PlaceSnapshot snapshot : placeSnapshots) { + res.add(snapshot.pos); + } + return res; + } + + public BlockRayTraceResult getRayTraceResult() { return rayTraceResult; } + + public BlockPos getTargetPos() { return rayTraceResult.getPos(); } + + public PlayerEntity getPlayer() { return player; } + + public void setPlayer(PlayerEntity player) { this.player = player; } + + public World getWorld() { return world; } + + public void setWorld(World world) { this.world = world; } + + public ItemStack getWand() { return wand; } + + protected int countItems() + { + if(player.inventory == null || player.inventory.mainInventory == null) return 0; + if(player.isCreative()) return Integer.MAX_VALUE; + + int total = 0; + ContainerManager containerManager = ConstructionWand.instance.containerManager; + LinkedList inventory = new LinkedList<>(player.inventory.offHandInventory); + inventory.addAll(player.inventory.mainInventory); + + for(ItemStack stack : inventory) { + if(stack == null) continue; + + if(WandUtil.stackEquals(stack, placeItem)) { + total += Math.max(0, stack.getCount()); + } + else { + int amount = containerManager.countItems(player, new ItemStack(placeItem), stack); + if(amount == Integer.MAX_VALUE) return Integer.MAX_VALUE; + total += amount; + } + } + return total; + } + + // Attempts to take specified number of items, returns number of missing items + protected int takeItems(int count) + { + if(player.inventory == null || player.inventory.mainInventory == null) return count; + if(player.isCreative()) return 0; + + LinkedList hotbar = new LinkedList<>(player.inventory.mainInventory.subList(0, 9)); + hotbar.addAll(player.inventory.offHandInventory); + LinkedList mainInv = new LinkedList<>(player.inventory.mainInventory.subList(9, player.inventory.mainInventory.size())); + + // Take items from main inv, loose items first + count = takeItemsInvList(count, mainInv, false); + count = takeItemsInvList(count, mainInv, true); + + // Take items from hotbar, containers first + count = takeItemsInvList(count, hotbar, true); + count = takeItemsInvList(count, hotbar, false); + + return count; + } + + private int takeItemsInvList(int count, LinkedList inv, boolean container) { + ContainerManager containerManager = ConstructionWand.instance.containerManager; + + for(ItemStack stack : inv) { + if(count == 0) break; + + if(container) { + int nCount = containerManager.useItems(player, new ItemStack(placeItem), stack, count); + count = nCount; + } + + if(!container && WandUtil.stackEquals(stack, placeItem)) { + int toTake = Math.min(count, stack.getCount()); + stack.shrink(toTake); + count -= toTake; + player.inventory.markDirty(); + } + } + return count; + } + + protected abstract void getBlockPositionList(); + + protected boolean canPlace(BlockPos pos) { + // Is position out of world? + if(!world.isBlockPresent(pos)) return false; + + // Is block at pos replaceable? + //BlockItemUseContext ctx = new WandItemUseContext(world, player, new ItemStack(placeItem), new BlockRayTraceResult(rayTraceResult.getHitVec(), rayTraceResult.getFace(), pos, false)); + BlockItemUseContext ctx = new WandItemUseContext(this, pos); + if(!ctx.canPlace()) return false; + + // If replace mode is off, target has to be air + if(!doReplace && !world.isAirBlock(pos)) return false; + + // Can block be placed? + BlockState blockState = placeItem.getBlock().getStateForPlacement(ctx); + if(blockState == null) return false; + blockState = Block.getValidBlockForPosition(blockState, world, pos); + if(blockState.getBlock() == Blocks.AIR || !blockState.isValidPosition(world, pos)) return false; + + // No entities colliding? + VoxelShape shape = blockState.getCollisionShape(world, pos); + if(shape.isEmpty()) return true; + AxisAlignedBB blockBB = shape.getBoundingBox().offset(pos); + return world.getEntitiesWithinAABB(LivingEntity.class, blockBB, EntityPredicates.NOT_SPECTATING).isEmpty(); + } + + private boolean placeBlock(PlaceSnapshot placeSnapshot) { + BlockPos blockPos = placeSnapshot.pos; + + //BlockItemUseContext ctx = new WandItemUseContext(world, player, new ItemStack(placeItem), new BlockRayTraceResult(rayTraceResult.getHitVec(), rayTraceResult.getFace(), blockPos, false)); + BlockItemUseContext ctx = new WandItemUseContext(this, blockPos); + if(!ctx.canPlace()) return false; + + BlockState placeBlock = Block.getBlockFromItem(placeItem).getStateForPlacement(ctx); + if(placeBlock == null) return false; + placeBlock = Block.getValidBlockForPosition(placeBlock, world, blockPos); + if(placeBlock.getBlock() == Blocks.AIR) return false; + + BlockState supportingBlock = placeSnapshot.supportingBlock; + + if(targetDirection) { + // Block properties to be copied (alignment/rotation properties) + for(IProperty property : new IProperty[] { + BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.FACING, BlockStateProperties.FACING_EXCEPT_UP, + BlockStateProperties.ROTATION_0_15, BlockStateProperties.AXIS, BlockStateProperties.HALF, BlockStateProperties.STAIRS_SHAPE}) + { + if(supportingBlock.has(property)) { + placeBlock = placeBlock.with(property, supportingBlock.get(property)); + } + } + + // Dont dupe double slabs + if(supportingBlock.has(BlockStateProperties.SLAB_TYPE)) { + SlabType slabType = supportingBlock.get(BlockStateProperties.SLAB_TYPE); + if(slabType != SlabType.DOUBLE) placeBlock = placeBlock.with(BlockStateProperties.SLAB_TYPE, slabType); + } + } + // Abort if placeEvent is canceled + BlockSnapshot snapshot = new BlockSnapshot(world, blockPos, placeBlock); + BlockEvent.EntityPlaceEvent placeEvent = new BlockEvent.EntityPlaceEvent(snapshot, placeBlock, player); + MinecraftForge.EVENT_BUS.post(placeEvent); + if(placeEvent.isCanceled()) return false; + + // Place the block + if(!world.setBlockState(blockPos, placeBlock)) { + ConstructionWand.LOGGER.info("Block could not be placed"); + return false; + } + world.notifyNeighbors(blockPos, placeBlock.getBlock()); + + // Update stats + player.addStat(Stats.ITEM_USED.get(placeItem)); + player.addStat(ModStats.USE_WAND); + + placeSnapshot.block = placeBlock; + return true; + } + + public boolean doIt() { + LinkedList placed = new LinkedList<>(); + + for(PlaceSnapshot snapshot : placeSnapshots) { + if(wand.isEmpty() || wandItem.getLimit(player, wand) == 0) continue; + + BlockPos pos = snapshot.pos; + + if(placeBlock(snapshot)) { + wand.damageItem(1, player, (e) -> e.sendBreakAnimation(player.swingingHand)); + + // If the item cant be taken, undo the placement + if(takeItems(1) == 0) placed.add(snapshot); + else { + ConstructionWand.LOGGER.info("Item could not be taken. Remove block: "+placeItem.toString()); + world.removeBlock(pos, false); + } + } + } + placeSnapshots = placed; + + // Play place sound + if(!placeSnapshots.isEmpty()) { + SoundType sound = placeSnapshots.getFirst().block.getSoundType(); + world.playSound(null, player.getPosition(), sound.getPlaceSound(), SoundCategory.BLOCKS, sound.volume, sound.pitch); + } + + // Add to job history for undo + if(placeSnapshots.size() > 1) ConstructionWand.instance.jobHistory.add(this); + + return !placeSnapshots.isEmpty(); + } + + public boolean undo() { + for(PlaceSnapshot snapshot : placeSnapshots) { + BlockState currentBlock = world.getBlockState(snapshot.pos); + + // If placed block is still present and can be broken, break it and return item + if(world.isBlockModifiable(player, snapshot.pos) && + (player.isCreative() || + (currentBlock.getBlockHardness(world, snapshot.pos) > -1 && world.getTileEntity(snapshot.pos) == null && currentBlock.getBlock() == snapshot.block.getBlock()))) + { + BlockEvent.BreakEvent breakEvent = new BlockEvent.BreakEvent(world, snapshot.pos, currentBlock, player); + MinecraftForge.EVENT_BUS.post(breakEvent); + if(breakEvent.isCanceled()) continue; + + world.removeBlock(snapshot.pos, false); + + if(!player.isCreative()) { + ItemStack stack = new ItemStack(placeItem); + if(!player.inventory.addItemStackToInventory(stack)) { + player.dropItem(stack, false); + } + } + } + } + player.inventory.markDirty(); + + // Play teleport sound + SoundEvent sound = SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT; + world.playSound(null, player.getPosition(), sound, SoundCategory.PLAYERS, 1.0F, 1.0F); + + return true; + } +} diff --git a/src/main/java/thetadev/constructionwand/network/PacketQueryUndo.java b/src/main/java/thetadev/constructionwand/network/PacketQueryUndo.java index 396d4a2..911c4e0 100644 --- a/src/main/java/thetadev/constructionwand/network/PacketQueryUndo.java +++ b/src/main/java/thetadev/constructionwand/network/PacketQueryUndo.java @@ -1,39 +1,39 @@ package thetadev.constructionwand.network; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.network.PacketBuffer; +import net.minecraftforge.fml.network.NetworkEvent; import thetadev.constructionwand.ConstructionWand; import java.util.function.Supplier; public class PacketQueryUndo { - public boolean undoPressed; + public boolean undoPressed; - public PacketQueryUndo(boolean undoPressed) { - this.undoPressed = undoPressed; - } + public PacketQueryUndo(boolean undoPressed) { + this.undoPressed = undoPressed; + } - public static void encode(PacketQueryUndo msg, FriendlyByteBuf buffer) { - buffer.writeBoolean(msg.undoPressed); - } + public static void encode(PacketQueryUndo msg, PacketBuffer buffer) { + buffer.writeBoolean(msg.undoPressed); + } - public static PacketQueryUndo decode(FriendlyByteBuf buffer) { - return new PacketQueryUndo(buffer.readBoolean()); - } + public static PacketQueryUndo decode(PacketBuffer buffer) { + return new PacketQueryUndo(buffer.readBoolean()); + } - public static class Handler - { - public static void handle(final PacketQueryUndo msg, final Supplier ctx) { - if(!ctx.get().getDirection().getReceptionSide().isServer()) return; + public static class Handler + { + public static void handle(final PacketQueryUndo msg, final Supplier ctx) { + if(!ctx.get().getDirection().getReceptionSide().isServer()) return; - ServerPlayer player = ctx.get().getSender(); - if(player == null) return; + ServerPlayerEntity player = ctx.get().getSender(); + if(player == null) return; - ConstructionWand.instance.undoHistory.updateClient(player, msg.undoPressed); + ConstructionWand.instance.jobHistory.updateClient(player, msg.undoPressed); - //ConstructionWand.LOGGER.debug("Undo queried"); - } - } + //ConstructionWand.LOGGER.debug("Undo queried"); + } + } } diff --git a/src/main/java/thetadev/constructionwand/network/PacketUndoBlocks.java b/src/main/java/thetadev/constructionwand/network/PacketUndoBlocks.java index 566ca6f..78f8ed4 100644 --- a/src/main/java/thetadev/constructionwand/network/PacketUndoBlocks.java +++ b/src/main/java/thetadev/constructionwand/network/PacketUndoBlocks.java @@ -1,50 +1,44 @@ package thetadev.constructionwand.network; -import net.minecraft.core.BlockPos; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.math.BlockPos; +import net.minecraftforge.fml.network.NetworkEvent; import thetadev.constructionwand.ConstructionWand; -import java.util.HashSet; -import java.util.Set; +import java.util.LinkedList; import java.util.function.Supplier; public class PacketUndoBlocks { - public HashSet undoBlocks; + public LinkedList undoBlocks; - public PacketUndoBlocks(Set undoBlocks) { - this.undoBlocks = new HashSet<>(undoBlocks); - } + public PacketUndoBlocks(LinkedList undoBlocks) { + this.undoBlocks = undoBlocks; + } - private PacketUndoBlocks(HashSet undoBlocks) { - this.undoBlocks = undoBlocks; - } + public static void encode(PacketUndoBlocks msg, PacketBuffer buffer) { + for(BlockPos pos : msg.undoBlocks) { + buffer.writeBlockPos(pos); + } + } - public static void encode(PacketUndoBlocks msg, FriendlyByteBuf buffer) { - for(BlockPos pos : msg.undoBlocks) { - buffer.writeBlockPos(pos); - } - } + public static PacketUndoBlocks decode(PacketBuffer buffer) { + LinkedList undoBlocks = new LinkedList<>(); - public static PacketUndoBlocks decode(FriendlyByteBuf buffer) { - HashSet undoBlocks = new HashSet<>(); + while(buffer.isReadable()) { + undoBlocks.add(buffer.readBlockPos()); + } + return new PacketUndoBlocks(undoBlocks); + } - while(buffer.isReadable()) { - undoBlocks.add(buffer.readBlockPos()); - } - return new PacketUndoBlocks(undoBlocks); - } + public static class Handler { + public static void handle(final PacketUndoBlocks msg, final Supplier ctx) { + if(!ctx.get().getDirection().getReceptionSide().isClient()) return; - public static class Handler - { - public static void handle(final PacketUndoBlocks msg, final Supplier ctx) { - if(!ctx.get().getDirection().getReceptionSide().isClient()) return; + //ConstructionWand.LOGGER.debug("PacketUndoBlocks received, Blocks: " + msg.undoBlocks.size()); + ConstructionWand.instance.renderBlockPreview.undoBlocks = msg.undoBlocks; - //ConstructionWand.LOGGER.debug("PacketUndoBlocks received, Blocks: " + msg.undoBlocks.size()); - ConstructionWand.instance.renderBlockPreview.undoBlocks = msg.undoBlocks; - - ctx.get().setPacketHandled(true); - } - } + ctx.get().setPacketHandled(true); + } + } } diff --git a/src/main/java/thetadev/constructionwand/network/PacketWandOption.java b/src/main/java/thetadev/constructionwand/network/PacketWandOption.java index e81d012..c4b4f29 100644 --- a/src/main/java/thetadev/constructionwand/network/PacketWandOption.java +++ b/src/main/java/thetadev/constructionwand/network/PacketWandOption.java @@ -1,60 +1,71 @@ package thetadev.constructionwand.network; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.IOption; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.items.wand.ItemWand; +import net.minecraft.entity.player.ServerPlayerEntity; +import net.minecraft.item.ItemStack; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.text.StringTextComponent; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.TranslationTextComponent; +import net.minecraftforge.fml.network.NetworkEvent; +import thetadev.constructionwand.ConstructionWand; +import thetadev.constructionwand.basics.*; +import thetadev.constructionwand.basics.options.IEnumOption; +import thetadev.constructionwand.basics.options.WandOptions; +import thetadev.constructionwand.items.ItemWand; +import java.util.Arrays; import java.util.function.Supplier; public class PacketWandOption { - public final String key; - public final String value; - public final boolean notify; + public byte[] options; - public PacketWandOption(IOption option, boolean notify) { - this(option.getKey(), option.getValueString(), notify); - } + public PacketWandOption(byte[] options) { + this.options = options; + } - private PacketWandOption(String key, String value, boolean notify) { - this.key = key; - this.value = value; - this.notify = notify; - } + public PacketWandOption(IEnumOption option, boolean dir) { + options = new byte[WandOptions.options.length]; - public static void encode(PacketWandOption msg, FriendlyByteBuf buffer) { - buffer.writeUtf(msg.key); - buffer.writeUtf(msg.value); - buffer.writeBoolean(msg.notify); - } + for(int i=0; i ctx) { - if(!ctx.get().getDirection().getReceptionSide().isServer()) return; + public static PacketWandOption decode(PacketBuffer buffer) { + byte[] options = buffer.readByteArray(WandOptions.options.length); + return new PacketWandOption(options); + } - ServerPlayer player = ctx.get().getSender(); - if(player == null) return; + public static class Handler + { + public static void handle(final PacketWandOption msg, final Supplier ctx) { + if(!ctx.get().getDirection().getReceptionSide().isServer()) return; - ItemStack wand = WandUtil.holdingWand(player); - if(wand == null) return; - WandOptions options = new WandOptions(wand); + ServerPlayerEntity player = ctx.get().getSender(); + if(player == null) return; - IOption option = options.get(msg.key); - if(option == null) return; - option.setValueString(msg.value); + ItemStack wand = WandUtil.holdingWand(player); + if(wand == null) return; + WandOptions options = new WandOptions(wand); - if(msg.notify) ItemWand.optionMessage(player, option); - player.getInventory().setChanged(); - } - } + String langPrefix = ConstructionWand.MODID + ".option."; + + for(int i=0; i1); + ItemWand.optionMessage(player, opt); + } + + player.inventory.markDirty(); + + //ConstructionWand.LOGGER.debug("Keys: "+ Arrays.toString(msg.options)); + } + } } diff --git a/src/main/java/thetadev/constructionwand/wand/WandItemUseContext.java b/src/main/java/thetadev/constructionwand/wand/WandItemUseContext.java deleted file mode 100644 index b1d5f50..0000000 --- a/src/main/java/thetadev/constructionwand/wand/WandItemUseContext.java +++ /dev/null @@ -1,33 +0,0 @@ -package thetadev.constructionwand.wand; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import thetadev.constructionwand.basics.WandUtil; - -public class WandItemUseContext extends BlockPlaceContext -{ - public WandItemUseContext(Level world, Player player, BlockHitResult rayTraceResult, BlockPos pos, BlockItem item) { - super(world, player, InteractionHand.MAIN_HAND, new ItemStack(item), - new BlockHitResult(getBlockHitVec(rayTraceResult, pos), rayTraceResult.getDirection(), pos, false)); - } - - private static Vec3 getBlockHitVec(BlockHitResult rayTraceResult, BlockPos pos) { - Vec3 hitVec = rayTraceResult.getLocation(); // Absolute coords of hit target - - Vec3 blockDelta = WandUtil.blockPosVec(rayTraceResult.getBlockPos()).subtract(WandUtil.blockPosVec(pos)); // Vector between start and current block - - return blockDelta.add(hitVec); // Absolute coords of current block hit target - } - - @Override - public boolean canPlace() { - return replaceClicked; - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/WandJob.java b/src/main/java/thetadev/constructionwand/wand/WandJob.java deleted file mode 100644 index 0eb6269..0000000 --- a/src/main/java/thetadev/constructionwand/wand/WandJob.java +++ /dev/null @@ -1,130 +0,0 @@ -package thetadev.constructionwand.wand; - -import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.HitResult; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.api.IWandSupplier; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.basics.ModStats; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.items.ModItems; -import thetadev.constructionwand.items.wand.ItemWand; -import thetadev.constructionwand.wand.supplier.SupplierInventory; -import thetadev.constructionwand.wand.supplier.SupplierRandom; -import thetadev.constructionwand.wand.undo.ISnapshot; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -public class WandJob -{ - public final Player player; - public final Level world; - public final BlockHitResult rayTraceResult; - public final WandOptions options; - public final ItemStack wand; - public final ItemWand wandItem; - - private final IWandAction wandAction; - private final IWandSupplier wandSupplier; - - private List placeSnapshots; - - public WandJob(Player player, Level world, BlockHitResult rayTraceResult, ItemStack wand) { - this.player = player; - this.world = world; - this.rayTraceResult = rayTraceResult; - this.placeSnapshots = new ArrayList<>(); - - // Get wand - this.wand = wand; - this.wandItem = (ItemWand) wand.getItem(); - options = new WandOptions(wand); - - // Select wand action and supplier based on options - wandSupplier = options.random.get() ? - new SupplierRandom(player, options) : new SupplierInventory(player, options); - wandAction = options.cores.get().getWandAction(); - - wandSupplier.getSupply(getTargetItem(world, rayTraceResult)); - } - - @Nullable - private static BlockItem getTargetItem(Level world, BlockHitResult rayTraceResult) { - // Get target item - Item tgitem = world.getBlockState(rayTraceResult.getBlockPos()).getBlock().asItem(); - if(!(tgitem instanceof BlockItem)) return null; - return (BlockItem) tgitem; - } - - public void getSnapshots() { - int limit; - // Infinity wand gets enhanced limit in creative mode - if(player.isCreative() && wandItem == ModItems.WAND_INFINITY.get()) limit = ConfigServer.LIMIT_CREATIVE.get(); - else limit = Math.min(wandItem.remainingDurability(wand), wandAction.getLimit(wand)); - - if(rayTraceResult.getType() == HitResult.Type.BLOCK) - placeSnapshots = wandAction.getSnapshots(world, player, rayTraceResult, wand, options, wandSupplier, limit); - else - placeSnapshots = wandAction.getSnapshotsFromAir(world, player, rayTraceResult, wand, options, wandSupplier, limit); - } - - public Set getBlockPositions() { - return placeSnapshots.stream().map(ISnapshot::getPos).collect(Collectors.toSet()); - } - - public int blockCount() { - return placeSnapshots.size(); - } - - public boolean doIt() { - ArrayList executed = new ArrayList<>(); - - for(ISnapshot snapshot : placeSnapshots) { - if(wand.isEmpty() || wandItem.remainingDurability(wand) == 0) break; - - if(snapshot.execute(world, player, rayTraceResult)) { - if(player.isCreative()) executed.add(snapshot); - else { - // If the item cant be taken, undo the placement - if(wandSupplier.takeItemStack(snapshot.getRequiredItems()) == 0) { - executed.add(snapshot); - wand.hurtAndBreak(1, player, e -> e.broadcastBreakEvent(InteractionHand.MAIN_HAND)); - } - else { - ConstructionWand.LOGGER.info("Item could not be taken. Remove block: " + - snapshot.getBlockState().getBlock().toString()); - snapshot.forceRestore(world); - } - } - player.awardStat(ModStats.USE_WAND); - } - } - placeSnapshots = executed; - - // Play place sound - if(!placeSnapshots.isEmpty()) { - SoundType sound = placeSnapshots.get(0).getBlockState().getSoundType(); - world.playSound(null, WandUtil.playerPos(player), sound.getPlaceSound(), SoundSource.BLOCKS, sound.volume, sound.pitch); - - // Add to job history for undo - ConstructionWand.instance.undoHistory.add(player, world, placeSnapshots); - } - - return !placeSnapshots.isEmpty(); - } -} \ No newline at end of file diff --git a/src/main/java/thetadev/constructionwand/wand/action/ActionAngel.java b/src/main/java/thetadev/constructionwand/wand/action/ActionAngel.java deleted file mode 100644 index 36033ab..0000000 --- a/src/main/java/thetadev/constructionwand/wand/action/ActionAngel.java +++ /dev/null @@ -1,71 +0,0 @@ -package thetadev.constructionwand.wand.action; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import net.minecraft.world.phys.Vec3; -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.api.IWandSupplier; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.wand.undo.ISnapshot; -import thetadev.constructionwand.wand.undo.PlaceSnapshot; - -import javax.annotation.Nonnull; -import java.util.LinkedList; -import java.util.List; - -public class ActionAngel implements IWandAction -{ - @Override - public int getLimit(ItemStack wand) { - return ConfigServer.getWandProperties(wand.getItem()).getAngel(); - } - - @Nonnull - @Override - public List getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { - LinkedList placeSnapshots = new LinkedList<>(); - - Direction placeDirection = rayTraceResult.getDirection(); - BlockPos currentPos = rayTraceResult.getBlockPos(); - BlockState supportingBlock = world.getBlockState(currentPos); - - for(int i = 0; i < limit; i++) { - currentPos = currentPos.offset(placeDirection.getOpposite().getNormal()); - - PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentPos, rayTraceResult, supportingBlock); - if(snapshot != null) { - placeSnapshots.add(snapshot); - break; - } - } - return placeSnapshots; - } - - @Nonnull - @Override - public List getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { - LinkedList placeSnapshots = new LinkedList<>(); - - if(!player.isCreative() && !ConfigServer.ANGEL_FALLING.get() && player.fallDistance > 10) return placeSnapshots; - - Vec3 playerVec = WandUtil.entityPositionVec(player); - Vec3 lookVec = player.getLookAngle().multiply(2, 2, 2); - Vec3 placeVec = playerVec.add(lookVec); - - BlockPos currentPos = new BlockPos(placeVec); - - PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentPos, rayTraceResult, null); - if(snapshot != null) placeSnapshots.add(snapshot); - - return placeSnapshots; - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/action/ActionConstruction.java b/src/main/java/thetadev/constructionwand/wand/action/ActionConstruction.java deleted file mode 100644 index c842ea0..0000000 --- a/src/main/java/thetadev/constructionwand/wand/action/ActionConstruction.java +++ /dev/null @@ -1,133 +0,0 @@ -package thetadev.constructionwand.wand.action; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.api.IWandSupplier; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.wand.undo.ISnapshot; -import thetadev.constructionwand.wand.undo.PlaceSnapshot; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -/** - * Default WandAction. Extends your building on the side you're facing. - */ -public class ActionConstruction implements IWandAction -{ - @Override - public int getLimit(ItemStack wand) { - return ConfigServer.getWandProperties(wand.getItem()).getLimit(); - } - - @Nonnull - @Override - public List getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { - LinkedList placeSnapshots = new LinkedList<>(); - LinkedList candidates = new LinkedList<>(); - HashSet allCandidates = new HashSet<>(); - - Direction placeDirection = rayTraceResult.getDirection(); - BlockState targetBlock = world.getBlockState(rayTraceResult.getBlockPos()); - BlockPos startingPoint = rayTraceResult.getBlockPos().offset(placeDirection.getNormal()); - - // Is place direction allowed by lock? - if(placeDirection == Direction.UP || placeDirection == Direction.DOWN) { - if(options.testLock(WandOptions.LOCK.NORTHSOUTH) || options.testLock(WandOptions.LOCK.EASTWEST)) - candidates.add(startingPoint); - } - else if(options.testLock(WandOptions.LOCK.HORIZONTAL) || options.testLock(WandOptions.LOCK.VERTICAL)) - candidates.add(startingPoint); - - while(!candidates.isEmpty() && placeSnapshots.size() < limit) { - BlockPos currentCandidate = candidates.removeFirst(); - try { - BlockPos supportingPoint = currentCandidate.offset(placeDirection.getOpposite().getNormal()); - BlockState candidateSupportingBlock = world.getBlockState(supportingPoint); - - if(options.matchBlocks(targetBlock.getBlock(), candidateSupportingBlock.getBlock()) && - allCandidates.add(currentCandidate)) { - PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentCandidate, rayTraceResult, candidateSupportingBlock); - if(snapshot == null) continue; - placeSnapshots.add(snapshot); - - switch(placeDirection) { - case DOWN: - case UP: - if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) { - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); - } - if(options.testLock(WandOptions.LOCK.EASTWEST)) { - candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); - } - if(options.testLock(WandOptions.LOCK.NORTHSOUTH) && options.testLock(WandOptions.LOCK.EASTWEST)) { - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal()).offset(Direction.WEST.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.WEST.getNormal())); - } - break; - case NORTH: - case SOUTH: - if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { - candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); - } - if(options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); - } - if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.WEST.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.WEST.getNormal())); - } - break; - case EAST: - case WEST: - if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); - } - if(options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); - } - if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.SOUTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.SOUTH.getNormal())); - } - break; - } - } - } catch(Exception e) { - // Can't do anything, could be anything. - // Skip if anything goes wrong. - } - } - return placeSnapshots; - } - - @Nonnull - @Override - public List getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { - return new ArrayList<>(); - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/action/ActionDestruction.java b/src/main/java/thetadev/constructionwand/wand/action/ActionDestruction.java deleted file mode 100644 index 9904c6d..0000000 --- a/src/main/java/thetadev/constructionwand/wand/action/ActionDestruction.java +++ /dev/null @@ -1,142 +0,0 @@ -package thetadev.constructionwand.wand.action; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.api.IWandAction; -import thetadev.constructionwand.api.IWandSupplier; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.wand.undo.DestroySnapshot; -import thetadev.constructionwand.wand.undo.ISnapshot; - -import javax.annotation.Nonnull; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; - -public class ActionDestruction implements IWandAction -{ - @Override - public int getLimit(ItemStack wand) { - return ConfigServer.getWandProperties(wand.getItem()).getDestruction(); - } - - @Nonnull - @Override - public List getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { - LinkedList destroySnapshots = new LinkedList<>(); - // Current list of block positions to process - LinkedList candidates = new LinkedList<>(); - // All positions that were processed (dont process blocks multiple times) - HashSet allCandidates = new HashSet<>(); - - // Block face the wand was pointed at - Direction breakFace = rayTraceResult.getDirection(); - // Block the wand was pointed at - BlockPos startingPoint = rayTraceResult.getBlockPos(); - BlockState targetBlock = world.getBlockState(rayTraceResult.getBlockPos()); - - // Is break direction allowed by lock? - // Tried to break blocks from top/bottom face, so the wand should allow breaking in NS/EW direction - if(breakFace == Direction.UP || breakFace == Direction.DOWN) { - if(options.testLock(WandOptions.LOCK.NORTHSOUTH) || options.testLock(WandOptions.LOCK.EASTWEST)) - candidates.add(startingPoint); - } - // Tried to break blocks from side face, so the wand should allow breaking in horizontal/vertical direction - else if(options.testLock(WandOptions.LOCK.HORIZONTAL) || options.testLock(WandOptions.LOCK.VERTICAL)) - candidates.add(startingPoint); - - // Process current candidates, stop when none are avaiable or block limit is reached - while(!candidates.isEmpty() && destroySnapshots.size() < limit) { - BlockPos currentCandidate = candidates.removeFirst(); - - // Only break blocks facing the player, with no collidable blocks in between - if(!WandUtil.isBlockPermeable(world, currentCandidate.offset(breakFace.getNormal()))) continue; - - try { - BlockState candidateBlock = world.getBlockState(currentCandidate); - - // If target and candidate blocks match and the current candidate has not been processed - if(options.matchBlocks(targetBlock.getBlock(), candidateBlock.getBlock()) && - allCandidates.add(currentCandidate)) { - DestroySnapshot snapshot = DestroySnapshot.get(world, player, currentCandidate); - if(snapshot == null) continue; - destroySnapshots.add(snapshot); - - switch(breakFace) { - case DOWN: - case UP: - if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) { - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); - } - if(options.testLock(WandOptions.LOCK.EASTWEST)) { - candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); - } - if(options.testLock(WandOptions.LOCK.NORTHSOUTH) && options.testLock(WandOptions.LOCK.EASTWEST)) { - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal()).offset(Direction.WEST.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.WEST.getNormal())); - } - break; - case NORTH: - case SOUTH: - if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { - candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); - } - if(options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); - } - if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.WEST.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.EAST.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.WEST.getNormal())); - } - break; - case EAST: - case WEST: - if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { - candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); - } - if(options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); - } - if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.SOUTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.NORTH.getNormal())); - candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.SOUTH.getNormal())); - } - break; - } - } - } catch(Exception e) { - // Can't do anything, could be anything. - // Skip if anything goes wrong. - } - } - return destroySnapshots; - } - - @Nonnull - @Override - public List getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, - ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { - return new ArrayList<>(); - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/supplier/SupplierInventory.java b/src/main/java/thetadev/constructionwand/wand/supplier/SupplierInventory.java deleted file mode 100644 index 8a74155..0000000 --- a/src/main/java/thetadev/constructionwand/wand/supplier/SupplierInventory.java +++ /dev/null @@ -1,144 +0,0 @@ -package thetadev.constructionwand.wand.supplier; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.api.IWandSupplier; -import thetadev.constructionwand.basics.ReplacementRegistry; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.basics.pool.IPool; -import thetadev.constructionwand.basics.pool.OrderedPool; -import thetadev.constructionwand.containers.ContainerManager; -import thetadev.constructionwand.wand.undo.PlaceSnapshot; - -import javax.annotation.Nullable; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.List; - -/** - * Default WandSupplier. Takes items from player inventory. - */ -public class SupplierInventory implements IWandSupplier -{ - protected final Player player; - protected final WandOptions options; - - protected HashMap itemCounts; - protected IPool itemPool; - - public SupplierInventory(Player player, WandOptions options) { - this.player = player; - this.options = options; - } - - public void getSupply(@Nullable BlockItem target) { - itemCounts = new LinkedHashMap<>(); - ItemStack offhandStack = player.getItemInHand(InteractionHand.OFF_HAND); - - itemPool = new OrderedPool<>(); - - // Block in offhand -> override - if(!offhandStack.isEmpty() && offhandStack.getItem() instanceof BlockItem) { - addBlockItem((BlockItem) offhandStack.getItem()); - } - // Otherwise use target block - else if(target != null && target != Items.AIR) { - addBlockItem(target); - - // Add replacement items - if(options.match.get() != WandOptions.MATCH.EXACT) { - for(Item it : ReplacementRegistry.getMatchingSet(target)) { - if(it instanceof BlockItem) addBlockItem((BlockItem) it); - } - } - } - } - - protected void addBlockItem(BlockItem item) { - int count = WandUtil.countItem(player, item); - if(count > 0) { - itemCounts.put(item, count); - itemPool.add(item); - } - } - - @Override - @Nullable - public PlaceSnapshot getPlaceSnapshot(Level world, BlockPos pos, BlockHitResult rayTraceResult, - @Nullable BlockState supportingBlock) { - if(!WandUtil.isPositionPlaceable(world, player, pos, options.replace.get())) return null; - itemPool.reset(); - - while(true) { - // Draw item from pool (returns null if none are left) - BlockItem item = itemPool.draw(); - if(item == null) return null; - - int count = itemCounts.get(item); - if(count == 0) continue; - - PlaceSnapshot placeSnapshot = PlaceSnapshot.get(world, player, rayTraceResult, pos, item, supportingBlock, options); - if(placeSnapshot != null) { - int ncount = count - 1; - itemCounts.put(item, ncount); - - // Remove item from pool if there are no items left - if(ncount == 0) itemPool.remove(item); - - return placeSnapshot; - } - } - } - - @Override - public int takeItemStack(ItemStack stack) { - int count = stack.getCount(); - Item item = stack.getItem(); - - if(player.getInventory().items == null) return count; - if(player.isCreative()) return 0; - - List hotbar = WandUtil.getHotbarWithOffhand(player); - List mainInv = WandUtil.getMainInv(player); - - // Take items from main inv, loose items first - count = takeItemsInvList(count, item, mainInv, false); - count = takeItemsInvList(count, item, mainInv, true); - - // Take items from hotbar, containers first - count = takeItemsInvList(count, item, hotbar, true); - count = takeItemsInvList(count, item, hotbar, false); - - return count; - } - - private int takeItemsInvList(int count, Item item, List inv, boolean container) { - ContainerManager containerManager = ConstructionWand.instance.containerManager; - - for(ItemStack stack : inv) { - if(count == 0) break; - - if(container) { - count = containerManager.useItems(player, new ItemStack(item), stack, count); - } - - if(!container && WandUtil.stackEquals(stack, item)) { - int toTake = Math.min(count, stack.getCount()); - stack.shrink(toTake); - count -= toTake; - player.getInventory().setChanged(); - } - } - return count; - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/supplier/SupplierRandom.java b/src/main/java/thetadev/constructionwand/wand/supplier/SupplierRandom.java deleted file mode 100644 index 8760aa4..0000000 --- a/src/main/java/thetadev/constructionwand/wand/supplier/SupplierRandom.java +++ /dev/null @@ -1,30 +0,0 @@ -package thetadev.constructionwand.wand.supplier; - -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.basics.pool.RandomPool; - -import javax.annotation.Nullable; -import java.util.LinkedHashMap; - -public class SupplierRandom extends SupplierInventory -{ - public SupplierRandom(Player player, WandOptions options) { - super(player, options); - } - - @Override - public void getSupply(@Nullable BlockItem target) { - itemCounts = new LinkedHashMap<>(); - - // Random mode -> add all items from hotbar - itemPool = new RandomPool<>(player.getRandom()); - - for(ItemStack stack : WandUtil.getHotbarWithOffhand(player)) { - if(stack.getItem() instanceof BlockItem) addBlockItem((BlockItem) stack.getItem()); - } - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/undo/DestroySnapshot.java b/src/main/java/thetadev/constructionwand/wand/undo/DestroySnapshot.java deleted file mode 100644 index 1606784..0000000 --- a/src/main/java/thetadev/constructionwand/wand/undo/DestroySnapshot.java +++ /dev/null @@ -1,77 +0,0 @@ -package thetadev.constructionwand.wand.undo; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.Fluids; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.basics.WandUtil; - -import javax.annotation.Nullable; - -public class DestroySnapshot implements ISnapshot -{ - private final BlockState block; - private final BlockPos pos; - - public DestroySnapshot(BlockState block, BlockPos pos) { - this.pos = pos; - this.block = block; - } - - @Nullable - public static DestroySnapshot get(Level world, Player player, BlockPos pos) { - if(!WandUtil.isBlockRemovable(world, player, pos)) return null; - - return new DestroySnapshot(world.getBlockState(pos), pos); - } - - @Override - public BlockPos getPos() { - return pos; - } - - @Override - public BlockState getBlockState() { - return block; - } - - @Override - public ItemStack getRequiredItems() { - return ItemStack.EMPTY; - } - - @Override - public boolean execute(Level world, Player player, BlockHitResult rayTraceResult) { - return WandUtil.removeBlock(world, player, block, pos); - } - - @Override - public boolean canRestore(Level world, Player player) { - // Is position out of world? - if(!world.isInWorldBounds(pos)) return false; - - // Is block modifiable? - if(!world.mayInteract(player, pos)) return false; - - // Ignore blocks and entities when in creative - if(player.isCreative()) return true; - - // Is block empty or fluid? - if(!world.isEmptyBlock(pos) && !world.getBlockState(pos).canBeReplaced(Fluids.EMPTY)) return false; - - return !WandUtil.entitiesCollidingWithBlock(world, block, pos); - } - - @Override - public boolean restore(Level world, Player player) { - return WandUtil.placeBlock(world, player, block, pos, null); - } - - @Override - public void forceRestore(Level world) { - world.setBlockAndUpdate(pos, block); - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/undo/ISnapshot.java b/src/main/java/thetadev/constructionwand/wand/undo/ISnapshot.java deleted file mode 100644 index c7ed971..0000000 --- a/src/main/java/thetadev/constructionwand/wand/undo/ISnapshot.java +++ /dev/null @@ -1,25 +0,0 @@ -package thetadev.constructionwand.wand.undo; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.BlockHitResult; - -public interface ISnapshot -{ - BlockPos getPos(); - - BlockState getBlockState(); - - ItemStack getRequiredItems(); - - boolean execute(Level world, Player player, BlockHitResult rayTraceResult); - - boolean canRestore(Level world, Player player); - - boolean restore(Level world, Player player); - - void forceRestore(Level world); -} diff --git a/src/main/java/thetadev/constructionwand/wand/undo/PlaceSnapshot.java b/src/main/java/thetadev/constructionwand/wand/undo/PlaceSnapshot.java deleted file mode 100644 index 732c2b0..0000000 --- a/src/main/java/thetadev/constructionwand/wand/undo/PlaceSnapshot.java +++ /dev/null @@ -1,130 +0,0 @@ -package thetadev.constructionwand.wand.undo; - -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.level.Level; -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.Property; -import net.minecraft.world.level.block.state.properties.SlabType; -import net.minecraft.world.phys.BlockHitResult; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.basics.option.WandOptions; -import thetadev.constructionwand.wand.WandItemUseContext; - -import javax.annotation.Nullable; - -public class PlaceSnapshot implements ISnapshot -{ - private BlockState block; - private final BlockPos pos; - private final BlockItem item; - private final BlockState supportingBlock; - private final boolean targetMode; - - public PlaceSnapshot(BlockState block, BlockPos pos, BlockItem item, BlockState supportingBlock, boolean targetMode) { - this.block = block; - this.pos = pos; - this.item = item; - this.supportingBlock = supportingBlock; - this.targetMode = targetMode; - } - - public static PlaceSnapshot get(Level world, Player player, BlockHitResult rayTraceResult, - BlockPos pos, BlockItem item, - @Nullable BlockState supportingBlock, @Nullable WandOptions options) { - boolean targetMode = options != null && supportingBlock != null && options.direction.get() == WandOptions.DIRECTION.TARGET; - BlockState blockState = getPlaceBlockstate(world, player, rayTraceResult, pos, item, supportingBlock, targetMode); - if(blockState == null) return null; - - return new PlaceSnapshot(blockState, pos, item, supportingBlock, targetMode); - } - - @Override - public BlockPos getPos() { - return pos; - } - - @Override - public BlockState getBlockState() { - return block; - } - - @Override - public ItemStack getRequiredItems() { - return new ItemStack(item); - } - - @Override - public boolean execute(Level world, Player player, BlockHitResult rayTraceResult) { - // Recalculate PlaceBlockState, because other blocks might be placed nearby - // Not doing this may cause game crashes (StackOverflowException) when placing lots of blocks - // with changing orientation like panes, iron bars or redstone. - block = getPlaceBlockstate(world, player, rayTraceResult, pos, item, supportingBlock, targetMode); - if(block == null) return false; - return WandUtil.placeBlock(world, player, block, pos, item); - } - - @Override - public boolean canRestore(Level world, Player player) { - return true; - } - - @Override - public boolean restore(Level world, Player player) { - return WandUtil.removeBlock(world, player, block, pos); - } - - @Override - public void forceRestore(Level world) { - world.removeBlock(pos, false); - } - - /** - * Tests if a certain block can be placed by the wand. - * If it can, returns the blockstate to be placed. - */ - @SuppressWarnings({"rawtypes", "unchecked"}) - @Nullable - private static BlockState getPlaceBlockstate(Level world, Player player, BlockHitResult rayTraceResult, - BlockPos pos, BlockItem item, - @Nullable BlockState supportingBlock, boolean targetMode) { - // Is block at pos replaceable? - BlockPlaceContext ctx = new WandItemUseContext(world, player, rayTraceResult, pos, item); - if(!ctx.canPlace()) return null; - - // Can block be placed? - BlockState blockState = item.getBlock().getStateForPlacement(ctx); - if(blockState == null || !blockState.canSurvive(world, pos)) return null; - - // Forbidden Tile Entity? - if(!WandUtil.isTEAllowed(blockState)) return null; - - // No entities colliding? - if(WandUtil.entitiesCollidingWithBlock(world, blockState, pos)) return null; - - // Copy block properties from supporting block - if(targetMode && supportingBlock != null) { - // Block properties to be copied (alignment/rotation properties) - - for(Property property : new Property[]{ - BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.FACING, BlockStateProperties.FACING_HOPPER, - BlockStateProperties.ROTATION_16, BlockStateProperties.AXIS, BlockStateProperties.HALF, BlockStateProperties.STAIRS_SHAPE}) { - if(supportingBlock.hasProperty(property) && blockState.hasProperty(property)) { - blockState = blockState.setValue(property, supportingBlock.getValue(property)); - } - } - - // Dont dupe double slabs - if(supportingBlock.hasProperty(BlockStateProperties.SLAB_TYPE) && blockState.hasProperty(BlockStateProperties.SLAB_TYPE)) { - SlabType slabType = supportingBlock.getValue(BlockStateProperties.SLAB_TYPE); - if(slabType != SlabType.DOUBLE) - blockState = blockState.setValue(BlockStateProperties.SLAB_TYPE, slabType); - } - } - return blockState; - } -} diff --git a/src/main/java/thetadev/constructionwand/wand/undo/UndoHistory.java b/src/main/java/thetadev/constructionwand/wand/undo/UndoHistory.java deleted file mode 100644 index 9443df5..0000000 --- a/src/main/java/thetadev/constructionwand/wand/undo/UndoHistory.java +++ /dev/null @@ -1,150 +0,0 @@ -package thetadev.constructionwand.wand.undo; - -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraftforge.network.PacketDistributor; -import thetadev.constructionwand.ConstructionWand; -import thetadev.constructionwand.basics.ConfigServer; -import thetadev.constructionwand.basics.WandUtil; -import thetadev.constructionwand.network.PacketUndoBlocks; - -import java.util.*; -import java.util.stream.Collectors; - -public class UndoHistory -{ - private final HashMap history; - - public UndoHistory() { - history = new HashMap<>(); - } - - private PlayerEntry getEntryFromPlayer(Player player) { - return history.computeIfAbsent(player.getUUID(), k -> new PlayerEntry()); - } - - public void add(Player player, Level world, List placeSnapshots) { - LinkedList list = getEntryFromPlayer(player).entries; - list.add(new HistoryEntry(placeSnapshots, world)); - while(list.size() > ConfigServer.UNDO_HISTORY.get()) list.removeFirst(); - } - - public void removePlayer(Player player) { - history.remove(player.getUUID()); - } - - public void updateClient(Player player, boolean ctrlDown) { - Level world = player.level; - if(world.isClientSide) return; - - // Set state of CTRL key - PlayerEntry playerEntry = getEntryFromPlayer(player); - playerEntry.undoActive = ctrlDown; - - LinkedList historyEntries = playerEntry.entries; - Set positions; - - // Send block positions of most recent entry to client - if(historyEntries.isEmpty()) positions = Collections.emptySet(); - else { - HistoryEntry entry = historyEntries.getLast(); - - if(entry == null || !entry.world.equals(world)) positions = Collections.emptySet(); - else positions = entry.getBlockPositions(); - } - - PacketUndoBlocks packet = new PacketUndoBlocks(positions); - ConstructionWand.instance.HANDLER.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), packet); - } - - public boolean isUndoActive(Player player) { - return getEntryFromPlayer(player).undoActive; - } - - public boolean undo(Player player, Level world, BlockPos pos) { - // If CTRL key is not pressed, return - PlayerEntry playerEntry = getEntryFromPlayer(player); - if(!playerEntry.undoActive) return false; - - // Get the most recent entry for undo - LinkedList historyEntries = playerEntry.entries; - if(historyEntries.isEmpty()) return false; - HistoryEntry entry = historyEntries.getLast(); - - // Player has to be in the same world and near the blocks - if(!entry.world.equals(world) || !entry.withinRange(pos)) return false; - - if(entry.undo(player)) { - historyEntries.remove(entry); - updateClient(player, true); - return true; - } - return false; - } - - private static class PlayerEntry - { - public final LinkedList entries; - public boolean undoActive; - - public PlayerEntry() { - entries = new LinkedList<>(); - undoActive = false; - } - } - - private static class HistoryEntry - { - public final List placeSnapshots; - public final Level world; - - public HistoryEntry(List placeSnapshots, Level world) { - this.placeSnapshots = placeSnapshots; - this.world = world; - } - - public Set getBlockPositions() { - return placeSnapshots.stream().map(ISnapshot::getPos).collect(Collectors.toSet()); - } - - public boolean withinRange(BlockPos pos) { - Set positions = getBlockPositions(); - - if(positions.contains(pos)) return true; - - for(BlockPos p : positions) { - if(pos.closerThan(p, 3)) return true; - } - return false; - } - - public boolean undo(Player player) { - // Check first if all snapshots can be restored - for(ISnapshot snapshot : placeSnapshots) { - if(!snapshot.canRestore(world, player)) return false; - } - for(ISnapshot snapshot : placeSnapshots) { - if(snapshot.restore(world, player) && !player.isCreative()) { - ItemStack stack = snapshot.getRequiredItems(); - - if(!player.getInventory().add(stack)) { - player.drop(stack, false); - } - } - } - player.getInventory().setChanged(); - - // Play teleport sound - SoundEvent sound = SoundEvents.CHORUS_FRUIT_TELEPORT; - world.playSound(null, WandUtil.playerPos(player), sound, SoundSource.PLAYERS, 1.0F, 1.0F); - - return true; - } - } -} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 880dce7..fe88cd8 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -1,31 +1,30 @@ -modLoader = "javafml" -loaderVersion = "[38,)" -license = "MIT License" +modLoader="javafml" +loaderVersion="[28,)" [[mods]] modId="constructionwand" version="${file.jarVersion}" displayName="Construction Wand" -displayURL="https://github.com/Theta-Dev/ConstructionWand" +displayURL="https://github.com/Theta-Dev/ConstructionWand" #optional logoFile="logo.png" authors="ThetaDev" description=''' Construction Wands make building easier! -With a Construction Wand you can place multiple blocks (up to 1024) at once, extending your build on the side you're -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. +With a Construction Wand you can place multiple blocks (up to 1024) at once, extending you build on the side you're facing. +Sneak+Right click to activate angel mode which allows you to place a block at the opposite side of the block facing you. +If you concentrate enough, you can even conjure a block in mid air! This is my first minecraft mod. May the odds be ever in your favor. ''' [[dependencies.constructionwand]] modId="forge" -mandatory = true -versionRange = "[38,)" -ordering = "NONE" + mandatory=true + versionRange="[28,)" + ordering="NONE" side="BOTH" [[dependencies.constructionwand]] modId="minecraft" -mandatory = true -versionRange = "[1.18, 1.19)" -ordering = "NONE" + mandatory=true + versionRange="[1.14.4]" + ordering="NONE" side="BOTH" diff --git a/src/main/resources/assets/constructionwand/lang/de_de.json b/src/main/resources/assets/constructionwand/lang/de_de.json index a4d2f8f..0db7b5c 100644 --- a/src/main/resources/assets/constructionwand/lang/de_de.json +++ b/src/main/resources/assets/constructionwand/lang/de_de.json @@ -3,31 +3,30 @@ "item.constructionwand.iron_wand": "Eiserner Stab", "item.constructionwand.diamond_wand": "Diamantener Stab", "item.constructionwand.infinity_wand": "Stab der Unendlichkeit", - "item.constructionwand.core_angel": "Kristall der Engel", - "item.constructionwand.core_destruction": "Kristall der Zerstörung", + + "constructionwand.key.category": "Construction Wand", + "constructionwand.key.wand": "Ausrichtung (+SHIFT: Ersetzungsmodus)", + "constructionwand.key.direction": "Ausrichtung", + "constructionwand.key.replace": "Ersetzungsmodus", "constructionwand.tooltip.blocks": "Max. %d Blöcke", "constructionwand.tooltip.shift": "Drücke [SHIFT]", - "constructionwand.tooltip.cores": "Kristalle im Stab:", - "constructionwand.tooltip.core_tip": "Kombiniere den Kristall mit deinem Stab im Craftingfeld", - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "Kristall der Konstruktion", - "constructionwand.option.cores.constructionwand:default.desc": "Platziere Blöcke, wohin du zeigst", - "constructionwand.option.cores.constructionwand:core_angel": "§6Kristall der Engel", - "constructionwand.option.cores.constructionwand:core_angel.desc": "Platziere hinter Blöcken sowie in der Luft", - "constructionwand.option.cores.constructionwand:core_destruction": "§cKristall der Zerstörung", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "Zerstöre Blöcke, wohin du zeigst", + "constructionwand.option.mode": "", + "constructionwand.option.mode.default": "Standardmodus", + "constructionwand.option.mode.default.desc": "Erweitere dein Gebäude auf der dir zugewandten Seite", + "constructionwand.option.mode.angel": "§6Engelsmodus", + "constructionwand.option.mode.angel.desc": "Platziere hinter Blöcken sowie in der Luft", "constructionwand.option.lock": "Beschränkung: ", "constructionwand.option.lock.horizontal": "§aHorizontal", - "constructionwand.option.lock.horizontal.desc": "Baut eine horizontale Säule vor dem Originalblock", + "constructionwand.option.lock.horizontal.desc": "Erweitert nach §arechts/links§f. Baut nicht auf der Ober/Unterseite", "constructionwand.option.lock.vertical": "§aVertikal", - "constructionwand.option.lock.vertical.desc": "Baut eine vertikale Säule vor dem Originalblock", - "constructionwand.option.lock.northsouth": "§6Nord/Süd", - "constructionwand.option.lock.northsouth.desc": "Baut eine Reihe in NS-Richtung auf dem Originalblock", - "constructionwand.option.lock.eastwest": "§6Ost/West", - "constructionwand.option.lock.eastwest.desc": "Baut eine Reihe in OW-Richtung auf dem Originalblock", + "constructionwand.option.lock.vertical.desc": "Erweitert nach §aoben/unten§f. Baut nicht auf der Ober/Unterseite", + "constructionwand.option.lock.northsouth": "§6North/South", + "constructionwand.option.lock.northsouth.desc": "Erweitert nach §aNorden/Süden§f. Baut nicht an den Seitenflächen", + "constructionwand.option.lock.eastwest": "§6East/West", + "constructionwand.option.lock.eastwest.desc": "Erweitert nach §aOsten/Westen§f. Baut nicht an den Seitenflächen", "constructionwand.option.lock.nolock": "§cKeine", "constructionwand.option.lock.nolock.desc": "Erweitert in jede Richtung", @@ -35,7 +34,7 @@ "constructionwand.option.direction.target": "§6Zielblock", "constructionwand.option.direction.target.desc": "Platziert Blöcke mit der selben Ausrichtung wie der Zielblock", "constructionwand.option.direction.player": "§aSpieler", - "constructionwand.option.direction.player.desc": "Platziert Blöcke in der Richtung, auf die der Spieler zeigt", + "constructionwand.option.direction.player.desc": "Place blocks facing the player", "constructionwand.option.replace": "Ersetzen: ", "constructionwand.option.replace.yes": "§aJa", @@ -43,28 +42,5 @@ "constructionwand.option.replace.no": "§cNein", "constructionwand.option.replace.no.desc": "Ersetzt keine Blöcke", - "constructionwand.option.match": "Vergleich: ", - "constructionwand.option.match.exact": "§aExakt", - "constructionwand.option.match.exact.desc": "Erweitert nur Blöcke, die gleich dem Startblock sind", - "constructionwand.option.match.similar": "§6Ähnlich", - "constructionwand.option.match.similar.desc": "Behandle ähnliche Blöcke (Erde/Gras) gleich", - "constructionwand.option.match.any": "§cAlle", - "constructionwand.option.match.any.desc": "Erweitert alle Blöcke", - - "constructionwand.option.random": "Zufallsmodus: ", - "constructionwand.option.random.yes": "§aEin", - "constructionwand.option.random.yes.desc": "Platziere zufällige Blöcke aus der Hotbar", - "constructionwand.option.random.no": "§cAus", - "constructionwand.option.random.no.desc": "Platziere Blöcke normal", - - "constructionwand.description.wand": "Ein %1$s kann maximal %2$d Blöcke auf der dir zugewandten Seite eines Bauwerks platzieren und hält %3$s.\n\nHalte %5$s gedrückt und scrolle, um die Platzierung zu beschränken (Horizontal, Vertikal, Nord/Süd, Ost/West, Keine).\n\nÖffne den Optionsbildschirm mit %6$s§9+Rechtsklick§0.\n\n§5§nRÜCKGÄNGIG§0§r\nHalte §9Schleichen+§0%4$s während du einen Block fokussierst. Die letzten platzierten Blöcke werden mit einem grünen Rahmen markiert. §9Schleichen+§0%4$s§9+Rechtsklick§0 auf einen dieser Blöcke macht diese Operation rückgängig und gibt dir alle Items zurück. Wenn du den Kristall der Zerstörung benutzt hast, werden die zerstörten Blöcke wiederhergestellt.\n\n§5§nCONTAINER§0§r\nShulkerkisten, Bündel und viele Container von anderen Mods können Baumaterial für deinen Stab bereitstellen.\n\n§5§nLINKE-HAND-PRIORITÄT§0§r\nWenn du einen Block in der linken Hand hältst, wird der Stab diesen anstatt des Blocks, den du anschaust, platzieren.", - "constructionwand.description.durability.limited": "für %d Blöcke", - "constructionwand.description.durability.unlimited": "unendlich lang", - "constructionwand.description.key.sneak": "Schleichen", - "constructionwand.description.key.sneak_opt": "Schleichen+%s", - "constructionwand.description.core": "§5§nINSTALLATION§0§r\nLege deinen neuen Kristall zusammen mit dem Stab auf eine Werkbank, um ihn einzusetzen. Um zwischen den Kristallen zu wechseln, halte %s gedrückt und klicke mit der linken Maustaste ins Leere. Alternativ kannst du den Kristall auch im Optionsbildschirm auswählen.", - "constructionwand.description.core_angel": "Der Kristall der Engel platziert einen Block auf der gegenüberliegenden Seites des Blocks (oder der Blockreihe) den du anschaust. Die maximale Entfernung hängt vom Material des Stabes ab. Ein Rechtsklick ins Leere platziert einen Block mitten in der Luft. Hierfür musst du den Block, den du platzieren willst, in der linken Hand halten.", - "constructionwand.description.core_destruction": "Der Kristall der Zerstörung zerstört Blöcke (keine Tile Entities) auf der dir zugewandten Seite. Die maximale Anzahl Blöcke hängt vonm Material des Stabes ab. Zerstörte Blöcke verschwinden im Nichts, du kannst Fehler jedoch rückgängig machen.", - "stat.constructionwand.use_wand": "Blöcke mithilfe des Stabs platziert" } \ No newline at end of file diff --git a/src/main/resources/assets/constructionwand/lang/en_us.json b/src/main/resources/assets/constructionwand/lang/en_us.json index 619fc45..2451ee7 100644 --- a/src/main/resources/assets/constructionwand/lang/en_us.json +++ b/src/main/resources/assets/constructionwand/lang/en_us.json @@ -3,31 +3,30 @@ "item.constructionwand.iron_wand": "Iron Wand", "item.constructionwand.diamond_wand": "Diamond Wand", "item.constructionwand.infinity_wand": "Infinity Wand", - "item.constructionwand.core_angel": "Angel Wand Core", - "item.constructionwand.core_destruction": "Destruction Wand Core", + + "constructionwand.key.category": "Construction Wand", + "constructionwand.key.wand": "Place direction (+SHIFT: Replacement mode)", + "constructionwand.key.direction": "Place direction", + "constructionwand.key.replace": "Replacement mode", "constructionwand.tooltip.blocks": "Max. %d blocks", "constructionwand.tooltip.shift": "Press [SHIFT]", - "constructionwand.tooltip.cores": "Wand cores:", - "constructionwand.tooltip.core_tip": "Combine the core with your wand in a crafting grid", - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "Construction Core", - "constructionwand.option.cores.constructionwand:default.desc": "Extend your building on the side facing you", - "constructionwand.option.cores.constructionwand:core_angel": "§6Angel Core", - "constructionwand.option.cores.constructionwand:core_angel.desc": "Place behind blocks and in mid air", - "constructionwand.option.cores.constructionwand:core_destruction": "§cDestruction Core", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "Destroys blocks on the side facing you", + "constructionwand.option.mode": "", + "constructionwand.option.mode.default": "Default mode", + "constructionwand.option.mode.default.desc": "Extend your building on the side facing you", + "constructionwand.option.mode.angel": "§6Angel mode", + "constructionwand.option.mode.angel.desc": "Place behind blocks and in mid air", "constructionwand.option.lock": "Restriction: ", - "constructionwand.option.lock.horizontal": "§aLeft/Right", - "constructionwand.option.lock.horizontal.desc": "Build a horizontal column in front of the original block", - "constructionwand.option.lock.vertical": "§aUp/Down", - "constructionwand.option.lock.vertical.desc": "Build a vertical column in front of the original block", + "constructionwand.option.lock.horizontal": "§aHorizontal", + "constructionwand.option.lock.horizontal.desc": "Extend §aleft/right§f from the original block. No building on top/bottom face", + "constructionwand.option.lock.vertical": "§aVertical", + "constructionwand.option.lock.vertical.desc": "Extend §aup/down§f from the original block. No building on top/bottom face", "constructionwand.option.lock.northsouth": "§6North/South", - "constructionwand.option.lock.northsouth.desc": "Build a row in N/S direction on top of the original block", + "constructionwand.option.lock.northsouth.desc": "Extend §anorth/south§f on top of the original block. No building on side faces", "constructionwand.option.lock.eastwest": "§6East/West", - "constructionwand.option.lock.eastwest.desc": "Build a row in E/W direction on top of the original block", + "constructionwand.option.lock.eastwest.desc": "Extend §aeast/west§f on top of the original block. No building on side faces", "constructionwand.option.lock.nolock": "§cNone", "constructionwand.option.lock.nolock.desc": "Extend from any side of the original block", @@ -43,28 +42,5 @@ "constructionwand.option.replace.no": "§cNo", "constructionwand.option.replace.no.desc": "Don't replace blocks", - "constructionwand.option.match": "Matching: ", - "constructionwand.option.match.exact": "§aExact", - "constructionwand.option.match.exact.desc": "Only extend blocks that are exactly the same", - "constructionwand.option.match.similar": "§6Similar", - "constructionwand.option.match.similar.desc": "Treat similar blocks (dirt/grass types) equally", - "constructionwand.option.match.any": "§cAny", - "constructionwand.option.match.any.desc": "Extend any block", - - "constructionwand.option.random": "Random: ", - "constructionwand.option.random.yes": "§aYes", - "constructionwand.option.random.yes.desc": "Place random blocks present in your hotbar", - "constructionwand.option.random.no": "§cNo", - "constructionwand.option.random.no.desc": "Don't randomize placed blocks", - - "constructionwand.description.wand": "The %1$s can place up to %2$d blocks at the side of a building facing you and lasts %3$s.\n\nHold down %5$s and scroll to change placement restriction (Horizontal, Vertical, North/South, East/West, No lock).\n\nOpen the option screen with %6$s§9+Right click§0.\n\n§5§nUNDO§0§r\nHolding down §9Sneak+§0%4$s while looking at a blocks will show you the last blocks you placed with a green border around them. §9Sneak+§0%4$s§9+Right clicking§0 any of them will undo the operation, giving you all the items back. If you used the Destruction core, it will restore the blocks.\n\n§5§nCONTAINERS§0§r\nShulker boxes, bundles and many containers from other mods can provide building blocks for the wand.\n\n§5§nOFFHAND PRIORITY§0§r\nHaving blocks in your offhand will place them instead of the block you're looking at.", - "constructionwand.description.durability.limited": "for %d blocks", - "constructionwand.description.durability.unlimited": "forever", - "constructionwand.description.key.sneak": "Sneak", - "constructionwand.description.key.sneak_opt": "Sneak+%s", - "constructionwand.description.core": "§5§nINSTALLATION§0§r\nPut your new core together with your wand in a crafting grid to install it. To switch between cores, hold down %s and left click empty space with your wand or use the option screen.", - "constructionwand.description.core_angel": "The angel core places a block on the opposite side of the block (or row of blocks) you are facing. Maximum distance depends on wand tier. Right click empty space to place a block in midair. To do that, you'll need to have the block you want to place in your offhand.", - "constructionwand.description.core_destruction": "The destruction core destroys blocks (no tile entities) on the side facing you. Maximum number of blocks depends on wand tier. Destroyed blocks disappear into the void, you can use the undo feature if you've made a mistake.", - "stat.constructionwand.use_wand": "Blocks placed using Wand" } \ No newline at end of file diff --git a/src/main/resources/assets/constructionwand/lang/ko_kr.json b/src/main/resources/assets/constructionwand/lang/ko_kr.json deleted file mode 100644 index 47df0b2..0000000 --- a/src/main/resources/assets/constructionwand/lang/ko_kr.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "item.constructionwand.stone_wand": "돌 완드", - "item.constructionwand.iron_wand": "철 완드", - "item.constructionwand.diamond_wand": "다이아몬드 완드", - "item.constructionwand.infinity_wand": "무한의 완드", - "item.constructionwand.core_angel": "천사 완드 코어", - "item.constructionwand.core_destruction": "파괴 완드 코어", - - "constructionwand.tooltip.blocks": "최대. %d 블록", - "constructionwand.tooltip.shift": "[SHIFT]를 누르세요.", - "constructionwand.tooltip.cores": "완드 코어:", - "constructionwand.tooltip.core_tip": "조합창에서 코어와 완드를 합치세요.", - - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "생성 코어", - "constructionwand.option.cores.constructionwand:default.desc": "당신 쪽으로 건물을 확장합니다.", - "constructionwand.option.cores.constructionwand:core_angel": "§6천사 코어", - "constructionwand.option.cores.constructionwand:core_angel.desc": "블록 뒤와 공중에 배치합니다.", - "constructionwand.option.cores.constructionwand:core_destruction": "§c파괴 코어", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "당신 쪽의 블록을 파괴합니다.", - - "constructionwand.option.lock": "제한: ", - "constructionwand.option.lock.horizontal": "§a오른쪽/왼쪽", - "constructionwand.option.lock.horizontal.desc": "원래 블록의 앞에 수평한 열을 만듭니다.", - "constructionwand.option.lock.vertical": "§a위/아래", - "constructionwand.option.lock.vertical.desc": "원래 블록의 앞에 수직한 열을 만듭니다.", - "constructionwand.option.lock.northsouth": "§6북쪽/남쪽", - "constructionwand.option.lock.northsouth.desc": "원래 블록의 위에 북/남 방향으로 행을 만듭니다.", - "constructionwand.option.lock.eastwest": "§6동쪽/서쪽", - "constructionwand.option.lock.eastwest.desc": "원래 블록의 위에 동/서 방향으로 행을 만듭니다.", - "constructionwand.option.lock.nolock": "§c없음", - "constructionwand.option.lock.nolock.desc": "원래 블록의 어느 방향으로도 확장합니다.", - - "constructionwand.option.direction": "방향: ", - "constructionwand.option.direction.target": "§6대상", - "constructionwand.option.direction.target.desc": "대상 블록과 같은 방향으로 블록을 배치합니다.", - "constructionwand.option.direction.player": "§a플레이어", - "constructionwand.option.direction.player.desc": "플레이어를 향해 블록을 배치합니다.", - - "constructionwand.option.replace": "재배치: ", - "constructionwand.option.replace.yes": "§a예", - "constructionwand.option.replace.yes.desc": "유체, 눈, 키 큰 잔디와 같은 특정 블록을 교체합니다.", - "constructionwand.option.replace.no": "§c아니오", - "constructionwand.option.replace.no.desc": "블록을 재배치하지 않습니다.", - - "constructionwand.option.match": "비교: ", - "constructionwand.option.match.exact": "§a정확", - "constructionwand.option.match.exact.desc": "완전히 같은 블록만 확장합니다.", - "constructionwand.option.match.similar": "§6유사", - "constructionwand.option.match.similar.desc": "비슷한 블록(흙/잔디)을 똑같이 취급합니다.", - "constructionwand.option.match.any": "§c아무거나", - "constructionwand.option.match.any.desc": "아무 블록이나 확장합니다.", - - "constructionwand.option.random": "무작위: ", - "constructionwand.option.random.yes": "§a예", - "constructionwand.option.random.yes.desc": "핫바에 있는 블록 중 무작위적으로 배치합니다.", - "constructionwand.option.random.no": "§c아니오", - "constructionwand.option.random.no.desc": "배치할 블록을 무작위적으로 하지 않습니다.", - - "constructionwand.description.wand": "%1$s는 당신 쪽으로 최대 %2$d 블록까지 배치할 수 있고, %3$s 지속됩니다.\n\n%5$s을(를) 누르고 스크롤 하여 배치 제한을 바꾸세요 (수평, 수직, 북쪽/남쪽, 동쪽/서쪽, 제한 없음).\n\n%6$s§9+우클릭§0으로 옵션 스크린을 여세요.\n\n§5§n실행 취소§0§r\n블록을 보면서 §9웅크리기+§0%4$s를 누르고 있으면 마지막으로 배치했던 블록들이 녹색 테두리로 표시됩니다. 그 중 아무거나 §9S웅크리기+§0%4$s§9+우클릭§0 하면 그 작업을 실행 취소하고, 모든 아이템을 돌려줍니다. 파괴 코어를 사용했다면, 블록들을 복원합니다.\n\n§5§n컨테이너§0§r\n셜커 상자, 꾸러미, 그리고 다른 모드의 컨테이너들은 완드에 건설 블록을 제공할 수 있습니다.\n\n§5§n보조손 우선도§0§r\n보조 손에 블록을 가지고 있으면 보고 있는 블록을 배치하는 대신에 보조 손의 블록을 배치할 것입니다.", - "constructionwand.description.durability.limited": "%d 블록 만큼", - "constructionwand.description.durability.unlimited": "영원히", - "constructionwand.description.key.sneak": "웅크리기", - "constructionwand.description.key.sneak_opt": "웅크리기+%s", - "constructionwand.description.core": "§5§n설치§0§r\n새 코어를 완드와 함께 조합창에 넣어 설치하세요. 코어 간에 전환하려면 %s 키를 누른 상태에서 완드로 빈 공간을 좌클릭하거나 옵션 화면을 사용하십시오.", - "constructionwand.description.core_angel": "엔젤 코어는 마주보고 있는 블록(또는 블록 행)의 반대쪽에 블록을 배치합니다. 최대 거리는 완드의 티어에 따라 다릅니다. 빈 공간을 우클릭하면 공중에 블록을 배치할 수 있습니다. 그렇게 하려면 보조 손에 배치하려는 블록이 있어야 합니다.", - "constructionwand.description.core_destruction": "파괴 코어는 당신 쪽의 (타일 엔티티가 없는)블록을 파괴합니다. 최대 블록 수는 완드의 티어에 따라 다릅니다. 파괴된 블록은 공허로 사라지며 실수를 했다면 실행 취소 기능을 사용할 수 있습니다.", - - "stat.constructionwand.use_wand": "완드로 배치한 블록 수" - } diff --git a/src/main/resources/assets/constructionwand/lang/pt_br.json b/src/main/resources/assets/constructionwand/lang/pt_br.json deleted file mode 100644 index b4c06aa..0000000 --- a/src/main/resources/assets/constructionwand/lang/pt_br.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "item.constructionwand.stone_wand": "Varinha de pedra", - "item.constructionwand.iron_wand": "Varinha de ferro", - "item.constructionwand.diamond_wand": "diamondWand", - "item.constructionwand.infinity_wand": "Varinha infinita", - "item.constructionwand.core_angel": "Angel Wand Core", - "item.constructionwand.core_destruction": "Destruction Wand Core", - - "constructionwand.tooltip.blocks": "Max. %d blocos", - "constructionwand.tooltip.shift": "Pressione Shift]", - "constructionwand.tooltip.cores": "Núcleos de varinhas:", - "constructionwand.tooltip.core_tip": "Combine o núcleo com sua varinha em uma grade de criação", - - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "Núcleo de construção", - "constructionwand.option.cores.constructionwand:default.desc": "Estender seu prédio do lado de frente para você", - "constructionwand.option.cores.constructionwand:core_angel": "§6angelCore", - "constructionwand.option.cores.constructionwand:core_angel.desc": "Coloque atrás dos quarteirões e no meio do ar", - "constructionwand.option.cores.constructionwand:core_destruction": "§cNúcleo de destruição", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "Destrói blocos do lado de frente para você", - - "constructionwand.option.lock": "Restrição: ", - "constructionwand.option.lock.horizontal": "§aEsquerda direita", - "constructionwand.option.lock.horizontal.desc": "Construa uma coluna horizontal em frente ao bloco original", - "constructionwand.option.lock.vertical": "§aCima baixo", - "constructionwand.option.lock.vertical.desc": "Construa uma coluna vertical em frente ao bloco original", - "constructionwand.option.lock.northsouth": "§6Norte Sul", - "constructionwand.option.lock.northsouth.desc": "Construa uma linha na direção N/s no topo do bloco original", - "constructionwand.option.lock.eastwest": "§6Leste Oeste", - "constructionwand.option.lock.eastwest.desc": "Construa uma linha na direção E/W no topo do bloco original", - "constructionwand.option.lock.nolock": "§cNenhum", - "constructionwand.option.lock.nolock.desc": "Estender de qualquer lado do bloco original", - - "constructionwand.option.direction": "Direção: ", - "constructionwand.option.direction.target": "§6Alvo", - "constructionwand.option.direction.target.desc": "Coloque blocos com a mesma direção que o bloco de destino", - "constructionwand.option.direction.player": "§aJogadora", - "constructionwand.option.direction.player.desc": "Coloque blocos de frente para o jogador", - - "constructionwand.option.replace": "Substituição: ", - "constructionwand.option.replace.yes": "§aSim", - "constructionwand.option.replace.yes.desc": "Substitua certos blocos como fluidos, neve e capim alto", - "constructionwand.option.replace.no": "§cNão", - "constructionwand.option.replace.no.desc": "Não substitua blocos", - - "constructionwand.option.match": "Coincidindo: ", - "constructionwand.option.match.exact": "§aExata", - "constructionwand.option.match.exact.desc": "Estender apenas blocos que são exatamente iguais", - "constructionwand.option.match.similar": "§6Semelhante", - "constructionwand.option.match.similar.desc": "Tratar blocos semelhantes (tipos de sujeira/grama) igualmente", - "constructionwand.option.match.any": "§cAlguma", - "constructionwand.option.match.any.desc": "Estender qualquer bloco", - - "constructionwand.option.random": "Aleatório: ", - "constructionwand.option.random.yes": "§aSim", - "constructionwand.option.random.yes.desc": "Coloque blocos aleatórios presentes em seu hotbar", - "constructionwand.option.random.no": "§cNão", - "constructionwand.option.random.no.desc": "Não randomize blocos colocados", - - "constructionwand.description.wand": "o %1$s pode colocar até %2$d bloqueios ao lado de um prédio de frente para você e dura %3$s.\n\nCalma %5$s e role para alterar a restrição de posicionamento (horizontal, vertical, norte/sul, leste/oeste, sem fechadura).\n\nAbra a tela de opção com %6$s§9+Clique com o botão direito do mouse§0.\n\n§5§nDESFAZER§0§r\nMantendo pressionada §9Esgueirar-se+§0%4$s Enquanto olha para um bloco, mostrará os últimos blocos que você colocou com uma borda verde ao redor deles. §9Esgueirar-se+§0%4$s§9+Certa clicando§0 Qualquer um deles desfazerá a operação, oferecendo todos os itens de volta.Se você usou o núcleo de destruição, ele restaurará os blocos.\n\n§5§nRECIPIENTES§0§r\nCaixas Shulker, pacotes e muitos contêineres de outros mods podem fornecer blocos de construção para a varinha.\n\n§5§nPrioridade imediata§0§r\nTer blocos em sua mão os colocará em vez do bloco que você está olhando.", - "constructionwand.description.durability.limited": "por %d blocos", - "constructionwand.description.durability.unlimited": "para todo sempre", - "constructionwand.description.key.sneak": "Esgueirar-se", - "constructionwand.description.key.sneak_opt": "Esgueirar-se+%s", - "constructionwand.description.core": "§5§nINSTALAÇÃO§0§r\nColoque seu novo núcleo junto com sua varinha em uma grade de criação para instalá -la.Para alternar entre núcleos, mantenha pressionado %s e o clique esquerdo, esvazie o espaço com sua varinha ou use a tela de opção.", - "constructionwand.description.core_angel": "O núcleo do anjo coloca um bloco no lado oposto do bloco (ou fileira de blocos) que você está enfrentando.A distância máxima depende da camada de varinha.Clique com o botão direito do mouse em espaço vazio para colocar um bloco no ar.Para fazer isso, você precisará ter o bloco que deseja colocar em sua mão.", - "constructionwand.description.core_destruction": "O núcleo de destruição destrói blocos (sem entidades de ladrilhos) do lado de frente para você.O número máximo de blocos depende da camada de varinha.Blocos destruídos desaparecem no vazio, você pode usar o recurso de desfazer se cometer um erro.", - - "stat.constructionwand.use_wand": "Blocos colocados usando varinha" - } \ No newline at end of file diff --git a/src/main/resources/assets/constructionwand/lang/ru_ru.json b/src/main/resources/assets/constructionwand/lang/ru_ru.json deleted file mode 100644 index 5e7ec8c..0000000 --- a/src/main/resources/assets/constructionwand/lang/ru_ru.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "item.constructionwand.stone_wand": "Каменный жезл", - "item.constructionwand.iron_wand": "Железный жезл", - "item.constructionwand.diamond_wand": "Алмазный жезл", - "item.constructionwand.infinity_wand": "Бесконечный жезл", - "item.constructionwand.core_angel": "Ангельское ядро для жезла", - "item.constructionwand.core_destruction": "Ядро разрушения для жезла", - - "constructionwand.tooltip.blocks": "Максимум %d блоков", - "constructionwand.tooltip.shift": "Нажмите [SHIFT]", - "constructionwand.tooltip.cores": "Ядер жезла:", - "constructionwand.tooltip.core_tip": "Объедините ядро со своим жезлом в сетке создания.", - - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "Ядро строительства", - "constructionwand.option.cores.constructionwand:default.desc": "Расширяйте свои строения на стороне, обращённой к Вам.", - "constructionwand.option.cores.constructionwand:core_angel": "§6Ангельское ядро", - "constructionwand.option.cores.constructionwand:core_angel.desc": "Размещает за блоками и в воздухе.", - "constructionwand.option.cores.constructionwand:core_destruction": "§cЯдро разрушения", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "Уничтожает блоки на стороне, обращённой к Вам.", - - "constructionwand.option.lock": "Ограничение: ", - "constructionwand.option.lock.horizontal": "§aВлево/Вправо", - "constructionwand.option.lock.horizontal.desc": "Строить горизонтальную колонну перед основным блоком.", - "constructionwand.option.lock.vertical": "§aВверх/Вниз", - "constructionwand.option.lock.vertical.desc": "Строить вертикальную колонну перед основным блоком.", - "constructionwand.option.lock.northsouth": "§6Север/Юг", - "constructionwand.option.lock.northsouth.desc": "Строить ряд в С/Ю направлении непосредственно за основным блоком.", - "constructionwand.option.lock.eastwest": "§6Восток/Запад", - "constructionwand.option.lock.eastwest.desc": "Строить ряд в В/З направлении непосредственно за основным блоком.", - "constructionwand.option.lock.nolock": "§cНичего", - "constructionwand.option.lock.nolock.desc": "Расширять с любой стороны основного блока.", - - "constructionwand.option.direction": "Направление: ", - "constructionwand.option.direction.target": "§6Цель", - "constructionwand.option.direction.target.desc": "Размещать блоки с таким же направлением как целевой блок.", - "constructionwand.option.direction.player": "§aИгрок", - "constructionwand.option.direction.player.desc": "Размещать блоки, обращённые к игроку.", - - "constructionwand.option.replace": "Замена: ", - "constructionwand.option.replace.yes": "§aДа", - "constructionwand.option.replace.yes.desc": "Заменять некоторые блоки как жидкости, снег и высокорослая трава.", - "constructionwand.option.replace.no": "§cНет", - "constructionwand.option.replace.no.desc": "Не заменять блоки.", - - "constructionwand.option.match": "Совпадение: ", - "constructionwand.option.match.exact": "§aТочное", - "constructionwand.option.match.exact.desc": "Расширять только абсолютно одинаковые блоки.", - "constructionwand.option.match.similar": "§6Похожее", - "constructionwand.option.match.similar.desc": "Подносить аналогичные блоки (пример: земля/трава) поровну.", - "constructionwand.option.match.any": "§cНикакое", - "constructionwand.option.match.any.desc": "Расширять любой блок.", - - "constructionwand.option.random": "Случайно: ", - "constructionwand.option.random.yes": "§aДа", - "constructionwand.option.random.yes.desc": "Размещать случайные блоки, имеющиеся в Вашей горячей панели.", - "constructionwand.option.random.no": "§cНет", - "constructionwand.option.random.no.desc": "Не располагать блоки в случайном порядке.", - - "constructionwand.description.wand": "%1$s может размещать до %2$d блоков сбоку от строения, обращённое к Вам и его хватит на %3$s блоков.\n\nУдерживайте %5$s и прокрутите колёсиком для изменения ограничения по размещении (Горизонтально, Вертикально, Север/Юг, Восток/Запад, Без ограничивания).\n\nОткройте экран настроек при помощи %6$s§9+щелчок правой кнопкой мыши§0.\n\n§5§nОТМЕНА§0§r\nУдерживайте §9Приседание+§0%4$s пока смотрите на блоки, установленные Вами, они будут выделены зелёным контуром. §9Приседание+§0%4$s§9+щелчок правой кнопкой мыши§0 на любой из них отменит операцию, вернув Вам все предметы обратно. Если использовать Ядро разрушения, то он вернёт блоки.\n\n§5§nКОНТЕЙНЕР§0§r\nШалкеровые ящики, мешки и множество контейнеров из других модов могут предоставлять строительные блоки в жезл.\n\n§5§nПРИОРИТЕТ ЛЕВОЙ РУКИ§0§r\nЕсли у Вас в левой руке находятся блоки, то они будут размещаться вместо блока, на который Вы смотрите.", - "constructionwand.description.durability.limited": "на %d блоков", - "constructionwand.description.durability.unlimited": "вечно", - "constructionwand.description.key.sneak": "Приседание", - "constructionwand.description.key.sneak_opt": "Приседание+%s", - "constructionwand.description.core": "§5§nУСТАНОВКА§0§r\nПоложите своё новое ядро вместе со своим жезлом в сетку создания для его установки. Для того, чтобы переключаться между ядрами, удерживайте %s и нажмите левую кнопку мыши по пустому пространству с жезлом в руке или используйте экран настроек.", - "constructionwand.description.core_angel": "Ангельское ядро размещает блоки на противоположной стороне блока (или ряда блоков), обращённые к Вам. Максимальное расстояние зависит от уровня жезла. Щелчок правой кнопкой мыши по пустому воздуху разместит блок в воздухе. Чтобы это сделать, Вам нужно иметь необходимые блоки в левой руке, чтобы разместить их.", - "constructionwand.description.core_destruction": "Ядро разрушения разрушает блоки (не функциональные блоки), обращённые к Вам. Максимально количество блоков зависит от уровня жезла. Разрушенные блоки исчезают в пустоту, можно использовать функцию отмены в случае допущенной ошибки.", - - "stat.constructionwand.use_wand": "Блоки, размещённые при помощи Жезла" -} diff --git a/src/main/resources/assets/constructionwand/lang/sv_se.json b/src/main/resources/assets/constructionwand/lang/sv_se.json deleted file mode 100644 index 23eb3bf..0000000 --- a/src/main/resources/assets/constructionwand/lang/sv_se.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "item.constructionwand.stone_wand": "Stenstav", - "item.constructionwand.iron_wand": "Järnstav", - "item.constructionwand.diamond_wand": "Diamantstav", - "item.constructionwand.infinity_wand": "Oändlighetsstav", - "item.constructionwand.core_angel": "Änglastavskärna", - "item.constructionwand.core_destruction": "Rivningsstavskärna", - - "constructionwand.tooltip.blocks": "Max. %d block", - "constructionwand.tooltip.shift": "Håll ned [SHIFT]", - "constructionwand.tooltip.cores": "Stavkärnor:", - "constructionwand.tooltip.core_tip": "Kombinera kärnan med din stav i ett tillverkningsrutnät", - - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "Byggkärna", - "constructionwand.option.cores.constructionwand:default.desc": "Utvidga din byggnad åt sidan som är riktad mot dig", - "constructionwand.option.cores.constructionwand:core_angel": "§6Änglakärna", - "constructionwand.option.cores.constructionwand:core_angel.desc": "Placera block bakom befintliga block och i luften", - "constructionwand.option.cores.constructionwand:core_destruction": "§cRivningskärna", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "Förstör block på sidan som är riktad mot dig", - - "constructionwand.option.lock": "Begränsning: ", - "constructionwand.option.lock.horizontal": "§aVänster/Höger", - "constructionwand.option.lock.horizontal.desc": "Bygg en horisontal kolumn framför originalblocket", - "constructionwand.option.lock.vertical": "§aUppåt/Nedåt", - "constructionwand.option.lock.vertical.desc": "Bygg en vertikal kolumn framför originalblocket", - "constructionwand.option.lock.northsouth": "§6Nord/Syd", - "constructionwand.option.lock.northsouth.desc": "Bygg en nord-/sydriktad rad ovanpå originalblocket", - "constructionwand.option.lock.eastwest": "§6Öst/Väst", - "constructionwand.option.lock.eastwest.desc": "Bygg en öst-/västriktad rad ovanpå originalblocket", - "constructionwand.option.lock.nolock": "§cIngen", - "constructionwand.option.lock.nolock.desc": "Utvidga från en valfri sida av originalblocket", - - "constructionwand.option.direction": "Riktning: ", - "constructionwand.option.direction.target": "§6Mål", - "constructionwand.option.direction.target.desc": "Placera block i samma riktning som målblocket", - "constructionwand.option.direction.player": "§aSpelare", - "constructionwand.option.direction.player.desc": "Placera block i samma riktning som spelaren tittar åt", - - "constructionwand.option.replace": "Ersättning: ", - "constructionwand.option.replace.yes": "§aJa", - "constructionwand.option.replace.yes.desc": "Ersätt vissa block, t.ex. vätskor, snö och högt gräs", - "constructionwand.option.replace.no": "§cNej", - "constructionwand.option.replace.no.desc": "Ersätt inte något block", - - "constructionwand.option.match": "Matchning: ", - "constructionwand.option.match.exact": "§aExakt", - "constructionwand.option.match.exact.desc": "Utvidga endast block som är exakt likadana", - "constructionwand.option.match.similar": "§6Liknande", - "constructionwand.option.match.similar.desc": "Behandla liknande block (jord-/grästyper) likadant", - "constructionwand.option.match.any": "§cAllting", - "constructionwand.option.match.any.desc": "Utvidga alla block", - - "constructionwand.option.random": "Slumpa: ", - "constructionwand.option.random.yes": "§aJa", - "constructionwand.option.random.yes.desc": "Placera slumpartade block från din föremålsmeny", - "constructionwand.option.random.no": "§cNej", - "constructionwand.option.random.no.desc": "Slumpa inte block som ska placeras ut", - - "constructionwand.description.wand": "En %1$s kan placera upp till %2$d block på sidan av en byggnad som är riktad mot dig och räcker %3$s.\n\nHåll ned %5$s och rulla med mushjulet för att ändra placeringsbegränsningen (horisontal, vertikal, nord/syd, öst/väst, ingen låsning).\n\nÖppna alternativmenyn med %6$s§9+Högerklick§0.\n\n§5§nÅNGRA§0§r\nNär du håller ned §9Smyga+§0%4$s medan du tittar på ett block kommer du se de senaste blocken du placerade omgivna av en grön ram. §9Smyg+§0%4$s§9+högerklicka§0 på något av dem för att ångra handlingen och få tillbaka alla föremål. Om du har använt rivningskärnan kommer blocken att återställas.\n\n§5§nBEHÅLLARE§0§r\nShulkerlådor, påsar och många behållare från andra moddar kan tillhandahålla byggblock för staven.\n\n§5§nPRIO FÖR SEKUNDÄR HAND§0§r\nBlocken i din sekundära hand placeras i stället för blocket du tittar på.", - "constructionwand.description.durability.limited": "för %d block", - "constructionwand.description.durability.unlimited": "för alltid", - "constructionwand.description.key.sneak": "Smyg", - "constructionwand.description.key.sneak_opt": "Smyg+%s", - "constructionwand.description.core": "§5§nINSTALLATION§0§r\nLägg din nya kärna tillsammans med din stav i ett tillverkningsrutnät för att installera den. Håll ned %s och vänsterklicka i luften med din stav eller använd alternativmenyn för att byta kärna.", - "constructionwand.description.core_angel": "Änglakärnan placerar ett block på den motsatta sidan av blocket (eller blockraden) som är riktad mot dig. Det maximala avståndet beror på stavens nivå. Högerklicka i luften för att placera ett block i luften. För att göra detta behöver du hålla blocket du vill placera i din sekundära hand.", - "constructionwand.description.core_destruction": "Rivningskärnan förstör block (inte blockentiteter) på sidan som är riktad mot dig. Det maximala antalet block beror på stavens nivå. Förstörda block försvinner helt och hållet, men du kan använda ångrafunktionen om du har gjort ett misstag.", - - "stat.constructionwand.use_wand": "Block placerade med stavar" -} diff --git a/src/main/resources/assets/constructionwand/lang/tr_tr.json b/src/main/resources/assets/constructionwand/lang/tr_tr.json deleted file mode 100644 index 05f5044..0000000 --- a/src/main/resources/assets/constructionwand/lang/tr_tr.json +++ /dev/null @@ -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ı açı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" -} \ No newline at end of file diff --git a/src/main/resources/assets/constructionwand/lang/zh_cn.json b/src/main/resources/assets/constructionwand/lang/zh_cn.json deleted file mode 100644 index 013bf8a..0000000 --- a/src/main/resources/assets/constructionwand/lang/zh_cn.json +++ /dev/null @@ -1,70 +0,0 @@ -{ - "item.constructionwand.stone_wand": "石制手杖", - "item.constructionwand.iron_wand": "铁制手杖", - "item.constructionwand.diamond_wand": "钻石手杖", - "item.constructionwand.infinity_wand": "无尽手杖", - "item.constructionwand.core_angel": "天使手杖核心", - "item.constructionwand.core_destruction": "破坏手杖核心", - - "constructionwand.tooltip.blocks": "最多放置%d个方块", - "constructionwand.tooltip.shift": "按 [SHIFT]", - "constructionwand.tooltip.cores": "手杖核心:", - "constructionwand.tooltip.core_tip": "将手杖核心与手杖组合在一起", - - "constructionwand.option.cores": "", - "constructionwand.option.cores.constructionwand:default": "建筑核心", - "constructionwand.option.cores.constructionwand:default.desc": "在面向你的一侧放置方块", - "constructionwand.option.cores.constructionwand:core_angel": "§6天使核心", - "constructionwand.option.cores.constructionwand:core_angel.desc": "在面向你的方块的背面放置方块,还可以悬空放置方块", - "constructionwand.option.cores.constructionwand:core_destruction": "§c毁灭核心", - "constructionwand.option.cores.constructionwand:core_destruction.desc": "破坏面向你一侧的方块", - - "constructionwand.option.lock": "锁定: ", - "constructionwand.option.lock.horizontal": "§a左 / 右", - "constructionwand.option.lock.horizontal.desc": "在起始方块的前面延伸一行水平方块", - "constructionwand.option.lock.vertical": "§a上 / 下", - "constructionwand.option.lock.vertical.desc": "在起始方块的前面延伸一列竖直方块", - "constructionwand.option.lock.northsouth": "§6南 / 北", - "constructionwand.option.lock.northsouth.desc": "在起始方块的上面,向南 / 北方向延伸一行", - "constructionwand.option.lock.eastwest": "§6东 / 西", - "constructionwand.option.lock.eastwest.desc": "在起始方块的上面,向东 / 西方向延伸一行", - "constructionwand.option.lock.nolock": "§c无", - "constructionwand.option.lock.nolock.desc": "从原始块的任意一面延伸", - - "constructionwand.option.direction": "方向: ", - "constructionwand.option.direction.target": "§6目标", - "constructionwand.option.direction.target.desc": "放置与的方块方向与目标方块的方向相同", - "constructionwand.option.direction.player": "§a玩家", - "constructionwand.option.direction.player.desc": "放置的方块面向玩家", - - "constructionwand.option.replace": "替换: ", - "constructionwand.option.replace.yes": "§a是", - "constructionwand.option.replace.yes.desc": "替换某些方块,如液体、雪、高草丛", - "constructionwand.option.replace.no": "§c否", - "constructionwand.option.replace.no.desc": "不替换方块", - - "constructionwand.option.match": "匹配: ", - "constructionwand.option.match.exact": "§a精确", - "constructionwand.option.match.exact.desc": "仅放置完全相同的方块", - "constructionwand.option.match.similar": "§6模糊", - "constructionwand.option.match.similar.desc": "相似的方块被认为是相同的(草方块 / 泥土类型)", - "constructionwand.option.match.any": "§c任意", - "constructionwand.option.match.any.desc": "放置任何方块", - - "constructionwand.option.random": "随机: ", - "constructionwand.option.random.yes": "§a是", - "constructionwand.option.random.yes.desc": "随机放置快捷栏中的方块", - "constructionwand.option.random.no": "§c否", - "constructionwand.option.random.no.desc": "不会随机放置方块", - - "constructionwand.description.wand": "%1$s可以在建筑物面向你的一侧放置最多%2$d个方块,持续时间为%3$s。\n\n按住%5$s并滚动以更改放置限制(水平、垂直、北/南、东/西、无锁定)。\n\n在选项配置GUI上打开%6$s§9+右键单击§0。\n\n§5§nUNDO§0§r\n在查看方块时向下折叠§9Sneak+§0%4$s将显示你放置的最后一个方块,并在其周围加上绿色边框。§9潜行+§0%4$s§9+右键单击其中任何一个方块将撤消操作,并将所有以此法放置的方块重返至玩家背包。如果你使用了破坏核心,它将恢复方块。\n\n§5§n容器§0§r\n潜影盒、收纳袋和许多其它模组存在于玩家背包内的容器都可以为建筑手杖提供构建所需的方块。\n\n§5§非即时优先级§0§r\n如果玩家在使用手杖时副手栏持有所需方块将被放置,而不是只是在你的手里放着。", - "constructionwand.description.durability.limited": "需要%d方块", - "constructionwand.description.durability.unlimited": "无限", - "constructionwand.description.key.sneak": "潜行", - "constructionwand.description.key.sneak_opt": "潜行+%s", - "constructionwand.description.core": "§5§n安装§0§r\n将新的手杖核心与你的手杖一起放入工作台中进行组装。如果你想要在核心功能之间切换,请按住%s并用手杖左键单击空地或使用手杖的选项配置GUI。", - "constructionwand.description.core_angel": "天使核心可将一个方块放置在你所面对的方块(或一排方块)的对面。最大距离取决于手杖材质。在空地上手持手杖并单击鼠标右键即可在空中放置方块。要做到这一点。你需要将想要被在空中放置的方块放在你的副手栏中。", - "constructionwand.description.core_destruction": "毁灭核心会破坏面向你一侧的方块(破坏时被破坏的方块不可存在实体)。最大破坏方块数取决于手杖材质。被使用毁灭核心破坏的方块会消失。如果你只是不小心使用了毁灭核心。可以使用“撤消”功能以撤回被破坏并消失的物品返回原处。", - - "stat.constructionwand.use_wand": "使用建筑手杖所放置的方块" -} diff --git a/src/main/resources/assets/constructionwand/models/item/diamond_wand.json b/src/main/resources/assets/constructionwand/models/item/diamond_wand.json new file mode 100644 index 0000000..e60a69b --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/diamond_wand.json @@ -0,0 +1,12 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/diamond_wand" + }, + "overrides": [{ + "predicate": { + "constructionwand:wand_mode": 1 + }, + "model": "constructionwand:item/diamond_wand_angel" + }] +} diff --git a/src/main/resources/assets/constructionwand/models/item/diamond_wand_angel.json b/src/main/resources/assets/constructionwand/models/item/diamond_wand_angel.json new file mode 100644 index 0000000..fc6c59b --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/diamond_wand_angel.json @@ -0,0 +1,7 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/diamond_wand", + "layer1": "constructionwand:items/overlay_angel" + } +} diff --git a/src/main/resources/assets/constructionwand/models/item/infinity_wand.json b/src/main/resources/assets/constructionwand/models/item/infinity_wand.json new file mode 100644 index 0000000..f095f9a --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/infinity_wand.json @@ -0,0 +1,12 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/infinity_wand" + }, + "overrides": [{ + "predicate": { + "constructionwand:wand_mode": 1 + }, + "model": "constructionwand:item/infinity_wand_angel" + }] +} diff --git a/src/main/resources/assets/constructionwand/models/item/infinity_wand_angel.json b/src/main/resources/assets/constructionwand/models/item/infinity_wand_angel.json new file mode 100644 index 0000000..8f65fec --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/infinity_wand_angel.json @@ -0,0 +1,7 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/infinity_wand", + "layer1": "constructionwand:items/overlay_angel" + } +} diff --git a/src/main/resources/assets/constructionwand/models/item/iron_wand.json b/src/main/resources/assets/constructionwand/models/item/iron_wand.json new file mode 100644 index 0000000..eaeb67a --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/iron_wand.json @@ -0,0 +1,12 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/iron_wand" + }, + "overrides": [{ + "predicate": { + "constructionwand:wand_mode": 1 + }, + "model": "constructionwand:item/iron_wand_angel" + }] +} diff --git a/src/main/resources/assets/constructionwand/models/item/iron_wand_angel.json b/src/main/resources/assets/constructionwand/models/item/iron_wand_angel.json new file mode 100644 index 0000000..c9eba70 --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/iron_wand_angel.json @@ -0,0 +1,7 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/iron_wand", + "layer1": "constructionwand:items/overlay_angel" + } +} diff --git a/src/main/resources/assets/constructionwand/models/item/stone_wand.json b/src/main/resources/assets/constructionwand/models/item/stone_wand.json new file mode 100644 index 0000000..7ea2a01 --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/stone_wand.json @@ -0,0 +1,12 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/stone_wand" + }, + "overrides": [{ + "predicate": { + "constructionwand:wand_mode": 1 + }, + "model": "constructionwand:item/stone_wand_angel" + }] +} diff --git a/src/main/resources/assets/constructionwand/models/item/stone_wand_angel.json b/src/main/resources/assets/constructionwand/models/item/stone_wand_angel.json new file mode 100644 index 0000000..c5d6367 --- /dev/null +++ b/src/main/resources/assets/constructionwand/models/item/stone_wand_angel.json @@ -0,0 +1,7 @@ +{ + "parent": "item/handheld", + "textures": { + "layer0": "constructionwand:items/stone_wand", + "layer1": "constructionwand:items/overlay_angel" + } +} diff --git a/src/main/resources/assets/constructionwand/textures/item/core_angel.png b/src/main/resources/assets/constructionwand/textures/item/core_angel.png deleted file mode 100644 index 4869087..0000000 Binary files a/src/main/resources/assets/constructionwand/textures/item/core_angel.png and /dev/null differ diff --git a/src/main/resources/assets/constructionwand/textures/item/core_destruction.png b/src/main/resources/assets/constructionwand/textures/item/core_destruction.png deleted file mode 100644 index 987968a..0000000 Binary files a/src/main/resources/assets/constructionwand/textures/item/core_destruction.png and /dev/null differ diff --git a/src/main/resources/assets/constructionwand/textures/item/overlay_core.png b/src/main/resources/assets/constructionwand/textures/item/overlay_core.png deleted file mode 100644 index b70e745..0000000 Binary files a/src/main/resources/assets/constructionwand/textures/item/overlay_core.png and /dev/null differ diff --git a/src/main/resources/assets/constructionwand/textures/item/diamond_wand.png b/src/main/resources/assets/constructionwand/textures/items/diamond_wand.png similarity index 100% rename from src/main/resources/assets/constructionwand/textures/item/diamond_wand.png rename to src/main/resources/assets/constructionwand/textures/items/diamond_wand.png diff --git a/src/main/resources/assets/constructionwand/textures/item/infinity_wand.png b/src/main/resources/assets/constructionwand/textures/items/infinity_wand.png similarity index 100% rename from src/main/resources/assets/constructionwand/textures/item/infinity_wand.png rename to src/main/resources/assets/constructionwand/textures/items/infinity_wand.png diff --git a/src/main/resources/assets/constructionwand/textures/item/iron_wand.png b/src/main/resources/assets/constructionwand/textures/items/iron_wand.png similarity index 100% rename from src/main/resources/assets/constructionwand/textures/item/iron_wand.png rename to src/main/resources/assets/constructionwand/textures/items/iron_wand.png diff --git a/src/main/resources/assets/constructionwand/textures/items/overlay_angel.png b/src/main/resources/assets/constructionwand/textures/items/overlay_angel.png new file mode 100644 index 0000000..be348ad Binary files /dev/null and b/src/main/resources/assets/constructionwand/textures/items/overlay_angel.png differ diff --git a/src/main/resources/assets/constructionwand/textures/item/stone_wand.png b/src/main/resources/assets/constructionwand/textures/items/stone_wand.png similarity index 100% rename from src/main/resources/assets/constructionwand/textures/item/stone_wand.png rename to src/main/resources/assets/constructionwand/textures/items/stone_wand.png diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta index 665308b..700e07e 100644 --- a/src/main/resources/pack.mcmeta +++ b/src/main/resources/pack.mcmeta @@ -1,6 +1,7 @@ { "pack": { - "description": "ConstructionWand resources", - "pack_format": 8 + "description": "examplemod resources", + "pack_format": 5, + "_comment": "A pack_format of 5 requires json lang files and some texture changes from 1.15. Note: we require v5 pack meta for all mods." } }