Compare commits

...

16 commits

Author SHA1 Message Date
61a95fcd1e add explaination to notes 2022-08-09 20:46:11 +02:00
44f1b531ec add notes 2022-08-09 20:39:54 +02:00
312d7597f9 Revert "update minecraft to 1.19.2"
This reverts commit 373be90a2e.
2022-08-09 20:28:52 +02:00
de61ff8fd6 fix dedicated server crash 2022-08-09 20:22:47 +02:00
373be90a2e update minecraft to 1.19.2 2022-08-09 20:21:07 +02:00
24eca43bb3 update minecraft to 1.19.1 2022-08-09 20:15:07 +02:00
4b04a9300e bump version to 2.8 2022-08-09 19:38:07 +02:00
f70347159e Merge branch '1.18.2' of github.com:Theta-Dev/ConstructionWand into 1.19 2022-08-09 19:37:29 +02:00
06d2488c6c fix config access before server start 2022-08-09 19:36:51 +02:00
f400310b59 fix text components 2022-08-09 18:40:44 +02:00
3a1316ce0f ported to Minecraft 1.19 2022-08-09 13:43:38 +02:00
28e97eca26
Merge pull request #50 from gjeodnd12165/patch-1
Korean Localization
2022-04-22 16:25:08 +02:00
gjeodnd12165
058cabe327
Create ko_kr.json 2022-04-18 17:17:01 +09:00
83d880cb2e update Botania integration for MC1.18.2 2022-03-26 00:28:07 +01:00
5f0cc62dbc remove superfluous inventory checks 2022-03-26 00:24:18 +01:00
Mrbysco
fc20293906 Port to 1.18.2
Convert item registering to DeferredRegister as vanilla freezes the registry which instantiating them outside of the RegistryEvent or DeferredRegister will result in an error.
2022-03-15 03:15:54 +01:00
37 changed files with 511 additions and 328 deletions

2
.gitignore vendored
View file

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

View file

