Compare commits

...

91 Commits

Author SHA1 Message Date
5896655b45 Stopped throwing exception if mod versions are mismatched. 2022-01-19 02:36:05 +00:00
89c9d06341 Changed build Version to 2.0.1. 2022-01-19 02:35:28 +00:00
9108dea65b Added rarity values to the diamond and netherite totems as well as all the charges. 2022-01-19 02:29:56 +00:00
1dd161a99d Updated generated data. 2022-01-18 23:10:10 +00:00
ef91a20db9 Made netherite totem fire-resistant. 2022-01-18 23:07:52 +00:00
488349714a Cleaned up comments and imports. 2022-01-18 23:01:18 +00:00
fdbd055a70 Fixed canTotemAffordTarget returning true when it shouldn't. Added multiplier in the item tooltip. 2022-01-18 23:00:55 +00:00
bf92ccd455 Changed recipes for diamond totem and charge. 2022-01-18 23:00:05 +00:00
1125a5f411 Added onto messages. 2022-01-18 22:59:40 +00:00
d81f70145e Fixed recipe for netherite charge always being disabled. 2022-01-18 21:59:24 +00:00
66bdaa5a30 Removed ability to set charge cost limit to 0. Changed max value for multiplier to 100 from integer max. 2022-01-18 21:54:38 +00:00
2c8e0595fc Minor exception message changes. 2022-01-18 21:53:49 +00:00
b0a30961b3 Updated packet handle methods for new totem item methods. 2022-01-18 21:53:22 +00:00
e752c75ccd Replaced totem nbt target_cost with target_deaths. Added method for checking if totem is full and if totem can afford a target. Added more text in item tooltip for different config settings. 2022-01-18 21:52:47 +00:00
27a8d35c2d Generated all new data. 2022-01-18 20:02:48 +00:00
471f20da09 Created textures for the iron totem and charge and netherite totem and charge. Renamed files for diamond totem and charge. 2022-01-18 20:02:34 +00:00
10fbf9a994 Updated language file to include all new items. 2022-01-18 20:01:37 +00:00
a778ddf7c6 Created recipes for all items. 2022-01-18 20:01:21 +00:00
34e4438386 Registering all new items. 2022-01-18 20:01:10 +00:00
461cc00515 Added all new items into model gen. 2022-01-18 20:01:00 +00:00
43439972b8 Created config for new totems. 2022-01-18 20:00:29 +00:00
0819bf0262 Fixed imports. 2022-01-18 20:00:05 +00:00
643f0c48ea Created new totem items. 2022-01-18 19:59:28 +00:00
ce1a247ee4 Created new recipe serializer for charge items. 2022-01-18 19:58:32 +00:00
ea87552981 Implemented template class for charge items. Created new charge items for more totems. 2022-01-18 19:57:57 +00:00
0fceaf6f1d Implemented charge cost multiplier into getTargetCost method. Added new getRawTargetCost method and a validateTargetCost method. 2022-01-18 18:28:56 +00:00
e83ec0e5ce Replaced target cost validation with method call. Added check if totem can revive more expensive targets. 2022-01-18 18:27:55 +00:00
3f8ac8ddde Rewrote handle method to use new totem item class. Improved target checking. Method now checks if the target cost has been updated since. Changed method for teleporting target to hopefully fix an issue where target got stuck in 'limbo'. Added a success message. 2022-01-18 18:00:06 +00:00
c30803112a Rewrote handle method to use new totem item class. 2022-01-18 17:57:51 +00:00
ebbbff68c9 Rewrote handle method to use new totem item class. Fixed issue where it only got the dynamic target cost regardless of totem using dynamic or static cost types. 2022-01-18 17:57:20 +00:00
82a9399146 Implemented the StrawTotemItem and StrawChargeItem. 2022-01-18 17:55:22 +00:00
b78433acfb Now using the template TotemItem class. 2022-01-18 17:54:34 +00:00
6b4c1d2c6b Created a template class for totem items. 2022-01-18 17:53:37 +00:00
c53236d0e6 Fixed the mod version pattern and allowing dev builds to work with non dev builds. 2022-01-18 17:51:30 +00:00
de2b214bc7 Packet version info now sends a senderIsServer boolean to differentiate between client and server when throwing MismatchedVersionException. Hopefully fixed mod version pattern. 2022-01-17 15:41:14 +00:00
e1868ac200 Fixed item being unusable on dedicated servers. 2022-01-16 22:21:09 +00:00
2b1cdf98c1 Changed buildVersion to 2.0.0. 2022-01-16 22:20:49 +00:00
c9fcce403d Implemented reviving. 2022-01-16 20:49:39 +00:00
6e9e46e516 Added new config option for being able to revive targets across dimensions. 2022-01-16 20:49:20 +00:00
aeef78f910 Added missing model for the straw charge item. 2022-01-16 20:48:52 +00:00
efa7c16be4 Added totem charging functionality to StrawTotemItem. Changed getMaxCharge() method to be global. 2022-01-16 19:47:41 +00:00
151828e474 Optimized imports. 2022-01-16 19:46:01 +00:00
3395810362 Implemented totem charging. 2022-01-16 19:45:46 +00:00
1067cb3a9a Implemented target changing on totems. 2022-01-16 17:51:21 +00:00
861998df1b Added straw charge item. 2022-01-16 17:50:55 +00:00
811b993409 Removed old unused recipe field. 2022-01-16 16:51:52 +00:00
e0b25a31b2 Updated generated data. 2022-01-16 16:50:16 +00:00
d3613c5eda Changed SIDE_PROXY to PROXY and type ISideProxy. 2022-01-16 16:48:53 +00:00
b1975e912e Made Straw totem use new Extended Recipe builder. Created ModRecipes and registering new TOTEM_RECIPE serializer. Removed old events from Registration and added RECIPE_SERIALIZERS. Created new TotemRecipe for totem items. 2022-01-16 16:48:07 +00:00
350176d6f9 Created an ExtendedShapedRecipe and Builder. 2022-01-16 16:46:37 +00:00
b06b88780f Removed old packet class. 2022-01-16 16:46:02 +00:00
6ecf7c414d Removed old way of updating recipes based on config reload. Reason: doesn't work on server. 2022-01-16 16:45:27 +00:00
288a034d63 Fixed low limit for network versions. Fixed exception when mod version is NONE. 2022-01-16 13:58:00 +00:00
62abe17ad4 Fixed getVersion not returning the version. 2022-01-16 13:56:47 +00:00
73ed4ff729 Updated forge 36.2.16 -> 26.2.20. 2022-01-16 13:41:22 +00:00
e6dcde1caa Registered new packet in channel. 2022-01-16 13:34:37 +00:00
b7d29ecf27 Renamed RecipeUpdateEventHandler to UpdateRecipesEventHandler. Added method for mod config reload event on server-side to send packet to client. 2022-01-16 13:34:18 +00:00
438d543283 Created packet for updating recipes. 2022-01-16 13:33:17 +00:00
2667cdd658 Initializing Network class. 2022-01-16 13:08:52 +00:00
bb455e3d44 Created initial Network class with version checking. 2022-01-16 13:08:24 +00:00
78636c242d Created MismatchedVersionException. 2022-01-16 13:08:17 +00:00
1ca4de1f4a Added method for getting the mod version. 2022-01-16 13:07:29 +00:00
9470faafac Updated .gitignore 2022-01-12 17:25:17 +00:00
85cb9c653d Added new RecipeUpdateEventHandler for refreshing recipe list when config file changes. 2022-01-12 17:20:33 +00:00
caf5d4037f Removed unused Client and Common configs. Removed future totems for now. Updated TotemConfig class. 2022-01-12 17:20:06 +00:00
3097334020 Removed unused items for now. 2022-01-12 17:19:12 +00:00
db255f99a6 Removed config options. 2022-01-12 17:18:54 +00:00
69a84bb8fe Disabled not used recipes temporarily. 2022-01-12 17:18:06 +00:00
9cb6ccf8cd Created new StrawTotemItem. 2022-01-12 17:17:18 +00:00
517162fa4b Optimized imports. 2022-01-12 17:16:23 +00:00
ff79d89481 Changed capitalization of item names and added entry for item group. 2022-01-12 17:15:23 +00:00
a0d160a056 Generated resources changed. 2022-01-12 17:14:46 +00:00
6f0f287dd5 Added back register method. 2022-01-09 19:28:34 +00:00
c91add1e80 Started rewrite. 2022-01-09 19:27:13 +00:00
06f28a4c94 Created default item group. 2022-01-09 19:26:38 +00:00
635d69a7ca Moved config initialization before registration. 2022-01-09 19:26:07 +00:00
50474bf894 Started implementing config files for totems. 2022-01-09 19:25:43 +00:00
eb9e7d5e5c Deleted old code. 2022-01-09 19:25:14 +00:00
582c8d4bd4 Created helper method for creating deferred registers. Changed variables to use camelCase. 2021-11-21 14:17:52 +00:00
d4cb7d7499 Changed variables to use camelCase. 2021-11-21 14:17:07 +00:00
4df5c42ff0 Removed constructor, changed variable names to use camelCase. 2021-11-21 14:16:14 +00:00
de7e1b2427 Moved networking into its own class. 2021-11-21 09:52:59 +00:00
749f6d2e30 Created template for Config. 2021-11-21 09:52:14 +00:00
7bf2815657 Cleaned up TotemOfReviving by moving most setup code to the new SideProxy. 2021-11-21 09:51:33 +00:00
3708d49755 Updated mappings (back) to official. 2021-11-21 07:48:12 +00:00
d61eabd754 Cleanup build.gradle. Added JEI as dependency. Changed mappings channel to official. 2021-11-21 07:46:55 +00:00
396db31fef Included version in gradle project name. 2021-11-20 22:14:34 +00:00
08c0e8809a Changed groupId to dev.micle from com.micle. Updated code to match new MCP mappings. 2021-11-20 22:13:55 +00:00
73e7c56f19 Restructured project and repo. 2021-11-20 21:52:06 +00:00
4332e9eaac Fixed amplifier and duration of poison afflicted from straw totem to balance it better. 2021-06-01 23:58:16 +01:00
34557c3e83 Straw totem fail chance decreases upon successful revival.
Failed attempts with the straw totem now apply poison instead of damaging the player.
2021-06-01 23:45:30 +01:00
85 changed files with 2301 additions and 881 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
/.gradle/
/.idea/
/build/
/run/
/src/test/
/src/generated/resources/.cache/

2
LICENSE Normal file
View File

@ -0,0 +1,2 @@
Copyright (c) 2021
All rights reserved.

View File

