Compare commits

..

10 commits

Author SHA1 Message Date
cccc7df440 update pack.mcmeta version 2021-12-09 12:06:43 +01:00
f349055463 bump version 2.4 -> 2.5 2021-12-09 11:51:50 +01:00
57cde80ce8 update readme 2021-12-09 11:51:42 +01:00
A. Regnander
ff832e0893 Update sv_se.json
Added new strings
2021-12-09 11:50:22 +01:00
435c7e3809 fix wand getting damaged in creative mode 2021-12-09 11:50:04 +01:00
79fb151d27 add JEI ingame documentation 2021-12-09 11:46:51 +01:00
A. Regnander
f71f98d298 Create sv_se.json 2021-12-09 11:27:12 +01:00
ce17d53f4b Fix destruction behind permeable blocks 2021-10-22 17:36:35 +02:00
2cfc4fe790 Rework HandlerCapability 2021-10-22 15:50:47 +02:00
1e1847d5a3 Fix #40 wand replacing half slabs
Fix destruction wand removing blocks not facing the player
2021-10-22 15:50:44 +02:00
68 changed files with 858 additions and 1244 deletions

View file

@ -1,10 +1,10 @@
buildscript { buildscript {
repositories { repositories {
maven { url = 'https://maven.minecraftforge.net' } maven { url = 'https://files.minecraftforge.net/maven' }
mavenCentral() mavenCentral()
} }
dependencies { 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' apply plugin: 'net.minecraftforge.gradle'
@ -16,10 +16,10 @@ version = "${mcversion}-${version_major}.${version_minor}"
group = "${author}.${modid}" group = "${author}.${modid}"
archivesBaseName = "${modid}" archivesBaseName = "${modid}"
java.toolchain.languageVersion = JavaLanguageVersion.of(17) sourceCompatibility = targetCompatibility = compileJava.sourceCompatibility = compileJava.targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
minecraft { minecraft {
mappings channel: project.mcp_channel, version: project.mcp_mappings mappings channel: 'snapshot', version: project.mcp_mappings
runs { runs {
client { client {

View file

@ -4,15 +4,14 @@ org.gradle.daemon=false
author=thetadev author=thetadev
modid=constructionwand modid=constructionwand
mcversion=1.18.1 mcversion=1.16.5
forgeversion=39.1.0 forgeversion=36.2.19
mcp_channel=official mcp_mappings=20200723-1.16.1
mcp_mappings=1.18.1
# Source: https://maven.blamejared.com/vazkii/botania/Botania/ # Source: https://maven.blamejared.com/vazkii/botania/Botania/
botania=1.18.1-429 botania=1.16.2-405
# Source: https://dvs1.progwml6.com/files/maven/mezz/jei/ # Source: https://dvs1.progwml6.com/files/maven/mezz/jei/
jei_version=jei-1.18.1:9.1.0.41 jei_version=jei-1.16.5:7.7.1.137
version_major=2 version_major=2
version_minor=11 version_minor=5

Binary file not shown.

View file

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

55
gradlew vendored
View file

@ -1,21 +1,5 @@
#!/usr/bin/env sh #!/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 ## Gradle start up script for UN*X
@ -44,7 +28,7 @@ APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"` 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. # 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. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum" MAX_FD="maximum"
@ -72,7 +56,7 @@ case "`uname`" in
Darwin* ) Darwin* )
darwin=true darwin=true
;; ;;
MSYS* | MINGW* ) MINGW* )
msys=true msys=true
;; ;;
NONSTOP* ) NONSTOP* )
@ -82,7 +66,6 @@ esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
@ -126,11 +109,10 @@ if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi fi
# For Cygwin or MSYS, switch paths to Windows format before running java # For Cygwin, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"` APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"` JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath # We build the pattern for arguments to be converted via cygpath
@ -156,19 +138,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
else else
eval `echo args$i`="\"$arg\"" eval `echo args$i`="\"$arg\""
fi fi
i=`expr $i + 1` i=$((i+1))
done done
case $i in case $i in
0) set -- ;; (0) set -- ;;
1) set -- "$args0" ;; (1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;; (2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;; (3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;; (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac esac
fi fi
@ -177,9 +159,14 @@ save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " " echo " "
} }
APP_ARGS=`save "$@"` APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules # 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" 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" "$@" exec "$JAVACMD" "$@"

43
gradlew.bat vendored
View file

@ -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 @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@ -29,18 +13,15 @@ if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" set DEFAULT_JVM_OPTS=
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if "%ERRORLEVEL%" == "0" goto init
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -54,7 +35,7 @@ goto fail
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute if exist "%JAVA_EXE%" goto init
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
@ -64,14 +45,28 @@ echo location of your Java installation.
goto fail goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%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 :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View file

@ -1,6 +1,6 @@
package thetadev.constructionwand; package thetadev.constructionwand;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
@ -8,8 +8,8 @@ import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.fml.network.simple.SimpleChannel;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import thetadev.constructionwand.basics.ConfigClient; import thetadev.constructionwand.basics.ConfigClient;
@ -53,9 +53,6 @@ public class ConstructionWand
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup); FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
MinecraftForge.EVENT_BUS.register(this); MinecraftForge.EVENT_BUS.register(this);
// Register Item DeferredRegister
ModItems.ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
// Config setup // Config setup
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ConfigServer.SPEC); ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ConfigServer.SPEC);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigClient.SPEC); ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigClient.SPEC);

View file

@ -1,13 +1,13 @@
package thetadev.constructionwand.api; package thetadev.constructionwand.api;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
public interface IContainerHandler public interface IContainerHandler
{ {
boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack); boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack);
int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack); int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack);
int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count); int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count);
} }

View file

@ -1,9 +1,9 @@
package thetadev.constructionwand.api; package thetadev.constructionwand.api;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.wand.undo.ISnapshot; import thetadev.constructionwand.wand.undo.ISnapshot;
@ -15,10 +15,10 @@ public interface IWandAction
int getLimit(ItemStack wand); int getLimit(ItemStack wand);
@Nonnull @Nonnull
List<ISnapshot> getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, List<ISnapshot> getSnapshots(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit); ItemStack wand, WandOptions options, IWandSupplier supplier, int limit);
@Nonnull @Nonnull
List<ISnapshot> getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, List<ISnapshot> getSnapshotsFromAir(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit); ItemStack wand, WandOptions options, IWandSupplier supplier, int limit);
} }

View file

@ -1,11 +1,11 @@
package thetadev.constructionwand.api; package thetadev.constructionwand.api;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import thetadev.constructionwand.wand.undo.PlaceSnapshot; import thetadev.constructionwand.wand.undo.PlaceSnapshot;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -20,7 +20,7 @@ public interface IWandSupplier
* in that position. * in that position.
*/ */
@Nullable @Nullable
PlaceSnapshot getPlaceSnapshot(Level world, BlockPos pos, BlockHitResult rayTraceResult, PlaceSnapshot getPlaceSnapshot(World world, BlockPos pos, BlockRayTraceResult rayTraceResult,
@Nullable BlockState supportingBlock); @Nullable BlockState supportingBlock);
/** /**

View file

@ -1,6 +1,6 @@
package thetadev.constructionwand.api; package thetadev.constructionwand.api;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ResourceLocation;
public interface IWandUpgrade public interface IWandUpgrade
{ {

View file

@ -1,6 +1,6 @@
package thetadev.constructionwand.basics; 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.event.entity.player.PlayerEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
@ -11,8 +11,8 @@ public class CommonEvents
{ {
@SubscribeEvent @SubscribeEvent
public static void logOut(PlayerEvent.PlayerLoggedOutEvent e) { public static void logOut(PlayerEvent.PlayerLoggedOutEvent e) {
Player player = e.getPlayer(); PlayerEntity player = e.getPlayer();
if(player.level.isClientSide) return; if(player.getEntityWorld().isRemote) return;
ConstructionWand.instance.undoHistory.removePlayer(player); ConstructionWand.instance.undoHistory.removePlayer(player);
} }
} }

View file

@ -1,10 +1,8 @@
package thetadev.constructionwand.basics; package thetadev.constructionwand.basics;
import net.minecraft.resources.ResourceLocation; import net.minecraft.item.Item;
import net.minecraft.world.item.Item; import net.minecraft.item.ItemTier;
import net.minecraft.world.item.Tiers;
import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.registries.RegistryObject;
import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.items.ModItems;
import java.util.Arrays; import java.util.Arrays;
@ -22,17 +20,17 @@ public class ConfigServer
public static final ForgeConfigSpec.ConfigValue<List<?>> SIMILAR_BLOCKS; public static final ForgeConfigSpec.ConfigValue<List<?>> SIMILAR_BLOCKS;
private static final String[] SIMILAR_BLOCKS_DEFAULT = { 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" "minecraft:dirt;minecraft:grass_block;minecraft:coarse_dirt;minecraft:podzol;minecraft:mycelium;minecraft:farmland;minecraft:grass_path"
}; };
public static final ForgeConfigSpec.BooleanValue TE_WHITELIST; public static final ForgeConfigSpec.BooleanValue TE_WHITELIST;
public static final ForgeConfigSpec.ConfigValue<List<?>> TE_LIST; public static final ForgeConfigSpec.ConfigValue<List<?>> TE_LIST;
private static final String[] TE_LIST_DEFAULT = {"chiselsandbits"}; private static final String[] TE_LIST_DEFAULT = {"chiselsandbits"};
private static final HashMap<ResourceLocation, WandProperties> wandProperties = new HashMap<>(); private static final HashMap<Item, WandProperties> wandProperties = new HashMap<>();
public static WandProperties getWandProperties(Item wand) { public static WandProperties getWandProperties(Item wand) {
return wandProperties.getOrDefault(wand.getRegistryName(), WandProperties.DEFAULT); return wandProperties.getOrDefault(wand, WandProperties.DEFAULT);
} }
public static class WandProperties public static class WandProperties
@ -55,10 +53,9 @@ public class ConfigServer
this.upgradeable = upgradeable; this.upgradeable = upgradeable;
} }
public WandProperties(ForgeConfigSpec.Builder builder, RegistryObject<Item> wandSupplier, int defDurability, int defLimit, public WandProperties(ForgeConfigSpec.Builder builder, Item wand, int defDurability, int defLimit,
int defAngel, int defDestruction, boolean defUpgradeable) { int defAngel, int defDestruction, boolean defUpgradeable) {
ResourceLocation registryName = wandSupplier.getId(); builder.push(wand.getRegistryName().getPath());
builder.push(registryName.getPath());
if(defDurability > 0) { if(defDurability > 0) {
builder.comment("Wand durability"); builder.comment("Wand durability");
@ -75,7 +72,7 @@ public class ConfigServer
upgradeable = builder.define("upgradeable", defUpgradeable); upgradeable = builder.define("upgradeable", defUpgradeable);
builder.pop(); builder.pop();
wandProperties.put(registryName, this); wandProperties.put(wand, this);
} }
public int getDurability() { public int getDurability() {
@ -107,9 +104,9 @@ public class ConfigServer
"in the /saves/myworld/serverconfig folder. If you want to change the serverconfig for all", "in the /saves/myworld/serverconfig folder. If you want to change the serverconfig for all",
"new worlds, copy the config files in the /defaultconfigs folder."); "new worlds, copy the config files in the /defaultconfigs folder.");
new WandProperties(BUILDER, ModItems.WAND_STONE, Tiers.STONE.getUses(), 9, 0, 0, false); new WandProperties(BUILDER, ModItems.WAND_STONE, ItemTier.STONE.getMaxUses(), 9, 0, 0, false);
new WandProperties(BUILDER, ModItems.WAND_IRON, Tiers.IRON.getUses(), 27, 2, 9, true); new WandProperties(BUILDER, ModItems.WAND_IRON, ItemTier.IRON.getMaxUses(), 27, 2, 9, true);
new WandProperties(BUILDER, ModItems.WAND_DIAMOND, Tiers.DIAMOND.getUses(), 128, 8, 25, true); new WandProperties(BUILDER, ModItems.WAND_DIAMOND, ItemTier.DIAMOND.getMaxUses(), 128, 8, 25, true);
new WandProperties(BUILDER, ModItems.WAND_INFINITY, 0, 1024, 16, 81, true); new WandProperties(BUILDER, ModItems.WAND_INFINITY, 0, 1024, 16, 81, true);
BUILDER.push("misc"); BUILDER.push("misc");

View file

@ -1,9 +1,9 @@
package thetadev.constructionwand.basics; package thetadev.constructionwand.basics;
import net.minecraft.core.Registry; import net.minecraft.stats.IStatFormatter;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.stats.StatFormatter;
import net.minecraft.stats.Stats; import net.minecraft.stats.Stats;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
public class ModStats public class ModStats
@ -17,6 +17,6 @@ public class ModStats
private static void registerStat(ResourceLocation registryName) { private static void registerStat(ResourceLocation registryName) {
// Compare with net.minecraft.stats.Stats#registerCustom // Compare with net.minecraft.stats.Stats#registerCustom
Registry.register(Registry.CUSTOM_STAT, registryName.getPath(), registryName); Registry.register(Registry.CUSTOM_STAT, registryName.getPath(), registryName);
Stats.CUSTOM.get(registryName, StatFormatter.DEFAULT); Stats.CUSTOM.get(registryName, IStatFormatter.DEFAULT);
} }
} }

View file

@ -1,10 +1,8 @@
package thetadev.constructionwand.basics; package thetadev.constructionwand.basics;
import net.minecraft.resources.ResourceLocation; import net.minecraft.block.Block;
import net.minecraft.world.item.Item; import net.minecraft.item.Item;
import net.minecraft.world.item.Items; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
@ -22,7 +20,7 @@ public class ReplacementRegistry
for(String id : ((String) key).split(";")) { for(String id : ((String) key).split(";")) {
Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(id)); Item item = ForgeRegistries.ITEMS.getValue(new ResourceLocation(id));
if(item == null || item == Items.AIR) { if(item == null) {
ConstructionWand.LOGGER.warn("Replacement Registry: Could not find item " + id); ConstructionWand.LOGGER.warn("Replacement Registry: Could not find item " + id);
continue; continue;
} }
@ -44,7 +42,6 @@ public class ReplacementRegistry
public static boolean matchBlocks(Block b1, Block b2) { public static boolean matchBlocks(Block b1, Block b2) {
if(b1 == b2) return true; if(b1 == b2) return true;
if(b1 == Blocks.AIR || b2 == Blocks.AIR) return false;
for(HashSet<Item> set : replacements) { for(HashSet<Item> set : replacements) {
if(set.contains(b1.asItem()) && set.contains(b2.asItem())) return true; if(set.contains(b1.asItem()) && set.contains(b2.asItem())) return true;

View file

@ -1,27 +1,31 @@
package thetadev.constructionwand.basics; package thetadev.constructionwand.basics;
import net.minecraft.core.BlockPos; import net.minecraft.block.Block;
import net.minecraft.core.Direction; import net.minecraft.block.BlockState;
import net.minecraft.resources.ResourceLocation; import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.stats.Stats; import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand; import net.minecraft.util.Direction;
import net.minecraft.world.entity.Entity; import net.minecraft.util.EntityPredicates;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.util.Hand;
import net.minecraft.world.entity.player.Player; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.item.BlockItem; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.item.Item; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.item.Items; import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.level.Level; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.World;
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.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot; import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.BlockEvent;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.containers.ContainerManager; import thetadev.constructionwand.containers.ContainerManager;
import thetadev.constructionwand.items.wand.ItemWand; import thetadev.constructionwand.items.wand.ItemWand;
import thetadev.constructionwand.wand.WandItemUseContext; import thetadev.constructionwand.wand.WandItemUseContext;
@ -29,12 +33,11 @@ import thetadev.constructionwand.wand.WandItemUseContext;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.function.Predicate;
public class WandUtil public class WandUtil
{ {
public static boolean stackEquals(ItemStack stackA, ItemStack stackB) { public static boolean stackEquals(ItemStack stackA, ItemStack stackB) {
return ItemStack.isSameItemSameTags(stackA, stackB); return ItemStack.areItemsEqual(stackA, stackB) && ItemStack.areItemStackTagsEqual(stackA, stackB);
} }
public static boolean stackEquals(ItemStack stackA, Item item) { public static boolean stackEquals(ItemStack stackA, Item item) {
@ -42,45 +45,45 @@ public class WandUtil
return stackEquals(stackA, stackB); return stackEquals(stackA, stackB);
} }
public static ItemStack holdingWand(Player player) { public static ItemStack holdingWand(PlayerEntity player) {
if(player.getItemInHand(InteractionHand.MAIN_HAND) != ItemStack.EMPTY && player.getItemInHand(InteractionHand.MAIN_HAND).getItem() instanceof ItemWand) { if(player.getHeldItem(Hand.MAIN_HAND) != ItemStack.EMPTY && player.getHeldItem(Hand.MAIN_HAND).getItem() instanceof ItemWand) {
return player.getItemInHand(InteractionHand.MAIN_HAND); return player.getHeldItem(Hand.MAIN_HAND);
} }
else if(player.getItemInHand(InteractionHand.OFF_HAND) != ItemStack.EMPTY && player.getItemInHand(InteractionHand.OFF_HAND).getItem() instanceof ItemWand) { else if(player.getHeldItem(Hand.OFF_HAND) != ItemStack.EMPTY && player.getHeldItem(Hand.OFF_HAND).getItem() instanceof ItemWand) {
return player.getItemInHand(InteractionHand.OFF_HAND); return player.getHeldItem(Hand.OFF_HAND);
} }
return null; return null;
} }
public static BlockPos playerPos(Player player) { public static BlockPos playerPos(PlayerEntity player) {
return new BlockPos(player.position()); return new BlockPos(player.getPositionVec());
} }
public static Vec3 entityPositionVec(Entity entity) { public static Vector3d entityPositionVec(Entity entity) {
return new Vec3(entity.getX(), entity.getY() - entity.getMyRidingOffset() + entity.getBbHeight() / 2, entity.getZ()); return new Vector3d(entity.getPosX(), entity.getPosY() - entity.getYOffset() + entity.getHeight() / 2, entity.getPosZ());
} }
public static Vec3 blockPosVec(BlockPos pos) { public static Vector3d blockPosVec(BlockPos pos) {
return new Vec3(pos.getX(), pos.getY(), pos.getZ()); return new Vector3d(pos.getX(), pos.getY(), pos.getZ());
} }
public static List<ItemStack> getHotbar(Player player) { public static List<ItemStack> getHotbar(PlayerEntity player) {
return player.getInventory().items.subList(0, 9); return player.inventory.mainInventory.subList(0, 9);
} }
public static List<ItemStack> getHotbarWithOffhand(Player player) { public static List<ItemStack> getHotbarWithOffhand(PlayerEntity player) {
ArrayList<ItemStack> inventory = new ArrayList<>(player.getInventory().items.subList(0, 9)); ArrayList<ItemStack> inventory = new ArrayList<>(player.inventory.mainInventory.subList(0, 9));
inventory.addAll(player.getInventory().offhand); inventory.addAll(player.inventory.offHandInventory);
return inventory; return inventory;
} }
public static List<ItemStack> getMainInv(Player player) { public static List<ItemStack> getMainInv(PlayerEntity player) {
return player.getInventory().items.subList(9, player.getInventory().items.size()); return player.inventory.mainInventory.subList(9, player.inventory.mainInventory.size());
} }
public static List<ItemStack> getFullInv(Player player) { public static List<ItemStack> getFullInv(PlayerEntity player) {
ArrayList<ItemStack> inventory = new ArrayList<>(player.getInventory().offhand); ArrayList<ItemStack> inventory = new ArrayList<>(player.inventory.offHandInventory);
inventory.addAll(player.getInventory().items); inventory.addAll(player.inventory.mainInventory);
return inventory; return inventory;
} }
@ -89,7 +92,7 @@ public class WandUtil
} }
public static boolean isTEAllowed(BlockState state) { public static boolean isTEAllowed(BlockState state) {
if(!state.hasBlockEntity()) return true; if(!state.hasTileEntity()) return true;
ResourceLocation name = state.getBlock().getRegistryName(); ResourceLocation name = state.getBlock().getRegistryName();
if(name == null) return false; if(name == null) return false;
@ -103,14 +106,14 @@ public class WandUtil
return isWhitelist == inList; return isWhitelist == inList;
} }
public static boolean placeBlock(Level world, Player player, BlockState block, BlockPos pos, @Nullable BlockItem item) { public static boolean placeBlock(World world, PlayerEntity player, BlockState block, BlockPos pos, @Nullable BlockItem item) {
if(!world.setBlockAndUpdate(pos, block)) { if(!world.setBlockState(pos, block)) {
ConstructionWand.LOGGER.info("Block could not be placed"); ConstructionWand.LOGGER.info("Block could not be placed");
return false; return false;
} }
// Remove block if placeEvent is canceled // Remove block if placeEvent is canceled
BlockSnapshot snapshot = BlockSnapshot.create(world.dimension(), world, pos); BlockSnapshot snapshot = BlockSnapshot.create(world.func_234923_W_(), world, pos);
BlockEvent.EntityPlaceEvent placeEvent = new BlockEvent.EntityPlaceEvent(snapshot, block, player); BlockEvent.EntityPlaceEvent placeEvent = new BlockEvent.EntityPlaceEvent(snapshot, block, player);
MinecraftForge.EVENT_BUS.post(placeEvent); MinecraftForge.EVENT_BUS.post(placeEvent);
if(placeEvent.isCanceled()) { if(placeEvent.isCanceled()) {
@ -122,22 +125,22 @@ public class WandUtil
if(item == null) stack = new ItemStack(block.getBlock().asItem()); if(item == null) stack = new ItemStack(block.getBlock().asItem());
else { else {
stack = new ItemStack(item); stack = new ItemStack(item);
player.awardStat(Stats.ITEM_USED.get(item)); player.addStat(Stats.ITEM_USED.get(item));
} }
// Call OnBlockPlaced method // Call OnBlockPlaced method
block.getBlock().setPlacedBy(world, pos, block, player, stack); block.getBlock().onBlockPlacedBy(world, pos, block, player, stack);
return true; return true;
} }
public static boolean removeBlock(Level world, Player player, @Nullable BlockState block, BlockPos pos) { public static boolean removeBlock(World world, PlayerEntity player, @Nullable BlockState block, BlockPos pos) {
BlockState currentBlock = world.getBlockState(pos); BlockState currentBlock = world.getBlockState(pos);
if(!world.mayInteract(player, pos)) return false; if(!world.isBlockModifiable(player, pos)) return false;
if(!player.isCreative()) { if(!player.isCreative()) {
if(currentBlock.getDestroySpeed(world, pos) <= -1 || world.getBlockEntity(pos) != null) return false; if(currentBlock.getBlockHardness(world, pos) <= -1 || world.getTileEntity(pos) != null) return false;
if(block != null) if(block != null)
if(!ReplacementRegistry.matchBlocks(currentBlock.getBlock(), block.getBlock())) return false; if(!ReplacementRegistry.matchBlocks(currentBlock.getBlock(), block.getBlock())) return false;
@ -151,8 +154,8 @@ public class WandUtil
return true; return true;
} }
public static int countItem(Player player, Item item) { public static int countItem(PlayerEntity player, Item item) {
if(player.getInventory().items == null) return 0; if(player.inventory == null || player.inventory.mainInventory == null) return 0;
if(player.isCreative()) return Integer.MAX_VALUE; if(player.isCreative()) return Integer.MAX_VALUE;
int total = 0; int total = 0;
@ -160,7 +163,7 @@ public class WandUtil
List<ItemStack> inventory = WandUtil.getFullInv(player); List<ItemStack> inventory = WandUtil.getFullInv(player);
for(ItemStack stack : inventory) { for(ItemStack stack : inventory) {
if(stack == null || stack.isEmpty()) continue; if(stack == null) continue;
if(WandUtil.stackEquals(stack, item)) { if(WandUtil.stackEquals(stack, item)) {
total += stack.getCount(); total += stack.getCount();
@ -174,16 +177,28 @@ public class WandUtil
return total; return total;
} }
private static boolean isPositionModifiable(Level world, Player player, BlockPos pos) { public static boolean matchBlocks(WandOptions options, Block b1, Block b2) {
switch(options.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;
}
private static boolean isPositionModifiable(World world, PlayerEntity player, BlockPos pos) {
// Is position out of world? // Is position out of world?
if(!world.isInWorldBounds(pos)) return false; if(!world.isBlockPresent(pos)) return false;
// Is block modifiable? // Is block modifiable?
if(!world.mayInteract(player, pos)) return false; if(!world.isBlockModifiable(player, pos)) return false;
// Limit range // Limit range
if(ConfigServer.MAX_RANGE.get() > 0 && if(ConfigServer.MAX_RANGE.get() > 0 &&
WandUtil.blockDistance(player.blockPosition(), pos) > ConfigServer.MAX_RANGE.get()) return false; WandUtil.blockDistance(player.getPosition(), pos) > ConfigServer.MAX_RANGE.get()) return false;
return true; return true;
} }
@ -192,42 +207,42 @@ public class WandUtil
* Tests if a wand can place a block at a certain position. * Tests if a wand can place a block at a certain position.
* This check is independent of the used block. * This check is independent of the used block.
*/ */
public static boolean isPositionPlaceable(Level world, Player player, BlockPos pos, boolean replace) { public static boolean isPositionPlaceable(World world, PlayerEntity player, BlockPos pos, boolean replace) {
if(!isPositionModifiable(world, player, pos)) return false; if(!isPositionModifiable(world, player, pos)) return false;
// If replace mode is off, target has to be air // If replace mode is off, target has to be air
if(world.isEmptyBlock(pos)) return true; if(world.isAirBlock(pos)) return true;
// Otherwise, check if the block can be replaced by a generic block // Otherwise, check if the block can be replaced by a generic block
return replace && world.getBlockState(pos).canBeReplaced( return replace && world.getBlockState(pos).isReplaceable(
new WandItemUseContext(world, player, new WandItemUseContext(world, player,
new BlockHitResult(new Vec3(0, 0, 0), Direction.DOWN, pos, false), new BlockRayTraceResult(new Vector3d(0, 0, 0), Direction.DOWN, pos, false),
pos, (BlockItem) Items.STONE)); pos, (BlockItem) Items.STONE));
} }
public static boolean isBlockRemovable(Level world, Player player, BlockPos pos) { public static boolean isBlockRemovable(World world, PlayerEntity player, BlockPos pos) {
if(!isPositionModifiable(world, player, pos)) return false; if(!isPositionModifiable(world, player, pos)) return false;
if(!player.isCreative()) { if(!player.isCreative()) {
return !(world.getBlockState(pos).getDestroySpeed(world, pos) <= -1) && world.getBlockEntity(pos) == null; return !(world.getBlockState(pos).getBlockHardness(world, pos) <= -1) && world.getTileEntity(pos) == null;
} }
return true; return true;
} }
public static boolean isBlockPermeable(Level world, BlockPos pos) { public static boolean isBlockPermeable(World world, BlockPos pos) {
return world.isEmptyBlock(pos) || world.getBlockState(pos).getCollisionShape(world, pos).isEmpty(); return world.isAirBlock(pos) || world.getBlockState(pos).getCollisionShape(world, pos).isEmpty();
} }
public static boolean entitiesCollidingWithBlock(Level world, BlockState blockState, BlockPos pos) { public static boolean entitiesCollidingWithBlock(World world, BlockState blockState, BlockPos pos) {
VoxelShape shape = blockState.getCollisionShape(world, pos); VoxelShape shape = blockState.getCollisionShape(world, pos);
if(!shape.isEmpty()) { if(!shape.isEmpty()) {
AABB blockBB = shape.bounds().move(pos); AxisAlignedBB blockBB = shape.getBoundingBox().offset(pos);
return !world.getEntitiesOfClass(LivingEntity.class, blockBB, Predicate.not(Entity::isSpectator)).isEmpty(); return !world.getEntitiesWithinAABB(LivingEntity.class, blockBB, EntityPredicates.NOT_SPECTATING).isEmpty();
} }
return false; return false;
} }
public static Direction fromVector(Vec3 vector) { public static Direction fromVector(Vector3d vector) {
return Direction.getNearest(vector.x, vector.y, vector.z); return Direction.getFacingFromVector(vector.x, vector.y, vector.z);
} }
} }