@ -16,8 +16,10 @@ version = "${mcversion}-${version_major}.${version_minor}"
group = "${author}.${modid}"
archivesBaseName = "${modid}"
// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17.
java.toolchain.languageVersion = JavaLanguageVersion.of(17)
println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}"
minecraft {
mappings channel: project.mcp_channel, version: project.mcp_mappings
@ -31,6 +33,9 @@ minecraft {
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
// property 'forge.enabledGameTestNamespaces', modid
mods {
constructionwand {
source sourceSets.main
@ -47,6 +52,8 @@ minecraft {
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
// property 'forge.enabledGameTestNamespaces', modid
mods {
constructionwand {
source sourceSets.main
@ -54,6 +61,25 @@ minecraft {
}
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
workingDirectory project.file('run')
property 'forge.logging.markers', 'REGISTRIES'
property 'forge.logging.console.level', 'debug'
property 'forge.enabledGameTestNamespaces', modid
mods {
examplemod {
source sourceSets.main
}
}
}
data {
workingDirectory project.file("run/client").canonicalPath
@ -101,17 +127,16 @@ dependencies {
version: "${project.mcversion}-${project.forgeversion}"
])
compileOnly fg.deobf("mezz.jei:${jei_version}:api")
runtimeOnly fg.deobf("mezz.jei:${jei_version}")
compileOnly "mezz.jei:jei-${mcversion}-common-api:${jei_version}"
compileOnly "mezz.jei:jei-${mcversion}-forge-api:${jei_version}"
// runtimeOnly "mezz.jei:jei-${mcversion}-forge:${jei_version}"
/*
compileOnly fg.deobf([
group: "vazkii.botania",
name: "Botania",
version: "${project.botania}",
classifier: "api"
])
*/
}
jar {
@ -145,4 +170,8 @@ publishing {
url "file:///${project.projectDir}/mcmodsrepo"
}
}
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}

View file

@ -4,15 +4,15 @@ org.gradle.daemon=false
author=thetadev
modid=constructionwand
mcversion=1.18.1
forgeversion=39.0.0
mcversion=1.19.1
forgeversion=42.0.9
mcp_channel=official
mcp_mappings=1.18.1
mcp_mappings=1.19.1
# Source: https://maven.blamejared.com/vazkii/botania/Botania/
# botania=1.16.2-405
botania=1.18.2-430-SNAPSHOT
# Source: https://dvs1.progwml6.com/files/maven/mezz/jei/
jei_version=jei-1.18.1:9.1.0.41
jei_version=11.2.0.244
version_major=2
version_minor=6
version_minor=8

Binary file not shown.

View file

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

269
gradlew vendored
View file

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

13
notes/Builds.md Normal file
View file

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

11
notes/test_command.md Normal file
View file

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

6
settings.gradle Normal file
View file

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

View file

@ -15,7 +15,6 @@ import org.apache.logging.log4j.Logger;
import thetadev.constructionwand.basics.ConfigClient;
import thetadev.constructionwand.basics.ConfigServer;
import thetadev.constructionwand.basics.ModStats;
import thetadev.constructionwand.basics.ReplacementRegistry;
import thetadev.constructionwand.client.ClientEvents;
import thetadev.constructionwand.client.RenderBlockPreview;
import thetadev.constructionwand.containers.ContainerManager;
@ -53,6 +52,9 @@ public class ConstructionWand
FMLJavaModLoadingContext.get().getModEventBus().addListener(this::clientSetup);
MinecraftForge.EVENT_BUS.register(this);
// Register Item DeferredRegister
ModItems.ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
// Config setup
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, ConfigServer.SPEC);
ModLoadingContext.get().registerConfig(ModConfig.Type.CLIENT, ConfigClient.SPEC);
@ -71,9 +73,6 @@ public class ConstructionWand
// Container registry
ContainerRegistrar.register();
//Replacement registry
ReplacementRegistry.init();
// Stats
ModStats.register();
}
@ -84,7 +83,6 @@ public class ConstructionWand
MinecraftForge.EVENT_BUS.register(new ClientEvents());
event.enqueueWork(ModItems::registerModelProperties);
event.enqueueWork(ModItems::registerItemColors);
}
public static ResourceLocation loc(String name) {

View file

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

View file

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

View file

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

View file

@ -20,7 +20,8 @@ import net.minecraft.world.phys.Vec3;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.level.BlockEvent;
import net.minecraftforge.registries.ForgeRegistries;
import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.containers.ContainerManager;
import thetadev.constructionwand.items.wand.ItemWand;
@ -91,7 +92,7 @@ public class WandUtil
public static boolean isTEAllowed(BlockState state) {
if(!state.hasBlockEntity()) return true;
ResourceLocation name = state.getBlock().getRegistryName();
ResourceLocation name = ForgeRegistries.BLOCKS.getKey(state.getBlock());
if(name == null) return false;
String fullId = name.toString();
@ -160,7 +161,7 @@ public class WandUtil
List<ItemStack> inventory = WandUtil.getFullInv(player);
for(ItemStack stack : inventory) {
if(stack == null) continue;
if(stack == null || stack.isEmpty()) continue;
if(WandUtil.stackEquals(stack, item)) {
total += stack.getCount();

View file

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

View file

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

View file

@ -12,7 +12,7 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import net.minecraftforge.client.event.DrawSelectionEvent;
import net.minecraftforge.client.event.RenderHighlightEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import thetadev.constructionwand.basics.WandUtil;
import thetadev.constructionwand.items.wand.ItemWand;
@ -26,7 +26,7 @@ public class RenderBlockPreview
public Set<BlockPos> undoBlocks;
@SubscribeEvent
public void renderBlockHighlight(DrawSelectionEvent.HighlightBlock event) {
public void renderBlockHighlight(RenderHighlightEvent.Block event) {
if(event.getTarget().getType() != HitResult.Type.BLOCK) return;
BlockHitResult rtr = event.getTarget();
@ -55,7 +55,7 @@ public class RenderBlockPreview
MultiBufferSource buffer = event.getMultiBufferSource();
VertexConsumer lineBuilder = buffer.getBuffer(RenderType.LINES);
double partialTicks = event.getPartialTicks();
double partialTicks = event.getPartialTick();
double d0 = player.xOld + (player.getX() - player.xOld) * partialTicks;
double d1 = player.yOld + player.getEyeHeight() + (player.getY() - player.yOld) * partialTicks;
double d2 = player.zOld + (player.getZ() - player.zOld) * partialTicks;

View file

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

View file

@ -1,6 +1,8 @@
package thetadev.constructionwand.containers;
import net.minecraftforge.fml.ModList;
import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.containers.handlers.HandlerBotania;
import thetadev.constructionwand.containers.handlers.HandlerBundle;
import thetadev.constructionwand.containers.handlers.HandlerCapability;
import thetadev.constructionwand.containers.handlers.HandlerShulkerbox;
@ -12,13 +14,9 @@ public class ContainerRegistrar
ConstructionWand.instance.containerManager.register(new HandlerShulkerbox());
ConstructionWand.instance.containerManager.register(new HandlerBundle());
/*
TODO: Reenable this when Botania gets ported to 1.17
if(ModList.get().isLoaded("botania")) {
ConstructionWand.instance.containerManager.register(new HandlerBotania());
ConstructionWand.LOGGER.info("Botania integration added");
}
*/
}
}

View file

@ -1,25 +1,28 @@
/*
TODO: Reenable this when Botania gets ported to 1.17
package thetadev.constructionwand.containers.handlers;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.Block;
import thetadev.constructionwand.api.IContainerHandler;
import vazkii.botania.api.BotaniaForgeCapabilities;
import vazkii.botania.api.item.IBlockProvider;
import java.util.Optional;
public class HandlerBotania implements IContainerHandler
{
@Override
public boolean matches(Player player, ItemStack itemStack, ItemStack inventoryStack) {
return inventoryStack != null && inventoryStack.getCount() == 1 && inventoryStack.getItem() instanceof IBlockProvider;
return inventoryStack != null && inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).isPresent();
}
@Override
public int countItems(Player player, ItemStack itemStack, ItemStack inventoryStack) {
IBlockProvider prov = (IBlockProvider) inventoryStack.getItem();
int provCount = prov.getBlockCount(player, itemStack, inventoryStack, Block.byItem(itemStack.getItem()));
Optional<IBlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve();
if(provOptional.isEmpty()) return 0;
IBlockProvider prov = provOptional.get();
int provCount = prov.getBlockCount(player, inventoryStack, Block.byItem(itemStack.getItem()));
if(provCount == -1)
return Integer.MAX_VALUE;
return provCount;
@ -27,10 +30,12 @@ public class HandlerBotania implements IContainerHandler
@Override
public int useItems(Player player, ItemStack itemStack, ItemStack inventoryStack, int count) {
IBlockProvider prov = (IBlockProvider) inventoryStack.getItem();
if(prov.provideBlock(player, itemStack, inventoryStack, Block.byItem(itemStack.getItem()), true))
Optional<IBlockProvider> provOptional = inventoryStack.getCapability(BotaniaForgeCapabilities.BLOCK_PROVIDER).resolve();
if(provOptional.isEmpty()) return 0;
IBlockProvider prov = provOptional.get();
if(prov.provideBlock(player, inventoryStack, Block.byItem(itemStack.getItem()), true))
return 0;
return count;
}
}
*/
}

View file

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

View file

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

View file

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

View file

@ -27,13 +27,13 @@ public class RecipeGenerator extends RecipeProvider
@Override
protected void buildCraftingRecipes(@Nonnull Consumer<FinishedRecipe> consumer) {
wandRecipe(consumer, ModItems.WAND_STONE, Inp.fromTag(ItemTags.STONE_TOOL_MATERIALS));
wandRecipe(consumer, ModItems.WAND_IRON, Inp.fromTag(Tags.Items.INGOTS_IRON));
wandRecipe(consumer, ModItems.WAND_DIAMOND, Inp.fromTag(Tags.Items.GEMS_DIAMOND));
wandRecipe(consumer, ModItems.WAND_INFINITY, Inp.fromTag(Tags.Items.NETHER_STARS));
wandRecipe(consumer, ModItems.WAND_STONE.get(), Inp.fromTag(ItemTags.STONE_TOOL_MATERIALS));
wandRecipe(consumer, ModItems.WAND_IRON.get(), Inp.fromTag(Tags.Items.INGOTS_IRON));
wandRecipe(consumer, ModItems.WAND_DIAMOND.get(), Inp.fromTag(Tags.Items.GEMS_DIAMOND));
wandRecipe(consumer, ModItems.WAND_INFINITY.get(), Inp.fromTag(Tags.Items.NETHER_STARS));
coreRecipe(consumer, ModItems.CORE_ANGEL, Inp.fromTag(Tags.Items.FEATHERS), Inp.fromTag(Tags.Items.INGOTS_GOLD));
coreRecipe(consumer, ModItems.CORE_DESTRUCTION, Inp.fromTag(Tags.Items.STORAGE_BLOCKS_DIAMOND), Inp.fromItem(Items.DIAMOND_PICKAXE));
coreRecipe(consumer, ModItems.CORE_ANGEL.get(), Inp.fromTag(Tags.Items.FEATHERS), Inp.fromTag(Tags.Items.INGOTS_GOLD));
coreRecipe(consumer, ModItems.CORE_DESTRUCTION.get(), Inp.fromTag(Tags.Items.STORAGE_BLOCKS_DIAMOND), Inp.fromItem(Items.DIAMOND_PICKAXE));
specialRecipe(consumer, RecipeWandUpgrade.SERIALIZER);
}

View file

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

View file

@ -1,12 +0,0 @@
package thetadev.constructionwand.items;
import net.minecraft.world.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,19 +1,18 @@
package thetadev.constructionwand.items;
import net.minecraft.client.Minecraft;
import net.minecraft.client.color.item.ItemColors;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.Tiers;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.client.event.RegisterColorHandlersEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegisterEvent;
import net.minecraftforge.registries.RegistryObject;
import thetadev.constructionwand.ConstructionWand;
import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.crafting.RecipeWandUpgrade;
@ -23,38 +22,24 @@ import thetadev.constructionwand.items.wand.ItemWand;
import thetadev.constructionwand.items.wand.ItemWandBasic;
import thetadev.constructionwand.items.wand.ItemWandInfinity;
import java.util.Arrays;
import java.util.HashSet;
@Mod.EventBusSubscriber(modid = ConstructionWand.MODID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ModItems
{
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, ConstructionWand.MODID);
// Wands
public static final Item WAND_STONE = new ItemWandBasic("stone_wand", propWand(), Tiers.STONE);
public static final Item WAND_IRON = new ItemWandBasic("iron_wand", propWand(), Tiers.IRON);
public static final Item WAND_DIAMOND = new ItemWandBasic("diamond_wand", propWand(), Tiers.DIAMOND);
public static final Item WAND_INFINITY = new ItemWandInfinity("infinity_wand", propWand());
public static final RegistryObject<Item> WAND_STONE = ITEMS.register("stone_wand", () -> new ItemWandBasic(propWand(), Tiers.STONE));
public static final RegistryObject<Item> WAND_IRON = ITEMS.register("iron_wand", () -> new ItemWandBasic(propWand(), Tiers.IRON));
public static final RegistryObject<Item> WAND_DIAMOND = ITEMS.register("diamond_wand", () -> new ItemWandBasic(propWand(), Tiers.DIAMOND));
public static final RegistryObject<Item> WAND_INFINITY = ITEMS.register("infinity_wand", () -> new ItemWandInfinity(propWand()));
// Cores
public static final Item CORE_ANGEL = new ItemCoreAngel("core_angel", propUpgrade());
public static final Item CORE_DESTRUCTION = new ItemCoreDestruction("core_destruction", propUpgrade());
public static final RegistryObject<Item> CORE_ANGEL = ITEMS.register("core_angel", () -> new ItemCoreAngel(propUpgrade()));
public static final RegistryObject<Item> CORE_DESTRUCTION = ITEMS.register("core_destruction", () -> new ItemCoreDestruction(propUpgrade()));
// Collections
public static final Item[] WANDS = {WAND_STONE, WAND_IRON, WAND_DIAMOND, WAND_INFINITY};
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 final RegistryObject<Item>[] WANDS = new RegistryObject[] {WAND_STONE, WAND_IRON, WAND_DIAMOND, WAND_INFINITY};
public static final RegistryObject<Item>[] CORES = new RegistryObject[] {CORE_ANGEL, CORE_DESTRUCTION};
public static Item.Properties propWand() {
return new Item.Properties().tab(CreativeModeTab.TAB_TOOLS);
@ -64,20 +49,17 @@ public class ModItems
return new Item.Properties().tab(CreativeModeTab.TAB_MISC).stacksTo(1);
}
private static void registerItem(IForgeRegistry<Item> reg, Item item) {
reg.register(item);
ALL_ITEMS.add(item);
}
@SubscribeEvent
public static void registerRecipeSerializers(RegistryEvent.Register<RecipeSerializer<?>> event) {
IForgeRegistry<RecipeSerializer<?>> r = event.getRegistry();
register(r, "wand_upgrade", RecipeWandUpgrade.SERIALIZER);
public static void registerRecipeSerializers(RegisterEvent event) {
event.register(ForgeRegistries.Keys.RECIPE_SERIALIZERS, registry -> {
registry.register("wand_upgrade", RecipeWandUpgrade.SERIALIZER);
});
}
@OnlyIn(Dist.CLIENT)
public static void registerModelProperties() {
for(Item item : WANDS) {
for(RegistryObject<Item> itemSupplier : WANDS) {
Item item = itemSupplier.get();
ItemProperties.register(
item, ConstructionWand.loc("using_core"),
(stack, world, entity, n) -> entity == null || !(stack.getItem() instanceof ItemWand) ? 0 :
@ -87,16 +69,12 @@ public class ModItems
}
@OnlyIn(Dist.CLIENT)
public static void registerItemColors() {
ItemColors colors = Minecraft.getInstance().getItemColors();
for(Item item : WANDS) {
colors.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ?
@SubscribeEvent
public static void registerItemColors(RegisterColorHandlersEvent.Item event) {
for(RegistryObject<Item> itemSupplier : WANDS) {
Item item = itemSupplier.get();
event.register((stack, layer) -> (layer == 1 && stack.getItem() instanceof ItemWand) ?
new WandOptions(stack).cores.get().getColor() : -1, item);
}
}
private static <V extends IForgeRegistryEntry<V>> void register(IForgeRegistry<V> reg, String name, IForgeRegistryEntry<V> thing) {
reg.register(thing.setRegistryName(ConstructionWand.loc(name)));
}
}

View file

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

View file

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

View file

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

View file

@ -3,12 +3,11 @@ package thetadev.constructionwand.items.wand;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.context.UseOnContext;
@ -25,17 +24,16 @@ import thetadev.constructionwand.basics.option.IOption;
import thetadev.constructionwand.basics.option.WandOptions;
import thetadev.constructionwand.data.ICustomItemModel;
import thetadev.constructionwand.data.ItemModelGenerator;
import thetadev.constructionwand.items.ItemBase;
import thetadev.constructionwand.wand.WandJob;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
public abstract class ItemWand extends ItemBase implements ICustomItemModel
public abstract class ItemWand extends Item implements ICustomItemModel
{
public ItemWand(String name, Properties properties) {
super(name, properties);
public ItemWand(Properties properties) {
super(properties);
}
@Nonnull
@ -107,35 +105,35 @@ public abstract class ItemWand extends ItemBase implements ICustomItemModel
if(Screen.hasShiftDown()) {
for(int i = 1; i < options.allOptions.length; i++) {
IOption<?> opt = options.allOptions[i];
lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.GRAY))
lines.add(Component.translatable(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(Component.translatable(opt.getValueTranslation()).withStyle(ChatFormatting.GRAY))
);
}
if(!options.cores.getUpgrades().isEmpty()) {
lines.add(new TextComponent(""));
lines.add(new TranslatableComponent(langTooltip + "cores").withStyle(ChatFormatting.GRAY));
lines.add(Component.literal(""));
lines.add(Component.translatable(langTooltip + "cores").withStyle(ChatFormatting.GRAY));
for(IWandCore core : options.cores.getUpgrades()) {
lines.add(new TranslatableComponent(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString()));
lines.add(Component.translatable(options.cores.getKeyTranslation() + "." + core.getRegistryName().toString()));
}
}
}
// Default tooltip: show block limit + active wand core
else {
IOption<?> opt = options.allOptions[0];
lines.add(new TranslatableComponent(langTooltip + "blocks", limit).withStyle(ChatFormatting.GRAY));
lines.add(new TranslatableComponent(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(new TranslatableComponent(opt.getValueTranslation()).withStyle(ChatFormatting.WHITE)));
lines.add(new TranslatableComponent(langTooltip + "shift").withStyle(ChatFormatting.AQUA));
lines.add(Component.translatable(langTooltip + "blocks", limit).withStyle(ChatFormatting.GRAY));
lines.add(Component.translatable(opt.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(Component.translatable(opt.getValueTranslation()).withStyle(ChatFormatting.WHITE)));
lines.add(Component.translatable(langTooltip + "shift").withStyle(ChatFormatting.AQUA));
}
}
public static void optionMessage(Player player, IOption<?> option) {
player.displayClientMessage(
new TranslatableComponent(option.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(new TranslatableComponent(option.getValueTranslation()).withStyle(ChatFormatting.WHITE))
.append(new TextComponent(" - ").withStyle(ChatFormatting.GRAY))
.append(new TranslatableComponent(option.getDescTranslation()).withStyle(ChatFormatting.WHITE))
Component.translatable(option.getKeyTranslation()).withStyle(ChatFormatting.AQUA)
.append(Component.translatable(option.getValueTranslation()).withStyle(ChatFormatting.WHITE))
.append(Component.literal(" - ").withStyle(ChatFormatting.GRAY))
.append(Component.translatable(option.getDescTranslation()).withStyle(ChatFormatting.WHITE))
, true);
}

View file

@ -10,8 +10,8 @@ public class ItemWandBasic extends ItemWand
{
private final Tier tier;
public ItemWandBasic(String name, Properties properties, Tier tier) {
super(name, properties.durability(tier.getUses()));
public ItemWandBasic(Properties properties, Tier tier) {
super(properties.durability(tier.getUses()));
this.tier = tier;
}

View file

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

View file

@ -74,7 +74,7 @@ public class WandJob
public void getSnapshots() {
int limit;
// Infinity wand gets enhanced limit in creative mode
if(player.isCreative() && wandItem == ModItems.WAND_INFINITY) limit = ConfigServer.LIMIT_CREATIVE.get();
if(player.isCreative() && wandItem == ModItems.WAND_INFINITY.get()) limit = ConfigServer.LIMIT_CREATIVE.get();
else limit = Math.min(wandItem.remainingDurability(wand), wandAction.getLimit(wand));
if(rayTraceResult.getType() == HitResult.Type.BLOCK)

View file

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

View file

@ -0,0 +1,70 @@
{
"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,6 +1,8 @@
{
"pack": {
"description": "ConstructionWand resources",
"pack_format": 8
"pack_format": 9,
"forge:resource_pack_format": 9,
"forge:data_pack_format": 10
}
}