@ -1,57 +1,30 @@
buildscript {
repositories {
maven { url = 'https://files.minecraftforge.net/maven' }
// These repositories are only for Gradle plugins, put any other repositories in the repository block further below
maven { url = 'https://maven.minecraftforge.net' }
mavenCentral()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '4.1.+', changing: true
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
}
}
apply plugin: 'net.minecraftforge.gradle'
// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.
apply plugin: 'eclipse'
apply plugin: 'maven-publish'
version = '1.0'
group = 'com.micle.totemofreviving' // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = 'totemofreviving'
def archiveVersion = "Forge-${project.mcVersion}-${project.buildVersion}" as Object
java.toolchain.languageVersion = JavaLanguageVersion.of(8) // Mojang ships Java 8 to end users, so your mod should target Java 8.
java.toolchain.languageVersion = JavaLanguageVersion.of(8)
println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
minecraft {
// The mappings can be changed at any time, and must be in the following format.
// Channel: Version:
// snapshot YYYYMMDD Snapshot are built nightly.
// stable # Stables are built at the discretion of the MCP team.
// official MCVersion Official field/method names from Mojang mapping files
//
// You must be aware of the Mojang license when using the 'official' mappings.
// See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md
//
// Use non-default mappings at your own risk. they may not always work.
// Simply re-run your setup task after changing the mappings to update your workspace.
mappings channel: 'official', version: '1.16.5'
// makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
mappings channel: 'official', version: mcVersion
// accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs {
client {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
// The markers can be changed as needed.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
mods {
@ -64,16 +37,7 @@ minecraft {
server {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
// The markers can be changed as needed.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
mods {
@ -86,19 +50,9 @@ minecraft {
data {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
// The markers can be changed as needed.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
// You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug'
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
args '--mod', 'totemofreviving', '--all',
'--existing', file('src/main/resources').toString(),
'--existing', file('src/generated/resources').toString(),
@ -113,65 +67,46 @@ minecraft {
}
}
// Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' }
dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied.
// The userdev artifact is a special name and will get all sorts of transformations applied to it.
minecraft 'net.minecraftforge:forge:1.16.5-36.1.4'
// You may put jars on which you depend on in ./libs or you may define them like so..
// compile "some.group:artifact:version:classifier"
// compile "some.group:artifact:version"
// Real examples
// compile 'com.mod-buildcraft:buildcraft:6.0.8:dev' // adds buildcraft to the dev env
// compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env
// The 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
// provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// These dependencies get remapped to your current MCP mappings
// deobf 'com.mod-buildcraft:buildcraft:6.0.8:dev'
// For more info...
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
sourceSets.main.resources {
srcDir 'src/generated/resources'
}
repositories {
maven {
name = "Progwml6 maven"
url = "https://dvs1.progwml6.com/files/maven/"
}
maven {
name = "ModMaven"
url = "https://modmaven.k-4u.nl"
}
}
dependencies {
minecraft "net.minecraftforge:forge:${project.mcVersion}-${project.forgeVersion}"
// JEI
if (project.hasProperty('jeiVersion')) {
// compile against JEI API but do not include it at runtime
compileOnly fg.deobf("mezz.jei:jei-${project.mcVersion}:${project.jeiVersion}:api")
// at runtime, use full JEI jar
runtimeOnly fg.deobf("mezz.jei:jei-${project.mcVersion}:${project.jeiVersion}")
}
}
// Example for how to get properties into the manifest for reading by the runtime..
jar {
archiveFileName = "${project.archivesBaseName}-${archiveVersion}.jar"
manifest {
attributes([
"Specification-Title": "totemofreviving",
"Specification-Vendor": "totemofrevivingsareus",
"Specification-Version": "1", // We are version 1 of ourselves
"Implementation-Title": project.name,
"Implementation-Version": "${version}",
"Implementation-Vendor" :"totemofrevivingsareus",
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
"Specification-Title" : project.name,
"Specification-Vendor" : project.author,
"Specification-Version" : "1",
"Implementation-Title" : project.name,
"Implementation-Vendor" : project.author,
"Implementation-Version" : archiveVersion,
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ")
])
}
}
// Example configuration to allow publishing using the maven-publish task
// This is the preferred method to reobfuscate your jar file
jar.finalizedBy('reobfJar')
// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing
//publish.dependsOn('reobfJar')
publishing {
publications {
mavenJava(MavenPublication) {
artifact jar
}
}
repositories {
maven {
url "file:///${project.projectDir}/mcmodsrepo"
}
}
}

14
gradle.properties Normal file
View File

@ -0,0 +1,14 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
group = dev.micle
archivesBaseName = TotemOfReviving
modID = totemofreviving
name = Micle's Totem of Reviving
author = Micle
buildVersion = 2.0.1
mcVersion = 1.16.5
forgeVersion = 36.2.20
jeiVersion = 7.+

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

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

185
gradlew vendored Executable file
View File

@ -0,0 +1,185 @@
#!/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
##
##############################################################################
# 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
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# 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
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
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
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" ;;
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, 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"
exec "$JAVACMD" "$@"

89
gradlew.bat vendored Normal file
View File

@ -0,0 +1,89 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

1
settings.gradle Normal file
View File

@ -0,0 +1 @@
rootProject.name = "${archivesBaseName}-1.16"

View File

@ -1,12 +1,24 @@
8a2b88672a3111967914bf84746ee02770dc8aca assets/totemofreviving/models/item/reviving_charge.json
8cb64e3801a8d717442aa39d4ba230bc762d44d5 assets/totemofreviving/models/item/diamond_charge.json
8369d36bbe5dba40b58258caafdc6e92096709e0 assets/totemofreviving/models/item/diamond_totem.json
d0616a5bf6dd99b6bf56d8af19273dae480b9b3d assets/totemofreviving/models/item/iron_charge.json
096cdf824c293ef8aba92d3133ccc8717ba7220c assets/totemofreviving/models/item/iron_totem.json
ebd87c84c4b34b81bdf803c3c3cbc929e340302e assets/totemofreviving/models/item/netherite_charge.json
b5ebbedcd843aaf7a304ca67e9412e7765c07d59 assets/totemofreviving/models/item/netherite_totem.json
6dfda0ccc2ea9fde90748a9fac81e6e122375b60 assets/totemofreviving/models/item/straw_charge.json
70680f30f3471070d6d4121f0787eb7e2a9d7318 assets/totemofreviving/models/item/straw_totem.json
9802f8a76c014c4e7d5b093643a0f8f2c75474bc assets/totemofreviving/models/item/totem_of_reviving.json
97e29a14be1fa658d16ee23c9791822f6d49dab7 data/totemofreviving/advancements/recipes/misc/reviving_charge.json
4a76d05fbd6fe375b097c1207f2967fd5fbfef5b data/totemofreviving/advancements/recipes/misc/straw_charge.json
8608de575125d59605ad619c16b826cee70c478e data/totemofreviving/advancements/recipes/misc/straw_totem.json
9be362836ef513789b2c8e3d88d35a6b802b5d27 data/totemofreviving/advancements/recipes/misc/totem_of_reviving.json
0a4143689809621511c8e586e6f030e2dd7a5927 data/totemofreviving/recipes/reviving_charge.json
72f1af6072cd28ad40e07d67256f2611bcb2d924 data/totemofreviving/recipes/straw_charge.json
ffba47b4fb65503d8143a387b05e191301b2b895 data/totemofreviving/recipes/straw_totem.json
8d9f9d28b0748d5dacbf0824b8f6531a6a00bbfa data/totemofreviving/recipes/totem_of_reviving.json
0967ae8d8b0dd9161eb1a9afe0fbc73a37e6ca84 data/totemofreviving/advancements/recipes/totemofreviving/diamond_charge.json
21dbe32fdcd5b1a827b6d647ca94cf792146a265 data/totemofreviving/advancements/recipes/totemofreviving/diamond_totem.json
f13e9966059fd682c695611fd565a9796f4360e1 data/totemofreviving/advancements/recipes/totemofreviving/iron_charge.json
d03047c25717cba5efd2ab89859f5ce183316498 data/totemofreviving/advancements/recipes/totemofreviving/iron_totem.json
5e9153e9c3e8b2aeb3f8504d3425c1dcd65dfa45 data/totemofreviving/advancements/recipes/totemofreviving/netherite_charge.json
2cc781919ec504a96437b68bdc30c8e6b9c94c4b data/totemofreviving/advancements/recipes/totemofreviving/netherite_totem.json
24d28e7046e24e660784d535ae127004c55bbdcb data/totemofreviving/advancements/recipes/totemofreviving/straw_charge.json
8608de575125d59605ad619c16b826cee70c478e data/totemofreviving/advancements/recipes/totemofreviving/straw_totem.json
55ee18c38e521feb4b8271e39a021c1215616e6d data/totemofreviving/recipes/diamond_charge.json
3383e970befe8cdc2344ee3a75b7601012a9490f data/totemofreviving/recipes/diamond_totem.json
cfce0a5c8a8598a994e6ba4290a8682782c095db data/totemofreviving/recipes/iron_charge.json
042713134f03852fbcc84f50523441801591245d data/totemofreviving/recipes/iron_totem.json
fd5884ac05c111741230992cf8491cd745b61706 data/totemofreviving/recipes/netherite_charge.json
fd0ce554aa6b14ebe0a0c77504fe7fd966147bf7 data/totemofreviving/recipes/netherite_totem.json
34210409c71afd345b237efd6928b387654c76f8 data/totemofreviving/recipes/straw_charge.json
b78c2abd8ad4889226f0a534c3982ff9a9fe1880 data/totemofreviving/recipes/straw_totem.json

View File

@ -1,6 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "totemofreviving:item/reviving_charge"
"layer0": "totemofreviving:item/diamond_charge"
}
}

View File

@ -1,6 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "totemofreviving:item/totem_of_reviving"
"layer0": "totemofreviving:item/diamond_totem"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "totemofreviving:item/iron_charge"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "totemofreviving:item/iron_totem"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "totemofreviving:item/netherite_charge"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "totemofreviving:item/netherite_totem"
}
}

View File

@ -2,7 +2,7 @@
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"totemofreviving:reviving_charge"
"totemofreviving:diamond_charge"
]
},
"criteria": {
@ -11,7 +11,7 @@
"conditions": {
"items": [
{
"item": "totemofreviving:totem_of_reviving"
"item": "totemofreviving:diamond_totem"
}
]
}
@ -19,7 +19,7 @@
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "totemofreviving:reviving_charge"
"recipe": "totemofreviving:diamond_charge"
}
}
},

View File

@ -2,7 +2,7 @@
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"totemofreviving:totem_of_reviving"
"totemofreviving:diamond_totem"
]
},
"criteria": {
@ -19,7 +19,7 @@
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "totemofreviving:totem_of_reviving"
"recipe": "totemofreviving:diamond_totem"
}
}
},

View File

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"totemofreviving:iron_charge"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "totemofreviving:iron_totem"
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "totemofreviving:iron_charge"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View File

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"totemofreviving:iron_totem"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "minecraft:emerald"
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "totemofreviving:iron_totem"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View File

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"totemofreviving:netherite_charge"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "totemofreviving:netherite_totem"
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "totemofreviving:netherite_charge"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View File

@ -0,0 +1,32 @@
{
"parent": "minecraft:recipes/root",
"rewards": {
"recipes": [
"totemofreviving:netherite_totem"
]
},
"criteria": {
"has_item": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"item": "minecraft:netherite_scrap"
}
]
}
},
"has_the_recipe": {
"trigger": "minecraft:recipe_unlocked",
"conditions": {
"recipe": "totemofreviving:netherite_totem"
}
}
},
"requirements": [
[
"has_item",
"has_the_recipe"
]
]
}

View File

@ -11,7 +11,7 @@
"conditions": {
"items": [
{
"item": "minecraft:emerald"
"item": "totemofreviving:straw_totem"
}
]
}

View File

@ -0,0 +1,25 @@
{
"type": "totemofreviving:totem_recipe",
"pattern": [
"IDI",
"PEP",
"IDI"
],
"key": {
"E": {
"item": "minecraft:emerald"
},
"D": {
"item": "minecraft:diamond"
},
"I": {
"item": "minecraft:iron_ingot"
},
"P": {
"item": "minecraft:ender_pearl"
}
},
"result": {
"item": "totemofreviving:diamond_charge"
}
}

View File

@ -0,0 +1,22 @@
{
"type": "totemofreviving:totem_recipe",
"pattern": [
"EDE",
"DTD",
"EDE"
],
"key": {
"T": {
"item": "minecraft:totem_of_undying"
},
"D": {
"item": "minecraft:diamond"
},
"E": {
"item": "minecraft:ender_pearl"
}
},
"result": {
"item": "totemofreviving:diamond_totem"
}
}

View File

@ -0,0 +1,22 @@
{
"type": "totemofreviving:charge_recipe",
"pattern": [
"NIN",
"IEI",
"NIN"
],
"key": {
"E": {
"item": "minecraft:emerald"
},
"I": {
"item": "minecraft:iron_ingot"
},
"N": {
"item": "minecraft:iron_nugget"
}
},
"result": {
"item": "totemofreviving:iron_charge"
}
}

View File

@ -0,0 +1,22 @@
{
"type": "totemofreviving:totem_recipe",
"pattern": [
" E ",
"IBI",
" I "
],
"key": {
"B": {
"item": "minecraft:iron_block"
},
"E": {
"item": "minecraft:emerald"
},
"I": {
"item": "minecraft:iron_ingot"
}
},
"result": {
"item": "totemofreviving:iron_totem"
}
}

View File

@ -0,0 +1,22 @@
{
"type": "totemofreviving:charge_recipe",
"pattern": [
"GNG",
"NCN",
"GNG"
],
"key": {
"C": {
"item": "totemofreviving:diamond_charge"
},
"N": {
"item": "minecraft:netherite_scrap"
},
"G": {
"item": "minecraft:gold_ingot"
}
},
"result": {
"item": "totemofreviving:netherite_charge"
}
}

View File

@ -0,0 +1,25 @@
{
"type": "totemofreviving:totem_recipe",
"pattern": [
"BNB",
"NTN",
"BGB"
],
"key": {
"T": {
"item": "totemofreviving:diamond_totem"
},
"N": {
"item": "minecraft:netherite_scrap"
},
"G": {
"item": "minecraft:gold_ingot"
},
"B": {
"item": "minecraft:nether_brick"
}
},
"result": {
"item": "totemofreviving:netherite_totem"
}
}

View File

@ -1,22 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"@E@",
"E#E",
"@E@"
],
"key": {
"#": {
"item": "minecraft:totem_of_undying"
},
"@": {
"item": "minecraft:diamond_block"
},
"E": {
"item": "minecraft:ender_pearl"
}
},
"result": {
"item": "totemofreviving:reviving_charge"
}
}

View File