View file

@ -1,15 +1,15 @@
package thetadev.constructionwand.basics.option; package thetadev.constructionwand.basics.option;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundNBT;
public class OptionBoolean implements IOption<Boolean> public class OptionBoolean implements IOption<Boolean>
{ {
private final CompoundTag tag; private final CompoundNBT tag;
private final String key; private final String key;
private final boolean enabled; private final boolean enabled;
private boolean value; private boolean value;
public OptionBoolean(CompoundTag tag, String key, boolean dval, boolean enabled) { public OptionBoolean(CompoundNBT tag, String key, boolean dval, boolean enabled) {
this.tag = tag; this.tag = tag;
this.key = key; this.key = key;
this.enabled = enabled; this.enabled = enabled;
@ -18,7 +18,7 @@ public class OptionBoolean implements IOption<Boolean>
else value = dval; else value = dval;
} }
public OptionBoolean(CompoundTag tag, String key, boolean dval) { public OptionBoolean(CompoundNBT tag, String key, boolean dval) {
this(tag, key, dval, true); this(tag, key, dval, true);
} }

View file

@ -1,18 +1,18 @@
package thetadev.constructionwand.basics.option; package thetadev.constructionwand.basics.option;
import com.google.common.base.Enums; import com.google.common.base.Enums;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundNBT;
public class OptionEnum<E extends Enum<E>> implements IOption<E> public class OptionEnum<E extends Enum<E>> implements IOption<E>
{ {
private final CompoundTag tag; private final CompoundNBT tag;
private final String key; private final String key;
private final Class<E> enumClass; private final Class<E> enumClass;
private final boolean enabled; private final boolean enabled;
private final E dval; private final E dval;
private E value; private E value;
public OptionEnum(CompoundTag tag, String key, Class<E> enumClass, E dval, boolean enabled) { public OptionEnum(CompoundNBT tag, String key, Class<E> enumClass, E dval, boolean enabled) {
this.tag = tag; this.tag = tag;
this.key = key; this.key = key;
this.enumClass = enumClass; this.enumClass = enumClass;
@ -22,7 +22,7 @@ public class OptionEnum<E extends Enum<E>> implements IOption<E>
value = Enums.getIfPresent(enumClass, tag.getString(key).toUpperCase()).or(dval); value = Enums.getIfPresent(enumClass, tag.getString(key).toUpperCase()).or(dval);
} }
public OptionEnum(CompoundTag tag, String key, Class<E> enumClass, E dval) { public OptionEnum(CompoundNBT tag, String key, Class<E> enumClass, E dval) {
this(tag, key, enumClass, dval, true); this(tag, key, enumClass, dval, true);
} }

View file

@ -1,9 +1,9 @@
package thetadev.constructionwand.basics.option; package thetadev.constructionwand.basics.option;
import net.minecraft.nbt.CompoundTag; import net.minecraft.block.Block;
import net.minecraft.world.item.ItemStack; import net.minecraft.block.Blocks;
import net.minecraft.world.level.block.Block; import net.minecraft.item.ItemStack;
import net.minecraft.world.level.block.Blocks; import net.minecraft.nbt.CompoundNBT;
import thetadev.constructionwand.api.IWandCore; import thetadev.constructionwand.api.IWandCore;
import thetadev.constructionwand.api.IWandUpgrade; import thetadev.constructionwand.api.IWandUpgrade;
import thetadev.constructionwand.basics.ReplacementRegistry; import thetadev.constructionwand.basics.ReplacementRegistry;
@ -13,7 +13,7 @@ import javax.annotation.Nullable;
public class WandOptions public class WandOptions
{ {
public final CompoundTag tag; public final CompoundNBT tag;
private static final String TAG_ROOT = "wand_options"; private static final String TAG_ROOT = "wand_options";
@ -50,7 +50,7 @@ public class WandOptions
public final IOption<?>[] allOptions; public final IOption<?>[] allOptions;
public WandOptions(ItemStack wandStack) { public WandOptions(ItemStack wandStack) {
tag = wandStack.getOrCreateTagElement(TAG_ROOT); tag = wandStack.getOrCreateChildTag(TAG_ROOT);
cores = new WandUpgradesSelectable<>(tag, "cores", new CoreDefault()); cores = new WandUpgradesSelectable<>(tag, "cores", new CoreDefault());

View file

@ -1,11 +1,11 @@
package thetadev.constructionwand.basics.option; package thetadev.constructionwand.basics.option;
import net.minecraft.nbt.CompoundTag; import net.minecraft.item.Item;
import net.minecraft.nbt.ListTag; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.StringTag; import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.Tag; import net.minecraft.nbt.StringNBT;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.item.Item; import net.minecraftforge.common.util.Constants;
import net.minecraftforge.registries.ForgeRegistries; import net.minecraftforge.registries.ForgeRegistries;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandUpgrade; import thetadev.constructionwand.api.IWandUpgrade;
@ -14,12 +14,12 @@ import java.util.ArrayList;
public class WandUpgrades<T extends IWandUpgrade> public class WandUpgrades<T extends IWandUpgrade>
{ {
protected final CompoundTag tag; protected final CompoundNBT tag;
protected final String key; protected final String key;
protected final ArrayList<T> upgrades; protected final ArrayList<T> upgrades;
protected final T dval; protected final T dval;
public WandUpgrades(CompoundTag tag, String key, T dval) { public WandUpgrades(CompoundNBT tag, String key, T dval) {
this.tag = tag; this.tag = tag;
this.key = key; this.key = key;
this.dval = dval; this.dval = dval;
@ -31,7 +31,7 @@ public class WandUpgrades<T extends IWandUpgrade>
} }
protected void deserialize() { protected void deserialize() {
ListTag listnbt = tag.getList(key, Tag.TAG_STRING); ListNBT listnbt = tag.getList(key, Constants.NBT.TAG_STRING);
boolean require_fix = false; boolean require_fix = false;
for(int i = 0; i < listnbt.size(); i++) { for(int i = 0; i < listnbt.size(); i++) {
@ -52,11 +52,11 @@ public class WandUpgrades<T extends IWandUpgrade>
} }
protected void serialize() { protected void serialize() {
ListTag listnbt = new ListTag(); ListNBT listnbt = new ListNBT();
for(T item : upgrades) { for(T item : upgrades) {
if(item == dval) continue; if(item == dval) continue;
listnbt.add(StringTag.valueOf(item.getRegistryName().toString())); listnbt.add(StringNBT.valueOf(item.getRegistryName().toString()));
} }
tag.put(key, listnbt); tag.put(key, listnbt);
} }

View file

@ -1,13 +1,13 @@
package thetadev.constructionwand.basics.option; package thetadev.constructionwand.basics.option;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundNBT;
import thetadev.constructionwand.api.IWandUpgrade; import thetadev.constructionwand.api.IWandUpgrade;
public class WandUpgradesSelectable<T extends IWandUpgrade> extends WandUpgrades<T> implements IOption<T> public class WandUpgradesSelectable<T extends IWandUpgrade> extends WandUpgrades<T> implements IOption<T>
{ {
private byte selector; private byte selector;
public WandUpgradesSelectable(CompoundTag tag, String key, T dval) { public WandUpgradesSelectable(CompoundNBT tag, String key, T dval) {
super(tag, key, dval); super(tag, key, dval);
} }

View file

@ -1,9 +1,9 @@
package thetadev.constructionwand.client; package thetadev.constructionwand.client;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.player.Player; import net.minecraft.client.util.InputMappings;
import net.minecraft.world.item.ItemStack; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraftforge.client.event.InputEvent; import net.minecraftforge.client.event.InputEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.eventbus.api.EventPriority; import net.minecraftforge.eventbus.api.EventPriority;
@ -27,7 +27,7 @@ public class ClientEvents
// Send state of OPT key to server // Send state of OPT key to server
@SubscribeEvent @SubscribeEvent
public void KeyEvent(InputEvent.KeyInputEvent event) { public void KeyEvent(InputEvent.KeyInputEvent event) {
Player player = Minecraft.getInstance().player; PlayerEntity player = Minecraft.getInstance().player;
if(player == null) return; if(player == null) return;
if(WandUtil.holdingWand(player) == null) return; if(WandUtil.holdingWand(player) == null) return;
@ -43,7 +43,7 @@ public class ClientEvents
// Sneak+(OPT)+Scroll to change direction lock // Sneak+(OPT)+Scroll to change direction lock
@SubscribeEvent(priority = EventPriority.HIGHEST) @SubscribeEvent(priority = EventPriority.HIGHEST)
public void MouseScrollEvent(InputEvent.MouseScrollEvent event) { public void MouseScrollEvent(InputEvent.MouseScrollEvent event) {
Player player = Minecraft.getInstance().player; PlayerEntity player = Minecraft.getInstance().player;
double scroll = event.getScrollDelta(); double scroll = event.getScrollDelta();
if(player == null || !modeKeyCombDown(player) || scroll == 0) return; if(player == null || !modeKeyCombDown(player) || scroll == 0) return;
@ -60,7 +60,7 @@ public class ClientEvents
// Sneak+(OPT)+Left click wand to change core // Sneak+(OPT)+Left click wand to change core
@SubscribeEvent @SubscribeEvent
public void onLeftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) { public void onLeftClickEmpty(PlayerInteractEvent.LeftClickEmpty event) {
Player player = event.getPlayer(); PlayerEntity player = event.getPlayer();
if(player == null || !modeKeyCombDown(player)) return; if(player == null || !modeKeyCombDown(player)) return;
@ -75,31 +75,29 @@ public class ClientEvents
// Sneak+(OPT)+Right click wand to open GUI // Sneak+(OPT)+Right click wand to open GUI
@SubscribeEvent @SubscribeEvent
public void onRightClickItem(PlayerInteractEvent.RightClickItem event) { public void onRightClickItem(PlayerInteractEvent.RightClickItem event) {
if(event.getSide().isServer()) return; PlayerEntity player = event.getPlayer();
Player player = event.getPlayer();
if(player == null || !guiKeyCombDown(player)) return; if(player == null || !guiKeyCombDown(player)) return;
ItemStack wand = event.getItemStack(); ItemStack wand = event.getItemStack();
if(!(wand.getItem() instanceof ItemWand)) return; if(!(wand.getItem() instanceof ItemWand)) return;
Minecraft.getInstance().setScreen(new ScreenWand(wand)); Minecraft.getInstance().displayGuiScreen(new ScreenWand(wand));
event.setCanceled(true); event.setCanceled(true);
} }
private static boolean isKeyDown(int id) { private static boolean isKeyDown(int id) {
return InputConstants.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), id); return InputMappings.isKeyDown(Minecraft.getInstance().getMainWindow().getHandle(), id);
} }
public static boolean isOptKeyDown() { public static boolean isOptKeyDown() {
return isKeyDown(ConfigClient.OPT_KEY.get()); return isKeyDown(ConfigClient.OPT_KEY.get());
} }
public static boolean modeKeyCombDown(Player player) { public static boolean modeKeyCombDown(PlayerEntity player) {
return player.isCrouching() && (isOptKeyDown() || !ConfigClient.SHIFTOPT_MODE.get()); return player.isSneaking() && (isOptKeyDown() || !ConfigClient.SHIFTOPT_MODE.get());
} }
public static boolean guiKeyCombDown(Player player) { public static boolean guiKeyCombDown(PlayerEntity player) {
return player.isCrouching() && (isOptKeyDown() || !ConfigClient.SHIFTOPT_GUI.get()); return player.isSneaking() && (isOptKeyDown() || !ConfigClient.SHIFTOPT_GUI.get());
} }
} }

View file

@ -1,18 +1,17 @@
package thetadev.constructionwand.client; package thetadev.constructionwand.client;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.vertex.VertexConsumer; import com.mojang.blaze3d.vertex.IVertexBuilder;
import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.IRenderTypeBuffer;
import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.WorldRenderer;
import net.minecraft.client.renderer.RenderType; import net.minecraft.entity.Entity;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.Entity; import net.minecraft.item.ItemStack;
import net.minecraft.world.entity.player.Player; import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.phys.AABB; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.phys.HitResult; import net.minecraftforge.client.event.DrawHighlightEvent;
import net.minecraftforge.client.event.DrawSelectionEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.items.wand.ItemWand; import thetadev.constructionwand.items.wand.ItemWand;
@ -22,29 +21,26 @@ import java.util.Set;
public class RenderBlockPreview public class RenderBlockPreview
{ {
private WandJob wandJob; public WandJob wandJob;
public Set<BlockPos> undoBlocks; public Set<BlockPos> undoBlocks;
@SubscribeEvent @SubscribeEvent
public void renderBlockHighlight(DrawSelectionEvent.HighlightBlock event) { public void renderBlockHighlight(DrawHighlightEvent event) {
if(event.getTarget().getType() != HitResult.Type.BLOCK) return; if(event.getTarget().getType() != RayTraceResult.Type.BLOCK) return;
BlockHitResult rtr = event.getTarget(); BlockRayTraceResult rtr = (BlockRayTraceResult) event.getTarget();
Entity entity = event.getCamera().getEntity(); Entity entity = event.getInfo().getRenderViewEntity();
if(!(entity instanceof Player player)) return; if(!(entity instanceof PlayerEntity)) return;
PlayerEntity player = (PlayerEntity) entity;
Set<BlockPos> blocks; Set<BlockPos> blocks;
float colorR = 0, colorG = 0, colorB = 0; float colorR = 0, colorG = 0, colorB = 0;
ItemStack wand = WandUtil.holdingWand(player); ItemStack wand = WandUtil.holdingWand(player);
if(wand == null) return; if(wand == null) return;
if(!(player.isCrouching() && ClientEvents.isOptKeyDown())) { if(!(player.isSneaking() && ClientEvents.isOptKeyDown())) {
// Use cached wandJob for previews of the same target pos/dir if(wandJob == null || !compareRTR(wandJob.rayTraceResult, rtr) || !(wandJob.wand.equals(wand))) {
// Exception: always update if blockCount < 2 to prevent 1-block previews when block updates wandJob = ItemWand.getWandJob(player, player.getEntityWorld(), rtr, wand);
// 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(); blocks = wandJob.getBlockPositions();
} }
@ -55,24 +51,27 @@ public class RenderBlockPreview
if(blocks == null || blocks.isEmpty()) return; if(blocks == null || blocks.isEmpty()) return;
PoseStack ms = event.getPoseStack(); MatrixStack ms = event.getMatrix();
MultiBufferSource buffer = event.getMultiBufferSource(); IRenderTypeBuffer buffer = event.getBuffers();
VertexConsumer lineBuilder = buffer.getBuffer(RenderType.LINES); IVertexBuilder lineBuilder = buffer.getBuffer(RenderTypes.TRANSLUCENT_LINES);
double partialTicks = event.getPartialTicks(); double partialTicks = event.getPartialTicks();
double d0 = player.xOld + (player.getX() - player.xOld) * partialTicks; double d0 = player.lastTickPosX + (player.getPosX() - player.lastTickPosX) * partialTicks;
double d1 = player.yOld + player.getEyeHeight() + (player.getY() - player.yOld) * partialTicks; double d1 = player.lastTickPosY + player.getEyeHeight() + (player.getPosY() - player.lastTickPosY) * partialTicks;
double d2 = player.zOld + (player.getZ() - player.zOld) * partialTicks; double d2 = player.lastTickPosZ + (player.getPosZ() - player.lastTickPosZ) * partialTicks;
ms.push();
for(BlockPos block : blocks) { for(BlockPos block : blocks) {
AABB aabb = new AABB(block).move(-d0, -d1, -d2); AxisAlignedBB aabb = new AxisAlignedBB(block).offset(-d0, -d1, -d2);
LevelRenderer.renderLineBox(ms, lineBuilder, aabb, colorR, colorG, colorB, 0.4F); WorldRenderer.drawBoundingBox(ms, lineBuilder, aabb, colorR, colorG, colorB, 0.4F);
} }
ms.pop();
event.setCanceled(true); event.setCanceled(true);
} }
private static boolean compareRTR(BlockHitResult rtr1, BlockHitResult rtr2) { private static boolean compareRTR(BlockRayTraceResult rtr1, BlockRayTraceResult rtr2) {
return rtr1.getBlockPos().equals(rtr2.getBlockPos()) && rtr1.getDirection().equals(rtr2.getDirection()); return rtr1.getPos().equals(rtr2.getPos()) && rtr1.getFace().equals(rtr2.getFace());
} }
} }

View file

@ -0,0 +1,37 @@
package thetadev.constructionwand.client;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.renderer.RenderState;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import org.lwjgl.opengl.GL11;
import thetadev.constructionwand.ConstructionWand;
import java.util.OptionalDouble;
public class RenderTypes
{
public static final RenderType TRANSLUCENT_LINES;
protected static final RenderState.TransparencyState TRANSLUCENT_TRANSPARENCY = new RenderState.TransparencyState("translucent_transparency", () -> {
RenderSystem.enableBlend();
RenderSystem.defaultBlendFunc();
}, RenderSystem::disableBlend);
protected static final RenderState.DepthTestState DEPTH_ALWAYS = new RenderState.DepthTestState("always", GL11.GL_ALWAYS);
static {
RenderType.State translucentNoDepthState = RenderType.State.getBuilder().transparency(TRANSLUCENT_TRANSPARENCY)
.line(new RenderState.LineState(OptionalDouble.of(2)))
.texture(new RenderState.TextureState())
.depthTest(DEPTH_ALWAYS)
.build(false);
TRANSLUCENT_LINES = RenderType.makeType(
ConstructionWand.MODID + ":translucent_lines",
DefaultVertexFormats.POSITION_COLOR,
GL11.GL_LINES,
256,
translucentNoDepthState
);
}
}

View file

@ -1,13 +1,13 @@
package thetadev.constructionwand.client; package thetadev.constructionwand.client;
import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.widget.button.Button;
import net.minecraft.network.chat.Component; import net.minecraft.item.ItemStack;
import net.minecraft.network.chat.TextComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.text.TranslationTextComponent;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.option.IOption; import thetadev.constructionwand.basics.option.IOption;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
@ -31,13 +31,15 @@ public class ScreenWand extends Screen
private static final int FIELD_HEIGHT = N_ROWS * (BUTTON_HEIGHT + SPACING_HEIGHT) - SPACING_HEIGHT; private static final int FIELD_HEIGHT = N_ROWS * (BUTTON_HEIGHT + SPACING_HEIGHT) - SPACING_HEIGHT;
public ScreenWand(ItemStack wand) { public ScreenWand(ItemStack wand) {
super(new TextComponent("ScreenWand")); super(new StringTextComponent("ScreenWand"));
this.wand = wand; this.wand = wand;
wandOptions = new WandOptions(wand); wandOptions = new WandOptions(wand);
} }
@Override @Override
protected void init() { public void init(@Nonnull Minecraft minecraft, int width, int height) {
super.init(minecraft, width, height);
createButton(0, 0, wandOptions.cores); createButton(0, 0, wandOptions.cores);
createButton(0, 1, wandOptions.lock); createButton(0, 1, wandOptions.lock);
createButton(0, 2, wandOptions.direction); createButton(0, 2, wandOptions.direction);
@ -47,26 +49,22 @@ public class ScreenWand extends Screen
} }
@Override @Override
public void render(@Nonnull PoseStack matrixStack, int mouseX, int mouseY, float partialTicks) { public void render(@Nonnull MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {
renderBackground(matrixStack); renderBackground(matrixStack);
drawCenteredString(matrixStack, font, wand.getDisplayName(), width / 2, height / 2 - FIELD_HEIGHT / 2 - SPACING_HEIGHT, 16777215);
super.render(matrixStack, mouseX, mouseY, partialTicks); super.render(matrixStack, mouseX, mouseY, partialTicks);
drawCenteredString(matrixStack, font, wand.getDisplayName(), width / 2, height / 2 - FIELD_HEIGHT / 2 - SPACING_HEIGHT, 16777215);
} }
@Override @Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) { public boolean charTyped(char character, int code) {
if (Minecraft.getInstance().options.keyInventory.matches(keyCode, scanCode)) { if(character == 'e') closeScreen();
this.onClose(); return super.charTyped(character, code);
return true;
} else {
return super.keyPressed(keyCode, scanCode, modifiers);
}
} }
private void createButton(int cx, int cy, IOption<?> option) { private void createButton(int cx, int cy, IOption<?> option) {
Button button = new Button(getX(cx), getY(cy), BUTTON_WIDTH, BUTTON_HEIGHT, getButtonLabel(option), bt -> clickButton(bt, option), (bt, ms, x, y) -> drawTooltip(ms, x, y, option)); Button button = new Button(getX(cx), getY(cy), BUTTON_WIDTH, BUTTON_HEIGHT, getButtonLabel(option), bt -> clickButton(bt, option), (bt, ms, x, y) -> drawTooltip(ms, x, y, option));
button.active = option.isEnabled(); button.active = option.isEnabled();
addRenderableWidget(button); addButton(button);
} }
private void clickButton(Button button, IOption<?> option) { private void clickButton(Button button, IOption<?> option) {
@ -75,9 +73,9 @@ public class ScreenWand extends Screen
button.setMessage(getButtonLabel(option)); button.setMessage(getButtonLabel(option));
} }
private void drawTooltip(PoseStack matrixStack, int mouseX, int mouseY, IOption<?> option) { private void drawTooltip(MatrixStack matrixStack, int mouseX, int mouseY, IOption<?> option) {
if(isMouseOver(mouseX, mouseY)) { if(isMouseOver(mouseX, mouseY)) {
renderTooltip(matrixStack, new TranslatableComponent(option.getDescTranslation()), mouseX, mouseY); renderTooltip(matrixStack, new TranslationTextComponent(option.getDescTranslation()), mouseX, mouseY);
} }
} }
@ -89,7 +87,7 @@ public class ScreenWand extends Screen
return height / 2 - FIELD_HEIGHT / 2 + n * (BUTTON_HEIGHT + SPACING_HEIGHT); return height / 2 - FIELD_HEIGHT / 2 + n * (BUTTON_HEIGHT + SPACING_HEIGHT);
} }
private Component getButtonLabel(IOption<?> option) { private ITextComponent getButtonLabel(IOption<?> option) {
return new TranslatableComponent(option.getKeyTranslation()).append(new TranslatableComponent(option.getValueTranslation())); return new TranslationTextComponent(option.getKeyTranslation()).append(new TranslationTextComponent(option.getValueTranslation()));
} }
} }

View file

@ -1,7 +1,7 @@
package thetadev.constructionwand.containers; package thetadev.constructionwand.containers;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.api.IContainerHandler;
import java.util.ArrayList; import java.util.ArrayList;
@ -18,7 +18,7 @@ public class ContainerManager
return handlers.add(handler); return handlers.add(handler);
} }
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) {
for(IContainerHandler handler : handlers) { for(IContainerHandler handler : handlers) {
if(handler.matches(player, itemStack, inventoryStack)) { if(handler.matches(player, itemStack, inventoryStack)) {
return handler.countItems(player, itemStack, inventoryStack); return handler.countItems(player, itemStack, inventoryStack);
@ -27,7 +27,7 @@ public class ContainerManager
return 0; return 0;
} }
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) {
for(IContainerHandler handler : handlers) { for(IContainerHandler handler : handlers) {
if(handler.matches(player, itemStack, inventoryStack)) { if(handler.matches(player, itemStack, inventoryStack)) {
return handler.useItems(player, itemStack, inventoryStack, count); return handler.useItems(player, itemStack, inventoryStack, count);

View file

@ -3,7 +3,6 @@ package thetadev.constructionwand.containers;
import net.minecraftforge.fml.ModList; import net.minecraftforge.fml.ModList;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.containers.handlers.HandlerBotania; import thetadev.constructionwand.containers.handlers.HandlerBotania;
import thetadev.constructionwand.containers.handlers.HandlerBundle;
import thetadev.constructionwand.containers.handlers.HandlerCapability; import thetadev.constructionwand.containers.handlers.HandlerCapability;
import thetadev.constructionwand.containers.handlers.HandlerShulkerbox; import thetadev.constructionwand.containers.handlers.HandlerShulkerbox;
@ -12,7 +11,6 @@ public class ContainerRegistrar
public static void register() { public static void register() {
ConstructionWand.instance.containerManager.register(new HandlerCapability()); ConstructionWand.instance.containerManager.register(new HandlerCapability());
ConstructionWand.instance.containerManager.register(new HandlerShulkerbox()); ConstructionWand.instance.containerManager.register(new HandlerShulkerbox());
ConstructionWand.instance.containerManager.register(new HandlerBundle());
if(ModList.get().isLoaded("botania")) { if(ModList.get().isLoaded("botania")) {
ConstructionWand.instance.containerManager.register(new HandlerBotania()); ConstructionWand.instance.containerManager.register(new HandlerBotania());

View file

@ -1,40 +1,34 @@
package thetadev.constructionwand.containers.handlers; package thetadev.constructionwand.containers.handlers;
import net.minecraft.world.entity.player.Player; import net.minecraft.block.Block;
import net.minecraft.world.item.ItemStack; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.level.block.Block; import net.minecraft.item.ItemStack;
import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.api.IContainerHandler;
import vazkii.botania.api.BotaniaForgeCapabilities;
import vazkii.botania.api.item.IBlockProvider; import vazkii.botania.api.item.IBlockProvider;
import java.util.Optional; /**
* Created by james on 28/12/16.
*/
public class HandlerBotania implements IContainerHandler public class HandlerBotania implements IContainerHandler
{ {
@Override @Override
public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { public boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) {
return inventoryStack != null && inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).isPresent(); return inventoryStack != null && inventoryStack.getCount() == 1 && inventoryStack.getItem() instanceof IBlockProvider;
} }
@Override @Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) {
Optional<IBlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve(); IBlockProvider prov = (IBlockProvider) inventoryStack.getItem();
if(provOptional.isEmpty()) return 0; int provCount = prov.getBlockCount(player, itemStack, inventoryStack, Block.getBlockFromItem(itemStack.getItem()));
IBlockProvider prov = provOptional.get();
int provCount = prov.getBlockCount(player, inventoryStack, Block.byItem(itemStack.getItem()));
if(provCount == -1) if(provCount == -1)
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
return provCount; return provCount;
} }
@Override @Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) {
Optional<IBlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve(); IBlockProvider prov = (IBlockProvider) inventoryStack.getItem();
if(provOptional.isEmpty()) return 0; if(prov.provideBlock(player, itemStack, inventoryStack, Block.getBlockFromItem(itemStack.getItem()), true))
IBlockProvider prov = provOptional.get();
if(prov.provideBlock(player, inventoryStack, Block.byItem(itemStack.getItem()), true))
return 0; return 0;
return count; return count;
} }

View file

@ -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<ItemStack> 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<ItemStack> 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<ItemStack> 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);
}
}
}

View file

@ -1,7 +1,7 @@
package thetadev.constructionwand.containers.handlers; package thetadev.constructionwand.containers.handlers;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraftforge.items.CapabilityItemHandler; import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler; import net.minecraftforge.items.IItemHandler;
import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.api.IContainerHandler;
@ -12,14 +12,14 @@ import java.util.Optional;
public class HandlerCapability implements IContainerHandler public class HandlerCapability implements IContainerHandler
{ {
@Override @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(); return inventoryStack != null && inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).isPresent();
} }
@Override @Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) {
Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve(); Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve();
if(itemHandlerOptional.isEmpty()) return 0; if(!itemHandlerOptional.isPresent()) return 0;
int total = 0; int total = 0;
@ -35,9 +35,9 @@ public class HandlerCapability implements IContainerHandler
} }
@Override @Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) {
Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve(); Optional<IItemHandler> itemHandlerOptional = inventoryStack.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY).resolve();
if(itemHandlerOptional.isEmpty()) return 0; if(!itemHandlerOptional.isPresent()) return 0;
IItemHandler itemHandler = itemHandlerOptional.get(); IItemHandler itemHandler = itemHandlerOptional.get();

View file

@ -1,13 +1,13 @@
package thetadev.constructionwand.containers.handlers; package thetadev.constructionwand.containers.handlers;
import net.minecraft.core.NonNullList; import net.minecraft.block.Block;
import net.minecraft.nbt.CompoundTag; import net.minecraft.block.ShulkerBoxBlock;
import net.minecraft.nbt.Tag; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.ContainerHelper; import net.minecraft.inventory.ItemStackHelper;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.nbt.CompoundNBT;
import net.minecraft.world.level.block.Block; import net.minecraft.util.NonNullList;
import net.minecraft.world.level.block.ShulkerBoxBlock; import net.minecraftforge.common.util.Constants;
import thetadev.constructionwand.api.IContainerHandler; import thetadev.constructionwand.api.IContainerHandler;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
@ -16,12 +16,12 @@ public class HandlerShulkerbox implements IContainerHandler
private final int SLOTS = 27; private final int SLOTS = 27;
@Override @Override
public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) { public boolean matches(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) {
return inventoryStack != null && inventoryStack.getCount() == 1 && Block.byItem(inventoryStack.getItem()) instanceof ShulkerBoxBlock; return inventoryStack != null && inventoryStack.getCount() == 1 && Block.getBlockFromItem(inventoryStack.getItem()) instanceof ShulkerBoxBlock;
} }
@Override @Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) { public int countItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack) {
int count = 0; int count = 0;
for(ItemStack stack : getItemList(inventoryStack)) { for(ItemStack stack : getItemList(inventoryStack)) {
@ -32,7 +32,7 @@ public class HandlerShulkerbox implements IContainerHandler
} }
@Override @Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) { public int useItems(PlayerEntity player, ItemStack itemStack, ItemStack inventoryStack, int count) {
NonNullList<ItemStack> itemList = getItemList(inventoryStack); NonNullList<ItemStack> itemList = getItemList(inventoryStack);
boolean changed = false; boolean changed = false;
@ -47,7 +47,7 @@ public class HandlerShulkerbox implements IContainerHandler
} }
if(changed) { if(changed) {
setItemList(inventoryStack, itemList); setItemList(inventoryStack, itemList);
player.getInventory().setChanged(); player.inventory.markDirty();
} }
return count; return count;
@ -55,21 +55,21 @@ public class HandlerShulkerbox implements IContainerHandler
private NonNullList<ItemStack> getItemList(ItemStack itemStack) { private NonNullList<ItemStack> getItemList(ItemStack itemStack) {
NonNullList<ItemStack> itemStacks = NonNullList.withSize(SLOTS, ItemStack.EMPTY); NonNullList<ItemStack> itemStacks = NonNullList.withSize(SLOTS, ItemStack.EMPTY);
CompoundTag rootTag = itemStack.getTag(); CompoundNBT rootTag = itemStack.getTag();
if(rootTag != null && rootTag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) { if(rootTag != null && rootTag.contains("BlockEntityTag", Constants.NBT.TAG_COMPOUND)) {
CompoundTag entityTag = rootTag.getCompound("BlockEntityTag"); CompoundNBT entityTag = rootTag.getCompound("BlockEntityTag");
if(entityTag.contains("Items", Tag.TAG_LIST)) { if(entityTag.contains("Items", Constants.NBT.TAG_LIST)) {
ContainerHelper.loadAllItems(entityTag, itemStacks); ItemStackHelper.loadAllItems(entityTag, itemStacks);
} }
} }
return itemStacks; return itemStacks;
} }
private void setItemList(ItemStack itemStack, NonNullList<ItemStack> itemStacks) { private void setItemList(ItemStack itemStack, NonNullList<ItemStack> itemStacks) {
CompoundTag rootTag = itemStack.getOrCreateTag(); CompoundNBT rootTag = itemStack.getOrCreateTag();
if(!rootTag.contains("BlockEntityTag", Tag.TAG_COMPOUND)) { if(!rootTag.contains("BlockEntityTag", Constants.NBT.TAG_COMPOUND)) {
rootTag.put("BlockEntityTag", new CompoundTag()); rootTag.put("BlockEntityTag", new CompoundNBT());
} }
ContainerHelper.saveAllItems(rootTag.getCompound("BlockEntityTag"), itemStacks); ItemStackHelper.saveAllItems(rootTag.getCompound("BlockEntityTag"), itemStacks);
} }
} }

View file

@ -1,12 +1,12 @@
package thetadev.constructionwand.crafting; package thetadev.constructionwand.crafting;
import net.minecraft.resources.ResourceLocation; import net.minecraft.inventory.CraftingInventory;
import net.minecraft.world.inventory.CraftingContainer; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.world.item.crafting.CustomRecipe; import net.minecraft.item.crafting.SpecialRecipe;
import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.item.crafting.SpecialRecipeSerializer;
import net.minecraft.world.item.crafting.SimpleRecipeSerializer; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.level.Level; import net.minecraft.world.World;
import thetadev.constructionwand.api.IWandUpgrade; import thetadev.constructionwand.api.IWandUpgrade;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
@ -14,21 +14,21 @@ import thetadev.constructionwand.items.wand.ItemWand;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class RecipeWandUpgrade extends CustomRecipe public class RecipeWandUpgrade extends SpecialRecipe
{ {
public static final SimpleRecipeSerializer<RecipeWandUpgrade> SERIALIZER = new SimpleRecipeSerializer<>(RecipeWandUpgrade::new); public static final SpecialRecipeSerializer<RecipeWandUpgrade> SERIALIZER = new SpecialRecipeSerializer<>(RecipeWandUpgrade::new);
public RecipeWandUpgrade(ResourceLocation resourceLocation) { public RecipeWandUpgrade(ResourceLocation resourceLocation) {
super(resourceLocation); super(resourceLocation);
} }
@Override @Override
public boolean matches(@Nonnull CraftingContainer inv, @Nonnull Level worldIn) { public boolean matches(@Nonnull CraftingInventory inv, @Nonnull World worldIn) {
ItemStack wand = null; ItemStack wand = null;
IWandUpgrade upgrade = null; IWandUpgrade upgrade = null;
for(int i = 0; i < inv.getContainerSize(); i++) { for(int i = 0; i < inv.getSizeInventory(); i++) {
ItemStack stack = inv.getItem(i); ItemStack stack = inv.getStackInSlot(i);
if(!stack.isEmpty()) { if(!stack.isEmpty()) {
if(wand == null && stack.getItem() instanceof ItemWand) wand = stack; if(wand == null && stack.getItem() instanceof ItemWand) wand = stack;
else if(upgrade == null && stack.getItem() instanceof IWandUpgrade) else if(upgrade == null && stack.getItem() instanceof IWandUpgrade)
@ -43,12 +43,12 @@ public class RecipeWandUpgrade extends CustomRecipe
@Nonnull @Nonnull
@Override @Override
public ItemStack assemble(@Nonnull CraftingContainer inv) { public ItemStack getCraftingResult(@Nonnull CraftingInventory inv) {
ItemStack wand = null; ItemStack wand = null;
IWandUpgrade upgrade = null; IWandUpgrade upgrade = null;
for(int i = 0; i < inv.getContainerSize(); i++) { for(int i = 0; i < inv.getSizeInventory(); i++) {
ItemStack stack = inv.getItem(i); ItemStack stack = inv.getStackInSlot(i);
if(!stack.isEmpty()) { if(!stack.isEmpty()) {
if(stack.getItem() instanceof ItemWand) wand = stack; if(stack.getItem() instanceof ItemWand) wand = stack;
else if(stack.getItem() instanceof IWandUpgrade) upgrade = (IWandUpgrade) stack.getItem(); else if(stack.getItem() instanceof IWandUpgrade) upgrade = (IWandUpgrade) stack.getItem();
@ -63,13 +63,13 @@ public class RecipeWandUpgrade extends CustomRecipe
} }
@Override @Override
public boolean canCraftInDimensions(int width, int height) { public boolean canFit(int width, int height) {
return width * height >= 2; return width * height >= 2;
} }
@Nonnull @Nonnull
@Override @Override
public RecipeSerializer<?> getSerializer() { public IRecipeSerializer<?> getSerializer() {
return SERIALIZER; return SERIALIZER;
} }
} }

View file

@ -1,10 +1,10 @@
package thetadev.constructionwand.data; package thetadev.constructionwand.data;
import net.minecraft.advancements.critereon.ItemPredicate; import net.minecraft.advancements.criterion.ItemPredicate;
import net.minecraft.tags.Tag; import net.minecraft.item.Item;
import net.minecraft.world.item.Item; import net.minecraft.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.tags.ITag;
import net.minecraft.world.level.ItemLike; import net.minecraft.util.IItemProvider;
public class Inp public class Inp
{ {
@ -18,11 +18,11 @@ public class Inp
this.predicate = predicate; this.predicate = predicate;
} }
public static Inp fromItem(ItemLike in) { public static Inp fromItem(IItemProvider in) {
return new Inp(in.asItem().getRegistryName().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build()); return new Inp(in.asItem().getRegistryName().getPath(), Ingredient.fromItems(in), ItemPredicate.Builder.create().item(in).build());
} }
public static Inp fromTag(Tag.Named<Item> in) { public static Inp fromTag(ITag.INamedTag<Item> in) {
return new Inp(in.getName().getPath(), Ingredient.of(in), ItemPredicate.Builder.item().of(in).build()); return new Inp(in.getName().getPath(), Ingredient.fromTag(in), ItemPredicate.Builder.create().tag(in).build());
} }
} }

View file

@ -1,11 +1,10 @@
package thetadev.constructionwand.data; package thetadev.constructionwand.data;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.item.Item;
import net.minecraftforge.client.model.generators.ItemModelProvider; import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.registries.RegistryObject;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.items.ModItems;
@ -19,8 +18,7 @@ public class ItemModelGenerator extends ItemModelProvider
@Override @Override
protected void registerModels() { protected void registerModels() {
for(RegistryObject<Item> itemObject : ModItems.ITEMS.getEntries()) { for(Item item : ModItems.ALL_ITEMS) {
Item item = itemObject.get();
String name = item.getRegistryName().getPath(); String name = item.getRegistryName().getPath();
if(item instanceof ICustomItemModel) if(item instanceof ICustomItemModel)

View file

@ -4,7 +4,7 @@ import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper; import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent; import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) @Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class ModData public class ModData

View file

@ -1,17 +1,13 @@
package thetadev.constructionwand.data; package thetadev.constructionwand.data;
import net.minecraft.data.DataGenerator; import net.minecraft.data.*;
import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.item.Items;
import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.item.crafting.SpecialRecipeSerializer;
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.tags.ItemTags;
import net.minecraft.world.item.Items; import net.minecraft.util.IItemProvider;
import net.minecraft.world.item.crafting.SimpleRecipeSerializer; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.level.ItemLike; import net.minecraft.util.registry.Registry;
import net.minecraftforge.common.Tags; import net.minecraftforge.common.Tags;
import net.minecraftforge.registries.ForgeRegistries;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.crafting.RecipeWandUpgrade; import thetadev.constructionwand.crafting.RecipeWandUpgrade;
import thetadev.constructionwand.items.ModItems; import thetadev.constructionwand.items.ModItems;
@ -26,44 +22,44 @@ public class RecipeGenerator extends RecipeProvider
} }
@Override @Override
protected void buildCraftingRecipes(@Nonnull Consumer<FinishedRecipe> consumer) { protected void registerRecipes(@Nonnull Consumer<IFinishedRecipe> consumer) {
wandRecipe(consumer, ModItems.WAND_STONE.get(), Inp.fromTag(ItemTags.STONE_TOOL_MATERIALS)); wandRecipe(consumer, ModItems.WAND_STONE, Inp.fromTag(ItemTags.field_232909_aa_)); //stone_tool_materials
wandRecipe(consumer, ModItems.WAND_IRON.get(), Inp.fromTag(Tags.Items.INGOTS_IRON)); wandRecipe(consumer, ModItems.WAND_IRON, Inp.fromTag(Tags.Items.INGOTS_IRON));
wandRecipe(consumer, ModItems.WAND_DIAMOND.get(), Inp.fromTag(Tags.Items.GEMS_DIAMOND)); wandRecipe(consumer, ModItems.WAND_DIAMOND, Inp.fromTag(Tags.Items.GEMS_DIAMOND));
wandRecipe(consumer, ModItems.WAND_INFINITY.get(), Inp.fromTag(Tags.Items.NETHER_STARS)); 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_ANGEL, 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)); coreRecipe(consumer, ModItems.CORE_DESTRUCTION, Inp.fromTag(Tags.Items.STORAGE_BLOCKS_DIAMOND), Inp.fromItem(Items.DIAMOND_PICKAXE));
specialRecipe(consumer, RecipeWandUpgrade.SERIALIZER); specialRecipe(consumer, RecipeWandUpgrade.SERIALIZER);
} }
private void wandRecipe(Consumer<FinishedRecipe> consumer, ItemLike wand, Inp material) { private void wandRecipe(Consumer<IFinishedRecipe> consumer, IItemProvider wand, Inp material) {
ShapedRecipeBuilder.shaped(wand) ShapedRecipeBuilder.shapedRecipe(wand)
.define('X', material.ingredient) .key('X', material.ingredient)
.define('#', Tags.Items.RODS_WOODEN) .key('#', Tags.Items.RODS_WOODEN)
.pattern(" X") .patternLine(" X")
.pattern(" # ") .patternLine(" # ")
.pattern("# ") .patternLine("# ")
.unlockedBy("has_item", inventoryTrigger(material.predicate)) .addCriterion("has_item", hasItem(material.predicate))
.save(consumer); .build(consumer);
} }
private void coreRecipe(Consumer<FinishedRecipe> consumer, ItemLike core, Inp item1, Inp item2) { private void coreRecipe(Consumer<IFinishedRecipe> consumer, IItemProvider core, Inp item1, Inp item2) {
ShapedRecipeBuilder.shaped(core) ShapedRecipeBuilder.shapedRecipe(core)
.define('O', item1.ingredient) .key('O', item1.ingredient)
.define('X', item2.ingredient) .key('X', item2.ingredient)
.define('#', Tags.Items.GLASS_PANES) .key('#', Tags.Items.GLASS_PANES)
.pattern(" #X") .patternLine(" #X")
.pattern("#O#") .patternLine("#O#")
.pattern("X# ") .patternLine("X# ")
.unlockedBy("has_item", inventoryTrigger(item1.predicate)) .addCriterion("has_item", hasItem(item1.predicate))
.save(consumer); .build(consumer);
} }
private void specialRecipe(Consumer<FinishedRecipe> consumer, SimpleRecipeSerializer<?> serializer) { private void specialRecipe(Consumer<IFinishedRecipe> consumer, SpecialRecipeSerializer<?> serializer) {
ResourceLocation name = ForgeRegistries.RECIPE_SERIALIZERS.getKey(serializer); ResourceLocation name = Registry.RECIPE_SERIALIZER.getKey(serializer);
SpecialRecipeBuilder.special(serializer).save(consumer, ConstructionWand.loc("dynamic/" + name.getPath()).toString()); CustomRecipeBuilder.customRecipe(serializer).build(consumer, ConstructionWand.loc("dynamic/" + name.getPath()).toString());
} }
@Nonnull @Nonnull

View file

@ -1,17 +1,16 @@
package thetadev.constructionwand.integrations.jei; package thetadev.constructionwand.integrations.jei;
import com.mojang.blaze3d.platform.InputConstants;
import mezz.jei.api.IModPlugin; import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin; import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.VanillaTypes; import mezz.jei.api.constants.VanillaTypes;
import mezz.jei.api.registration.IRecipeRegistration; import mezz.jei.api.registration.IRecipeRegistration;
import net.minecraft.ChatFormatting; import net.minecraft.client.util.InputMappings;
import net.minecraft.network.chat.Component; import net.minecraft.util.text.TextFormatting;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.item.Item; import net.minecraft.util.ResourceLocation;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.Item;
import net.minecraftforge.registries.RegistryObject; import net.minecraft.item.ItemStack;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.ConfigClient; import thetadev.constructionwand.basics.ConfigClient;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
@ -32,38 +31,36 @@ public class ConstructionWandJeiPlugin implements IModPlugin
return pluginId; return pluginId;
} }
private Component keyComboComponent(boolean shiftOpt, Component optkeyComponent) { private ITextComponent keyComboComponent(boolean shiftOpt, ITextComponent optkeyComponent) {
String key = shiftOpt ? "sneak_opt" : "sneak"; String key = shiftOpt ? "sneak_opt" : "sneak";
return new TranslatableComponent(baseKey + "key." + key, optkeyComponent).withStyle(ChatFormatting.BLUE); return new TranslationTextComponent(baseKey + "key." + key, optkeyComponent).mergeStyle(TextFormatting.BLUE);
} }
@Override @Override
public void registerRecipes(IRecipeRegistration registration) { public void registerRecipes(IRecipeRegistration registration) {
Component optkeyComponent = new TranslatableComponent(InputConstants.getKey(ConfigClient.OPT_KEY.get(), -1).getName()) ITextComponent optkeyComponent = new TranslationTextComponent(InputMappings.getInputByCode(ConfigClient.OPT_KEY.get(), -1).getTranslationKey())
.withStyle(ChatFormatting.BLUE); .mergeStyle(TextFormatting.BLUE);
Component wandModeComponent = keyComboComponent(ConfigClient.SHIFTOPT_MODE.get(), optkeyComponent); ITextComponent wandModeComponent = keyComboComponent(ConfigClient.SHIFTOPT_MODE.get(), optkeyComponent);
Component wandGuiComponent = keyComboComponent(ConfigClient.SHIFTOPT_GUI.get(), optkeyComponent); ITextComponent wandGuiComponent = keyComboComponent(ConfigClient.SHIFTOPT_GUI.get(), optkeyComponent);
for(RegistryObject<Item> wandSupplier : ModItems.WANDS) { for(Item wand : ModItems.WANDS) {
Item wand = wandSupplier.get();
ConfigServer.WandProperties wandProperties = ConfigServer.getWandProperties(wand); ConfigServer.WandProperties wandProperties = ConfigServer.getWandProperties(wand);
String durabilityKey = wand == ModItems.WAND_INFINITY.get() ? "unlimited" : "limited"; String durabilityKey = wand == ModItems.WAND_INFINITY ? "unlimited" : "limited";
Component durabilityComponent = new TranslatableComponent(baseKey + "durability." + durabilityKey, wandProperties.getDurability()); ITextComponent durabilityComponent = new TranslationTextComponent(baseKey + "durability." + durabilityKey, wandProperties.getDurability());
registration.addIngredientInfo(new ItemStack(wand), VanillaTypes.ITEM, registration.addIngredientInfo(new ItemStack(wand), VanillaTypes.ITEM,
new TranslatableComponent(baseKey + "wand", new TranslationTextComponent(baseKey + "wand",
new TranslatableComponent(baseKeyItem + wand.getRegistryName().getPath()), new TranslationTextComponent(baseKeyItem + wand.getRegistryName().getPath()),
wandProperties.getLimit(), durabilityComponent, wandProperties.getLimit(), durabilityComponent,
optkeyComponent, wandModeComponent, wandGuiComponent) optkeyComponent, wandModeComponent, wandGuiComponent)
); );
} }
for(RegistryObject<Item> coreSupplier : ModItems.CORES) { for(Item core : ModItems.CORES) {
Item core = coreSupplier.get();
registration.addIngredientInfo(new ItemStack(core), VanillaTypes.ITEM, registration.addIngredientInfo(new ItemStack(core), VanillaTypes.ITEM,
new TranslatableComponent(baseKey + core.getRegistryName().getPath()), new TranslationTextComponent(baseKey + core.getRegistryName().getPath()),
new TranslatableComponent(baseKey + "core", wandModeComponent) new TranslationTextComponent(baseKey + "core", wandModeComponent)
); );
} }
} }

View file

@ -0,0 +1,12 @@
package thetadev.constructionwand.items;
import net.minecraft.item.Item;
import thetadev.constructionwand.ConstructionWand;
public class ItemBase extends Item
{
public ItemBase(String name, Properties properties) {
super(properties);
setRegistryName(ConstructionWand.MODID, name);
}
}

View file

@ -1,18 +1,19 @@
package thetadev.constructionwand.items; package thetadev.constructionwand.items;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.color.item.ItemColors; import net.minecraft.client.renderer.color.ItemColors;
import net.minecraft.client.renderer.item.ItemProperties; import net.minecraft.item.Item;
import net.minecraft.world.item.CreativeModeTab; import net.minecraft.item.ItemGroup;
import net.minecraft.world.item.Item; import net.minecraft.item.ItemModelsProperties;
import net.minecraft.world.item.Tiers; import net.minecraft.item.ItemTier;
import net.minecraft.world.item.crafting.RecipeSerializer; import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.*; import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.crafting.RecipeWandUpgrade; import thetadev.constructionwand.crafting.RecipeWandUpgrade;
@ -22,46 +23,64 @@ import thetadev.constructionwand.items.wand.ItemWand;
import thetadev.constructionwand.items.wand.ItemWandBasic; import thetadev.constructionwand.items.wand.ItemWandBasic;
import thetadev.constructionwand.items.wand.ItemWandInfinity; import thetadev.constructionwand.items.wand.ItemWandInfinity;
import java.util.Arrays;
import java.util.HashSet;
@Mod.EventBusSubscriber(modid = ConstructionWand.MODID, bus = Mod.EventBusSubscriber.Bus.MOD) @Mod.EventBusSubscriber(modid = ConstructionWand.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ModItems public class ModItems
{ {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ConstructionWand.MODID);
// Wands // Wands
public static final RegistryObject<Item> WAND_STONE = ITEMS.register("stone_wand", () -> new ItemWandBasic(propWand(), Tiers.STONE)); public static final Item WAND_STONE = new ItemWandBasic("stone_wand", propWand(), ItemTier.STONE);
public static final RegistryObject<Item> WAND_IRON = ITEMS.register("iron_wand", () -> new ItemWandBasic(propWand(), Tiers.IRON)); public static final Item WAND_IRON = new ItemWandBasic("iron_wand", propWand(), ItemTier.IRON);
public static final RegistryObject<Item> WAND_DIAMOND = ITEMS.register("diamond_wand", () -> new ItemWandBasic(propWand(), Tiers.DIAMOND)); public static final Item WAND_DIAMOND = new ItemWandBasic("diamond_wand", propWand(), ItemTier.DIAMOND);
public static final RegistryObject<Item> WAND_INFINITY = ITEMS.register("infinity_wand", () -> new ItemWandInfinity(propWand())); public static final Item WAND_INFINITY = new ItemWandInfinity("infinity_wand", propWand());
// Cores // Cores
public static final RegistryObject<Item> CORE_ANGEL = ITEMS.register("core_angel", () -> new ItemCoreAngel(propUpgrade())); public static final Item CORE_ANGEL = new ItemCoreAngel("core_angel", propUpgrade());
public static final RegistryObject<Item> CORE_DESTRUCTION = ITEMS.register("core_destruction", () -> new ItemCoreDestruction(propUpgrade())); public static final Item CORE_DESTRUCTION = new ItemCoreDestruction("core_destruction", propUpgrade());
// Collections // Collections
public static final RegistryObject<Item>[] WANDS = new RegistryObject[] {WAND_STONE, WAND_IRON, WAND_DIAMOND, WAND_INFINITY}; public static final Item[] WANDS = {WAND_STONE, WAND_IRON, WAND_DIAMOND, WAND_INFINITY};
public static final RegistryObject<Item>[] CORES = new RegistryObject[] {CORE_ANGEL, CORE_DESTRUCTION}; public static final Item[] CORES = {CORE_ANGEL, CORE_DESTRUCTION};
public static final HashSet<Item> ALL_ITEMS = new HashSet<>();
@SubscribeEvent
public static void registerItems(RegistryEvent.Register<Item> event) {
IForgeRegistry<Item> r = event.getRegistry();
r.registerAll(WANDS);
ALL_ITEMS.addAll(Arrays.asList(WANDS));
registerItem(r, CORE_ANGEL);
registerItem(r, CORE_DESTRUCTION);
}
public static Item.Properties propWand() { public static Item.Properties propWand() {
return new Item.Properties().tab(CreativeModeTab.TAB_TOOLS); return new Item.Properties().group(ItemGroup.TOOLS);
} }
private static Item.Properties propUpgrade() { private static Item.Properties propUpgrade() {
return new Item.Properties().tab(CreativeModeTab.TAB_MISC).stacksTo(1); return new Item.Properties().group(ItemGroup.MISC).maxStackSize(1);
}
private static void registerItem(IForgeRegistry<Item> reg, Item item) {
reg.register(item);
ALL_ITEMS.add(item);
} }
@SubscribeEvent @SubscribeEvent
public static void registerRecipeSerializers(RegistryEvent.Register<RecipeSerializer<?>> event) { public static void registerRecipeSerializers(RegistryEvent.Register<IRecipeSerializer<?>> event) {
IForgeRegistry<RecipeSerializer<?>> r = event.getRegistry(); IForgeRegistry<IRecipeSerializer<?>> r = event.getRegistry();
register(r, "wand_upgrade", RecipeWandUpgrade.SERIALIZER); register(r, "wand_upgrade", RecipeWandUpgrade.SERIALIZER);
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public static void registerModelProperties() { public static void registerModelProperties() {
for(RegistryObject<Item> itemSupplier : WANDS) { for(Item item : WANDS) {
Item item = itemSupplier.get(); ItemModelsProperties.func_239418_a_(
ItemProperties.register(
item, ConstructionWand.loc("using_core"), item, ConstructionWand.loc("using_core"),
(stack, world, entity, n) -> entity == null || !(stack.getItem() instanceof ItemWand) ? 0 : (stack, world, entity) -> entity == null || !(stack.getItem() instanceof ItemWand) ? 0 :
new WandOptions(stack).cores.get().getColor() > -1 ? 1 : 0 new WandOptions(stack).cores.get().getColor() > -1 ? 1 : 0
); );
} }
@ -71,8 +90,7 @@ public class ModItems
public static void registerItemColors() { public static void registerItemColors() {
ItemColors colors = Minecraft.getInstance().getItemColors(); ItemColors colors = Minecraft.getInstance().getItemColors();
for(RegistryObject<Item> itemSupplier : WANDS) { for(Item item : WANDS) {
Item item = itemSupplier.get();
colors.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ? colors.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ?
new WandOptions(stack).cores.get().getColor() : -1, item); new WandOptions(stack).cores.get().getColor() : -1, item);
} }

View file

@ -1,6 +1,6 @@
package thetadev.constructionwand.items.core; package thetadev.constructionwand.items.core;
import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ResourceLocation;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandCore; import thetadev.constructionwand.api.IWandCore;

View file

@ -1,31 +1,31 @@
package thetadev.constructionwand.items.core; package thetadev.constructionwand.items.core;
import net.minecraft.ChatFormatting; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.network.chat.Component; import net.minecraft.item.ItemStack;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.item.Item; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.World;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandCore; import thetadev.constructionwand.api.IWandCore;
import thetadev.constructionwand.items.ItemBase;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.List; import java.util.List;
public abstract class ItemCore extends Item implements IWandCore public abstract class ItemCore extends ItemBase implements IWandCore
{ {
public ItemCore(Properties properties) { public ItemCore(String name, Properties properties) {
super(properties); super(name, properties);
} }
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void appendHoverText(@Nonnull ItemStack itemstack, Level worldIn, @Nonnull List<Component> lines, @Nonnull TooltipFlag extraInfo) { public void addInformation(@Nonnull ItemStack itemstack, World worldIn, @Nonnull List<ITextComponent> lines, @Nonnull ITooltipFlag extraInfo) {
lines.add(new TranslatableComponent(ConstructionWand.MODID + ".option.cores." + getRegistryName().toString() + ".desc") lines.add(new TranslationTextComponent(ConstructionWand.MODID + ".option.cores." + getRegistryName().toString() + ".desc")
.withStyle(ChatFormatting.GRAY)); .mergeStyle(TextFormatting.GRAY));
lines.add(new TranslatableComponent(ConstructionWand.MODID + ".tooltip.core_tip") lines.add(new TranslationTextComponent(ConstructionWand.MODID + ".tooltip.core_tip")
.withStyle(ChatFormatting.AQUA)); .mergeStyle(TextFormatting.AQUA));
} }
} }

View file

@ -5,8 +5,8 @@ import thetadev.constructionwand.wand.action.ActionAngel;
public class ItemCoreAngel extends ItemCore public class ItemCoreAngel extends ItemCore
{ {
public ItemCoreAngel(Properties properties) { public ItemCoreAngel(String name, Properties properties) {
super(properties); super(name, properties);
} }
@Override @Override

View file

@ -5,8 +5,8 @@ import thetadev.constructionwand.wand.action.ActionDestruction;
public class ItemCoreDestruction extends ItemCore public class ItemCoreDestruction extends ItemCore
{ {
public ItemCoreDestruction(Properties properties) { public ItemCoreDestruction(String name, Properties properties) {
super(properties); super(name, properties);
} }
@Override @Override

View file

@ -1,21 +1,20 @@
package thetadev.constructionwand.items.wand; package thetadev.constructionwand.items.wand;
import net.minecraft.ChatFormatting; import net.minecraft.block.BlockState;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screen.Screen;
import net.minecraft.network.chat.Component; import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.network.chat.TextComponent; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.network.chat.TranslatableComponent; import net.minecraft.item.ItemStack;
import net.minecraft.world.InteractionHand; import net.minecraft.item.ItemUseContext;
import net.minecraft.world.InteractionResult; import net.minecraft.util.ActionResult;
import net.minecraft.world.InteractionResultHolder; import net.minecraft.util.ActionResultType;
import net.minecraft.world.entity.player.Player; import net.minecraft.util.Hand;
import net.minecraft.world.item.Item; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.item.TooltipFlag; import net.minecraft.util.text.StringTextComponent;
import net.minecraft.world.item.context.UseOnContext; import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.level.Level; import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.World;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraftforge.api.distmarker.Dist; import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.client.model.generators.ModelFile; import net.minecraftforge.client.model.generators.ModelFile;
@ -26,55 +25,56 @@ import thetadev.constructionwand.basics.option.IOption;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.data.ICustomItemModel; import thetadev.constructionwand.data.ICustomItemModel;
import thetadev.constructionwand.data.ItemModelGenerator; import thetadev.constructionwand.data.ItemModelGenerator;
import thetadev.constructionwand.items.ItemBase;
import thetadev.constructionwand.wand.WandJob; import thetadev.constructionwand.wand.WandJob;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public abstract class ItemWand extends Item implements ICustomItemModel public abstract class ItemWand extends ItemBase implements ICustomItemModel
{ {
public ItemWand(Properties properties) { public ItemWand(String name, Properties properties) {
super(properties); super(name, properties);
} }
@Nonnull @Nonnull
@Override @Override
public InteractionResult useOn(UseOnContext context) { public ActionResultType onItemUse(ItemUseContext context) {
Player player = context.getPlayer(); PlayerEntity player = context.getPlayer();
InteractionHand hand = context.getHand(); Hand hand = context.getHand();
Level world = context.getLevel(); World world = context.getWorld();
if(world.isClientSide || player == null) return InteractionResult.FAIL; if(world.isRemote || player == null) return ActionResultType.FAIL;
ItemStack stack = player.getItemInHand(hand); ItemStack stack = player.getHeldItem(hand);
if(player.isCrouching() && ConstructionWand.instance.undoHistory.isUndoActive(player)) { if(player.isSneaking() && ConstructionWand.instance.undoHistory.isUndoActive(player)) {
return ConstructionWand.instance.undoHistory.undo(player, world, context.getClickedPos()) ? InteractionResult.SUCCESS : InteractionResult.FAIL; return ConstructionWand.instance.undoHistory.undo(player, world, context.getPos()) ? ActionResultType.SUCCESS : ActionResultType.FAIL;
} }
else { else {
WandJob job = getWandJob(player, world, new BlockHitResult(context.getClickLocation(), context.getClickedFace(), context.getClickedPos(), false), stack); WandJob job = getWandJob(player, world, new BlockRayTraceResult(context.getHitVec(), context.getFace(), context.getPos(), false), stack);
return job.doIt() ? InteractionResult.SUCCESS : InteractionResult.FAIL; return job.doIt() ? ActionResultType.SUCCESS : ActionResultType.FAIL;
} }
} }
@Nonnull @Nonnull
@Override @Override
public InteractionResultHolder<ItemStack> use(@Nonnull Level world, Player player, @Nonnull InteractionHand hand) { public ActionResult<ItemStack> onItemRightClick(@Nonnull World world, PlayerEntity player, @Nonnull Hand hand) {
ItemStack stack = player.getItemInHand(hand); ItemStack stack = player.getHeldItem(hand);
if(!player.isCrouching()) { if(!player.isSneaking()) {
if(world.isClientSide) return InteractionResultHolder.fail(stack); if(world.isRemote) return ActionResult.resultFail(stack);
// Right click: Place angel block // Right click: Place angel block
WandJob job = getWandJob(player, world, BlockHitResult.miss(player.getLookAngle(), WandJob job = getWandJob(player, world, BlockRayTraceResult.createMiss(player.getLookVec(),
WandUtil.fromVector(player.getLookAngle()), WandUtil.playerPos(player)), stack); WandUtil.fromVector(player.getLookVec()), WandUtil.playerPos(player)), stack);
return job.doIt() ? InteractionResultHolder.success(stack) : InteractionResultHolder.fail(stack); return job.doIt() ? ActionResult.resultSuccess(stack) : ActionResult.resultFail(stack);
} }
return InteractionResultHolder.fail(stack); return ActionResult.resultFail(stack);
} }
public static WandJob getWandJob(Player player, Level world, @Nullable BlockHitResult rayTraceResult, ItemStack wand) { public static WandJob getWandJob(PlayerEntity player, World world, @Nullable BlockRayTraceResult rayTraceResult, ItemStack wand) {
WandJob wandJob = new WandJob(player, world, rayTraceResult, wand); WandJob wandJob = new WandJob(player, world, rayTraceResult, wand);
wandJob.getSnapshots(); wandJob.getSnapshots();
@ -82,12 +82,12 @@ public abstract class ItemWand extends Item implements ICustomItemModel
} }
@Override @Override
public boolean isCorrectToolForDrops(@Nonnull BlockState blockIn) { public boolean canHarvestBlock(@Nonnull BlockState blockIn) {
return false; return false;
} }
@Override @Override
public boolean isValidRepairItem(@Nonnull ItemStack toRepair, @Nonnull ItemStack repair) { public boolean getIsRepairable(@Nonnull ItemStack toRepair, @Nonnull ItemStack repair) {
return false; return false;
} }
@ -95,9 +95,8 @@ public abstract class ItemWand extends Item implements ICustomItemModel
return Integer.MAX_VALUE; return Integer.MAX_VALUE;
} }
@Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public void appendHoverText(@Nonnull ItemStack itemstack, Level worldIn, @Nonnull List<Component> lines, @Nonnull TooltipFlag extraInfo) { public void addInformation(@Nonnull ItemStack itemstack, World worldIn, @Nonnull List<ITextComponent> lines, @Nonnull ITooltipFlag extraInfo) {
WandOptions options = new WandOptions(itemstack); WandOptions options = new WandOptions(itemstack);
int limit = options.cores.get().getWandAction().getLimit(itemstack); int limit = options.cores.get().getWandAction().getLimit(itemstack);
@ -107,35 +106,35 @@ public abstract class ItemWand extends Item implements ICustomItemModel
if(Screen.hasShiftDown()) { if(Screen.hasShiftDown()) {
for(int i = 1; i < options.allOptions.length; i++) { for(int i = 1; i < options.allOptions.length; i++) {
IOption<?> opt = options.allOptions[i]; IOption<?> opt = options.allOptions[i];
lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA) lines.add(new TranslationTextComponent(opt.getKeyTranslation()).mergeStyle(TextFormatting.AQUA)
.append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.GRAY)) .append(new TranslationTextComponent(opt.getValueTranslation()).mergeStyle(TextFormatting.GRAY))
); );
} }
if(!options.cores.getUpgrades().isEmpty()) { if(!options.cores.getUpgrades().isEmpty()) {
lines.add(new TextComponent("")); lines.add(new StringTextComponent(""));
lines.add(new TranslatableComponent(langTooltip + "cores").withStyle(ChatFormatting.GRAY)); lines.add(new TranslationTextComponent(langTooltip + "cores").mergeStyle(TextFormatting.GRAY));
for(IWandCore core : options.cores.getUpgrades()) { for(IWandCore core : options.cores.getUpgrades()) {
lines.add(new TranslatableComponent(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString())); lines.add(new TranslationTextComponent(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString()));
} }
} }
} }
// Default tooltip: show block limit + active wand core // Default tooltip: show block limit + active wand core
else { else {
IOption<?> opt = options.allOptions[0]; IOption<?> opt = options.allOptions[0];
lines.add(new TranslatableComponent(langTooltip + "blocks", limit).withStyle(ChatFormatting.GRAY)); lines.add(new TranslationTextComponent(langTooltip + "blocks", limit).mergeStyle(TextFormatting.GRAY));
lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA) lines.add(new TranslationTextComponent(opt.getKeyTranslation()).mergeStyle(TextFormatting.AQUA)
.append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.WHITE))); .append(new TranslationTextComponent(opt.getValueTranslation()).mergeStyle(TextFormatting.WHITE)));
lines.add(new TranslatableComponent(langTooltip + "shift").withStyle(ChatFormatting.AQUA)); lines.add(new TranslationTextComponent(langTooltip + "shift").mergeStyle(TextFormatting.AQUA));
} }
} }
public static void optionMessage(Player player, IOption<?> option) { public static void optionMessage(PlayerEntity player, IOption<?> option) {
player.displayClientMessage( player.sendStatusMessage(
new TranslatableComponent(option.getKeyTranslation()).withStyle(ChatFormatting.AQUA) new TranslationTextComponent(option.getKeyTranslation()).mergeStyle(TextFormatting.AQUA)
.append(new TranslatableComponent(option.getValueTranslation()).withStyle(ChatFormatting.WHITE)) .append(new TranslationTextComponent(option.getValueTranslation()).mergeStyle(TextFormatting.WHITE))
.append(new TextComponent(" - ").withStyle(ChatFormatting.GRAY)) .append(new StringTextComponent(" - ").mergeStyle(TextFormatting.GRAY))
.append(new TranslatableComponent(option.getDescTranslation()).withStyle(ChatFormatting.WHITE)) .append(new TranslationTextComponent(option.getDescTranslation()).mergeStyle(TextFormatting.WHITE))
, true); , true);
} }

View file

@ -1,17 +1,17 @@
package thetadev.constructionwand.items.wand; package thetadev.constructionwand.items.wand;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.IItemTier;
import net.minecraft.world.item.Tier; import net.minecraft.item.ItemStack;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
public class ItemWandBasic extends ItemWand public class ItemWandBasic extends ItemWand
{ {
private final Tier tier; private final IItemTier tier;
public ItemWandBasic(Properties properties, Tier tier) { public ItemWandBasic(String name, Properties properties, IItemTier tier) {
super(properties.durability(tier.getUses())); super(name, properties.maxDamage(tier.getMaxUses()));
this.tier = tier; this.tier = tier;
} }
@ -22,11 +22,11 @@ public class ItemWandBasic extends ItemWand
@Override @Override
public int remainingDurability(ItemStack stack) { public int remainingDurability(ItemStack stack) {
return stack.getMaxDamage() - stack.getDamageValue(); return stack.getMaxDamage() - stack.getDamage();
} }
@Override @Override
public boolean isValidRepairItem(@Nonnull ItemStack toRepair, @Nonnull ItemStack repair) { public boolean getIsRepairable(@Nonnull ItemStack toRepair, @Nonnull ItemStack repair) {
return this.tier.getRepairIngredient().test(repair); return this.tier.getRepairMaterial().test(repair);
} }
} }

View file

@ -3,7 +3,7 @@ package thetadev.constructionwand.items.wand;
public class ItemWandInfinity extends ItemWand public class ItemWandInfinity extends ItemWand
{ {
public ItemWandInfinity(Properties properties) { public ItemWandInfinity(String name, Properties properties) {
super(properties.stacksTo(1).fireResistant()); super(name, properties.maxStackSize(1).isBurnable());
} }
} }

View file

@ -1,8 +1,8 @@
package thetadev.constructionwand.network; package thetadev.constructionwand.network;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import java.util.function.Supplier; import java.util.function.Supplier;
@ -15,11 +15,11 @@ public class PacketQueryUndo
this.undoPressed = undoPressed; this.undoPressed = undoPressed;
} }
public static void encode(PacketQueryUndo msg, FriendlyByteBuf buffer) { public static void encode(PacketQueryUndo msg, PacketBuffer buffer) {
buffer.writeBoolean(msg.undoPressed); buffer.writeBoolean(msg.undoPressed);
} }
public static PacketQueryUndo decode(FriendlyByteBuf buffer) { public static PacketQueryUndo decode(PacketBuffer buffer) {
return new PacketQueryUndo(buffer.readBoolean()); return new PacketQueryUndo(buffer.readBoolean());
} }
@ -28,7 +28,7 @@ public class PacketQueryUndo
public static void handle(final PacketQueryUndo msg, final Supplier<NetworkEvent.Context> ctx) { public static void handle(final PacketQueryUndo msg, final Supplier<NetworkEvent.Context> ctx) {
if(!ctx.get().getDirection().getReceptionSide().isServer()) return; if(!ctx.get().getDirection().getReceptionSide().isServer()) return;
ServerPlayer player = ctx.get().getSender(); ServerPlayerEntity player = ctx.get().getSender();
if(player == null) return; if(player == null) return;
ConstructionWand.instance.undoHistory.updateClient(player, msg.undoPressed); ConstructionWand.instance.undoHistory.updateClient(player, msg.undoPressed);

View file

@ -1,8 +1,8 @@
package thetadev.constructionwand.network; package thetadev.constructionwand.network;
import net.minecraft.core.BlockPos; import net.minecraft.network.PacketBuffer;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.util.math.BlockPos;
import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import java.util.HashSet; import java.util.HashSet;
@ -21,13 +21,13 @@ public class PacketUndoBlocks
this.undoBlocks = undoBlocks; this.undoBlocks = undoBlocks;
} }
public static void encode(PacketUndoBlocks msg, FriendlyByteBuf buffer) { public static void encode(PacketUndoBlocks msg, PacketBuffer buffer) {
for(BlockPos pos : msg.undoBlocks) { for(BlockPos pos : msg.undoBlocks) {
buffer.writeBlockPos(pos); buffer.writeBlockPos(pos);
} }
} }
public static PacketUndoBlocks decode(FriendlyByteBuf buffer) { public static PacketUndoBlocks decode(PacketBuffer buffer) {
HashSet<BlockPos> undoBlocks = new HashSet<>(); HashSet<BlockPos> undoBlocks = new HashSet<>();
while(buffer.isReadable()) { while(buffer.isReadable()) {

View file

@ -1,9 +1,9 @@
package thetadev.constructionwand.network; package thetadev.constructionwand.network;
import net.minecraft.network.FriendlyByteBuf; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.network.PacketBuffer;
import net.minecraftforge.network.NetworkEvent; import net.minecraftforge.fml.network.NetworkEvent;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.basics.option.IOption; import thetadev.constructionwand.basics.option.IOption;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
@ -27,14 +27,14 @@ public class PacketWandOption
this.notify = notify; this.notify = notify;
} }
public static void encode(PacketWandOption msg, FriendlyByteBuf buffer) { public static void encode(PacketWandOption msg, PacketBuffer buffer) {
buffer.writeUtf(msg.key); buffer.writeString(msg.key);
buffer.writeUtf(msg.value); buffer.writeString(msg.value);
buffer.writeBoolean(msg.notify); buffer.writeBoolean(msg.notify);
} }
public static PacketWandOption decode(FriendlyByteBuf buffer) { public static PacketWandOption decode(PacketBuffer buffer) {
return new PacketWandOption(buffer.readUtf(100), buffer.readUtf(100), buffer.readBoolean()); return new PacketWandOption(buffer.readString(100), buffer.readString(100), buffer.readBoolean());
} }
public static class Handler public static class Handler
@ -42,7 +42,7 @@ public class PacketWandOption
public static void handle(final PacketWandOption msg, final Supplier<NetworkEvent.Context> ctx) { public static void handle(final PacketWandOption msg, final Supplier<NetworkEvent.Context> ctx) {
if(!ctx.get().getDirection().getReceptionSide().isServer()) return; if(!ctx.get().getDirection().getReceptionSide().isServer()) return;
ServerPlayer player = ctx.get().getSender(); ServerPlayerEntity player = ctx.get().getSender();
if(player == null) return; if(player == null) return;
ItemStack wand = WandUtil.holdingWand(player); ItemStack wand = WandUtil.holdingWand(player);
@ -54,7 +54,7 @@ public class PacketWandOption
option.setValueString(msg.value); option.setValueString(msg.value);
if(msg.notify) ItemWand.optionMessage(player, option); if(msg.notify) ItemWand.optionMessage(player, option);
player.getInventory().setChanged(); player.inventory.markDirty();
} }
} }
} }

View file

@ -1,27 +1,27 @@
package thetadev.constructionwand.wand; package thetadev.constructionwand.wand;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.InteractionHand; import net.minecraft.item.BlockItem;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.Hand;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.World;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
public class WandItemUseContext extends BlockPlaceContext public class WandItemUseContext extends BlockItemUseContext
{ {
public WandItemUseContext(Level world, Player player, BlockHitResult rayTraceResult, BlockPos pos, BlockItem item) { public WandItemUseContext(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult, BlockPos pos, BlockItem item) {
super(world, player, InteractionHand.MAIN_HAND, new ItemStack(item), super(world, player, Hand.MAIN_HAND, new ItemStack(item),
new BlockHitResult(getBlockHitVec(rayTraceResult, pos), rayTraceResult.getDirection(), pos, false)); new BlockRayTraceResult(getBlockHitVec(rayTraceResult, pos), rayTraceResult.getFace(), pos, false));
} }
private static Vec3 getBlockHitVec(BlockHitResult rayTraceResult, BlockPos pos) { private static Vector3d getBlockHitVec(BlockRayTraceResult rayTraceResult, BlockPos pos) {
Vec3 hitVec = rayTraceResult.getLocation(); // Absolute coords of hit target Vector3d hitVec = rayTraceResult.getHitVec(); // Absolute coords of hit target
Vec3 blockDelta = WandUtil.blockPosVec(rayTraceResult.getBlockPos()).subtract(WandUtil.blockPosVec(pos)); // Vector between start and current block Vector3d blockDelta = WandUtil.blockPosVec(rayTraceResult.getPos()).subtract(WandUtil.blockPosVec(pos)); // Vector between start and current block
return blockDelta.add(hitVec); // Absolute coords of current block hit target return blockDelta.add(hitVec); // Absolute coords of current block hit target
} }

View file

@ -1,16 +1,15 @@
package thetadev.constructionwand.wand; package thetadev.constructionwand.wand;
import net.minecraft.core.BlockPos; import net.minecraft.block.SoundType;
import net.minecraft.sounds.SoundSource; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.InteractionHand; import net.minecraft.item.BlockItem;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.Item;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.Item; import net.minecraft.util.SoundCategory;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.level.block.SoundType; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import net.minecraft.world.phys.HitResult;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
@ -32,9 +31,9 @@ import java.util.stream.Collectors;
public class WandJob public class WandJob
{ {
public final Player player; public final PlayerEntity player;
public final Level world; public final World world;
public final BlockHitResult rayTraceResult; public final BlockRayTraceResult rayTraceResult;
public final WandOptions options; public final WandOptions options;
public final ItemStack wand; public final ItemStack wand;
public final ItemWand wandItem; public final ItemWand wandItem;
@ -44,7 +43,7 @@ public class WandJob
private List<ISnapshot> placeSnapshots; private List<ISnapshot> placeSnapshots;
public WandJob(Player player, Level world, BlockHitResult rayTraceResult, ItemStack wand) { public WandJob(PlayerEntity player, World world, BlockRayTraceResult rayTraceResult, ItemStack wand) {
this.player = player; this.player = player;
this.world = world; this.world = world;
this.rayTraceResult = rayTraceResult; this.rayTraceResult = rayTraceResult;
@ -64,9 +63,9 @@ public class WandJob
} }
@Nullable @Nullable
private static BlockItem getTargetItem(Level world, BlockHitResult rayTraceResult) { private static BlockItem getTargetItem(World world, BlockRayTraceResult rayTraceResult) {
// Get target item // Get target item
Item tgitem = world.getBlockState(rayTraceResult.getBlockPos()).getBlock().asItem(); Item tgitem = world.getBlockState(rayTraceResult.getPos()).getBlock().asItem();
if(!(tgitem instanceof BlockItem)) return null; if(!(tgitem instanceof BlockItem)) return null;
return (BlockItem) tgitem; return (BlockItem) tgitem;
} }
@ -74,10 +73,10 @@ public class WandJob
public void getSnapshots() { public void getSnapshots() {
int limit; int limit;
// Infinity wand gets enhanced limit in creative mode // Infinity wand gets enhanced limit in creative mode
if(player.isCreative() && wandItem == ModItems.WAND_INFINITY.get()) limit = ConfigServer.LIMIT_CREATIVE.get(); if(player.isCreative() && wandItem == ModItems.WAND_INFINITY) limit = ConfigServer.LIMIT_CREATIVE.get();
else limit = Math.min(wandItem.remainingDurability(wand), wandAction.getLimit(wand)); else limit = Math.min(wandItem.remainingDurability(wand), wandAction.getLimit(wand));
if(rayTraceResult.getType() == HitResult.Type.BLOCK) if(rayTraceResult.getType() == RayTraceResult.Type.BLOCK)
placeSnapshots = wandAction.getSnapshots(world, player, rayTraceResult, wand, options, wandSupplier, limit); placeSnapshots = wandAction.getSnapshots(world, player, rayTraceResult, wand, options, wandSupplier, limit);
else else
placeSnapshots = wandAction.getSnapshotsFromAir(world, player, rayTraceResult, wand, options, wandSupplier, limit); placeSnapshots = wandAction.getSnapshotsFromAir(world, player, rayTraceResult, wand, options, wandSupplier, limit);
@ -87,10 +86,6 @@ public class WandJob
return placeSnapshots.stream().map(ISnapshot::getPos).collect(Collectors.toSet()); return placeSnapshots.stream().map(ISnapshot::getPos).collect(Collectors.toSet());
} }
public int blockCount() {
return placeSnapshots.size();
}
public boolean doIt() { public boolean doIt() {
ArrayList<ISnapshot> executed = new ArrayList<>(); ArrayList<ISnapshot> executed = new ArrayList<>();
@ -103,7 +98,7 @@ public class WandJob
// If the item cant be taken, undo the placement // If the item cant be taken, undo the placement
if(wandSupplier.takeItemStack(snapshot.getRequiredItems()) == 0) { if(wandSupplier.takeItemStack(snapshot.getRequiredItems()) == 0) {
executed.add(snapshot); executed.add(snapshot);
wand.hurtAndBreak(1, player, e -> e.broadcastBreakEvent(InteractionHand.MAIN_HAND)); wand.damageItem(1, player, (e) -> e.sendBreakAnimation(player.swingingHand));
} }
else { else {
ConstructionWand.LOGGER.info("Item could not be taken. Remove block: " + ConstructionWand.LOGGER.info("Item could not be taken. Remove block: " +
@ -111,7 +106,7 @@ public class WandJob
snapshot.forceRestore(world); snapshot.forceRestore(world);
} }
} }
player.awardStat(ModStats.USE_WAND); player.addStat(ModStats.USE_WAND);
} }
} }
placeSnapshots = executed; placeSnapshots = executed;
@ -119,7 +114,7 @@ public class WandJob
// Play place sound // Play place sound
if(!placeSnapshots.isEmpty()) { if(!placeSnapshots.isEmpty()) {
SoundType sound = placeSnapshots.get(0).getBlockState().getSoundType(); SoundType sound = placeSnapshots.get(0).getBlockState().getSoundType();
world.playSound(null, WandUtil.playerPos(player), sound.getPlaceSound(), SoundSource.BLOCKS, sound.volume, sound.pitch); world.playSound(null, WandUtil.playerPos(player), sound.getPlaceSound(), SoundCategory.BLOCKS, sound.volume, sound.pitch);
// Add to job history for undo // Add to job history for undo
ConstructionWand.instance.undoHistory.add(player, world, placeSnapshots); ConstructionWand.instance.undoHistory.add(player, world, placeSnapshots);

View file

@ -1,13 +1,13 @@
package thetadev.constructionwand.wand.action; package thetadev.constructionwand.wand.action;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.core.Direction; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.Direction;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.util.math.vector.Vector3d;
import net.minecraft.world.phys.Vec3; import net.minecraft.world.World;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
@ -29,16 +29,16 @@ public class ActionAngel implements IWandAction
@Nonnull @Nonnull
@Override @Override
public List<ISnapshot> getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, public List<ISnapshot> getSnapshots(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) {
LinkedList<ISnapshot> placeSnapshots = new LinkedList<>(); LinkedList<ISnapshot> placeSnapshots = new LinkedList<>();
Direction placeDirection = rayTraceResult.getDirection(); Direction placeDirection = rayTraceResult.getFace();
BlockPos currentPos = rayTraceResult.getBlockPos(); BlockPos currentPos = rayTraceResult.getPos();
BlockState supportingBlock = world.getBlockState(currentPos); BlockState supportingBlock = world.getBlockState(currentPos);
for(int i = 0; i < limit; i++) { for(int i = 0; i < limit; i++) {
currentPos = currentPos.offset(placeDirection.getOpposite().getNormal()); currentPos = currentPos.offset(placeDirection.getOpposite());
PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentPos, rayTraceResult, supportingBlock); PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentPos, rayTraceResult, supportingBlock);
if(snapshot != null) { if(snapshot != null) {
@ -51,15 +51,15 @@ public class ActionAngel implements IWandAction
@Nonnull @Nonnull
@Override @Override
public List<ISnapshot> getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, public List<ISnapshot> getSnapshotsFromAir(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) {
LinkedList<ISnapshot> placeSnapshots = new LinkedList<>(); LinkedList<ISnapshot> placeSnapshots = new LinkedList<>();
if(!player.isCreative() && !ConfigServer.ANGEL_FALLING.get() && player.fallDistance > 10) return placeSnapshots; if(!player.isCreative() && !ConfigServer.ANGEL_FALLING.get() && player.fallDistance > 10) return placeSnapshots;
Vec3 playerVec = WandUtil.entityPositionVec(player); Vector3d playerVec = WandUtil.entityPositionVec(player);
Vec3 lookVec = player.getLookAngle().multiply(2, 2, 2); Vector3d lookVec = player.getLookVec().mul(2, 2, 2);
Vec3 placeVec = playerVec.add(lookVec); Vector3d placeVec = playerVec.add(lookVec);
BlockPos currentPos = new BlockPos(placeVec); BlockPos currentPos = new BlockPos(placeVec);

View file

@ -1,15 +1,16 @@
package thetadev.constructionwand.wand.action; package thetadev.constructionwand.wand.action;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.core.Direction; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.Direction;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.wand.undo.ISnapshot; import thetadev.constructionwand.wand.undo.ISnapshot;
import thetadev.constructionwand.wand.undo.PlaceSnapshot; import thetadev.constructionwand.wand.undo.PlaceSnapshot;
@ -32,15 +33,15 @@ public class ActionConstruction implements IWandAction
@Nonnull @Nonnull
@Override @Override
public List<ISnapshot> getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, public List<ISnapshot> getSnapshots(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) {
LinkedList<ISnapshot> placeSnapshots = new LinkedList<>(); LinkedList<ISnapshot> placeSnapshots = new LinkedList<>();
LinkedList<BlockPos> candidates = new LinkedList<>(); LinkedList<BlockPos> candidates = new LinkedList<>();
HashSet<BlockPos> allCandidates = new HashSet<>(); HashSet<BlockPos> allCandidates = new HashSet<>();
Direction placeDirection = rayTraceResult.getDirection(); Direction placeDirection = rayTraceResult.getFace();
BlockState targetBlock = world.getBlockState(rayTraceResult.getBlockPos()); BlockState targetBlock = world.getBlockState(rayTraceResult.getPos());
BlockPos startingPoint = rayTraceResult.getBlockPos().offset(placeDirection.getNormal()); BlockPos startingPoint = rayTraceResult.getPos().offset(placeDirection);
// Is place direction allowed by lock? // Is place direction allowed by lock?
if(placeDirection == Direction.UP || placeDirection == Direction.DOWN) { if(placeDirection == Direction.UP || placeDirection == Direction.DOWN) {
@ -53,10 +54,10 @@ public class ActionConstruction implements IWandAction
while(!candidates.isEmpty() && placeSnapshots.size() < limit) { while(!candidates.isEmpty() && placeSnapshots.size() < limit) {
BlockPos currentCandidate = candidates.removeFirst(); BlockPos currentCandidate = candidates.removeFirst();
try { try {
BlockPos supportingPoint = currentCandidate.offset(placeDirection.getOpposite().getNormal()); BlockPos supportingPoint = currentCandidate.offset(placeDirection.getOpposite());
BlockState candidateSupportingBlock = world.getBlockState(supportingPoint); BlockState candidateSupportingBlock = world.getBlockState(supportingPoint);
if(options.matchBlocks(targetBlock.getBlock(), candidateSupportingBlock.getBlock()) && if(WandUtil.matchBlocks(options, targetBlock.getBlock(), candidateSupportingBlock.getBlock()) &&
allCandidates.add(currentCandidate)) { allCandidates.add(currentCandidate)) {
PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentCandidate, rayTraceResult, candidateSupportingBlock); PlaceSnapshot snapshot = supplier.getPlaceSnapshot(world, currentCandidate, rayTraceResult, candidateSupportingBlock);
if(snapshot == null) continue; if(snapshot == null) continue;
@ -66,52 +67,52 @@ public class ActionConstruction implements IWandAction
case DOWN: case DOWN:
case UP: case UP:
if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) { if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) {
candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); candidates.add(currentCandidate.offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH));
} }
if(options.testLock(WandOptions.LOCK.EASTWEST)) { if(options.testLock(WandOptions.LOCK.EASTWEST)) {
candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.WEST));
} }
if(options.testLock(WandOptions.LOCK.NORTHSOUTH) && options.testLock(WandOptions.LOCK.EASTWEST)) { 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).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.NORTH.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.NORTH).offset(Direction.WEST));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH).offset(Direction.WEST));
} }
break; break;
case NORTH: case NORTH:
case SOUTH: case SOUTH:
if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { if(options.testLock(WandOptions.LOCK.HORIZONTAL)) {
candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.WEST));
} }
if(options.testLock(WandOptions.LOCK.VERTICAL)) { if(options.testLock(WandOptions.LOCK.VERTICAL)) {
candidates.add(currentCandidate.offset(Direction.UP.getNormal())); candidates.add(currentCandidate.offset(Direction.UP));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN));
} }
if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { 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).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.WEST));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.WEST));
} }
break; break;
case EAST: case EAST:
case WEST: case WEST:
if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { if(options.testLock(WandOptions.LOCK.HORIZONTAL)) {
candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); candidates.add(currentCandidate.offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH));
} }
if(options.testLock(WandOptions.LOCK.VERTICAL)) { if(options.testLock(WandOptions.LOCK.VERTICAL)) {
candidates.add(currentCandidate.offset(Direction.UP.getNormal())); candidates.add(currentCandidate.offset(Direction.UP));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN));
} }
if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { 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).offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.SOUTH));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.NORTH.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.SOUTH));
} }
break; break;
} }
@ -126,7 +127,7 @@ public class ActionConstruction implements IWandAction
@Nonnull @Nonnull
@Override @Override
public List<ISnapshot> getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, public List<ISnapshot> getSnapshotsFromAir(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) {
return new ArrayList<>(); return new ArrayList<>();
} }