@ -1,19 +1,19 @@
{
"type": "minecraft:crafting_shaped",
"type": "totemofreviving:charge_recipe",
"pattern": [
"IWI",
"NWN",
"WEW",
"IWI"
"NWN"
],
"key": {
"W": {
"item": "minecraft:wheat"
},
"E": {
"item": "minecraft:emerald"
},
"I": {
"item": "minecraft:iron_ingot"
"W": {
"item": "minecraft:wheat"
},
"N": {
"item": "minecraft:iron_nugget"
}
},
"result": {

View File

@ -1,15 +1,15 @@
{
"type": "minecraft:crafting_shaped",
"type": "totemofreviving:totem_recipe",
"pattern": [
"NSN",
"NWN",
"N/N"
"N|N"
],
"key": {
"W": {
"item": "minecraft:wheat"
},
"/": {
"|": {
"item": "minecraft:stick"
},
"S": {

View File

@ -1,19 +0,0 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"@@@",
"@#@",
"@@@"
],
"key": {
"#": {
"item": "minecraft:totem_of_undying"
},
"@": {
"item": "minecraft:diamond"
}
},
"result": {
"item": "totemofreviving:totem_of_reviving"
}
}

View File

@ -1,53 +0,0 @@
package com.micle.totemofreviving;
import com.micle.totemofreviving.network.C2SRequestPlayerRevive;
import com.micle.totemofreviving.network.C2SRequestTotemCharge;
import com.micle.totemofreviving.network.C2SRequestTotemTarget;
import com.micle.totemofreviving.setup.Registration;
import net.minecraft.server.management.PlayerList;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel;
@Mod(TotemOfReviving.MOD_ID)
public class TotemOfReviving {
public static final String MOD_ID = "totemofreviving";
public static PlayerList players;
private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation(TotemOfReviving.MOD_ID, "main"),
() -> PROTOCOL_VERSION,
PROTOCOL_VERSION::equals,
PROTOCOL_VERSION::equals
);
public TotemOfReviving() {
Registration.register();
int id = 0;
INSTANCE.registerMessage(id++,
C2SRequestPlayerRevive.class,
C2SRequestPlayerRevive::encode,
C2SRequestPlayerRevive::decode,
C2SRequestPlayerRevive::handle
);
INSTANCE.registerMessage(id++,
C2SRequestTotemTarget.class,
C2SRequestTotemTarget::encode,
C2SRequestTotemTarget::decode,
C2SRequestTotemTarget::handle
);
INSTANCE.registerMessage(id++,
C2SRequestTotemCharge.class,
C2SRequestTotemCharge::encode,
C2SRequestTotemCharge::decode,
C2SRequestTotemCharge::handle
);
// Register ourselves for server and other game events we are interested in
MinecraftForge.EVENT_BUS.register(this);
}
}

View File

@ -1,24 +0,0 @@
package com.micle.totemofreviving.data;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.data.client.ModItemModelProvider;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
@Mod.EventBusSubscriber(modid = TotemOfReviving.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class DataGenerators {
private DataGenerators() {}
@SubscribeEvent
public static void gatherData(GatherDataEvent e) {
DataGenerator gen = e.getGenerator();
ExistingFileHelper existing_file_helper = e.getExistingFileHelper();
gen.addProvider(new ModItemModelProvider(gen, existing_file_helper));
gen.addProvider(new ModRecipeProvider(gen));
}
}

View File

@ -1,53 +0,0 @@
package com.micle.totemofreviving.data;
import com.micle.totemofreviving.setup.ModItems;
import net.minecraft.data.*;
import net.minecraft.item.Items;
import java.util.function.Consumer;
public class ModRecipeProvider extends RecipeProvider {
public ModRecipeProvider(DataGenerator generator_in) {
super(generator_in);
}
@Override
protected void buildShapelessRecipes(Consumer<IFinishedRecipe> consumer) {
ShapedRecipeBuilder.shaped(ModItems.TOTEM_OF_REVIVING.get())
.define('#', Items.TOTEM_OF_UNDYING)
.define('@', Items.DIAMOND)
.pattern("@@@")
.pattern("@#@")
.pattern("@@@")
.unlockedBy("has_item", has(Items.TOTEM_OF_UNDYING))
.save(consumer);
ShapedRecipeBuilder.shaped(ModItems.REVIVING_CHARGE.get())
.define('#', Items.TOTEM_OF_UNDYING)
.define('@', Items.DIAMOND_BLOCK)
.define('E', Items.ENDER_PEARL)
.pattern("@E@")
.pattern("E#E")
.pattern("@E@")
.unlockedBy("has_item", has(ModItems.TOTEM_OF_REVIVING.get()))
.save(consumer);
ShapedRecipeBuilder.shaped(ModItems.STRAW_TOTEM.get())
.define('W', Items.WHEAT)
.define('/', Items.STICK)
.define('S', Items.STRING)
.define('N', Items.IRON_NUGGET)
.pattern("NSN")
.pattern("NWN")
.pattern("N/N")
.unlockedBy("has_item", has(Items.WHEAT))
.save(consumer);
ShapedRecipeBuilder.shaped(ModItems.STRAW_CHARGE.get())
.define('W', Items.WHEAT)
.define('E', Items.EMERALD)
.define('I', Items.IRON_INGOT)
.pattern("IWI")
.pattern("WEW")
.pattern("IWI")
.unlockedBy("has_item", has(Items.EMERALD))
.save(consumer);
}
}

View File

@ -1,33 +0,0 @@
package com.micle.totemofreviving.data.client;
import com.google.gson.JsonElement;
import com.micle.totemofreviving.TotemOfReviving;
import net.minecraft.data.DataGenerator;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.model.generators.ItemModelBuilder;
import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper;
import java.util.function.BiConsumer;
import java.util.function.Supplier;
public class ModItemModelProvider extends ItemModelProvider {
public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existing_file_helper) {
super(generator, TotemOfReviving.MOD_ID, existing_file_helper);
}
@Override
protected void registerModels() {
ModelFile item_generated = getExistingFile(mcLoc("item/generated"));
builder(item_generated, "totem_of_reviving");
builder(item_generated, "reviving_charge");
builder(item_generated, "straw_totem");
builder(item_generated, "straw_charge");
}
private ItemModelBuilder builder(ModelFile item_generated, String name) {
return getBuilder(name).parent(item_generated).texture("layer0", "item/" + name);
}
}

View File

@ -1,13 +0,0 @@
package com.micle.totemofreviving.events;
import com.micle.totemofreviving.TotemOfReviving;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.server.ServerLifecycleHooks;
public class ServerTickEventHandler {
@SubscribeEvent
public void onServerTick(TickEvent.ServerTickEvent event) {
TotemOfReviving.players = ServerLifecycleHooks.getCurrentServer().getPlayerList();
}
}

View File

@ -1,11 +0,0 @@
package com.micle.totemofreviving.items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.Rarity;
public class RevivingChargeItem extends Item {
public RevivingChargeItem() {
super(new Item.Properties().tab(ItemGroup.TAB_MISC).rarity(Rarity.RARE));
}
}

View File

@ -1,11 +0,0 @@
package com.micle.totemofreviving.items;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.Rarity;
public class StrawChargeItem extends Item {
public StrawChargeItem() {
super(new Item.Properties().tab(ItemGroup.TAB_MISC).rarity(Rarity.UNCOMMON));
}
}

View File

@ -1,86 +0,0 @@
package com.micle.totemofreviving.items;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.network.C2SRequestPlayerRevive;
import com.micle.totemofreviving.network.C2SRequestTotemCharge;
import com.micle.totemofreviving.network.C2SRequestTotemTarget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFW;
import java.util.List;
public class StrawTotemItem extends Item {
public static final String TAG_CHARGE_AMOUNT = "charge";
public static final String TAG_TARGET_INDEX = "target_index";
public static final String TAG_TARGET_NAME = "target_name";
public static final String TAG_FAIL_CHANCE = "fail_chance";
public static final int STARTING_FAIL_CHANCE = 45;
public StrawTotemItem() {
super(new Item.Properties().tab(ItemGroup.TAB_MISC).stacksTo(1).rarity(Rarity.UNCOMMON));
}
@Override
public void appendHoverText(ItemStack stack, World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
super.appendHoverText(stack, world, tooltip, flag);
tooltip.add(new StringTextComponent(TextFormatting.GOLD + "Charges: " + TextFormatting.GRAY + stack.getOrCreateTag().getInt(TAG_CHARGE_AMOUNT)));
tooltip.add(new StringTextComponent(TextFormatting.GOLD + "Target: " + TextFormatting.GRAY + stack.getOrCreateTag().getString(TAG_TARGET_NAME)));
tooltip.add(new StringTextComponent(TextFormatting.GOLD + "Fail Chance: " + TextFormatting.GRAY + stack.getOrCreateTag().getInt(TAG_FAIL_CHANCE)));
tooltip.add(new StringTextComponent( TextFormatting.DARK_GRAY + "" + TextFormatting.ITALIC + "\"Feels kinda funky.\""));
tooltip.add(new StringTextComponent(""));
if (InputMappings.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_SHIFT)) {
tooltip.add(new StringTextComponent(TextFormatting.YELLOW + "R-CLICK"));
tooltip.add(new StringTextComponent(TextFormatting.GOLD + "When other hand is empty: attempt to revive target."));
tooltip.add(new StringTextComponent(TextFormatting.GOLD + "When other hand has " + TextFormatting.GRAY + "Straw Reviving Charge" + TextFormatting.GOLD + ": charge totem."));
tooltip.add(new StringTextComponent(""));
tooltip.add(new StringTextComponent(TextFormatting.YELLOW + "SHIFT R-CLICK"));
tooltip.add(new StringTextComponent(TextFormatting.GOLD + "Cycle through available targets."));
} else {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "[" + TextFormatting.WHITE + "LSHIFT" + TextFormatting.GRAY + "] for advanced tooltip."));
}
}
@Override
public void onCraftedBy(ItemStack stack, World world, PlayerEntity player) {
super.onCraftedBy(stack, world, player);
stack.getOrCreateTag().putInt(TAG_CHARGE_AMOUNT, 0);
stack.getOrCreateTag().putInt(TAG_FAIL_CHANCE, STARTING_FAIL_CHANCE);
}
@Override
@OnlyIn(Dist.CLIENT)
public ActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
if (!world.isClientSide) { return super.use(world, player, hand); }
if (player.isCrouching()) {
TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemTarget(player.getUUID(), hand));
} else {
Hand item_charge_hand = Hand.MAIN_HAND;
if (hand.equals(Hand.MAIN_HAND)) {
item_charge_hand = Hand.OFF_HAND;
}
Item item_charge = player.getItemInHand(item_charge_hand).getItem();
if (item_charge instanceof StrawChargeItem) {
TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemCharge(player.getUUID(), hand, item_charge_hand));
} else {
TotemOfReviving.INSTANCE.sendToServer(new C2SRequestPlayerRevive(player.getUUID(), hand));
}
}
return super.use(world, player, hand);
}
}

View File

@ -1,82 +0,0 @@
package com.micle.totemofreviving.items;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.network.C2SRequestPlayerRevive;
import com.micle.totemofreviving.network.C2SRequestTotemCharge;
import com.micle.totemofreviving.network.C2SRequestTotemTarget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFW;
import java.util.List;
public class TotemOfRevivingItem extends Item {
public static final String TAG_CHARGE_AMOUNT = "charge";
public static final String TAG_TARGET_INDEX = "target_index";
public static final String TAG_TARGET_NAME = "target_name";
public TotemOfRevivingItem() {
super(new Item.Properties().tab(ItemGroup.TAB_MISC).stacksTo(1).rarity(Rarity.RARE));
}
@Override
public void appendHoverText(ItemStack stack, World world, List<ITextComponent> tooltip, ITooltipFlag flag) {
super.appendHoverText(stack, world, tooltip, flag);
tooltip.add(new StringTextComponent(TextFormatting.DARK_AQUA + "Charges: " + TextFormatting.BLUE + stack.getOrCreateTag().getInt(TAG_CHARGE_AMOUNT)));
tooltip.add(new StringTextComponent(TextFormatting.DARK_AQUA + "Target: " + TextFormatting.BLUE + stack.getOrCreateTag().getString(TAG_TARGET_NAME)));
tooltip.add(new StringTextComponent(""));
if (InputMappings.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_SHIFT)) {
tooltip.add(new StringTextComponent(TextFormatting.AQUA + "R-CLICK"));
tooltip.add(new StringTextComponent(TextFormatting.DARK_AQUA + "When other hand is empty: attempt to revive target."));
tooltip.add(new StringTextComponent(TextFormatting.DARK_AQUA + "When other hand has " + TextFormatting.BLUE + "Reviving Charge" + TextFormatting.DARK_AQUA + ": charge totem."));
tooltip.add(new StringTextComponent(""));
tooltip.add(new StringTextComponent(TextFormatting.AQUA + "SHIFT R-CLICK"));
tooltip.add(new StringTextComponent(TextFormatting.DARK_AQUA + "Cycle through available targets."));
} else {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "[" + TextFormatting.WHITE + "LSHIFT" + TextFormatting.GRAY + "] for advanced tooltip."));
}
}
@Override
public void onCraftedBy(ItemStack stack, World world, PlayerEntity player) {
super.onCraftedBy(stack, world, player);
stack.getOrCreateTag().putInt(TAG_CHARGE_AMOUNT, 0);
}
@Override
@OnlyIn(Dist.CLIENT)
public ActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
if (!world.isClientSide) { return super.use(world, player, hand); }
if (player.isCrouching()) {
TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemTarget(player.getUUID(), hand));
} else {
Hand item_charge_hand = Hand.MAIN_HAND;
if (hand.equals(Hand.MAIN_HAND)) {
item_charge_hand = Hand.OFF_HAND;
}
Item item_charge = player.getItemInHand(item_charge_hand).getItem();
if (item_charge instanceof RevivingChargeItem) {
TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemCharge(player.getUUID(), hand, item_charge_hand));
} else {
TotemOfReviving.INSTANCE.sendToServer(new C2SRequestPlayerRevive(player.getUUID(), hand));
}
}
return super.use(world, player, hand);
}
}

View File

@ -1,86 +0,0 @@
package com.micle.totemofreviving.network;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.items.StrawTotemItem;
import com.micle.totemofreviving.items.TotemOfRevivingItem;
import com.micle.totemofreviving.utils.Utils;
import net.minecraft.client.audio.Sound;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.PacketBuffer;
import net.minecraft.stats.Stats;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Hand;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.GameType;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.UUID;
import java.util.function.Supplier;
public class C2SRequestPlayerRevive {
private final UUID player_uuid;
private final Hand hand;
public C2SRequestPlayerRevive(final UUID player_uuid, final Hand hand) {
this.player_uuid = player_uuid;
this.hand = hand;
}
public static void encode(final C2SRequestPlayerRevive msg, final PacketBuffer packet_buffer) {
packet_buffer.writeUUID(msg.player_uuid);
packet_buffer.writeEnum(msg.hand);
}
public static C2SRequestPlayerRevive decode(final PacketBuffer packet_buffer) {
return new C2SRequestPlayerRevive(packet_buffer.readUUID(), packet_buffer.readEnum(Hand.class));
}
public static void handle(final C2SRequestPlayerRevive msg, final Supplier<NetworkEvent.Context> context_supplier) {
final NetworkEvent.Context context = context_supplier.get();
context.enqueueWork(() -> {
final ServerPlayerEntity sender = TotemOfReviving.players.getPlayer(msg.player_uuid);
if (sender == null) { return; }
ItemStack item = sender.getItemInHand(msg.hand);
if (item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_TARGET_INDEX) > TotemOfReviving.players.getPlayerCount()-1 || item.getOrCreateTag().getString(TotemOfRevivingItem.TAG_TARGET_NAME).equals("")) {
sender.sendMessage(new StringTextComponent(TextFormatting.RED + "Error getting target! (Try selecting the target again)"), sender.getUUID());
} else {
ServerPlayerEntity player_to_revive = TotemOfReviving.players.getPlayerByName(item.getOrCreateTag().getString(TotemOfRevivingItem.TAG_TARGET_NAME));
ServerWorld player_to_revive_world = player_to_revive.getLevel();
ServerWorld sender_world = sender.getLevel();
int required_charge = player_to_revive.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS));
if (player_to_revive.isSpectator()) {
if (player_to_revive_world.equals(sender_world)) {
if (item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT) >= required_charge) {
if (item.getOrCreateTag().contains(StrawTotemItem.TAG_FAIL_CHANCE)) {
int fail_chance = item.getOrCreateTag().getInt(StrawTotemItem.TAG_FAIL_CHANCE);
if (Utils.randomIntRange(0, 100) <= fail_chance) {
item.getOrCreateTag().putInt(StrawTotemItem.TAG_CHARGE_AMOUNT, item.getOrCreateTag().getInt(StrawTotemItem.TAG_CHARGE_AMOUNT)-required_charge);
item.getOrCreateTag().putInt(StrawTotemItem.TAG_FAIL_CHANCE, fail_chance-(5*required_charge));
sender.hurt(DamageSource.GENERIC, (sender.getHealth() * (fail_chance / 100.0f)));
return;
}
}
player_to_revive.teleportTo(sender.getX(), sender.getY(), sender.getZ());
player_to_revive.setGameMode(GameType.SURVIVAL);
item.getOrCreateTag().putInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT, item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT) - required_charge);
sender.sendMessage(new StringTextComponent(TextFormatting.GRAY + "Successfully revived " + TextFormatting.DARK_GRAY + player_to_revive.getDisplayName().getString()), sender.getUUID());
} else {
sender.sendMessage(new StringTextComponent(TextFormatting.GRAY + "Not enough charge! Required charge is: " + TextFormatting.DARK_GRAY + required_charge), sender.getUUID());
}
} else {
sender.sendMessage(new StringTextComponent(TextFormatting.DARK_GRAY + player_to_revive.getDisplayName().getString() + TextFormatting.GRAY + " is not in this dimension!"), sender.getUUID());
}
} else {
sender.sendMessage(new StringTextComponent(TextFormatting.DARK_GRAY + player_to_revive.getDisplayName().getString() + TextFormatting.GRAY + " is not dead!"), sender.getUUID());
}
}
});
context.setPacketHandled(true);
}
}

View File

@ -1,63 +0,0 @@
package com.micle.totemofreviving.network;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.items.StrawTotemItem;
import com.micle.totemofreviving.items.TotemOfRevivingItem;
import com.micle.totemofreviving.utils.Utils;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.DamageSource;
import net.minecraft.util.Hand;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.UUID;
import java.util.function.Supplier;
public class C2SRequestTotemCharge {
private final UUID player_uuid;
private final Hand hand;
private final Hand item_charge_hand;
public C2SRequestTotemCharge(final UUID player_uuid, final Hand hand, final Hand item_charge_hand) {
this.player_uuid = player_uuid;
this.hand = hand;
this.item_charge_hand = item_charge_hand;
}
public static void encode(final C2SRequestTotemCharge msg, final PacketBuffer packet_buffer) {
packet_buffer.writeUUID(msg.player_uuid);
packet_buffer.writeEnum(msg.hand);
packet_buffer.writeEnum(msg.item_charge_hand);
}
public static C2SRequestTotemCharge decode(final PacketBuffer packet_buffer) {
return new C2SRequestTotemCharge(packet_buffer.readUUID(), packet_buffer.readEnum(Hand.class), packet_buffer.readEnum(Hand.class));
}
public static void handle(final C2SRequestTotemCharge msg, final Supplier<NetworkEvent.Context> context_supplier) {
final NetworkEvent.Context context = context_supplier.get();
context.enqueueWork(() -> {
final ServerPlayerEntity sender = TotemOfReviving.players.getPlayer(msg.player_uuid);
if (sender == null) { return; }
ItemStack charge_item = sender.getItemInHand(msg.item_charge_hand);
ItemStack totem_item = sender.getItemInHand(msg.hand);
charge_item.setCount(charge_item.getCount()-1);
totem_item.getOrCreateTag().putInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT, totem_item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT)+1);
if (totem_item.getOrCreateTag().contains(StrawTotemItem.TAG_FAIL_CHANCE)) {
int fail_chance = totem_item.getOrCreateTag().getInt(StrawTotemItem.TAG_FAIL_CHANCE);
if (Utils.randomIntRange(0, 100) <= fail_chance) {
sender.setItemInHand(msg.hand, new ItemStack(Items.AIR));
sender.hurt(DamageSource.GENERIC, (sender.getHealth() * (fail_chance / 100.0f)));
} else {
totem_item.getOrCreateTag().putInt(StrawTotemItem.TAG_FAIL_CHANCE, fail_chance+5);
}
}
});
context.setPacketHandled(true);
}
}

View File

@ -1,52 +0,0 @@
package com.micle.totemofreviving.network;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.items.TotemOfRevivingItem;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Hand;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.UUID;
import java.util.function.Supplier;
public class C2SRequestTotemTarget {
private final UUID player_uuid;
private final Hand hand;
public C2SRequestTotemTarget(final UUID player_uuid, final Hand hand) {
this.player_uuid = player_uuid;
this.hand = hand;
}
public static void encode(final C2SRequestTotemTarget msg, final PacketBuffer packet_buffer) {
packet_buffer.writeUUID(msg.player_uuid);
packet_buffer.writeEnum(msg.hand);
}
public static C2SRequestTotemTarget decode(final PacketBuffer packet_buffer) {
return new C2SRequestTotemTarget(packet_buffer.readUUID(), packet_buffer.readEnum(Hand.class));
}
public static void handle(final C2SRequestTotemTarget msg, final Supplier<NetworkEvent.Context> context_supplier) {
final NetworkEvent.Context context = context_supplier.get();
context.enqueueWork(() -> {
final ServerPlayerEntity sender = TotemOfReviving.players.getPlayer(msg.player_uuid);
if (sender == null) { return; }
ItemStack item = sender.getItemInHand(msg.hand);
int current_player_index = item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_TARGET_INDEX) + 1;
if (current_player_index > TotemOfReviving.players.getPlayerCount()-1) {
current_player_index = 0;
}
item.getOrCreateTag().putInt(TotemOfRevivingItem.TAG_TARGET_INDEX, current_player_index);
item.getOrCreateTag().putString(TotemOfRevivingItem.TAG_TARGET_NAME, TotemOfReviving.players.getPlayers().get(current_player_index).getDisplayName().getString());
sender.sendMessage(new StringTextComponent(TextFormatting.GRAY + "Target: " + TextFormatting.DARK_GRAY + item.getOrCreateTag().getString(TotemOfRevivingItem.TAG_TARGET_NAME)), sender.getUUID());
});
context.setPacketHandled(true);
}
}

View File

@ -1,19 +0,0 @@
package com.micle.totemofreviving.setup;
import com.micle.totemofreviving.items.RevivingChargeItem;
import com.micle.totemofreviving.items.StrawChargeItem;
import com.micle.totemofreviving.items.StrawTotemItem;
import com.micle.totemofreviving.items.TotemOfRevivingItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraftforge.fml.RegistryObject;
public class ModItems {
public static final RegistryObject<Item> TOTEM_OF_REVIVING = Registration.ITEMS.register("totem_of_reviving", TotemOfRevivingItem::new);
public static final RegistryObject<Item> REVIVING_CHARGE = Registration.ITEMS.register("reviving_charge", RevivingChargeItem::new);
public static final RegistryObject<Item> STRAW_TOTEM = Registration.ITEMS.register("straw_totem", StrawTotemItem::new);
public static final RegistryObject<Item> STRAW_CHARGE = Registration.ITEMS.register("straw_charge", StrawChargeItem::new);
static void register() {
}
}

View File

@ -1,25 +0,0 @@
package com.micle.totemofreviving.setup;
import com.micle.totemofreviving.TotemOfReviving;
import com.micle.totemofreviving.events.ServerTickEventHandler;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
public class Registration {
public static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, TotemOfReviving.MOD_ID);
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, TotemOfReviving.MOD_ID);
public static void register() {
IEventBus mod_event_bus = FMLJavaModLoadingContext.get().getModEventBus();
BLOCKS.register(mod_event_bus);
ITEMS.register(mod_event_bus);
MinecraftForge.EVENT_BUS.register(new ServerTickEventHandler());
ModItems.register();
}
}

View File

@ -1,19 +0,0 @@
package com.micle.totemofreviving.utils;
public class Utils {
public static float clamp(float val, float min, float max) {
return Math.max(min, Math.min(max, val));
}
public static int randomIntRange(int min, int max) {
return (int) randomDoubleRange(min, max);
}
public static float randomFloatRange(float min, float max) {
return (float) randomDoubleRange(min, max);
}
public static double randomDoubleRange(double min, double max) {
return ((Math.random() * (max - min)) + min);
}
}

View File

@ -0,0 +1,13 @@
package dev.micle.totemofreviving;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
public interface ISideProxy {
MinecraftServer getServer();
PlayerEntity getClientPlayer();
ClientWorld getClientWorld();
}

View File

@ -0,0 +1,100 @@
package dev.micle.totemofreviving;
import dev.micle.totemofreviving.config.Config;
import dev.micle.totemofreviving.data.DataGenerators;
import dev.micle.totemofreviving.network.Network;
import dev.micle.totemofreviving.setup.Registration;
import net.minecraft.client.Minecraft;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.server.MinecraftServer;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.AddReloadListenerEvent;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.event.lifecycle.*;
import net.minecraftforge.fml.event.server.FMLServerStartedEvent;
import net.minecraftforge.fml.event.server.FMLServerStoppingEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
class SideProxy implements ISideProxy {
private static MinecraftServer server = null;
// Common setup
SideProxy() {
Registration.register();
Config.init();
Network.init();
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(DataGenerators::gatherData);
modEventBus.addListener(SideProxy::setup);
modEventBus.addListener(SideProxy::imcEnqueue);
modEventBus.addListener(SideProxy::imcProcess);
MinecraftForge.EVENT_BUS.addListener(SideProxy::onAddReloadListeners);
MinecraftForge.EVENT_BUS.addListener(SideProxy::serverStarted);
MinecraftForge.EVENT_BUS.addListener(SideProxy::serverStopping);
}
private static void setup(FMLCommonSetupEvent event) {}
private static void imcEnqueue(InterModEnqueueEvent event) {}
private static void imcProcess(InterModProcessEvent event) {}
private static void onAddReloadListeners(AddReloadListenerEvent event) {}
private static void serverStarted(FMLServerStartedEvent event) {
server = event.getServer();
}
private static void serverStopping(FMLServerStoppingEvent event) {
server = null;
}
@Override
public MinecraftServer getServer() {
return server;
}
@Override
public PlayerEntity getClientPlayer() {
return null;
}
@Override
public ClientWorld getClientWorld() {
return null;
}
// Client setup
static class Client extends SideProxy {
Client() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(Client::setup);
FMLJavaModLoadingContext.get().getModEventBus().addListener(Client::postSetup);
}
private static void setup(FMLClientSetupEvent event) {}
private static void postSetup(FMLLoadCompleteEvent event) {}
@Override
public PlayerEntity getClientPlayer() {
return Minecraft.getInstance().player;
}
@Override
public ClientWorld getClientWorld() {
return Minecraft.getInstance().level;
}
}
// Server setup
static class Server extends SideProxy {
Server() {
FMLJavaModLoadingContext.get().getModEventBus().addListener(Server::setup);
}
private static void setup(FMLDedicatedServerSetupEvent event) {}
}
}