View file

@ -1,12 +1,12 @@
package thetadev.constructionwand.wand.action; package thetadev.constructionwand.wand.action;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.core.Direction; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.Direction;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import thetadev.constructionwand.api.IWandAction; import thetadev.constructionwand.api.IWandAction;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
@ -30,7 +30,7 @@ public class ActionDestruction implements IWandAction
@Nonnull @Nonnull
@Override @Override
public List<ISnapshot> getSnapshots(Level world, Player player, BlockHitResult rayTraceResult, public List<ISnapshot> getSnapshots(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) {
LinkedList<ISnapshot> destroySnapshots = new LinkedList<>(); LinkedList<ISnapshot> destroySnapshots = new LinkedList<>();
// Current list of block positions to process // Current list of block positions to process
@ -39,10 +39,10 @@ public class ActionDestruction implements IWandAction
HashSet<BlockPos> allCandidates = new HashSet<>(); HashSet<BlockPos> allCandidates = new HashSet<>();
// Block face the wand was pointed at // Block face the wand was pointed at
Direction breakFace = rayTraceResult.getDirection(); Direction breakFace = rayTraceResult.getFace();
// Block the wand was pointed at // Block the wand was pointed at
BlockPos startingPoint = rayTraceResult.getBlockPos(); BlockPos startingPoint = rayTraceResult.getPos();
BlockState targetBlock = world.getBlockState(rayTraceResult.getBlockPos()); BlockState targetBlock = world.getBlockState(rayTraceResult.getPos());
// Is break direction allowed by lock? // Is break direction allowed by lock?
// Tried to break blocks from top/bottom face, so the wand should allow breaking in NS/EW direction // Tried to break blocks from top/bottom face, so the wand should allow breaking in NS/EW direction
@ -59,13 +59,13 @@ public class ActionDestruction implements IWandAction
BlockPos currentCandidate = candidates.removeFirst(); BlockPos currentCandidate = candidates.removeFirst();
// Only break blocks facing the player, with no collidable blocks in between // Only break blocks facing the player, with no collidable blocks in between
if(!WandUtil.isBlockPermeable(world, currentCandidate.offset(breakFace.getNormal()))) continue; if(!WandUtil.isBlockPermeable(world, currentCandidate.offset(breakFace))) continue;
try { try {
BlockState candidateBlock = world.getBlockState(currentCandidate); BlockState candidateBlock = world.getBlockState(currentCandidate);
// If target and candidate blocks match and the current candidate has not been processed // If target and candidate blocks match and the current candidate has not been processed
if(options.matchBlocks(targetBlock.getBlock(), candidateBlock.getBlock()) && if(WandUtil.matchBlocks(options, targetBlock.getBlock(), candidateBlock.getBlock()) &&
allCandidates.add(currentCandidate)) { allCandidates.add(currentCandidate)) {
DestroySnapshot snapshot = DestroySnapshot.get(world, player, currentCandidate); DestroySnapshot snapshot = DestroySnapshot.get(world, player, currentCandidate);
if(snapshot == null) continue; if(snapshot == null) continue;
@ -75,52 +75,52 @@ public class ActionDestruction implements IWandAction
case DOWN: case DOWN:
case UP: case UP:
if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) { if(options.testLock(WandOptions.LOCK.NORTHSOUTH)) {
candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); candidates.add(currentCandidate.offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH));
} }
if(options.testLock(WandOptions.LOCK.EASTWEST)) { if(options.testLock(WandOptions.LOCK.EASTWEST)) {
candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.WEST));
} }
if(options.testLock(WandOptions.LOCK.NORTHSOUTH) && options.testLock(WandOptions.LOCK.EASTWEST)) { 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).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.NORTH.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.NORTH).offset(Direction.WEST));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH).offset(Direction.WEST));
} }
break; break;
case NORTH: case NORTH:
case SOUTH: case SOUTH:
if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { if(options.testLock(WandOptions.LOCK.HORIZONTAL)) {
candidates.add(currentCandidate.offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.WEST));
} }
if(options.testLock(WandOptions.LOCK.VERTICAL)) { if(options.testLock(WandOptions.LOCK.VERTICAL)) {
candidates.add(currentCandidate.offset(Direction.UP.getNormal())); candidates.add(currentCandidate.offset(Direction.UP));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN));
} }
if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { 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).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.WEST));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.EAST.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.EAST));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.WEST.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.WEST));
} }
break; break;
case EAST: case EAST:
case WEST: case WEST:
if(options.testLock(WandOptions.LOCK.HORIZONTAL)) { if(options.testLock(WandOptions.LOCK.HORIZONTAL)) {
candidates.add(currentCandidate.offset(Direction.NORTH.getNormal())); candidates.add(currentCandidate.offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.SOUTH));
} }
if(options.testLock(WandOptions.LOCK.VERTICAL)) { if(options.testLock(WandOptions.LOCK.VERTICAL)) {
candidates.add(currentCandidate.offset(Direction.UP.getNormal())); candidates.add(currentCandidate.offset(Direction.UP));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN));
} }
if(options.testLock(WandOptions.LOCK.HORIZONTAL) && options.testLock(WandOptions.LOCK.VERTICAL)) { 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).offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.UP.getNormal()).offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.UP).offset(Direction.SOUTH));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.NORTH.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.NORTH));
candidates.add(currentCandidate.offset(Direction.DOWN.getNormal()).offset(Direction.SOUTH.getNormal())); candidates.add(currentCandidate.offset(Direction.DOWN).offset(Direction.SOUTH));
} }
break; break;
} }
@ -135,7 +135,7 @@ public class ActionDestruction implements IWandAction
@Nonnull @Nonnull
@Override @Override
public List<ISnapshot> getSnapshotsFromAir(Level world, Player player, BlockHitResult rayTraceResult, public List<ISnapshot> getSnapshotsFromAir(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) { ItemStack wand, WandOptions options, IWandSupplier supplier, int limit) {
return new ArrayList<>(); return new ArrayList<>();
} }