View File

@ -0,0 +1,58 @@
package dev.micle.totemofreviving;
import dev.micle.totemofreviving.setup.ModItems;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.util.Optional;
import java.util.Random;
@Mod(TotemOfReviving.MOD_ID)
public final class TotemOfReviving {
public static final String MOD_ID = "totemofreviving";
public static final String MOD_NAME = "Micle's Totem of Reviving";
public static final ItemGroup ITEM_GROUP = new ItemGroup(MOD_ID) {
@Override
public ItemStack makeIcon() {
return new ItemStack(ModItems.STRAW_TOTEM.get());
}
};
public static final String RESOURCE_PREFIX = MOD_ID + ':';
public static final Random RANDOM = new Random();
public static final Logger LOGGER = LogManager.getLogger(MOD_NAME);
public static TotemOfReviving INSTANCE;
public static ISideProxy PROXY;
public TotemOfReviving() {
INSTANCE = this;
PROXY = DistExecutor.safeRunForDist(
() -> SideProxy.Client::new,
() -> SideProxy.Server::new
);
}
public static String getVersion() {
Optional<? extends ModContainer> optional = ModList.get().getModContainerById(MOD_ID);
if (optional.isPresent()) {
return optional.get().getModInfo().getVersion().toString();
}
return "0.0.0";
}
public static ResourceLocation createResourceLocation(String name) {
if (name.contains(":")) {
throw new IllegalArgumentException("name containes namespace");
}
return new ResourceLocation(MOD_ID, name);
}
}

View File

@ -0,0 +1,95 @@
package dev.micle.totemofreviving.config;
import dev.micle.totemofreviving.item.totem.DiamondTotemItem;
import dev.micle.totemofreviving.item.totem.IronTotemItem;
import dev.micle.totemofreviving.item.totem.NetheriteTotemItem;
import dev.micle.totemofreviving.item.totem.StrawTotemItem;
import net.minecraftforge.common.ForgeConfigSpec;
import net.minecraftforge.fml.ModLoadingContext;
import net.minecraftforge.fml.config.ModConfig;
public final class Config {
public static void init() {
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, Server.SPEC);
}
public static class Server {
private static final ForgeConfigSpec SPEC;
private static final TotemConfig STRAW_TOTEM_CONFIG;
private static final TotemConfig IRON_TOTEM_CONFIG;
private static final TotemConfig DIAMOND_TOTEM_CONFIG;
private static final TotemConfig NETHERITE_TOTEM_CONFIG;
static {
ForgeConfigSpec.Builder builder = new ForgeConfigSpec.Builder();
builder.comment("WHEN MAKING CHANGES IT IS RECOMMENDED TO NOT BE IN A WORLD.\n" +
"CHANGES WILL MOST LIKELY REQUIRE A RESTART FOR EVERYTHING TO WORK PROPERLY.");
STRAW_TOTEM_CONFIG = new TotemConfig(builder, StrawTotemItem.getName(), true, -1, 3,
1, false, false, 1);
IRON_TOTEM_CONFIG = new TotemConfig(builder, IronTotemItem.getName(), true, -1, 5,
0.75, false, false, 4);
DIAMOND_TOTEM_CONFIG = new TotemConfig(builder, DiamondTotemItem.getName(), true, -1, 10,
0.5, false, false, 10);
NETHERITE_TOTEM_CONFIG = new TotemConfig(builder, NetheriteTotemItem.getName(), true, 1, 1,
1, true, true, 0);
SPEC = builder.build();
}
public static TotemConfig getStrawTotemConfig() { return STRAW_TOTEM_CONFIG; }
public static TotemConfig getIronTotemConfig() { return IRON_TOTEM_CONFIG; }
public static TotemConfig getDiamondTotemConfig() { return DIAMOND_TOTEM_CONFIG; }
public static TotemConfig getNetheriteTotemConfig() { return NETHERITE_TOTEM_CONFIG; }
}
public static class TotemConfig {
private final ForgeConfigSpec.BooleanValue IS_ENABLED;
private final ForgeConfigSpec.IntValue CHARGE_COST;
private final ForgeConfigSpec.IntValue CHARGE_COST_LIMIT;
private final ForgeConfigSpec.DoubleValue CHARGE_COST_MULTIPLIER;
private final ForgeConfigSpec.BooleanValue CAN_REVIVE_MORE_EXPENSIVE_TARGETS;
private final ForgeConfigSpec.BooleanValue CAN_REVIVE_ACROSS_DIMENSIONS;
private final ForgeConfigSpec.IntValue DURABILITY;
TotemConfig(ForgeConfigSpec.Builder builder, String name, boolean isEnabled, int chargeCost,
int chargeCostLimit, double chargeCostMultiplier, boolean canReviveMoreExpensiveTargets,
boolean canReviveAcrossDimensions, int durability) {
builder.push(name);
IS_ENABLED = builder
.comment("Is the " + name + " enabled?")
.define("isEnabled", isEnabled);
CHARGE_COST = builder
.comment("The charge cost to revive a player.\n" +
"-1 means the cost is dynamic (follows the amount of deaths the target has)\n" +
"Higher values set the charge cost to static, meaning that this will be the amount of charges needed to revive someone.")
.defineInRange("chargeCost", chargeCost, -1, Integer.MAX_VALUE);
CHARGE_COST_LIMIT = builder
.comment("The max amount of charge this totem can hold at once. Only works with dynamic cost.")
.defineInRange("chargeCostLimit", chargeCostLimit, 1, Integer.MAX_VALUE);
CHARGE_COST_MULTIPLIER = builder
.comment("Charge cost multiplier. 0.5 means the charge cost will be 50% of the original cost. Only works with dynamic cost.")
.defineInRange("chargeCostMultiplier", chargeCostMultiplier, 0.01, 100);
CAN_REVIVE_MORE_EXPENSIVE_TARGETS = builder
.comment("Is the totem able to revive targets that cost more than the totems max charge?\n" +
"This only applies if the totem is fully charged. (dynamic wont work if limit is 0)")
.define("canReviveMoreExpensiveTargets", canReviveMoreExpensiveTargets);
CAN_REVIVE_ACROSS_DIMENSIONS = builder
.comment("Is the totem able to revive targets across dimensions?")
.define("canReviveAcrossDimensions", canReviveAcrossDimensions);
DURABILITY = builder
.comment("The durability of the totem. 0 means unbreakable.")
.defineInRange("durability", durability, 0, Integer.MAX_VALUE);
builder.pop();
}
public boolean getIsEnabled() { return IS_ENABLED.get(); }
public int getChargeCost() { return CHARGE_COST.get(); }
public int getChargeCostLimit() { return CHARGE_COST_LIMIT.get(); }
public double getChargeCostMultiplier() { return CHARGE_COST_MULTIPLIER.get(); }
public boolean getCanReviveMoreExpensiveTargets() { return CAN_REVIVE_MORE_EXPENSIVE_TARGETS.get(); }
public boolean getCanReviveAcrossDimensions() { return CAN_REVIVE_ACROSS_DIMENSIONS.get(); }
public int getDurability() { return DURABILITY.get(); }
}
}

View File

@ -0,0 +1,22 @@
package dev.micle.totemofreviving.data;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.data.client.ModItemModelProvider;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.GatherDataEvent;
@Mod.EventBusSubscriber(modid = TotemOfReviving.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD)
public class DataGenerators {
@SubscribeEvent
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
generator.addProvider(new ModItemModelProvider(generator, existingFileHelper));
generator.addProvider(new ModRecipeProvider(generator));
}
}

View File

@ -0,0 +1,99 @@
package dev.micle.totemofreviving.data;
import dev.micle.totemofreviving.item.crafting.ExtendedShapedRecipeBuilder;
import dev.micle.totemofreviving.setup.ModItems;
import dev.micle.totemofreviving.setup.ModRecipes;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.IFinishedRecipe;
import net.minecraft.data.RecipeProvider;
import net.minecraft.item.Items;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.function.Consumer;
public class ModRecipeProvider extends RecipeProvider {
public ModRecipeProvider(DataGenerator generator) {
super(generator);
}
@Override
@ParametersAreNonnullByDefault
protected void buildShapelessRecipes(Consumer<IFinishedRecipe> consumer) {
ExtendedShapedRecipeBuilder.shaped(ModRecipes.TOTEM_RECIPE.get(), ModItems.STRAW_TOTEM.get())
.define('W', Items.WHEAT)
.define('|', Items.STICK)
.define('S', Items.STRING)
.define('N', Items.IRON_NUGGET)
.pattern("NSN")
.pattern("NWN")
.pattern("N|N")
.unlockedBy("has_item", has(Items.WHEAT))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.TOTEM_RECIPE.get(), ModItems.IRON_TOTEM.get())
.define('B', Items.IRON_BLOCK)
.define('E', Items.EMERALD)
.define('I', Items.IRON_INGOT)
.pattern(" E ")
.pattern("IBI")
.pattern(" I ")
.unlockedBy("has_item", has(Items.EMERALD))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.TOTEM_RECIPE.get(), ModItems.DIAMOND_TOTEM.get())
.define('T', Items.TOTEM_OF_UNDYING)
.define('D', Items.DIAMOND)
.define('E', Items.ENDER_PEARL)
.pattern("EDE")
.pattern("DTD")
.pattern("EDE")
.unlockedBy("has_item", has(Items.TOTEM_OF_UNDYING))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.TOTEM_RECIPE.get(), ModItems.NETHERITE_TOTEM.get())
.define('T', ModItems.DIAMOND_TOTEM.get())
.define('N', Items.NETHERITE_SCRAP)
.define('G', Items.GOLD_INGOT)
.define('B', Items.NETHER_BRICK)
.pattern("BNB")
.pattern("NTN")
.pattern("BGB")
.unlockedBy("has_item", has(Items.NETHERITE_SCRAP))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.CHARGE_RECIPE.get(), ModItems.STRAW_CHARGE.get())
.define('E', Items.EMERALD)
.define('W', Items.WHEAT)
.define('N', Items.IRON_NUGGET)
.pattern("NWN")
.pattern("WEW")
.pattern("NWN")
.unlockedBy("has_item", has(ModItems.STRAW_TOTEM.get()))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.CHARGE_RECIPE.get(), ModItems.IRON_CHARGE.get())
.define('E', Items.EMERALD)
.define('I', Items.IRON_INGOT)
.define('N', Items.IRON_NUGGET)
.pattern("NIN")
.pattern("IEI")
.pattern("NIN")
.unlockedBy("has_item", has(ModItems.IRON_TOTEM.get()))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.TOTEM_RECIPE.get(), ModItems.DIAMOND_CHARGE.get())
.define('E', Items.EMERALD)
.define('D', Items.DIAMOND)
.define('I', Items.IRON_INGOT)
.define('P', Items.ENDER_PEARL)
.pattern("IDI")
.pattern("PEP")
.pattern("IDI")
.unlockedBy("has_item", has(ModItems.DIAMOND_TOTEM.get()))
.save(consumer);
ExtendedShapedRecipeBuilder.shaped(ModRecipes.CHARGE_RECIPE.get(), ModItems.NETHERITE_CHARGE.get())
.define('C', ModItems.DIAMOND_CHARGE.get())
.define('N', Items.NETHERITE_SCRAP)
.define('G', Items.GOLD_INGOT)
.pattern("GNG")
.pattern("NCN")
.pattern("GNG")
.unlockedBy("has_item", has(ModItems.NETHERITE_TOTEM.get()))
.save(consumer);
}
}

View File

@ -0,0 +1,41 @@
package dev.micle.totemofreviving.data.client;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.item.charge.DiamondChargeItem;
import dev.micle.totemofreviving.item.charge.IronChargeItem;
import dev.micle.totemofreviving.item.charge.NetheriteChargeItem;
import dev.micle.totemofreviving.item.charge.StrawChargeItem;
import dev.micle.totemofreviving.item.totem.DiamondTotemItem;
import dev.micle.totemofreviving.item.totem.IronTotemItem;
import dev.micle.totemofreviving.item.totem.NetheriteTotemItem;
import dev.micle.totemofreviving.item.totem.StrawTotemItem;
import net.minecraft.data.DataGenerator;
import net.minecraftforge.client.model.generators.ItemModelBuilder;
import net.minecraftforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper;
public class ModItemModelProvider extends ItemModelProvider {
public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {
super(generator, TotemOfReviving.MOD_ID, existingFileHelper);
}
@Override
protected void registerModels() {
ModelFile itemGenerated = getExistingFile(mcLoc("item/generated"));
builder(itemGenerated, StrawTotemItem.getName());
builder(itemGenerated, IronTotemItem.getName());
builder(itemGenerated, DiamondTotemItem.getName());
builder(itemGenerated, NetheriteTotemItem.getName());
builder(itemGenerated, StrawChargeItem.getName());
builder(itemGenerated, IronChargeItem.getName());
builder(itemGenerated, DiamondChargeItem.getName());
builder(itemGenerated, NetheriteChargeItem.getName());
}
private ItemModelBuilder builder(ModelFile itemGenerated, String name) {
return getBuilder(name).parent(itemGenerated).texture("layer0", "item/" + name);
}
}

View File

@ -0,0 +1,49 @@
package dev.micle.totemofreviving.item.charge;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.config.Config;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
public class ChargeItem extends Item {
public ChargeItem() {
this(Rarity.COMMON);
}
public ChargeItem(Rarity rarity) {
super(new Item.Properties().tab(TotemOfReviving.ITEM_GROUP).stacksTo(64).rarity(rarity));
}
@Override
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public void appendHoverText(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag tooltipFlag) {
if (isEnabled(stack)) {
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Used for charging its corresponding totem."));
} else {
tooltip.add(new StringTextComponent(TextFormatting.RED + "Totem is disabled!"));
}
super.appendHoverText(stack, world, tooltip, tooltipFlag);
}
public static boolean isEnabled(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof StrawChargeItem) { return Config.Server.getStrawTotemConfig().getIsEnabled(); }
if (item instanceof IronChargeItem) { return Config.Server.getIronTotemConfig().getIsEnabled(); }
if (item instanceof DiamondChargeItem) { return Config.Server.getDiamondTotemConfig().getIsEnabled(); }
if (item instanceof NetheriteChargeItem) { return Config.Server.getNetheriteTotemConfig().getIsEnabled(); }
return false;
}
}

View File

@ -0,0 +1,13 @@
package dev.micle.totemofreviving.item.charge;
import net.minecraft.item.Rarity;
public class DiamondChargeItem extends ChargeItem {
public DiamondChargeItem() {
super(Rarity.RARE);
}
public static String getName() {
return "diamond_charge";
}
}

View File

@ -0,0 +1,9 @@
package dev.micle.totemofreviving.item.charge;
public class IronChargeItem extends ChargeItem {
public IronChargeItem() {}
public static String getName() {
return "iron_charge";
}
}

View File

@ -0,0 +1,13 @@
package dev.micle.totemofreviving.item.charge;
import net.minecraft.item.Rarity;
public class NetheriteChargeItem extends ChargeItem {
public NetheriteChargeItem() {
super(Rarity.EPIC);
}
public static String getName() {
return "netherite_charge";
}
}

View File

@ -0,0 +1,13 @@
package dev.micle.totemofreviving.item.charge;
import net.minecraft.item.Rarity;
public class StrawChargeItem extends ChargeItem {
public StrawChargeItem() {
super(Rarity.UNCOMMON);
}
public static String getName() {
return "straw_charge";
}
}

View File

@ -0,0 +1,33 @@
package dev.micle.totemofreviving.item.crafting;
import dev.micle.totemofreviving.item.charge.ChargeItem;
import dev.micle.totemofreviving.setup.ModRecipes;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.world.World;
public class ChargeRecipe extends ExtendedShapedRecipe {
public ChargeRecipe(ShapedRecipe recipe) {
super(recipe);
}
@Override
public IRecipeSerializer<?> getSerializer() {
return ModRecipes.CHARGE_RECIPE.get();
}
@Override
public boolean matches(CraftingInventory inventory, World world) {
if (!ChargeItem.isEnabled(getResultItem())) {
return false;
}
return getBaseRecipe().matches(inventory, world);
}
@Override
public ItemStack assemble(CraftingInventory inventory) {
return getBaseRecipe().getResultItem();
}
}

View File

@ -0,0 +1,88 @@
package dev.micle.totemofreviving.item.crafting;
import com.google.gson.JsonObject;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.ResourceLocation;
import net.minecraft.world.World;
import net.minecraftforge.registries.ForgeRegistryEntry;
import javax.annotation.Nullable;
import java.util.function.BiConsumer;
import java.util.function.Function;
public abstract class ExtendedShapedRecipe extends ShapedRecipe {
private static final IRecipeSerializer<ShapedRecipe> BASE_SERIALIZER = IRecipeSerializer.SHAPED_RECIPE;
private final ShapedRecipe recipe;
public ExtendedShapedRecipe(ShapedRecipe recipe) {
super(recipe.getId(), recipe.getGroup(), recipe.getRecipeWidth(), recipe.getRecipeHeight(), recipe.getIngredients(), recipe.getResultItem());
this.recipe = recipe;
}
public ShapedRecipe getBaseRecipe() {
return this.recipe;
}
@Override
public abstract IRecipeSerializer<?> getSerializer();
@Override
public abstract boolean matches(CraftingInventory inventory, World world);
@Override
public abstract ItemStack assemble(CraftingInventory inventory);
public static class Serializer<T extends ExtendedShapedRecipe> extends ForgeRegistryEntry<IRecipeSerializer<?>> implements IRecipeSerializer<T> {
private final Function<ShapedRecipe, T> recipeFactory;
@Nullable private final BiConsumer<JsonObject, T> readJson;
@Nullable private final BiConsumer<PacketBuffer, T> readBuffer;
@Nullable private final BiConsumer<PacketBuffer, T> writeBuffer;
public Serializer(Function<ShapedRecipe, T> recipeFactory,
@Nullable BiConsumer<JsonObject, T> readJson,
@Nullable BiConsumer<PacketBuffer, T> readBuffer,
@Nullable BiConsumer<PacketBuffer, T> writeBuffer) {
this.recipeFactory = recipeFactory;
this.readJson = readJson;
this.readBuffer = readBuffer;
this.writeBuffer = writeBuffer;
}
public static <S extends ExtendedShapedRecipe> Serializer<S> basic(Function<ShapedRecipe, S> recipeFactory) {
return new Serializer<>(recipeFactory, null, null, null);
}
@Override
public T fromJson(ResourceLocation recipeId, JsonObject json) {
ShapedRecipe recipe = BASE_SERIALIZER.fromJson(recipeId, json);
T result = this.recipeFactory.apply(recipe);
if (this.readJson != null) {
this.readJson.accept(json, result);
}
return result;
}
@Override
public T fromNetwork(ResourceLocation recipeId, PacketBuffer buffer) {
ShapedRecipe recipe = BASE_SERIALIZER.fromNetwork(recipeId, buffer);
T result = this.recipeFactory.apply(recipe);
if (this.readBuffer != null) {
this.readBuffer.accept(buffer, result);
}
return result;
}
@Override
public void toNetwork(PacketBuffer buffer, T recipe) {
BASE_SERIALIZER.toNetwork(buffer, recipe.getBaseRecipe());
if (this.writeBuffer != null) {
this.writeBuffer.accept(buffer, recipe);
}
}
}
}

View File

@ -0,0 +1,184 @@
package dev.micle.totemofreviving.item.crafting;
import com.google.common.collect.Sets;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import net.minecraft.advancements.Advancement;
import net.minecraft.advancements.AdvancementRewards;
import net.minecraft.advancements.ICriterionInstance;
import net.minecraft.advancements.IRequirementsStrategy;
import net.minecraft.advancements.criterion.EntityPredicate;
import net.minecraft.advancements.criterion.RecipeUnlockedTrigger;
import net.minecraft.data.IFinishedRecipe;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.Ingredient;
import net.minecraft.tags.ITag;
import net.minecraft.util.IItemProvider;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nullable;
import java.util.*;
import java.util.function.Consumer;
public class ExtendedShapedRecipeBuilder {
private final IRecipeSerializer<?> serializer;
private final Item result;
private final int count;
private final List<String> pattern = new ArrayList<>();
private final Map<Character, Ingredient> key = new LinkedHashMap<>();
private final Advancement.Builder advancementBuilder = Advancement.Builder.advancement();
private boolean hasAdvancementCriterion = false;
private String group = "";
private ExtendedShapedRecipeBuilder(IRecipeSerializer<?> serializer, IItemProvider result, int count) {
this.serializer = serializer;
this.result = result.asItem();
this.count = count;
}
public static ExtendedShapedRecipeBuilder shaped(IRecipeSerializer<?> serializer, IItemProvider result) {
return shaped(serializer, result, 1);
}
public static ExtendedShapedRecipeBuilder shaped(IRecipeSerializer<?> serializer, IItemProvider result, int count) {
return new ExtendedShapedRecipeBuilder(serializer, result, count);
}
public ExtendedShapedRecipeBuilder define(Character symbol, ITag<Item> tagIn) {
return this.define(symbol, Ingredient.of(tagIn));
}
public ExtendedShapedRecipeBuilder define(Character symbol, IItemProvider itemIn) {
return this.define(symbol, Ingredient.of(itemIn));
}
public ExtendedShapedRecipeBuilder define(Character symbol, Ingredient ingredientIn) {
if (this.key.containsKey(symbol)) {
throw new IllegalArgumentException("Symbol '" + symbol + "' is already defined!");
} else if (symbol == ' ') {
throw new IllegalArgumentException("Symbol ' ' (whitespace) is reserved and cannot be defined");
} else {
this.key.put(symbol, ingredientIn);
return this;
}
}
public ExtendedShapedRecipeBuilder pattern(String patternIn) {
if (!this.pattern.isEmpty() && patternIn.length() != this.pattern.get(0).length()) {
throw new IllegalArgumentException("Pattern must be the same width on every line!");
} else {
this.pattern.add(patternIn);
return this;
}
}
public ExtendedShapedRecipeBuilder unlockedBy(String name, ICriterionInstance criterionIn) {
this.advancementBuilder.addCriterion(name, criterionIn);
this.hasAdvancementCriterion = true;
return this;
}
public ExtendedShapedRecipeBuilder group(String groupIn) {
this.group = groupIn;
return this;
}
public void save(Consumer<IFinishedRecipe> consumer) {
save(consumer, this.result.getRegistryName());
}
public void save(Consumer<IFinishedRecipe> consumer, ResourceLocation id) {
this.validate(id);
if (this.hasAdvancementCriterion && !this.advancementBuilder.getCriteria().isEmpty()) {
this.advancementBuilder.parent(new ResourceLocation("recipes/root"))
.addCriterion("has_the_recipe", new RecipeUnlockedTrigger.Instance(EntityPredicate.AndPredicate.ANY, id))
.rewards(AdvancementRewards.Builder.recipe(id))
.requirements(IRequirementsStrategy.OR);
}
ResourceLocation advancementId = new ResourceLocation(id.getNamespace(), "recipes/" + this.result.getItemCategory().getRecipeFolderName() + "/" + id.getPath());
consumer.accept(new Result(id, this, advancementId));
}
private void validate(ResourceLocation id) {
if (this.pattern.isEmpty()) {
throw new IllegalStateException("No pattern is defined for shaped recipe " + id + "!");
} else {
Set<Character> set = Sets.newHashSet(this.key.keySet());
set.remove(' ');
for (String s : this.pattern) {
for (int i = 0; i < s.length(); ++i) {
char c0 = s.charAt(i);
if (!this.key.containsKey(c0) && c0 != ' ') {
throw new IllegalStateException("Pattern in recipe " + id + " uses undefined symbol '" + c0 + "'");
}
set.remove(c0);
}
}
if (!set.isEmpty()) {
throw new IllegalStateException("Ingredients are defined but not used in pattern for recipe " + id);
} else if (this.pattern.size() == 1 && this.pattern.get(0).length() == 1) {
throw new IllegalStateException("Shaped recipe " + id + " only takes in a single item - should it be a shapeless recipe instead?");
}
}
}
public static class Result implements IFinishedRecipe {
private final ResourceLocation id;
private final ExtendedShapedRecipeBuilder builder;
private final ResourceLocation advancementId;
public Result(ResourceLocation id, ExtendedShapedRecipeBuilder builder, ResourceLocation advancementId) {
this.id = id;
this.builder = builder;
this.advancementId = advancementId;
}
@Override
public void serializeRecipeData(JsonObject json) {
if (!builder.group.isEmpty()) {
json.addProperty("group", builder.group);
}
JsonArray pattern = new JsonArray();
builder.pattern.forEach(pattern::add);
json.add("pattern", pattern);
JsonObject key = new JsonObject();
builder.key.forEach((c, ingredient) -> key.add(String.valueOf(c), ingredient.toJson()));
json.add("key", key);
JsonObject result = new JsonObject();
result.addProperty("item", builder.result.getRegistryName().toString());
if (builder.count > 1) {
result.addProperty("count", builder.count);
}
json.add("result", result);
}
@Override
public IRecipeSerializer<?> getType() {
return builder.serializer;
}
@Override
public ResourceLocation getId() {
return id;
}
@Nullable
@Override
public JsonObject serializeAdvancement() {
return builder.hasAdvancementCriterion ? builder.advancementBuilder.serializeToJson() : null;
}
@Nullable
@Override
public ResourceLocation getAdvancementId() {
return builder.hasAdvancementCriterion ? advancementId : null;
}
}
}

View File

@ -0,0 +1,33 @@
package dev.micle.totemofreviving.item.crafting;
import dev.micle.totemofreviving.item.totem.TotemItem;
import dev.micle.totemofreviving.setup.ModRecipes;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraft.item.crafting.ShapedRecipe;
import net.minecraft.world.World;
public class TotemRecipe extends ExtendedShapedRecipe {
public TotemRecipe(ShapedRecipe recipe) {
super(recipe);
}
@Override
public IRecipeSerializer<?> getSerializer() {
return ModRecipes.TOTEM_RECIPE.get();
}
@Override
public boolean matches(CraftingInventory inventory, World world) {
if (!TotemItem.isEnabled(getResultItem())) {
return false;
}
return getBaseRecipe().matches(inventory, world);
}
@Override
public ItemStack assemble(CraftingInventory inventory) {
return getBaseRecipe().getResultItem();
}
}