View file

@ -1,15 +1,15 @@
package thetadev.constructionwand.wand.supplier; package thetadev.constructionwand.wand.supplier;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.world.InteractionHand; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.entity.player.Player; import net.minecraft.item.BlockItem;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.Item;
import net.minecraft.world.item.Item; import net.minecraft.item.ItemStack;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.Items;
import net.minecraft.world.item.Items; import net.minecraft.util.Hand;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.api.IWandSupplier; import thetadev.constructionwand.api.IWandSupplier;
import thetadev.constructionwand.basics.ReplacementRegistry; import thetadev.constructionwand.basics.ReplacementRegistry;
@ -30,20 +30,20 @@ import java.util.List;
*/ */
public class SupplierInventory implements IWandSupplier public class SupplierInventory implements IWandSupplier
{ {
protected final Player player; protected final PlayerEntity player;
protected final WandOptions options; protected final WandOptions options;
protected HashMap<BlockItem, Integer> itemCounts; protected HashMap<BlockItem, Integer> itemCounts;
protected IPool<BlockItem> itemPool; protected IPool<BlockItem> itemPool;
public SupplierInventory(Player player, WandOptions options) { public SupplierInventory(PlayerEntity player, WandOptions options) {
this.player = player; this.player = player;
this.options = options; this.options = options;
} }
public void getSupply(@Nullable BlockItem target) { public void getSupply(@Nullable BlockItem target) {
itemCounts = new LinkedHashMap<>(); itemCounts = new LinkedHashMap<>();
ItemStack offhandStack = player.getItemInHand(InteractionHand.OFF_HAND); ItemStack offhandStack = player.getHeldItem(Hand.OFF_HAND);
itemPool = new OrderedPool<>(); itemPool = new OrderedPool<>();
@ -74,7 +74,7 @@ public class SupplierInventory implements IWandSupplier
@Override @Override
@Nullable @Nullable
public PlaceSnapshot getPlaceSnapshot(Level world, BlockPos pos, BlockHitResult rayTraceResult, public PlaceSnapshot getPlaceSnapshot(World world, BlockPos pos, BlockRayTraceResult rayTraceResult,
@Nullable BlockState supportingBlock) { @Nullable BlockState supportingBlock) {
if(!WandUtil.isPositionPlaceable(world, player, pos, options.replace.get())) return null; if(!WandUtil.isPositionPlaceable(world, player, pos, options.replace.get())) return null;
itemPool.reset(); itemPool.reset();
@ -105,7 +105,7 @@ public class SupplierInventory implements IWandSupplier
int count = stack.getCount(); int count = stack.getCount();
Item item = stack.getItem(); Item item = stack.getItem();
if(player.getInventory().items == null) return count; if(player.inventory == null || player.inventory.mainInventory == null) return count;
if(player.isCreative()) return 0; if(player.isCreative()) return 0;
List<ItemStack> hotbar = WandUtil.getHotbarWithOffhand(player); List<ItemStack> hotbar = WandUtil.getHotbarWithOffhand(player);
@ -136,7 +136,7 @@ public class SupplierInventory implements IWandSupplier
int toTake = Math.min(count, stack.getCount()); int toTake = Math.min(count, stack.getCount());
stack.shrink(toTake); stack.shrink(toTake);
count -= toTake; count -= toTake;
player.getInventory().setChanged(); player.inventory.markDirty();
} }
} }
return count; return count;

View file

@ -1,8 +1,8 @@
package thetadev.constructionwand.wand.supplier; package thetadev.constructionwand.wand.supplier;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.BlockItem; import net.minecraft.item.BlockItem;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.basics.pool.RandomPool; import thetadev.constructionwand.basics.pool.RandomPool;
@ -12,7 +12,7 @@ import java.util.LinkedHashMap;
public class SupplierRandom extends SupplierInventory public class SupplierRandom extends SupplierInventory
{ {
public SupplierRandom(Player player, WandOptions options) { public SupplierRandom(PlayerEntity player, WandOptions options) {
super(player, options); super(player, options);
} }
@ -21,7 +21,7 @@ public class SupplierRandom extends SupplierInventory
itemCounts = new LinkedHashMap<>(); itemCounts = new LinkedHashMap<>();
// Random mode -> add all items from hotbar // Random mode -> add all items from hotbar
itemPool = new RandomPool<>(player.getRandom()); itemPool = new RandomPool<>(player.getRNG());
for(ItemStack stack : WandUtil.getHotbarWithOffhand(player)) { for(ItemStack stack : WandUtil.getHotbarWithOffhand(player)) {
if(stack.getItem() instanceof BlockItem) addBlockItem((BlockItem) stack.getItem()); if(stack.getItem() instanceof BlockItem) addBlockItem((BlockItem) stack.getItem());

View file

@ -1,12 +1,12 @@
package thetadev.constructionwand.wand.undo; package thetadev.constructionwand.wand.undo;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.fluid.Fluids;
import net.minecraft.world.level.Level; import net.minecraft.item.ItemStack;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.material.Fluids; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
import javax.annotation.Nullable; import javax.annotation.Nullable;
@ -22,7 +22,7 @@ public class DestroySnapshot implements ISnapshot
} }
@Nullable @Nullable
public static DestroySnapshot get(Level world, Player player, BlockPos pos) { public static DestroySnapshot get(World world, PlayerEntity player, BlockPos pos) {
if(!WandUtil.isBlockRemovable(world, player, pos)) return null; if(!WandUtil.isBlockRemovable(world, player, pos)) return null;
return new DestroySnapshot(world.getBlockState(pos), pos); return new DestroySnapshot(world.getBlockState(pos), pos);
@ -44,34 +44,34 @@ public class DestroySnapshot implements ISnapshot
} }
@Override @Override
public boolean execute(Level world, Player player, BlockHitResult rayTraceResult) { public boolean execute(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult) {
return WandUtil.removeBlock(world, player, block, pos); return WandUtil.removeBlock(world, player, block, pos);
} }
@Override @Override
public boolean canRestore(Level world, Player player) { public boolean canRestore(World world, PlayerEntity player) {
// Is position out of world? // Is position out of world?
if(!world.isInWorldBounds(pos)) return false; if(!world.isBlockPresent(pos)) return false;
// Is block modifiable? // Is block modifiable?
if(!world.mayInteract(player, pos)) return false; if(!world.isBlockModifiable(player, pos)) return false;
// Ignore blocks and entities when in creative // Ignore blocks and entities when in creative
if(player.isCreative()) return true; if(player.isCreative()) return true;
// Is block empty or fluid? // Is block empty or fluid?
if(!world.isEmptyBlock(pos) && !world.getBlockState(pos).canBeReplaced(Fluids.EMPTY)) return false; if(!world.isAirBlock(pos) && !world.getBlockState(pos).isReplaceable(Fluids.EMPTY)) return false;
return !WandUtil.entitiesCollidingWithBlock(world, block, pos); return !WandUtil.entitiesCollidingWithBlock(world, block, pos);
} }
@Override @Override
public boolean restore(Level world, Player player) { public boolean restore(World world, PlayerEntity player) {
return WandUtil.placeBlock(world, player, block, pos, null); return WandUtil.placeBlock(world, player, block, pos, null);
} }
@Override @Override
public void forceRestore(Level world) { public void forceRestore(World world) {
world.setBlockAndUpdate(pos, block); world.setBlockState(pos, block);
} }
} }

View file

@ -1,11 +1,11 @@
package thetadev.constructionwand.wand.undo; package thetadev.constructionwand.wand.undo;
import net.minecraft.core.BlockPos; import net.minecraft.block.BlockState;
import net.minecraft.world.entity.player.Player; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.world.level.Level; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.World;
public interface ISnapshot public interface ISnapshot
{ {
@ -15,11 +15,11 @@ public interface ISnapshot
ItemStack getRequiredItems(); ItemStack getRequiredItems();
boolean execute(Level world, Player player, BlockHitResult rayTraceResult); boolean execute(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult);
boolean canRestore(Level world, Player player); boolean canRestore(World world, PlayerEntity player);
boolean restore(Level world, Player player); boolean restore(World world, PlayerEntity player);
void forceRestore(Level world); void forceRestore(World world);
} }

View file

@ -1,16 +1,18 @@
package thetadev.constructionwand.wand.undo; package thetadev.constructionwand.wand.undo;
import net.minecraft.core.BlockPos; import net.minecraft.block.Block;
import net.minecraft.world.entity.player.Player; import net.minecraft.block.BlockState;
import net.minecraft.world.item.BlockItem; import net.minecraft.block.Blocks;
import net.minecraft.world.item.ItemStack; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.item.BlockItem;
import net.minecraft.world.level.Level; import net.minecraft.item.BlockItemUseContext;
import net.minecraft.world.level.block.state.BlockState; import net.minecraft.item.ItemStack;
import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.state.Property;
import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.state.properties.SlabType;
import net.minecraft.world.phys.BlockHitResult; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.world.World;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.basics.option.WandOptions; import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.wand.WandItemUseContext; import thetadev.constructionwand.wand.WandItemUseContext;
@ -33,7 +35,7 @@ public class PlaceSnapshot implements ISnapshot
this.targetMode = targetMode; this.targetMode = targetMode;
} }
public static PlaceSnapshot get(Level world, Player player, BlockHitResult rayTraceResult, public static PlaceSnapshot get(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
BlockPos pos, BlockItem item, BlockPos pos, BlockItem item,
@Nullable BlockState supportingBlock, @Nullable WandOptions options) { @Nullable BlockState supportingBlock, @Nullable WandOptions options) {
boolean targetMode = options != null && supportingBlock != null && options.direction.get() == WandOptions.DIRECTION.TARGET; boolean targetMode = options != null && supportingBlock != null && options.direction.get() == WandOptions.DIRECTION.TARGET;
@ -59,7 +61,7 @@ public class PlaceSnapshot implements ISnapshot
} }
@Override @Override
public boolean execute(Level world, Player player, BlockHitResult rayTraceResult) { public boolean execute(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult) {
// Recalculate PlaceBlockState, because other blocks might be placed nearby // Recalculate PlaceBlockState, because other blocks might be placed nearby
// Not doing this may cause game crashes (StackOverflowException) when placing lots of blocks // Not doing this may cause game crashes (StackOverflowException) when placing lots of blocks
// with changing orientation like panes, iron bars or redstone. // with changing orientation like panes, iron bars or redstone.
@ -69,17 +71,17 @@ public class PlaceSnapshot implements ISnapshot
} }
@Override @Override
public boolean canRestore(Level world, Player player) { public boolean canRestore(World world, PlayerEntity player) {
return true; return true;
} }
@Override @Override
public boolean restore(Level world, Player player) { public boolean restore(World world, PlayerEntity player) {
return WandUtil.removeBlock(world, player, block, pos); return WandUtil.removeBlock(world, player, block, pos);
} }
@Override @Override
public void forceRestore(Level world) { public void forceRestore(World world) {
world.removeBlock(pos, false); world.removeBlock(pos, false);
} }
@ -89,16 +91,16 @@ public class PlaceSnapshot implements ISnapshot
*/ */
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
@Nullable @Nullable
private static BlockState getPlaceBlockstate(Level world, Player player, BlockHitResult rayTraceResult, private static BlockState getPlaceBlockstate(World world, PlayerEntity player, BlockRayTraceResult rayTraceResult,
BlockPos pos, BlockItem item, BlockPos pos, BlockItem item,
@Nullable BlockState supportingBlock, boolean targetMode) { @Nullable BlockState supportingBlock, boolean targetMode) {
// Is block at pos replaceable? // Is block at pos replaceable?
BlockPlaceContext ctx = new WandItemUseContext(world, player, rayTraceResult, pos, item); BlockItemUseContext ctx = new WandItemUseContext(world, player, rayTraceResult, pos, item);
if(!ctx.canPlace()) return null; if(!ctx.canPlace()) return null;
// Can block be placed? // Can block be placed?
BlockState blockState = item.getBlock().getStateForPlacement(ctx); BlockState blockState = item.getBlock().getStateForPlacement(ctx);
if(blockState == null || !blockState.canSurvive(world, pos)) return null; if(blockState == null) return null;
// Forbidden Tile Entity? // Forbidden Tile Entity?
if(!WandUtil.isTEAllowed(blockState)) return null; if(!WandUtil.isTEAllowed(blockState)) return null;
@ -106,23 +108,26 @@ public class PlaceSnapshot implements ISnapshot
// No entities colliding? // No entities colliding?
if(WandUtil.entitiesCollidingWithBlock(world, blockState, pos)) return null; if(WandUtil.entitiesCollidingWithBlock(world, blockState, pos)) return null;
// Adjust blockstate to neighbors
blockState = Block.getValidBlockForPosition(blockState, world, pos);
if(blockState.getBlock() == Blocks.AIR || !blockState.isValidPosition(world, pos)) return null;
// Copy block properties from supporting block // Copy block properties from supporting block
if(targetMode && supportingBlock != null) { if(targetMode && supportingBlock != null) {
// Block properties to be copied (alignment/rotation properties) // Block properties to be copied (alignment/rotation properties)
for(Property property : new Property[]{ for(Property property : new Property[]{
BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.FACING, BlockStateProperties.FACING_HOPPER, BlockStateProperties.HORIZONTAL_FACING, BlockStateProperties.FACING, BlockStateProperties.FACING_EXCEPT_UP,
BlockStateProperties.ROTATION_16, BlockStateProperties.AXIS, BlockStateProperties.HALF, BlockStateProperties.STAIRS_SHAPE}) { BlockStateProperties.ROTATION_0_15, BlockStateProperties.AXIS, BlockStateProperties.HALF, BlockStateProperties.STAIRS_SHAPE}) {
if(supportingBlock.hasProperty(property) && blockState.hasProperty(property)) { if(supportingBlock.hasProperty(property) && blockState.hasProperty(property)) {
blockState = blockState.setValue(property, supportingBlock.getValue(property)); blockState = blockState.with(property, supportingBlock.get(property));
} }
} }
// Dont dupe double slabs // Dont dupe double slabs
if(supportingBlock.hasProperty(BlockStateProperties.SLAB_TYPE) && blockState.hasProperty(BlockStateProperties.SLAB_TYPE)) { if(supportingBlock.hasProperty(BlockStateProperties.SLAB_TYPE) && blockState.hasProperty(BlockStateProperties.SLAB_TYPE)) {
SlabType slabType = supportingBlock.getValue(BlockStateProperties.SLAB_TYPE); SlabType slabType = supportingBlock.get(BlockStateProperties.SLAB_TYPE);
if(slabType != SlabType.DOUBLE) if(slabType != SlabType.DOUBLE) blockState = blockState.with(BlockStateProperties.SLAB_TYPE, slabType);
blockState = blockState.setValue(BlockStateProperties.SLAB_TYPE, slabType);
} }
} }
return blockState; return blockState;

View file

@ -1,14 +1,14 @@
package thetadev.constructionwand.wand.undo; package thetadev.constructionwand.wand.undo;
import net.minecraft.core.BlockPos; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.sounds.SoundEvent; import net.minecraft.item.ItemStack;
import net.minecraft.sounds.SoundEvents; import net.minecraft.util.SoundCategory;
import net.minecraft.sounds.SoundSource; import net.minecraft.util.SoundEvent;
import net.minecraft.world.entity.player.Player; import net.minecraft.util.SoundEvents;
import net.minecraft.world.item.ItemStack; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.level.Level; import net.minecraft.world.World;
import net.minecraftforge.network.PacketDistributor; import net.minecraftforge.fml.network.PacketDistributor;
import thetadev.constructionwand.ConstructionWand; import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.ConfigServer; import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.WandUtil; import thetadev.constructionwand.basics.WandUtil;
@ -25,23 +25,23 @@ public class UndoHistory
history = new HashMap<>(); history = new HashMap<>();
} }
private PlayerEntry getEntryFromPlayer(Player player) { private PlayerEntry getEntryFromPlayer(PlayerEntity player) {
return history.computeIfAbsent(player.getUUID(), k -> new PlayerEntry()); return history.computeIfAbsent(player.getUniqueID(), k -> new PlayerEntry());
} }
public void add(Player player, Level world, List<ISnapshot> placeSnapshots) { public void add(PlayerEntity player, World world, List<ISnapshot> placeSnapshots) {
LinkedList<HistoryEntry> list = getEntryFromPlayer(player).entries; LinkedList<HistoryEntry> list = getEntryFromPlayer(player).entries;
list.add(new HistoryEntry(placeSnapshots, world)); list.add(new HistoryEntry(placeSnapshots, world));
while(list.size() > ConfigServer.UNDO_HISTORY.get()) list.removeFirst(); while(list.size() > ConfigServer.UNDO_HISTORY.get()) list.removeFirst();
} }
public void removePlayer(Player player) { public void removePlayer(PlayerEntity player) {
history.remove(player.getUUID()); history.remove(player.getUniqueID());
} }
public void updateClient(Player player, boolean ctrlDown) { public void updateClient(PlayerEntity player, boolean ctrlDown) {
Level world = player.level; World world = player.getEntityWorld();
if(world.isClientSide) return; if(world.isRemote) return;
// Set state of CTRL key // Set state of CTRL key
PlayerEntry playerEntry = getEntryFromPlayer(player); PlayerEntry playerEntry = getEntryFromPlayer(player);
@ -60,14 +60,14 @@ public class UndoHistory
} }
PacketUndoBlocks packet = new PacketUndoBlocks(positions); PacketUndoBlocks packet = new PacketUndoBlocks(positions);
ConstructionWand.instance.HANDLER.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), packet); ConstructionWand.instance.HANDLER.send(PacketDistributor.PLAYER.with(() -> (ServerPlayerEntity) player), packet);
} }
public boolean isUndoActive(Player player) { public boolean isUndoActive(PlayerEntity player) {
return getEntryFromPlayer(player).undoActive; return getEntryFromPlayer(player).undoActive;
} }
public boolean undo(Player player, Level world, BlockPos pos) { public boolean undo(PlayerEntity player, World world, BlockPos pos) {
// If CTRL key is not pressed, return // If CTRL key is not pressed, return
PlayerEntry playerEntry = getEntryFromPlayer(player); PlayerEntry playerEntry = getEntryFromPlayer(player);
if(!playerEntry.undoActive) return false; if(!playerEntry.undoActive) return false;
@ -102,9 +102,9 @@ public class UndoHistory
private static class HistoryEntry private static class HistoryEntry
{ {
public final List<ISnapshot> placeSnapshots; public final List<ISnapshot> placeSnapshots;
public final Level world; public final World world;
public HistoryEntry(List<ISnapshot> placeSnapshots, Level world) { public HistoryEntry(List<ISnapshot> placeSnapshots, World world) {
this.placeSnapshots = placeSnapshots; this.placeSnapshots = placeSnapshots;
this.world = world; this.world = world;
} }
@ -119,12 +119,12 @@ public class UndoHistory
if(positions.contains(pos)) return true; if(positions.contains(pos)) return true;
for(BlockPos p : positions) { for(BlockPos p : positions) {
if(pos.closerThan(p, 3)) return true; if(pos.withinDistance(p, 3)) return true;
} }
return false; return false;
} }
public boolean undo(Player player) { public boolean undo(PlayerEntity player) {
// Check first if all snapshots can be restored // Check first if all snapshots can be restored
for(ISnapshot snapshot : placeSnapshots) { for(ISnapshot snapshot : placeSnapshots) {
if(!snapshot.canRestore(world, player)) return false; if(!snapshot.canRestore(world, player)) return false;
@ -133,16 +133,16 @@ public class UndoHistory
if(snapshot.restore(world, player) && !player.isCreative()) { if(snapshot.restore(world, player) && !player.isCreative()) {
ItemStack stack = snapshot.getRequiredItems(); ItemStack stack = snapshot.getRequiredItems();
if(!player.getInventory().add(stack)) { if(!player.inventory.addItemStackToInventory(stack)) {
player.drop(stack, false); player.dropItem(stack, false);
} }
} }
} }
player.getInventory().setChanged(); player.inventory.markDirty();
// Play teleport sound // Play teleport sound
SoundEvent sound = SoundEvents.CHORUS_FRUIT_TELEPORT; SoundEvent sound = SoundEvents.ITEM_CHORUS_FRUIT_TELEPORT;
world.playSound(null, WandUtil.playerPos(player), sound, SoundSource.PLAYERS, 1.0F, 1.0F); world.playSound(null, WandUtil.playerPos(player), sound, SoundCategory.PLAYERS, 1.0F, 1.0F);
return true; return true;
} }

View file

@ -1,6 +1,6 @@
modLoader = "javafml" modLoader="javafml"
loaderVersion = "[38,)" loaderVersion="[33,)"
license = "MIT License" license="MIT License"
[[mods]] [[mods]]
modId="constructionwand" modId="constructionwand"
version="${file.jarVersion}" version="${file.jarVersion}"
@ -19,13 +19,13 @@ This is my first minecraft mod. May the odds be ever in your favor.
''' '''
[[dependencies.constructionwand]] [[dependencies.constructionwand]]
modId="forge" modId="forge"
mandatory = true mandatory=true
versionRange = "[38,)" versionRange="[33,)"
ordering = "NONE" ordering="NONE"
side="BOTH" side="BOTH"
[[dependencies.constructionwand]] [[dependencies.constructionwand]]
modId="minecraft" modId="minecraft"
mandatory = true mandatory = true
versionRange = "[1.18, 1.19)" versionRange = "[1.16.2, 1.17)"
ordering = "NONE" ordering = "NONE"
side="BOTH" side="BOTH"

View file

@ -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": "완드로 배치한 블록 수"
}

View file

@ -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"
}

View file

@ -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": "Блоки, размещённые при помощи Жезла"
}

View file

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

View file

@ -1,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": "使用建筑手杖所放置的方块"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

View file

@ -1,6 +1,6 @@
{ {
"pack": { "pack": {
"description": "ConstructionWand resources", "description": "ConstructionWand resources",
"pack_format": 8 "pack_format": 6
} }
} }