View File

@ -0,0 +1,21 @@
package dev.micle.totemofreviving.item.totem;
import dev.micle.totemofreviving.config.Config;
import dev.micle.totemofreviving.item.charge.DiamondChargeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
public class DiamondTotemItem extends TotemItem {
public DiamondTotemItem() {
super(Rarity.RARE, Config.Server.getDiamondTotemConfig().getDurability());
}
public static String getName() {
return "diamond_totem";
}
@Override
public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof DiamondChargeItem);
}
}

View File

@ -0,0 +1,20 @@
package dev.micle.totemofreviving.item.totem;
import dev.micle.totemofreviving.config.Config;
import dev.micle.totemofreviving.item.charge.IronChargeItem;
import net.minecraft.item.ItemStack;
public class IronTotemItem extends TotemItem {
public IronTotemItem() {
super(Config.Server.getIronTotemConfig().getDurability());
}
public static String getName() {
return "iron_totem";
}
@Override
public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof IronChargeItem);
}
}

View File

@ -0,0 +1,26 @@
package dev.micle.totemofreviving.item.totem;
import dev.micle.totemofreviving.config.Config;
import dev.micle.totemofreviving.item.charge.NetheriteChargeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
public class NetheriteTotemItem extends TotemItem {
public NetheriteTotemItem() {
super(Rarity.EPIC, Config.Server.getNetheriteTotemConfig().getDurability());
}
public static String getName() {
return "netherite_totem";
}
@Override
public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof NetheriteChargeItem);
}
@Override
public boolean isFireResistant() {
return true;
}
}

View File

@ -0,0 +1,21 @@
package dev.micle.totemofreviving.item.totem;
import dev.micle.totemofreviving.config.Config;
import dev.micle.totemofreviving.item.charge.StrawChargeItem;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
public class StrawTotemItem extends TotemItem {
public StrawTotemItem() {
super(Rarity.UNCOMMON, Config.Server.getStrawTotemConfig().getDurability());
}
public static String getName() {
return "straw_totem";
}
@Override
public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof StrawChargeItem);
}
}

View File

@ -0,0 +1,261 @@
package dev.micle.totemofreviving.item.totem;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.config.Config;
import dev.micle.totemofreviving.network.ChangeTargetPacket;
import dev.micle.totemofreviving.network.ChargeTotemPacket;
import dev.micle.totemofreviving.network.Network;
import dev.micle.totemofreviving.network.ReviveTargetPacket;
import net.minecraft.client.Minecraft;
import net.minecraft.client.util.ITooltipFlag;
import net.minecraft.client.util.InputMappings;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Rarity;
import net.minecraft.stats.Stats;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.world.World;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.lwjgl.glfw.GLFW;
import javax.annotation.Nullable;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import java.util.UUID;
public abstract class TotemItem extends Item {
private static final String TAG_TARGET_INDEX = "target_index";
private static final String TAG_TARGET_UUID = "target_uuid";
private static final String TAG_TARGET_NAME = "target_name";
private static final String TAG_TARGET_DEATHS = "target_deaths";
private static final String TAG_CHARGE = "charge";
public TotemItem(int durability) {
this(Rarity.COMMON, durability);
}
public TotemItem(Rarity rarity, int durability) {
super(new Item.Properties().tab(TotemOfReviving.ITEM_GROUP).stacksTo(1).rarity(rarity).defaultDurability(durability));
}
public abstract boolean isCharge(ItemStack stack);
public static int getTargetIndex(ItemStack stack) {
if (!isTotem(stack)) { return -1; }
return stack.getOrCreateTag().getInt(TAG_TARGET_INDEX);
}
public static void setTargetIndex(ItemStack stack, int targetIndex) {
if (!isTotem(stack)) { return; }
stack.getOrCreateTag().putInt(TAG_TARGET_INDEX, targetIndex);
}
public static UUID getTargetUUID(ItemStack stack) {
if (!isTotem(stack)) { return null; }
try {
return UUID.fromString(stack.getOrCreateTag().getString(TAG_TARGET_UUID));
} catch (IllegalArgumentException exception) {
return null;
}
}
public static void setTargetUUID(ItemStack stack, UUID targetUUID) {
if (!isTotem(stack)) { return; }
stack.getOrCreateTag().putString(TAG_TARGET_UUID, targetUUID.toString());
}
public static String getTargetName(ItemStack stack) {
if (!isTotem(stack)) { return null; }
return stack.getOrCreateTag().getString(TAG_TARGET_NAME);
}
public static void setTargetName(ItemStack stack, String targetName) {
if (!isTotem(stack)) { return; }
stack.getOrCreateTag().putString(TAG_TARGET_NAME, targetName);
}
public static int getTargetCost(ItemStack stack) {
if (!isTotem(stack)) { return -1; }
return !isCostDynamic(stack) ? getConfig(stack).getChargeCost() :
(int)(getTargetDeaths(stack) * getConfig(stack).getChargeCostMultiplier());
}
public static int getTargetDeaths(ItemStack stack) {
if (!isTotem(stack)) { return -1; }
return stack.getOrCreateTag().getInt(TAG_TARGET_DEATHS);
}
public static void setTargetDeaths(ItemStack stack, ServerPlayerEntity target) {
if (!isTotem(stack)) { return; }
stack.getOrCreateTag().putInt(TAG_TARGET_DEATHS, target.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS)));
}
public static boolean isTotemFull(ItemStack stack) {
if (!isTotem(stack)) { return false; }
return getCharge(stack) == getMaxCharge(stack);
}
public static boolean canTotemAffordTarget(ItemStack stack) {
if (!isTotem(stack)) { return false; }
if (getCharge(stack) < getTargetCost(stack)) {
if (!isTotemFull(stack)) {
return false;
}
return isTotemFull(stack) && canReviveMoreExpensiveTargets(stack);
}
return true;
}
public static int getCharge(ItemStack stack) {
if (!isTotem(stack)) { return -1; }
int charge = stack.getOrCreateTag().getInt(TAG_CHARGE);
int maxCharge = getMaxCharge(stack);
if (charge > maxCharge) {
charge = maxCharge;
setCharge(stack, charge);
}
return charge;
}
public static void setCharge(ItemStack stack, int charge) {
if (!isTotem(stack)) { return; }
stack.getOrCreateTag().putInt(TAG_CHARGE, charge);
}
public static int getMaxCharge(ItemStack stack) {
Config.TotemConfig config = getConfig(stack);
if (config == null) { return -1; }
if (config.getChargeCost() == -1) {
return config.getChargeCostLimit();
}
return config.getChargeCost();
}
public static boolean isCostDynamic(ItemStack stack) {
if (!isTotem(stack)) { return false; }
return getConfig(stack).getChargeCost() == -1;
}
public static boolean canReviveAcrossDimensions(ItemStack stack) {
if (!isTotem(stack)) { return false; }
return getConfig(stack).getCanReviveAcrossDimensions();
}
public static boolean canReviveMoreExpensiveTargets(ItemStack stack) {
if (!isTotem(stack)) { return false; }
return getConfig(stack).getCanReviveMoreExpensiveTargets();
}
public static boolean isEnabled(ItemStack stack) {
if (!isTotem(stack)) { return false; }
return getConfig(stack).getIsEnabled();
}
@Override
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public void appendHoverText(ItemStack stack, @Nullable World world, List<ITextComponent> tooltip, ITooltipFlag tooltipFlag) {
if (world == null) { return; }
UUID targetUUID = getTargetUUID(stack);
String targetName = getTargetName(stack);
int targetCost = getTargetCost(stack);
int charge = getCharge(stack);
int maxCharge = getMaxCharge(stack);
double multiplier = getConfig(stack).getChargeCostMultiplier();
if (getConfig(stack).getIsEnabled()) {
if (targetUUID == null) {
tooltip.add(new StringTextComponent(TextFormatting.RED + "Target: " + TextFormatting.DARK_RED + "NONE"));
} else {
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Target: " + TextFormatting.GRAY + targetName));
}
tooltip.add(new StringTextComponent(""));
if (!canTotemAffordTarget(stack)) {
tooltip.add(new StringTextComponent(TextFormatting.RED + "Charges: " + TextFormatting.DARK_RED + "(" + charge + "/" + targetCost + ") " +
TextFormatting.RED + "[Max: " + TextFormatting.DARK_RED + maxCharge + TextFormatting.RED + "] [Multi: " + TextFormatting.DARK_RED + multiplier + TextFormatting.RED + "]"));
} else {
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Charges: " + TextFormatting.GRAY + "(" + charge + "/" + targetCost + ") " +
TextFormatting.WHITE + "[Max: " + TextFormatting.GRAY + maxCharge + TextFormatting.WHITE + "] [Multi: " + TextFormatting.GRAY + multiplier + TextFormatting.WHITE + "]"));
}
if (canReviveMoreExpensiveTargets(stack)) {
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Can revive more expensive targets."));
}
if (canReviveAcrossDimensions(stack)) {
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Can revive targets across dimensions."));
}
tooltip.add(new StringTextComponent(""));
if (InputMappings.isKeyDown(Minecraft.getInstance().getWindow().getWindow(), GLFW.GLFW_KEY_LEFT_SHIFT)) {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Showing advanced tooltip."));
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "[" + TextFormatting.GRAY + "R-CLICK" + TextFormatting.WHITE + "]"));
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "When second hand is empty: revive target."));
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "When second hand is holding a reviving charge: charge totem."));
tooltip.add(new StringTextComponent(""));
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "[" + TextFormatting.GRAY + "L-SHIFT + R-CLICK" + TextFormatting.WHITE + "]"));
tooltip.add(new StringTextComponent(TextFormatting.WHITE + "Change target."));
} else {
tooltip.add(new StringTextComponent(TextFormatting.GRAY + "Hold [" + TextFormatting.DARK_GRAY + "L-SHIFT" + TextFormatting.GRAY + "] for advanced tooltip."));
}
} else {
tooltip.add(new StringTextComponent(TextFormatting.RED + "Totem is disabled!"));
}
super.appendHoverText(stack, world, tooltip, tooltipFlag);
}
@Override
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public ActionResult<ItemStack> use(World world, PlayerEntity player, Hand hand) {
if (!getConfig(player.getItemInHand(hand)).getIsEnabled() || !world.isClientSide) {
return super.use(world, player, hand);
}
ItemStack chargeItem = (hand.equals(Hand.MAIN_HAND)) ? player.getOffhandItem() : player.getMainHandItem();
if (player.isCrouching()) {
Network.channel.sendToServer(new ChangeTargetPacket(hand));
} else {
if (isCharge(chargeItem)) {
Network.channel.sendToServer(new ChargeTotemPacket(hand));
} else {
Network.channel.sendToServer(new ReviveTargetPacket(hand));
}
}
return super.use(world, player, hand);
}
@Override
public int getMaxDamage(ItemStack stack) {
return getConfig(stack).getDurability();
}
@Override
public boolean isDamageable(ItemStack stack) {
return (getConfig(stack).getDurability() != 0);
}
@Override
public int getDamage(ItemStack stack) {
if (isDamageable(stack) && super.getDamage(stack) >= getMaxDamage(stack)) {
stack.setCount(0);
return getMaxDamage(stack);
}
return (isDamageable(stack)) ? super.getDamage(stack) : 0;
}
private static boolean isTotem(ItemStack stack) {
return (stack.getItem() instanceof TotemItem);
}
private static Config.TotemConfig getConfig(ItemStack stack) {
Item item = stack.getItem();
if (item instanceof StrawTotemItem) { return Config.Server.getStrawTotemConfig(); }
if (item instanceof IronTotemItem) { return Config.Server.getIronTotemConfig(); }
if (item instanceof DiamondTotemItem) { return Config.Server.getDiamondTotemConfig(); }
if (item instanceof NetheriteTotemItem) { return Config.Server.getNetheriteTotemConfig(); }
return null;
}
}

View File

@ -0,0 +1,55 @@
package dev.micle.totemofreviving.network;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.item.totem.TotemItem;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.server.management.PlayerList;
import net.minecraft.util.Hand;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
public class ChangeTargetPacket {
private final Hand hand;
public ChangeTargetPacket(final Hand hand) {
this.hand = hand;
}
public static void encode(final ChangeTargetPacket packet, final PacketBuffer buffer) {
Network.writeVersionInfo(buffer, false);
buffer.writeEnum(packet.hand);
}
public static ChangeTargetPacket decode(final PacketBuffer buffer) {
Network.checkVersion(buffer);
return new ChangeTargetPacket(buffer.readEnum(Hand.class));
}
public static void handle(final ChangeTargetPacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
final NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
ServerPlayerEntity sender = context.getSender();
if (sender == null) { return; }
ItemStack totemStack = sender.getItemInHand(packet.hand);
PlayerList playerList = TotemOfReviving.PROXY.getServer().getPlayerList();
int targetIndex = TotemItem.getTargetIndex(totemStack) + 1;
if (targetIndex > playerList.getPlayerCount()-1) { targetIndex = 0; }
ServerPlayerEntity target = playerList.getPlayers().get(targetIndex);
TotemItem.setTargetIndex(totemStack, targetIndex);
TotemItem.setTargetUUID(totemStack, target.getUUID());
TotemItem.setTargetName(totemStack, target.getDisplayName().getString());
TotemItem.setTargetDeaths(totemStack, target);
sender.sendMessage(new StringTextComponent(TextFormatting.WHITE + "Now targetting " + TextFormatting.GRAY + target.getDisplayName().getString() + "."), sender.getUUID());
});
context.setPacketHandled(true);
}
}

View File

@ -0,0 +1,45 @@
package dev.micle.totemofreviving.network;
import dev.micle.totemofreviving.item.totem.TotemItem;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Hand;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
public class ChargeTotemPacket {
private final Hand hand;
public ChargeTotemPacket(final Hand hand) {
this.hand = hand;
}
public static void encode(final ChargeTotemPacket packet, final PacketBuffer buffer) {
Network.writeVersionInfo(buffer, false);
buffer.writeEnum(packet.hand);
}
public static ChargeTotemPacket decode(final PacketBuffer buffer) {
Network.checkVersion(buffer);
return new ChargeTotemPacket(buffer.readEnum(Hand.class));
}
public static void handle(final ChargeTotemPacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
final NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
ServerPlayerEntity sender = context.getSender();
if (sender == null) { return; }
ItemStack totemStack = (packet.hand.equals(Hand.MAIN_HAND)) ? sender.getMainHandItem() : sender.getOffhandItem();
ItemStack chargeStack = (packet.hand.equals(Hand.MAIN_HAND)) ? sender.getOffhandItem() : sender.getMainHandItem();
if (TotemItem.isTotemFull(totemStack)) { return; }
TotemItem.setCharge(totemStack, TotemItem.getCharge(totemStack) + 1);
chargeStack.setCount(chargeStack.getCount() - 1);
});
context.setPacketHandled(true);
}
}

View File

@ -0,0 +1,83 @@
package dev.micle.totemofreviving.network;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.util.MismatchedVersionException;
import net.minecraft.network.PacketBuffer;
import net.minecraftforge.fml.network.NetworkRegistry;
import net.minecraftforge.fml.network.simple.SimpleChannel;
import java.util.Objects;
import java.util.regex.Pattern;
public class Network {
public static final String VERSION = TotemOfReviving.MOD_ID + "-net-1";
private static final Pattern NET_VERSION_PATTERN = Pattern.compile(TotemOfReviving.MOD_ID + "-net-\\d+$");
private static final Pattern MOD_VERSION_PATTERN = Pattern.compile("Forge-\\d+\\.\\d+\\.\\d+-\\d+\\.\\d+\\.\\d+$");
public static SimpleChannel channel;
public static void init() {
channel = NetworkRegistry.ChannelBuilder.named(TotemOfReviving.createResourceLocation("network"))
.clientAcceptedVersions(s -> Objects.equals(s, VERSION))
.serverAcceptedVersions(s -> Objects.equals(s, VERSION))
.networkProtocolVersion(() -> VERSION)
.simpleChannel();
int id = 0;
channel.messageBuilder(ChangeTargetPacket.class, id++)
.encoder(ChangeTargetPacket::encode)
.decoder(ChangeTargetPacket::decode)
.consumer(ChangeTargetPacket::handle)
.add();
channel.messageBuilder(ChargeTotemPacket.class, id++)
.encoder(ChargeTotemPacket::encode)
.decoder(ChargeTotemPacket::decode)
.consumer(ChargeTotemPacket::handle)
.add();
channel.messageBuilder(ReviveTargetPacket.class, id++)
.encoder(ReviveTargetPacket::encode)
.decoder(ReviveTargetPacket::decode)
.consumer(ReviveTargetPacket::handle)
.add();
}
public static void writeVersionInfo(PacketBuffer buffer, boolean senderIsServer) {
buffer.writeBoolean(senderIsServer);
buffer.writeUtf(VERSION);
buffer.writeUtf(TotemOfReviving.getVersion());
}
public static void checkVersion(PacketBuffer buffer) {
boolean senderIsServer = buffer.readBoolean();
String serverNetVersion = (senderIsServer) ? readNetVersion(buffer) : VERSION;
String serverModVersion = (senderIsServer) ? readModVersion(buffer) : TotemOfReviving.getVersion();
String clientNetVersion = (senderIsServer) ? VERSION : readNetVersion(buffer);
String clientModVersion = (senderIsServer) ? TotemOfReviving.getVersion() : readModVersion(buffer);
if (!serverNetVersion.equals(clientNetVersion)) {
throw new MismatchedVersionException(
String.format("The server and client are running different versions of [Micle's Totem of Reviving]. " +
"Try updating this mod on either the client and or the server. " +
"Client version is %s (%s). Server version is %s (%s)",
clientModVersion, clientNetVersion,
serverModVersion, serverNetVersion)
);
}
}
public static String readNetVersion(PacketBuffer buffer) {
String netVersion = buffer.readUtf();
if (!NET_VERSION_PATTERN.matcher(netVersion).matches()) {
return "UNKNOWN (" + netVersion + ")";
}
return netVersion;
}
public static String readModVersion(PacketBuffer buffer) {
String modVersion = buffer.readUtf();
if (!modVersion.equals("NONE") && !MOD_VERSION_PATTERN.matcher(modVersion).matches()) {
return "UNKNOWN (" + modVersion + ")";
}
return modVersion;
}
}

View File

@ -0,0 +1,73 @@
package dev.micle.totemofreviving.network;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.item.totem.TotemItem;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.Hand;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextFormatting;
import net.minecraftforge.fml.network.NetworkEvent;
import java.util.function.Supplier;
public class ReviveTargetPacket {
private final Hand hand;
public ReviveTargetPacket(final Hand hand) {
this.hand = hand;
}
public static void encode(final ReviveTargetPacket packet, final PacketBuffer buffer) {
Network.writeVersionInfo(buffer, false);
buffer.writeEnum(packet.hand);
}
public static ReviveTargetPacket decode(final PacketBuffer buffer) {
Network.checkVersion(buffer);
return new ReviveTargetPacket(buffer.readEnum(Hand.class));
}
public static void handle(final ReviveTargetPacket packet, final Supplier<NetworkEvent.Context> contextSupplier) {
final NetworkEvent.Context context = contextSupplier.get();
context.enqueueWork(() -> {
ServerPlayerEntity sender = context.getSender();
if (sender == null) { return; }
ItemStack totemStack = sender.getItemInHand(packet.hand);
ServerPlayerEntity target;
try {
target = TotemOfReviving.PROXY.getServer().getPlayerList().getPlayer(TotemItem.getTargetUUID(totemStack));
if (target == null) { throw new NullPointerException("Target is null!"); }
} catch (NullPointerException exception) {
sender.sendMessage(new StringTextComponent(TextFormatting.WHITE + "Unable to find player!"), sender.getUUID());
return;
}
if (!target.isSpectator()) {
sender.sendMessage(new StringTextComponent(TextFormatting.GRAY + target.getDisplayName().getString() + TextFormatting.WHITE + " is not dead!"), sender.getUUID());
return;
}
if (!target.getLevel().equals(sender.getLevel()) && !TotemItem.canReviveAcrossDimensions(totemStack)) {
sender.sendMessage(new StringTextComponent(TextFormatting.GRAY + target.getDisplayName().getString() + TextFormatting.WHITE + " is in a different dimension!"), sender.getUUID());
return;
}
TotemItem.setTargetDeaths(totemStack, target);
if (!TotemItem.canTotemAffordTarget(totemStack)) {
sender.sendMessage(new StringTextComponent(TextFormatting.WHITE + "Not enough charge!"), sender.getUUID());
return;
}
target.teleportTo(sender.getLevel(), sender.position().x, sender.position().y, sender.position().z, sender.yRot, sender.xRot);
target.setGameMode(sender.getLevel().getServer().getDefaultGameType());
TotemItem.setCharge(totemStack, TotemItem.getCharge(totemStack) - TotemItem.getTargetCost(totemStack));
totemStack.hurtAndBreak(1, sender, e -> e.broadcastBreakEvent(packet.hand));
sender.sendMessage(new StringTextComponent(TextFormatting.WHITE + "Successfully revived " + TextFormatting.GRAY + target.getDisplayName().getString() + "!"), sender.getUUID());
});
context.setPacketHandled(true);
}
}

View File

@ -0,0 +1,26 @@
package dev.micle.totemofreviving.setup;
import dev.micle.totemofreviving.item.charge.DiamondChargeItem;
import dev.micle.totemofreviving.item.charge.IronChargeItem;
import dev.micle.totemofreviving.item.charge.NetheriteChargeItem;
import dev.micle.totemofreviving.item.charge.StrawChargeItem;
import dev.micle.totemofreviving.item.totem.DiamondTotemItem;
import dev.micle.totemofreviving.item.totem.IronTotemItem;
import dev.micle.totemofreviving.item.totem.NetheriteTotemItem;
import dev.micle.totemofreviving.item.totem.StrawTotemItem;
import net.minecraft.item.Item;
import net.minecraftforge.fml.RegistryObject;
public class ModItems {
public static RegistryObject<Item> STRAW_TOTEM = Registration.ITEMS.register(StrawTotemItem.getName(), StrawTotemItem::new);
public static RegistryObject<Item> IRON_TOTEM = Registration.ITEMS.register(IronTotemItem.getName(), IronTotemItem::new);
public static RegistryObject<Item> DIAMOND_TOTEM = Registration.ITEMS.register(DiamondTotemItem.getName(), DiamondTotemItem::new);
public static RegistryObject<Item> NETHERITE_TOTEM = Registration.ITEMS.register(NetheriteTotemItem.getName(), NetheriteTotemItem::new);
public static RegistryObject<Item> STRAW_CHARGE = Registration.ITEMS.register(StrawChargeItem.getName(), StrawChargeItem::new);
public static RegistryObject<Item> IRON_CHARGE = Registration.ITEMS.register(IronChargeItem.getName(), IronChargeItem::new);
public static RegistryObject<Item> DIAMOND_CHARGE = Registration.ITEMS.register(DiamondChargeItem.getName(), DiamondChargeItem::new);
public static RegistryObject<Item> NETHERITE_CHARGE = Registration.ITEMS.register(NetheriteChargeItem.getName(), NetheriteChargeItem::new);
public static void register() {}
}

View File

@ -0,0 +1,16 @@
package dev.micle.totemofreviving.setup;
import dev.micle.totemofreviving.item.crafting.ChargeRecipe;
import dev.micle.totemofreviving.item.crafting.ExtendedShapedRecipe;
import dev.micle.totemofreviving.item.crafting.TotemRecipe;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraftforge.fml.RegistryObject;
public class ModRecipes {
public static final RegistryObject<IRecipeSerializer<?>> TOTEM_RECIPE =
Registration.RECIPE_SERIALIZERS.register("totem_recipe", () -> ExtendedShapedRecipe.Serializer.basic(TotemRecipe::new));
public static final RegistryObject<IRecipeSerializer<?>> CHARGE_RECIPE =
Registration.RECIPE_SERIALIZERS.register("charge_recipe", () -> ExtendedShapedRecipe.Serializer.basic(ChargeRecipe::new));
public static void register() {}
}

View File

@ -0,0 +1,30 @@
package dev.micle.totemofreviving.setup;
import dev.micle.totemofreviving.TotemOfReviving;
import net.minecraft.item.Item;
import net.minecraft.item.crafting.IRecipeSerializer;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
public class Registration {
public static final DeferredRegister<Item> ITEMS = create(ForgeRegistries.ITEMS);
public static final DeferredRegister<IRecipeSerializer<?>> RECIPE_SERIALIZERS = create(ForgeRegistries.RECIPE_SERIALIZERS);
public static void register() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
ITEMS.register(modEventBus);
ModItems.register();
RECIPE_SERIALIZERS.register(modEventBus);
ModRecipes.register();
}
private static <T extends IForgeRegistryEntry<T>> DeferredRegister<T> create(IForgeRegistry<T> registry) {
return DeferredRegister.create(registry, TotemOfReviving.MOD_ID);
}
}

View File

@ -0,0 +1,7 @@
package dev.micle.totemofreviving.util;
public class MismatchedVersionException extends RuntimeException {
public MismatchedVersionException(String msg) {
super(msg);
}
}

View File

@ -1,6 +1,11 @@
{
"item.totemofreviving.totem_of_reviving": "Totem of Reviving",
"item.totemofreviving.reviving_charge": "Reviving charge",
"item.totemofreviving.straw_totem": "Straw Totem of Reviving",
"item.totemofreviving.straw_charge": "Straw reviving charge"
"itemGroup.totemofreviving": "Micle's Totem of Reviving",
"item.totemofreviving.straw_totem": "Straw totem of reviving",
"item.totemofreviving.iron_totem": "Iron totem of reviving",
"item.totemofreviving.diamond_totem": "Diamond totem of reviving",
"item.totemofreviving.netherite_totem": "Netherite totem of reviving",
"item.totemofreviving.straw_charge": "Straw reviving charge",
"item.totemofreviving.iron_charge": "Iron reviving charge",
"item.totemofreviving.diamond_charge": "Diamond reviving charge",
"item.totemofreviving.netherite_charge": "Netherite reviving charge"
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 721 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B