Compare commits

...

76 Commits

Author SHA1 Message Date
c2a88e33c3 Merge pull request 'Release 1.21.1-v3.0.0' (#8) from 1.21.1/dev into 1.21.1/main
Reviewed-on: #8
2026-01-18 02:01:30 +00:00
067ac953ec Merge pull request '1.21.1/feat/6-update' (#7) from 1.21.1/feat/6-update into 1.21.1/dev
Reviewed-on: #7
2026-01-18 01:59:33 +00:00
9f797a9112 Adjusted default config value. 2026-01-18 02:52:54 +01:00
05192b2601 Fixed charge going below 0 when reviving more expensive targets with dynamic cost. Fixing tooltip cost appearing in red when the target's cost is more than the max charge capacity but the totem can revive more expensive targets. 2026-01-18 02:48:22 +01:00
c21ba74432 Using config for getting totem max durability for tooltip. 2026-01-18 02:36:43 +01:00
ed3dcc3d1e Checking config for unbreakable status to make tooltips more accurate in menus such as the creative menu. 2026-01-18 02:21:02 +01:00
07184045e4 Rebalanced default configs. Displaying static cost in tooltip. 2026-01-18 02:18:15 +01:00
6bb74b3635 Updated totem tooltip to display N/A for cost when the target is also N/A. 2026-01-18 00:52:36 +01:00
8b296c6750 Changed diamond totem default config to allow reviving across dimensions. 2026-01-18 00:49:04 +01:00
85b67a1a8d Switched rarities of Iron and Straw totems to be consistent in regard to progression. 2026-01-18 00:46:24 +01:00
8dbeb36d13 Updated item constructors to simplify usage. 2026-01-18 00:41:24 +01:00
ef50e0084c Updated totem tooltip to display general durability information. 2026-01-18 00:35:15 +01:00
27634a9bdf Updated config comments. 2026-01-18 00:18:48 +01:00
7afc1956bb Reworked durability configs to be dynamically set during inventory tick update whenever a config change is detected. Added unbreakable text to totem tooltip. Fixed server world crashing when reviving player due to closing level (try-with-resources). 2026-01-18 00:00:36 +01:00
5a9fd203d3 Bumped version number. 2026-01-14 02:23:06 +01:00
b4d6a9dba1 Ensuring target costs at least 1 charge when using dynamic cost. 2026-01-14 01:52:09 +01:00
9afca9c3b9 Extracted general methods from LangAsset into ComponentHelper class. 2026-01-14 01:07:20 +01:00
b0c5e9ba3d Converted charge item tooltip to use lang file. Improved tooltip to display corresponding totem's name. 2026-01-14 01:04:50 +01:00
859775d7b5 Inverted colors to improve readability of messages. 2026-01-14 00:44:46 +01:00
984f5ca8d6 Improved look of tooltips. Changed colors to improve readability. Implemented helper method for adding indent to components. 2026-01-14 00:43:46 +01:00
11e6aee70e Reworked tooltip for totems to look better and be translatable via lang files. Implemented helper method for creating text components displaying keybind keys. 2026-01-14 00:10:47 +01:00
8bc56f76de Removed hard coded lang string reference. 2026-01-12 22:20:55 +01:00
684cb23f74 Ported cycle totem message to lang file. 2026-01-12 22:19:00 +01:00
24d21126b0 Implemented LangAsset enum to declare translatable keys for strings. Moved message strings for reviving functionality into lang file. 2026-01-12 22:15:41 +01:00
925f244cc0 Removed old networking code. 2026-01-12 04:37:21 +01:00
dbabba477a CycleTarget method now returns message component. Implemented totem functionality without any extra networking. 2026-01-12 04:36:44 +01:00
5b2771c1f7 Fixed advanced tooltip key press check. Removed old broken mod key mappings. 2026-01-12 03:57:26 +01:00
b03aa3e0ed Fixed totem data not saving or synchronizing on a dedicated server. 2026-01-12 03:40:41 +01:00
4bb8e9dca0 Removed the need for template files. Replaced logo file with png as jpg seems to not work with NeoForge. 2026-01-12 01:22:46 +01:00
06ef028b6c Updated mods.toml. 2026-01-11 01:19:49 +01:00
6eabe7b3c5 Updated gitignore. Updated mod id across project. Fixed gradle not replacing properties in mods.toml. 2026-01-11 01:18:18 +01:00
8abbf5384e WIP: Temporarily disabling old networking code. 2026-01-11 00:40:15 +01:00
1c45352037 Ported charge items. Implemented property helper. Made netherite charges fire-resistant. 2026-01-11 00:25:55 +01:00
935ccd14bb Implemented new methods for each totem item. Implemented helper for generating item properties, now also adding totem data to the item. 2026-01-11 00:20:54 +01:00
0f35787a53 WIP use method. Fixed remaining methods. 2026-01-11 00:00:30 +01:00
4c6d9b4b14 Ported totem tooltip. Implemented helpers for getting target UUID from totem data. 2026-01-10 19:51:56 +01:00
af097ffdf5 Extracted code into method. 2026-01-10 19:27:17 +01:00
300e0a940a Rewrote TotemItem methods to simplify usage and keep functionality within the same class. 2026-01-10 19:24:37 +01:00
b400f4334a WIP: Logic cleanup. 2026-01-09 07:05:33 +01:00
39f8544e08 WIP: Converting methods to utilize Optionals. 2026-01-09 05:55:38 +01:00
f41bead3d2 Included charge in totem data. 2026-01-09 05:40:01 +01:00
56f274a81b WIP: Included target deaths in data component. 2026-01-09 05:26:42 +01:00
91f3f9dbdd WIP: Included target name in data component. 2026-01-09 05:20:04 +01:00
7421a5a18d WIP: Included target UUID in data component. 2026-01-09 05:14:49 +01:00
f6e47d78e1 WIP: Creating DataComponent for totem items. 2026-01-09 05:01:09 +01:00
2f1a9793a3 Ported datagens. 2026-01-09 01:01:53 +01:00
2bfe6b72e5 Ported registers. 2026-01-09 00:45:40 +01:00
e8b0b1987b Removed old metadata. 2026-01-09 00:38:33 +01:00
2262cc5952 Ported config. 2026-01-09 00:37:25 +01:00
9a0415effd Ported remainder of main class. 2026-01-09 00:08:13 +01:00
681ebeeeb7 Ported side proxy. 2026-01-09 00:02:21 +01:00
aff7f9ae54 Ported gradle and metadata to NeoForge. 2026-01-08 23:36:45 +01:00
407e26a179 Updated gradle and metadata. 2026-01-08 22:17:34 +01:00
f79326266a Merge pull request 'feat/4-update_assets_again' (#5) from feat/4-update_assets_again into 1.20
Reviewed-on: #5
2025-06-19 01:34:10 +00:00
2c4cc90940 Updated mod icon file. 2025-06-19 02:33:09 +01:00
33c1b2491e Updated web assets. 2025-06-19 02:32:00 +01:00
1b1f758639 Rendered new images. 2025-06-19 02:31:54 +01:00
e2fa33fa5f Updated blender project. 2025-06-19 02:31:42 +01:00
d63e4bf8b4 Updated ignores. 2025-06-19 01:57:19 +01:00
500c25a00e Added guidelines. 2025-06-19 01:57:09 +01:00
b0ce5e588a Merge pull request 'Added drop shadow to icon.' (#3) from feat/1-update_assets into 1.20
Reviewed-on: #3
2025-06-18 04:12:33 +00:00
5e21576347 Added drop shadow to icon. 2025-06-18 04:12:33 +00:00
20719b6d42 Merge pull request 'feat/1-update_assets' (#2) from feat/1-update_assets into 1.20
Reviewed-on: #2
2025-06-17 01:26:23 +00:00
0aa1243942 Oopsie. 2025-06-17 02:25:46 +01:00
fc14404b18 Updated mod logo file. 2025-06-17 02:25:04 +01:00
9995ed6965 Created web assets. 2025-06-17 02:16:50 +01:00
a4aab10b44 Added blender world model files. 2025-06-17 02:16:38 +01:00
6f52afcd13 Rendered images. 2025-06-17 02:16:14 +01:00
cefcf02415 Setup blender project. 2025-06-17 02:15:20 +01:00
1eedce3667 Updated item models to have correct up and forward directions. 2025-06-17 01:11:30 +01:00
b856b42500 Added all item models and textures. 2025-06-16 21:38:34 +01:00
af394094b7 Updated ignore and added attributes files. 2025-06-16 21:34:28 +01:00
3485db8f2d Changed build version number to v2.0.0. 2024-01-27 17:36:40 +00:00
3c5425d0c4 Finished porting to 1.20.1. 2024-01-26 21:23:09 +00:00
60f5d27640 Creative mode tabs:
- Changed translation key for creative mode tab name to follow vanilla.
- Removed old creative mode tab register event handler.
- Created new creative mode tab registration setup.
- Optimized imports.
2024-01-26 21:10:17 +00:00
fb7304ccc4 Changed versions. 2024-01-26 20:50:10 +00:00
129 changed files with 1897 additions and 1255 deletions

4
.gitattributes vendored
View File

@ -1,8 +1,8 @@
*.blend filter=lfs diff=lfs merge=lfs -text *.blend filter=lfs diff=lfs merge=lfs -text
*.obj filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text *.png filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text *.jpg filter=lfs diff=lfs merge=lfs -text
*.kra filter=lfs diff=lfs merge=lfs -text *.obj filter=lfs diff=lfs merge=lfs -text
*.mtl filter=lfs diff=lfs merge=lfs -text *.mtl filter=lfs diff=lfs merge=lfs -text
*.bbmodel filter=lfs diff=lfs merge=lfs -text *.bbmodel filter=lfs diff=lfs merge=lfs -text
*.kra filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text *.ogg filter=lfs diff=lfs merge=lfs -text

230
.gitignore vendored
View File

@ -1,6 +1,224 @@
/.gradle/ ### Assets
/.idea/ *.blend?
/build/ *~
/run/
/src/test/ ### Minecraft
/src/generated/resources/.cache/ /src/generated/resources/.cache/*
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea/*
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### ForgeGradle template
# Minecraft client/server files
run/
### Java template
# Compiled class file
*.class
# Log file
*.log
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
replay_pid*
### JetBrains template
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# AWS User-specific
.idea/**/aws.xml
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# SonarLint plugin
.idea/sonarlint/
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### ForgeGradle template
# Minecraft client/server files
run/
### Gradle template
.gradle
**/build/
!src/**/build/
# Ignore Gradle GUI config
gradle-app.setting
# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored)
!gradle-wrapper.jar
# Avoid ignore Gradle wrappper properties
!gradle-wrapper.properties
# Cache of project
.gradletasknamecache
# Eclipse Gradle plugin generated files
# Eclipse Core
.project
# JDT-specific (Eclipse Java Development Tools)
.classpath

61
assets/images/README.md Normal file
View File

@ -0,0 +1,61 @@
# Composition guidelines
The following are guidelines for rendering image assets.
## General
### Color Management
- Filmic - Medium High Contrast
### World
- Global Illumination - 1.0
### Sun
- Strength - 5.0
### Volume
- Fournier-Forand
- IOR 1.0
- Density 0.01
## Icon
400 x 400 RGBA PNG
### Item
- Camera position should be x=0.0, Y=1.0, Z=0.0.
- Camera angle should be X=90, Y=0, Z=180.
- Camera perspective @ focal length 30mm.
- Camera DOF @ item.
### Block
- Camera position should be X=0.5, Y=1.0, Z=0.5.
- Camera angle should be X=90, Y=0, Z=150.
- Camera should have a damped track to block.
- Camera should have a rotation limit on the y axis.
- Camera no DOF.
- Camera orthographic @ scale 2.0.
## Banner
1200 x 400 RGB PNG
- Camera perspective @ focal length 50mm (1x).
- Camera DOF @ focus distance 5m (1x).
- Gap between icon and text should be 1 grid.
- Text is Minecraft font, size 72.
- Text has 4px stroke.
- Icon has default drop shadow.
## Logo
400 x 400 RGB PNG
- Camera perspective @ focal length 150mm (3x).
- Camera DOF @ focus distance 15m (3x).
## Card
200 x 300 RGB PNG
- Camera perspective @ focal length 150mm (3x).
- Camera DOF @ focus distance 15m (3x).
- Icon should be scaled down to half.
- Gap between icon and text should be 1 grid.
- Text is Minecraft font, size 26.
- Text has 2px stroke.
- Icon has default drop shadow.

BIN
assets/images/blender/totem_of_reviving.blend (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/blender/world-Alpha.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/blender/world-RGB.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/blender/world-RGBA.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/blender/world.mtl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/blender/world.obj (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/banner-vignette.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/banner.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/card-vignette.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/card.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/icon.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/logo-vignette.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/renders/logo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/banner.jpg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/banner.kra (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/card.jpg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/card.kra (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/logo.jpg (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/logo.kra (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/images/web/logo.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/diamond_totem/diamond-totem.bbmodel (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/diamond_totem/diamond-totem.mtl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/diamond_totem/diamond-totem.obj (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/diamond_totem/diamond_totem.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/iron_totem/iron-totem.bbmodel (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/iron_totem/iron-totem.mtl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/iron_totem/iron-totem.obj (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/iron_totem/iron_totem.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/netherite_totem/netherite-totem.bbmodel (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/netherite_totem/netherite-totem.mtl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/netherite_totem/netherite-totem.obj (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/netherite_totem/netherite_totem.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/straw_totem/straw-totem.bbmodel (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/straw_totem/straw-totem.mtl (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/straw_totem/straw-totem.obj (Stored with Git LFS) Normal file

Binary file not shown.

BIN
assets/items/straw_totem/straw_totem.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@ -1,112 +1,191 @@
buildscript { plugins {
id 'java-library'
id 'maven-publish'
id 'net.neoforged.moddev' version '2.0.137'
id 'idea'
}
tasks.named('wrapper', Wrapper).configure {
// Define wrapper values here so as to not have to always do so when updating gradlew.properties.
// Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with
// documentation attached on cursor hover of gradle classes and methods. However, this comes with increased
// file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards.
// (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`)
distributionType = Wrapper.DistributionType.BIN
}
group = mod_group_id
version = mod_version
repositories { repositories {
// These repositories are only for Gradle plugins, put any other repositories in the repository block further below // Add here additional repositories if required by some of the dependencies below.
maven { url = 'https://maven.minecraftforge.net' }
mavenCentral()
}
dependencies {
classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true
}
} }
apply plugin: 'net.minecraftforge.gradle' base {
archivesName = "${mod_id}-${minecraft_version}"
}
def archiveVersion = "${project.mcVersion}-${project.buildVersion}" as Object java {
toolchain.languageVersion = JavaLanguageVersion.of(21)
}
java.toolchain.languageVersion = JavaLanguageVersion.of(17) neoForge {
// Specify the version of NeoForge to use.
version = project.neo_version
minecraft { parchment {
mappings channel: 'official', version: mcVersion mappingsVersion = project.parchment_mappings_version
minecraftVersion = project.parchment_minecraft_version
}
accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // This line is optional. Access Transformers are automatically detected
// accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg')
// Default run configurations.
// These can be tweaked, removed, or duplicated as needed.
runs { runs {
client { client {
workingDirectory project.file('run') client()
property 'forge.logging.markers', 'REGISTRIES' // Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.logging.console.level', 'debug' systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
mods {
totemofreviving {
source sourceSets.main
}
}
} }
server { server {
workingDirectory project.file('run') server()
programArgument '--nogui'
property 'forge.logging.markers', 'REGISTRIES' systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
property 'forge.logging.console.level', 'debug'
mods {
totemofreviving {
source sourceSets.main
}
} }
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
type = "gameTestServer"
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
} }
data { data {
workingDirectory project.file('run') data()
property 'forge.logging.markers', 'REGISTRIES' // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
property 'forge.logging.console.level', 'debug' // gameDirectory = project.file('run-data')
args '--mod', 'totemofreviving', '--all', // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
'--existing', file('src/main/resources').toString(), programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
'--existing', file('src/generated/resources').toString(), }
'--output', file('src/generated/resources/')
// applies to all the run configs above
configureEach {
// Recommended logging data for a userdev environment
// The markers can be added/remove as needed separated by commas.
// "SCAN": For mods scan.
// "REGISTRIES": For firing of registry events.
// "REGISTRYDUMP": For getting the contents of all registries.
systemProperty '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
logLevel = org.slf4j.event.Level.DEBUG
}
}
mods { mods {
totemofreviving { // define mod <-> source bindings
source sourceSets.main // these are used to tell the game which sources are for which mod
} // multi mod projects should define one per mod
} "${mod_id}" {
sourceSet(sourceSets.main)
} }
} }
} }
// Include resources generated by data generators.
sourceSets.main.resources { sourceSets.main.resources {
srcDir 'src/generated/resources' srcDir 'src/generated/resources'
} }
repositories { // Sets up a dependency configuration called 'localRuntime'.
maven { // This configuration should be used instead of 'runtimeOnly' to declare
name = "Progwml6 maven" // a dependency that will be present for runtime testing but that is
url = "https://dvs1.progwml6.com/files/maven/" // "optional", meaning it will not be pulled by dependents of this mod.
} configurations {
maven { runtimeClasspath.extendsFrom localRuntime
name = "ModMaven"
url = "https://modmaven.dev"
}
} }
dependencies { dependencies {
minecraft "net.minecraftforge:forge:${project.mcVersion}-${project.forgeVersion}" // Example optional mod dependency with JEI
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
// compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}"
// We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it
// localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}"
// JEI // Example mod dependency using a mod jar from ./libs with a flat dir repository
if (project.hasProperty('jeiVersion')) { // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar
// compile against JEI API but do not include it at runtime // The group id is ignored when searching -- in this case, it is "blank"
compileOnly fg.deobf("mezz.jei:jei-${project.mcVersion}-forge-api:${project.jeiVersion}") // implementation "blank:coolmod-${mc_version}:${coolmod_version}"
// at runtime, use full JEI jar
runtimeOnly fg.deobf("mezz.jei:jei-${project.mcVersion}-forge:${project.jeiVersion}") // Example mod dependency using a file as dependency
// implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
// Example project dependency using a sister or child project:
// implementation project(":myproject")
// For more info:
// http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
// http://www.gradle.org/docs/current/userguide/dependency_management.html
}
// This block of code expands all declared replace properties in the specified resource targets.
// A missing property will result in an error. Properties are expanded using ${} Groovy notation.
// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments.
// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html
tasks.withType(ProcessResources).configureEach {
var replaceProperties = [
minecraft_version : minecraft_version,
minecraft_version_range: minecraft_version_range,
neo_version : neo_version,
neo_version_range : neo_version_range,
loader_version_range : loader_version_range,
mod_id : mod_id,
mod_name : mod_name,
mod_license : mod_license,
mod_version : mod_version,
mod_authors : mod_authors,
mod_description : mod_description
]
inputs.properties replaceProperties
filesMatching(['META-INF/neoforge.mods.toml']) {
expand replaceProperties
} }
} }
jar { // Example configuration to allow publishing using the maven-publish plugin
archiveFileName = "${project.archivesBaseName}-${archiveVersion}.jar" publishing {
manifest { publications {
attributes([ register('mavenJava', MavenPublication) {
"Specification-Title" : project.name, from components.java
"Specification-Vendor" : project.author, }
"Specification-Version" : "1", }
"Implementation-Title" : project.name, repositories {
"Implementation-Vendor" : project.author, maven {
"Implementation-Version" : archiveVersion, url "file://${project.projectDir}/repo"
"Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") }
])
} }
} }
jar.finalizedBy('reobfJar') tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
idea {
module {
downloadSources = true
downloadJavadoc = true
}
}

View File

@ -1,14 +1,23 @@
org.gradle.jvmargs=-Xmx3G org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=true
org.gradle.configuration-cache=true
group = dev.micle mod_id=totem_of_reviving
archivesBaseName = micles-totem-of-reviving-forge mod_name=Micle's Totem of Reviving
modID = totemofreviving mod_license=All Rights Reserved
name = Micle's Totem of Reviving mod_version=3.0.0
author = Micle mod_group_id=dev.micle
mod_authors=Micle
mod_description=Totems to revive your friends in hardcore.
buildVersion = 2.0.0 minecraft_version=1.21.1
mcVersion = 1.19.4 minecraft_version_range=[1.21.1,1.22)
forgeVersion = 45.2.8
#jeiVersion = 11.+ neo_version=21.1.217
neo_version_range=[21.1.217,21.2)
loader_version_range=[1,)
parchment_minecraft_version=1.21.1
parchment_mappings_version=2024.11.17

View File

@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

View File

@ -1 +1,16 @@
rootProject.name = 'TotemOfReviving-1.19' pluginManagement {
repositories {
gradlePluginPortal()
maven {
name = 'MinecraftForge'
url = 'https://maven.minecraftforge.net/'
}
maven { url = 'https://maven.parchmentmc.org' }
}
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0'
}
rootProject.name = "${mod_id}-${minecraft_version}"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -5,9 +5,7 @@
"conditions": { "conditions": {
"items": [ "items": [
{ {
"items": [ "items": "totem_of_reviving:iron_totem"
"totemofreviving:iron_totem"
]
} }
] ]
}, },
@ -15,20 +13,20 @@
}, },
"has_the_recipe": { "has_the_recipe": {
"conditions": { "conditions": {
"recipe": "totemofreviving:iron_charge" "recipe": "totem_of_reviving:iron_charge"
}, },
"trigger": "minecraft:recipe_unlocked" "trigger": "minecraft:recipe_unlocked"
} }
}, },
"requirements": [ "requirements": [
[ [
"has_item", "has_the_recipe",
"has_the_recipe" "has_item"
] ]
], ],
"rewards": { "rewards": {
"recipes": [ "recipes": [
"totemofreviving:iron_charge" "totem_of_reviving:iron_charge"
] ]
} }
} }

View File

@ -5,9 +5,7 @@
"conditions": { "conditions": {
"items": [ "items": [
{ {
"items": [ "items": "minecraft:emerald"
"minecraft:emerald"
]
} }
] ]
}, },
@ -15,20 +13,20 @@
}, },
"has_the_recipe": { "has_the_recipe": {
"conditions": { "conditions": {
"recipe": "totemofreviving:iron_totem" "recipe": "totem_of_reviving:iron_totem"
}, },
"trigger": "minecraft:recipe_unlocked" "trigger": "minecraft:recipe_unlocked"
} }
}, },
"requirements": [ "requirements": [
[ [
"has_item", "has_the_recipe",
"has_the_recipe" "has_item"
] ]
], ],
"rewards": { "rewards": {
"recipes": [ "recipes": [
"totemofreviving:iron_totem" "totem_of_reviving:iron_totem"
] ]
} }
} }

View File

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

View File

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

View File

@ -5,9 +5,7 @@
"conditions": { "conditions": {
"items": [ "items": [
{ {
"items": [ "items": "totem_of_reviving:straw_totem"
"totemofreviving:straw_totem"
]
} }
] ]
}, },
@ -15,20 +13,20 @@
}, },
"has_the_recipe": { "has_the_recipe": {
"conditions": { "conditions": {
"recipe": "totemofreviving:straw_charge" "recipe": "totem_of_reviving:straw_charge"
}, },
"trigger": "minecraft:recipe_unlocked" "trigger": "minecraft:recipe_unlocked"
} }
}, },
"requirements": [ "requirements": [
[ [
"has_item", "has_the_recipe",
"has_the_recipe" "has_item"
] ]
], ],
"rewards": { "rewards": {
"recipes": [ "recipes": [
"totemofreviving:straw_charge" "totem_of_reviving:straw_charge"
] ]
} }
} }

View File

@ -5,9 +5,7 @@
"conditions": { "conditions": {
"items": [ "items": [
{ {
"items": [ "items": "minecraft:wheat"
"minecraft:wheat"
]
} }
] ]
}, },
@ -15,20 +13,20 @@
}, },
"has_the_recipe": { "has_the_recipe": {
"conditions": { "conditions": {
"recipe": "totemofreviving:straw_totem" "recipe": "totem_of_reviving:straw_totem"
}, },
"trigger": "minecraft:recipe_unlocked" "trigger": "minecraft:recipe_unlocked"
} }
}, },
"requirements": [ "requirements": [
[ [
"has_item", "has_the_recipe",
"has_the_recipe" "has_item"
] ]
], ],
"rewards": { "rewards": {
"recipes": [ "recipes": [
"totemofreviving:straw_totem" "totem_of_reviving:straw_totem"
] ]
} }
} }

View File

@ -21,7 +21,7 @@
"IDI" "IDI"
], ],
"result": { "result": {
"item": "totemofreviving:diamond_charge" "count": 1,
}, "id": "totem_of_reviving:diamond_charge"
"show_notification": true }
} }

View File

@ -18,7 +18,7 @@
"EDE" "EDE"
], ],
"result": { "result": {
"item": "totemofreviving:diamond_totem" "count": 1,
}, "id": "totem_of_reviving:diamond_totem"
"show_notification": true }
} }

View File

@ -18,7 +18,7 @@
"NIN" "NIN"
], ],
"result": { "result": {
"item": "totemofreviving:iron_charge" "count": 1,
}, "id": "totem_of_reviving:iron_charge"
"show_notification": true }
} }

View File

@ -18,7 +18,7 @@
" I " " I "
], ],
"result": { "result": {
"item": "totemofreviving:iron_totem" "count": 1,
}, "id": "totem_of_reviving:iron_totem"
"show_notification": true }
} }

View File

@ -3,7 +3,7 @@
"category": "equipment", "category": "equipment",
"key": { "key": {
"C": { "C": {
"item": "totemofreviving:diamond_charge" "item": "totem_of_reviving:diamond_charge"
}, },
"G": { "G": {
"item": "minecraft:gold_ingot" "item": "minecraft:gold_ingot"
@ -18,7 +18,7 @@
"GNG" "GNG"
], ],
"result": { "result": {
"item": "totemofreviving:netherite_charge" "count": 1,
}, "id": "totem_of_reviving:netherite_charge"
"show_notification": true }
} }

View File

@ -12,7 +12,7 @@
"item": "minecraft:netherite_scrap" "item": "minecraft:netherite_scrap"
}, },
"T": { "T": {
"item": "totemofreviving:diamond_totem" "item": "totem_of_reviving:diamond_totem"
} }
}, },
"pattern": [ "pattern": [
@ -21,7 +21,7 @@
"BGB" "BGB"
], ],
"result": { "result": {
"item": "totemofreviving:netherite_totem" "count": 1,
}, "id": "totem_of_reviving:netherite_totem"
"show_notification": true }
} }

View File

@ -18,7 +18,7 @@
"NWN" "NWN"
], ],
"result": { "result": {
"item": "totemofreviving:straw_charge" "count": 1,
}, "id": "totem_of_reviving:straw_charge"
"show_notification": true }
} }

View File

@ -21,7 +21,7 @@
"N|N" "N|N"
], ],
"result": { "result": {
"item": "totemofreviving:straw_totem" "count": 1,
}, "id": "totem_of_reviving:straw_totem"
"show_notification": true }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,45 @@
package dev.micle.totem_of_reviving;
import dev.micle.totem_of_reviving.proxy.IProxy;
import dev.micle.totem_of_reviving.proxy.Proxy;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.loading.FMLEnvironment;
import java.util.Optional;
@Mod(TotemOfReviving.MOD_ID)
public final class TotemOfReviving {
public static final String MOD_ID = "totem_of_reviving";
private static IProxy proxy;
public TotemOfReviving(IEventBus modEventBus, ModContainer modContainer) {
proxy = FMLEnvironment.dist == Dist.CLIENT
? new Proxy.Client(modEventBus, modContainer)
: new Proxy.Server(modEventBus, modContainer);
}
public static ResourceLocation createResourceLocation(String name) {
if (name.contains(":")) {
throw new IllegalArgumentException("Name contains namespace");
}
return ResourceLocation.fromNamespaceAndPath(MOD_ID, name);
}
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 IProxy getProxy() {
return proxy;
}
}

View File

@ -0,0 +1,46 @@
package dev.micle.totem_of_reviving.component;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.netty.buffer.ByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import java.util.Objects;
public class TotemConfigHashData {
public static final Codec<TotemConfigHashData> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
Codec.INT.fieldOf("configHash").forGetter(TotemConfigHashData::getConfigHash)
).apply(instance, TotemConfigHashData::new)
);
public static final StreamCodec<ByteBuf, TotemConfigHashData> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.INT, TotemConfigHashData::getConfigHash,
TotemConfigHashData::new
);
private final int configHash;
public TotemConfigHashData(int configHash) {
this.configHash = configHash;
}
public int getConfigHash() {
return this.configHash;
}
@Override
public int hashCode() {
return Objects.hash(this.configHash);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else {
return obj instanceof TotemConfigHashData tchd
&& this.configHash == tchd.configHash;
}
}
}

View File

@ -0,0 +1,92 @@
package dev.micle.totem_of_reviving.component;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import io.netty.buffer.ByteBuf;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import java.util.Objects;
import java.util.Optional;
import java.util.UUID;
public class TotemData {
public static final Codec<TotemData> CODEC = RecordCodecBuilder.create(instance ->
instance.group(
Codec.INT.fieldOf("targetIndex").forGetter(TotemData::getTargetIndex),
Codec.STRING.fieldOf("targetUUID").forGetter(TotemData::getTargetStringUUID),
Codec.STRING.fieldOf("targetName").forGetter(TotemData::getTargetName),
Codec.INT.fieldOf("targetDeaths").forGetter(TotemData::getTargetDeaths),
Codec.INT.fieldOf("charge").forGetter(TotemData::getCharge)
).apply(instance, TotemData::new)
);
public static final StreamCodec<ByteBuf, TotemData> STREAM_CODEC = StreamCodec.composite(
ByteBufCodecs.INT, TotemData::getTargetIndex,
ByteBufCodecs.STRING_UTF8, TotemData::getTargetStringUUID,
ByteBufCodecs.STRING_UTF8, TotemData::getTargetName,
ByteBufCodecs.INT, TotemData::getTargetDeaths,
ByteBufCodecs.INT, TotemData::getCharge,
TotemData::new
);
private final int targetIndex;
private final String targetUUID;
private final String targetName;
private final int targetDeaths;
private final int charge;
public TotemData(int targetIndex, String targetUUID, String targetName, int targetDeaths, int charge) {
this.targetIndex = targetIndex;
this.targetUUID = targetUUID;
this.targetName = targetName;
this.targetDeaths = targetDeaths;
this.charge = charge;
}
public int getTargetIndex() {
return targetIndex;
}
public String getTargetStringUUID() {
return targetUUID;
}
public Optional<UUID> getTargetUUID() {
Optional<UUID> targetUUID = Optional.empty();
try {
targetUUID = Optional.of(UUID.fromString(this.targetUUID));
} catch (IllegalArgumentException ignored) {}
return targetUUID;
}
public String getTargetName() {
return targetName;
}
public int getTargetDeaths() {
return targetDeaths;
}
public int getCharge() {
return charge;
}
@Override
public int hashCode() {
return Objects.hash(this.targetIndex, this.targetUUID, this.targetName, this.targetDeaths, this.charge);
}
@Override
public boolean equals(Object obj) {
if (obj == this) {
return true;
} else {
return obj instanceof TotemData td
&& this.targetIndex == td.targetIndex
&& Objects.equals(this.targetUUID, td.targetUUID)
&& Objects.equals(this.targetName, td.targetName)
&& this.targetDeaths == td.targetDeaths
&& this.charge == td.charge;
}
}
}

View File

@ -0,0 +1,21 @@
package dev.micle.totem_of_reviving.data;
import dev.micle.totem_of_reviving.data.client.ModItemModelProvider;
import net.minecraft.data.DataGenerator;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.neoforge.common.data.ExistingFileHelper;
import net.neoforged.neoforge.data.event.GatherDataEvent;
@EventBusSubscriber
public class DataGenerators {
@SubscribeEvent
public static void gatherData(GatherDataEvent event) {
DataGenerator generator = event.getGenerator();
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
generator.addProvider(event.includeServer(), new ModItemModelProvider(generator, existingFileHelper));
generator.addProvider(event.includeServer(), new ModRecipeProvider(generator.getPackOutput(), event.getLookupProvider()));
}
}

View File

@ -1,24 +1,25 @@
package dev.micle.totemofreviving.data; package dev.micle.totem_of_reviving.data;
import dev.micle.totemofreviving.setup.ModItems; import dev.micle.totem_of_reviving.setup.ModItems;
import net.minecraft.data.DataGenerator; import net.minecraft.core.HolderLookup;
import net.minecraft.data.recipes.FinishedRecipe; import net.minecraft.data.PackOutput;
import net.minecraft.data.recipes.RecipeCategory; import net.minecraft.data.recipes.RecipeCategory;
import net.minecraft.data.recipes.RecipeOutput;
import net.minecraft.data.recipes.RecipeProvider; import net.minecraft.data.recipes.RecipeProvider;
import net.minecraft.data.recipes.ShapedRecipeBuilder; import net.minecraft.data.recipes.ShapedRecipeBuilder;
import net.minecraft.world.item.Items; import net.minecraft.world.item.Items;
import javax.annotation.ParametersAreNonnullByDefault; import javax.annotation.ParametersAreNonnullByDefault;
import java.util.function.Consumer; import java.util.concurrent.CompletableFuture;
public class ModRecipeProvider extends RecipeProvider { public class ModRecipeProvider extends RecipeProvider {
public ModRecipeProvider(DataGenerator generator) { public ModRecipeProvider(PackOutput packOutput, CompletableFuture<HolderLookup.Provider> registries) {
super(generator.getPackOutput()); super(packOutput, registries);
} }
@Override
@ParametersAreNonnullByDefault @ParametersAreNonnullByDefault
protected void buildRecipes(Consumer<FinishedRecipe> consumer) { @Override
protected void buildRecipes(RecipeOutput consumer) {
ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, ModItems.STRAW_TOTEM.get()) ShapedRecipeBuilder.shaped(RecipeCategory.TOOLS, ModItems.STRAW_TOTEM.get())
.define('W', Items.WHEAT) .define('W', Items.WHEAT)
.define('|', Items.STICK) .define('|', Items.STICK)

View File

@ -1,19 +1,19 @@
package dev.micle.totemofreviving.data.client; package dev.micle.totem_of_reviving.data.client;
import dev.micle.totemofreviving.TotemOfReviving; import dev.micle.totem_of_reviving.TotemOfReviving;
import dev.micle.totemofreviving.item.charge.DiamondChargeItem; import dev.micle.totem_of_reviving.item.charge.DiamondChargeItem;
import dev.micle.totemofreviving.item.charge.IronChargeItem; import dev.micle.totem_of_reviving.item.charge.IronChargeItem;
import dev.micle.totemofreviving.item.charge.NetheriteChargeItem; import dev.micle.totem_of_reviving.item.charge.NetheriteChargeItem;
import dev.micle.totemofreviving.item.charge.StrawChargeItem; import dev.micle.totem_of_reviving.item.charge.StrawChargeItem;
import dev.micle.totemofreviving.item.totem.DiamondTotemItem; import dev.micle.totem_of_reviving.item.totem.DiamondTotemItem;
import dev.micle.totemofreviving.item.totem.IronTotemItem; import dev.micle.totem_of_reviving.item.totem.IronTotemItem;
import dev.micle.totemofreviving.item.totem.NetheriteTotemItem; import dev.micle.totem_of_reviving.item.totem.NetheriteTotemItem;
import dev.micle.totemofreviving.item.totem.StrawTotemItem; import dev.micle.totem_of_reviving.item.totem.StrawTotemItem;
import net.minecraft.data.DataGenerator; import net.minecraft.data.DataGenerator;
import net.minecraftforge.client.model.generators.ItemModelBuilder; import net.neoforged.neoforge.client.model.generators.ItemModelBuilder;
import net.minecraftforge.client.model.generators.ItemModelProvider; import net.neoforged.neoforge.client.model.generators.ItemModelProvider;
import net.minecraftforge.client.model.generators.ModelFile; import net.neoforged.neoforge.client.model.generators.ModelFile;
import net.minecraftforge.common.data.ExistingFileHelper; import net.neoforged.neoforge.common.data.ExistingFileHelper;
public class ModItemModelProvider extends ItemModelProvider { public class ModItemModelProvider extends ItemModelProvider {
public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) { public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existingFileHelper) {

View File

@ -0,0 +1,37 @@
package dev.micle.totem_of_reviving.item.charge;
import dev.micle.totem_of_reviving.util.LangAsset;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.TooltipFlag;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
public abstract class ChargeItem extends Item {
public ChargeItem(Rarity rarity, boolean isFireResistant) {
super(createProperties(rarity, isFireResistant));
}
public abstract Component getTotemDisplayName();
public static Properties createProperties(Rarity rarity, boolean isFireResistant) {
Properties properties = new Properties().stacksTo(64).rarity(rarity);
if (isFireResistant) properties = properties.fireResistant();
return properties;
}
@Override
@ParametersAreNonnullByDefault
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
tooltipComponents.add(LangAsset.TOOLTIP_CHARGE.getComponent(
getTotemDisplayName()
).withStyle(ChatFormatting.GRAY));
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
}
}

View File

@ -0,0 +1,20 @@
package dev.micle.totem_of_reviving.item.charge;
import dev.micle.totem_of_reviving.setup.ModItems;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Rarity;
public class DiamondChargeItem extends ChargeItem {
public DiamondChargeItem() {
super(Rarity.RARE, false);
}
public static String getName() {
return "diamond_charge";
}
@Override
public Component getTotemDisplayName() {
return ModItems.DIAMOND_TOTEM.get().getDefaultInstance().getDisplayName();
}
}

View File

@ -0,0 +1,20 @@
package dev.micle.totem_of_reviving.item.charge;
import dev.micle.totem_of_reviving.setup.ModItems;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Rarity;
public class IronChargeItem extends ChargeItem {
public IronChargeItem() {
super(Rarity.UNCOMMON, false);
}
public static String getName() {
return "iron_charge";
}
@Override
public Component getTotemDisplayName() {
return ModItems.IRON_TOTEM.get().getDefaultInstance().getDisplayName();
}
}

View File

@ -0,0 +1,20 @@
package dev.micle.totem_of_reviving.item.charge;
import dev.micle.totem_of_reviving.setup.ModItems;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Rarity;
public class NetheriteChargeItem extends ChargeItem {
public NetheriteChargeItem() {
super(Rarity.EPIC, true);
}
public static String getName() {
return "netherite_charge";
}
@Override
public Component getTotemDisplayName() {
return ModItems.NETHERITE_TOTEM.get().getDefaultInstance().getDisplayName();
}
}

View File

@ -0,0 +1,20 @@
package dev.micle.totem_of_reviving.item.charge;
import dev.micle.totem_of_reviving.setup.ModItems;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Rarity;
public class StrawChargeItem extends ChargeItem {
public StrawChargeItem() {
super(Rarity.COMMON, false);
}
public static String getName() {
return "straw_charge";
}
@Override
public Component getTotemDisplayName() {
return ModItems.STRAW_TOTEM.get().getDefaultInstance().getDisplayName();
}
}

View File

@ -1,13 +1,13 @@
package dev.micle.totemofreviving.item.totem; package dev.micle.totem_of_reviving.item.totem;
import dev.micle.totemofreviving.item.charge.DiamondChargeItem; import dev.micle.totem_of_reviving.item.charge.DiamondChargeItem;
import dev.micle.totemofreviving.setup.Config; import dev.micle.totem_of_reviving.setup.Config;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity; import net.minecraft.world.item.Rarity;
public class DiamondTotemItem extends TotemItem { public class DiamondTotemItem extends TotemItem {
public DiamondTotemItem() { public DiamondTotemItem() {
super(Rarity.RARE, Config.Server.getDiamondTotemConfig().getDurability()); super(Rarity.RARE, false);
} }
public static String getName() { public static String getName() {
@ -18,4 +18,9 @@ public class DiamondTotemItem extends TotemItem {
public boolean isCharge(ItemStack stack) { public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof DiamondChargeItem); return (stack.getItem() instanceof DiamondChargeItem);
} }
@Override
public Config.TotemConfig getConfig() {
return Config.Server.getDiamondTotemConfig();
}
} }

View File

@ -0,0 +1,26 @@
package dev.micle.totem_of_reviving.item.totem;
import dev.micle.totem_of_reviving.item.charge.IronChargeItem;
import dev.micle.totem_of_reviving.setup.Config;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity;
public class IronTotemItem extends TotemItem {
public IronTotemItem() {
super(Rarity.UNCOMMON, false);
}
public static String getName() {
return "iron_totem";
}
@Override
public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof IronChargeItem);
}
@Override
public Config.TotemConfig getConfig() {
return Config.Server.getIronTotemConfig();
}
}

View File

@ -1,13 +1,13 @@
package dev.micle.totemofreviving.item.totem; package dev.micle.totem_of_reviving.item.totem;
import dev.micle.totemofreviving.item.charge.NetheriteChargeItem; import dev.micle.totem_of_reviving.item.charge.NetheriteChargeItem;
import dev.micle.totemofreviving.setup.Config; import dev.micle.totem_of_reviving.setup.Config;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity; import net.minecraft.world.item.Rarity;
public class NetheriteTotemItem extends TotemItem { public class NetheriteTotemItem extends TotemItem {
public NetheriteTotemItem() { public NetheriteTotemItem() {
super(Rarity.EPIC, Config.Server.getNetheriteTotemConfig().getDurability()); super(Rarity.EPIC, true);
} }
public static String getName() { public static String getName() {
@ -20,7 +20,7 @@ public class NetheriteTotemItem extends TotemItem {
} }
@Override @Override
public boolean isFireResistant() { public Config.TotemConfig getConfig() {
return true; return Config.Server.getNetheriteTotemConfig();
} }
} }

View File

@ -1,13 +1,13 @@
package dev.micle.totemofreviving.item.totem; package dev.micle.totem_of_reviving.item.totem;
import dev.micle.totemofreviving.item.charge.StrawChargeItem; import dev.micle.totem_of_reviving.item.charge.StrawChargeItem;
import dev.micle.totemofreviving.setup.Config; import dev.micle.totem_of_reviving.setup.Config;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity; import net.minecraft.world.item.Rarity;
public class StrawTotemItem extends TotemItem { public class StrawTotemItem extends TotemItem {
public StrawTotemItem() { public StrawTotemItem() {
super(Rarity.UNCOMMON, Config.Server.getStrawTotemConfig().getDurability()); super(Rarity.COMMON, false);
} }
public static String getName() { public static String getName() {
@ -18,4 +18,9 @@ public class StrawTotemItem extends TotemItem {
public boolean isCharge(ItemStack stack) { public boolean isCharge(ItemStack stack) {
return (stack.getItem() instanceof StrawChargeItem); return (stack.getItem() instanceof StrawChargeItem);
} }
@Override
public Config.TotemConfig getConfig() {
return Config.Server.getStrawTotemConfig();
}
} }

View File

@ -0,0 +1,321 @@
package dev.micle.totem_of_reviving.item.totem;
import com.mojang.blaze3d.platform.InputConstants;
import dev.micle.totem_of_reviving.component.TotemConfigHashData;
import dev.micle.totem_of_reviving.component.TotemData;
import dev.micle.totem_of_reviving.setup.Config;
import dev.micle.totem_of_reviving.setup.ModDataComponents;
import dev.micle.totem_of_reviving.util.ComponentHelper;
import dev.micle.totem_of_reviving.util.LangAsset;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.PlayerList;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.component.Unbreakable;
import net.minecraft.world.level.Level;
import org.jetbrains.annotations.NotNull;
import javax.annotation.ParametersAreNonnullByDefault;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
public abstract class TotemItem extends Item {
public TotemItem(Rarity rarity, boolean isFireResistant) {
super(createProperties(rarity, isFireResistant));
}
public static Properties createProperties(Rarity rarity, boolean isFireResistant) {
Properties properties = new Properties().stacksTo(1).rarity(rarity);
if (isFireResistant) properties = properties.fireResistant();
properties = properties.component(ModDataComponents.TOTEM_DATA.get(), new TotemData(
0, "", "", 0, 0
));
return properties;
}
public abstract boolean isCharge(ItemStack stack);
public abstract Config.TotemConfig getConfig();
private boolean isChargeFull(TotemData totemData) {
return totemData.getCharge() >= getMaxCharge();
}
private boolean isChargeCostDynamic() {
return getConfig().getChargeCost() == -1;
}
private boolean isUnbreakable() {
return getConfig().getDurability() == 0;
}
private int getMaxCharge() {
return isChargeCostDynamic()
? getConfig().getChargeCostLimit()
: getConfig().getChargeCost();
}
private int getTargetCost(TotemData totemData) {
return isChargeCostDynamic()
? Math.max(1, (int)(totemData.getTargetDeaths() * getConfig().getChargeCostMultiplier()))
: getConfig().getChargeCost();
}
private boolean canAffordTarget(TotemData totemData) {
return totemData.getCharge() >= getTargetCost(totemData) || (isChargeFull(totemData) && getConfig().getCanReviveMoreExpensiveTargets());
}
private static TotemData getTotemData(ItemStack itemStack) {
return itemStack.getComponents().get(ModDataComponents.TOTEM_DATA.get());
}
private static void setTotemData(ItemStack itemStack, TotemData totemData) {
itemStack.set(ModDataComponents.TOTEM_DATA.get(), totemData);
}
public static boolean isTotem(ItemStack stack) {
return (stack.getItem() instanceof TotemItem);
}
public static Component cycleTarget(ItemStack itemStack, PlayerList playerList) {
if (!isTotem(itemStack)) return Component.empty();
TotemData totemData = getTotemData(itemStack);
int targetIndex = totemData.getTargetIndex() + 1;
targetIndex = targetIndex >= playerList.getPlayerCount() ? 0 : targetIndex;
ServerPlayer target = playerList.getPlayers().get(targetIndex);
totemData = new TotemData(
targetIndex,
target.getStringUUID(),
target.getScoreboardName(),
target.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS)),
totemData.getCharge()
);
setTotemData(itemStack, totemData);
return LangAsset.MESSAGE_NOW_TARGETING.getComponent(
Component.literal(totemData.getTargetName()).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY);
}
public static boolean chargeTotem(ItemStack totemStack, ItemStack chargeStack) {
if (!isTotem(totemStack)) return false;
TotemData totemData = getTotemData(totemStack);
TotemItem totemItem = ((TotemItem) totemStack.getItem());
if (!totemItem.isCharge(chargeStack)) return false;
if (totemItem.isChargeFull(totemData)) return false;
setTotemData(totemStack, new TotemData(
totemData.getTargetIndex(),
totemData.getTargetStringUUID(),
totemData.getTargetName(),
totemData.getTargetDeaths(),
totemData.getCharge() + 1
));
chargeStack.setCount(chargeStack.getCount() - 1);
return true;
}
public static Component reviveTarget(EquipmentSlot slot, ItemStack itemStack, ServerPlayer user, PlayerList playerList) {
if (!isTotem(itemStack)) return Component.empty();
TotemData totemData = getTotemData(itemStack);
TotemItem totemItem = ((TotemItem) itemStack.getItem());
Config.TotemConfig config = totemItem.getConfig();
Optional<UUID> targetUUID = totemData.getTargetUUID();
if (targetUUID.isEmpty()) {
return LangAsset.MESSAGE_UNABLE_TO_FIND_PLAYER.getComponent().withStyle(ChatFormatting.RED);
}
ServerPlayer target = playerList.getPlayer(targetUUID.get());
if (target == null) {
return LangAsset.MESSAGE_UNABLE_TO_FIND_PLAYER.getComponent().withStyle(ChatFormatting.RED);
}
totemData = new TotemData(
totemData.getTargetIndex(),
totemData.getTargetStringUUID(),
totemData.getTargetName(),
target.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS)),
totemData.getCharge()
);
setTotemData(itemStack, totemData);
if (!target.isSpectator()) {
return LangAsset.MESSAGE_PLAYER_IS_NOT_DEAD.getComponent(
Component.literal(totemData.getTargetName()).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY);
}
if (!target.serverLevel().equals(user.serverLevel()) && !config.getCanReviveAcrossDimensions()) {
return LangAsset.MESSAGE_PLAYER_IS_IN_ANOTHER_DIMENSION.getComponent(
Component.literal(totemData.getTargetName()).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY);
}
if (!totemItem.canAffordTarget(totemData)) {
return LangAsset.MESSAGE_NOT_ENOUGH_CHARGE.getComponent().withStyle(ChatFormatting.WHITE);
}
target.teleportTo(user.serverLevel(), user.position().x, user.position().y, user.position().z, user.getYRot(), user.getXRot());
target.setGameMode(user.serverLevel().getServer().getDefaultGameType());
totemData = new TotemData(
totemData.getTargetIndex(),
totemData.getTargetStringUUID(),
totemData.getTargetName(),
totemData.getTargetDeaths(),
Math.max(0, totemData.getCharge() - totemItem.getTargetCost(totemData))
);
setTotemData(itemStack, totemData);
itemStack.hurtAndBreak(1, user, slot);
return LangAsset.MESSAGE_SUCCESSFULLY_REVIVED_TARGET.getComponent(
Component.literal(totemData.getTargetName()).withStyle(ChatFormatting.GREEN)
).withStyle(ChatFormatting.DARK_GREEN);
}
@Override
@ParametersAreNonnullByDefault
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> tooltipComponents, TooltipFlag tooltipFlag) {
Minecraft minecraft = Minecraft.getInstance();
TotemData totemData = getTotemData(stack);
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_TARGET.getComponent(
totemData.getTargetUUID().isPresent()
? Component.literal(totemData.getTargetName()).withStyle(ChatFormatting.WHITE)
: LangAsset.GENERAL_NA.getComponent().withStyle(ChatFormatting.RED)
).withStyle(ChatFormatting.GRAY));
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_TARGET_COST.getComponent(
totemData.getTargetUUID().isPresent()
? Component.literal(String.format("%d", getTargetCost(totemData))).withStyle(
getTargetCost(totemData) <= getMaxCharge() || (getConfig().getCanReviveMoreExpensiveTargets())
? ChatFormatting.WHITE
: ChatFormatting.RED
)
: LangAsset.GENERAL_NA.getComponent().withStyle(ChatFormatting.RED)
).withStyle(ChatFormatting.GRAY));
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_CHARGES.getComponent(
Component.literal(String.format("%d / %d", totemData.getCharge(), getMaxCharge())).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY));
tooltipComponents.add(
isUnbreakable()
? LangAsset.GENERAL_UNBREAKABLE.getComponent().withStyle(ChatFormatting.WHITE)
: LangAsset.TOOLTIP_TOTEM_DURABILITY.getComponent(
Component.literal(String.format("%d / %d", getConfig().getDurability() - stack.getDamageValue(), getConfig().getDurability())).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY)
);
tooltipComponents.add(Component.empty());
if (isChargeCostDynamic()) {
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_DYNAMIC_COST.getComponent(
Component.literal(String.format("%.2f", getConfig().getChargeCostMultiplier())).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC));
} else {
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_STATIC_COST.getComponent(
Component.literal(String.format("%d", getMaxCharge())).withStyle(ChatFormatting.WHITE)
).withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC));
}
if (getConfig().getCanReviveMoreExpensiveTargets()) {
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_CAN_REVIVE_MORE_EXPENSIVE_TARGETS.getComponent().withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC));
}
if (getConfig().getCanReviveAcrossDimensions()) {
tooltipComponents.add(LangAsset.TOOLTIP_TOTEM_CAN_REVIVE_ACROSS_DIMENSIONS.getComponent().withStyle(ChatFormatting.GRAY, ChatFormatting.ITALIC));
}
tooltipComponents.add(Component.empty());
if (InputConstants.isKeyDown(minecraft.getWindow().getWindow(), minecraft.options.keyShift.getKey().getValue())) {
tooltipComponents.add(LangAsset.TOOLTIP_ADVANCED_TOOLTIP_SHOWN.getComponent().withStyle(ChatFormatting.DARK_GRAY, ChatFormatting.UNDERLINE));
tooltipComponents.add(ComponentHelper.createKeyText(false, new ChatFormatting[]{ChatFormatting.GOLD}, new ChatFormatting[]{ChatFormatting.GOLD, ChatFormatting.ITALIC}, minecraft.options.keyUse));
tooltipComponents.add(ComponentHelper.addIndentToComponent(LangAsset.TOOLTIP_TOTEM_REVIVE_INSTRUCTION.getComponent().withStyle(ChatFormatting.GRAY), 1));
tooltipComponents.add(ComponentHelper.addIndentToComponent(LangAsset.TOOLTIP_TOTEM_CHARGE_INSTRUCTION.getComponent().withStyle(ChatFormatting.GRAY), 1));
tooltipComponents.add(Component.empty());
tooltipComponents.add(ComponentHelper.createKeyText(false, new ChatFormatting[]{ChatFormatting.GOLD}, new ChatFormatting[]{ChatFormatting.GOLD, ChatFormatting.ITALIC}, minecraft.options.keyShift, minecraft.options.keyUse));
tooltipComponents.add(ComponentHelper.addIndentToComponent(LangAsset.TOOLTIP_TOTEM_CHANGE_TARGET_INSTRUCTION.getComponent().withStyle(ChatFormatting.GRAY), 1));
} else {
tooltipComponents.add(LangAsset.TOOLTIP_ADVANCED_TOOLTIP_HIDDEN.getComponent(
ComponentHelper.createKeyText(false, new ChatFormatting[]{ChatFormatting.GOLD}, new ChatFormatting[]{ChatFormatting.GOLD, ChatFormatting.ITALIC}, minecraft.options.keyShift)
).withStyle(ChatFormatting.GRAY));
}
super.appendHoverText(stack, context, tooltipComponents, tooltipFlag);
}
@Override
@ParametersAreNonnullByDefault
public void inventoryTick(ItemStack stack, Level level, Entity entity, int slotId, boolean isSelected) {
if (level.isClientSide) {
super.inventoryTick(stack, level, entity, slotId, isSelected);
return;
}
TotemConfigHashData totemConfigHashData = stack.get(ModDataComponents.TOTEM_CONFIG_HASH_DATA);
if (totemConfigHashData == null || totemConfigHashData.getConfigHash() != getConfig().getConfigHash()) {
if (isUnbreakable()) {
stack.set(DataComponents.UNBREAKABLE, new Unbreakable(false));
stack.remove(DataComponents.MAX_DAMAGE);
stack.remove(DataComponents.DAMAGE);
} else {
stack.remove(DataComponents.UNBREAKABLE);
stack.set(DataComponents.MAX_DAMAGE, getConfig().getDurability());
stack.set(DataComponents.DAMAGE, 0);
}
stack.set(ModDataComponents.TOTEM_CONFIG_HASH_DATA, new TotemConfigHashData(getConfig().getConfigHash()));
}
super.inventoryTick(stack, level, entity, slotId, isSelected);
}
@Override
@ParametersAreNonnullByDefault
public @NotNull InteractionResultHolder<ItemStack> use(Level level, Player player, InteractionHand usedHand) {
if (level.isClientSide) return super.use(level, player, usedHand);
MinecraftServer server = level.getServer();
if (server == null) return super.use(level, player, usedHand);
EquipmentSlot slot = (usedHand.equals(InteractionHand.MAIN_HAND)) ? EquipmentSlot.MAINHAND : EquipmentSlot.OFFHAND;
ItemStack totemStack = (usedHand.equals(InteractionHand.MAIN_HAND)) ? player.getMainHandItem() : player.getOffhandItem();
ItemStack chargeStack = (usedHand.equals(InteractionHand.MAIN_HAND)) ? player.getOffhandItem() : player.getMainHandItem();
if (player.isCrouching()) {
// Change Target
player.sendSystemMessage(cycleTarget(totemStack, server.getPlayerList()));
} else {
if (isCharge(chargeStack)) {
// Charge Totem
chargeTotem(totemStack, chargeStack);
} else {
// Revive Target
player.sendSystemMessage(reviveTarget(slot, totemStack, server.getPlayerList().getPlayer(player.getUUID()), server.getPlayerList()));
}
}
return super.use(level, player, usedHand);
}
}

View File

@ -1,11 +1,18 @@
package dev.micle.totemofreviving.proxy; package dev.micle.totem_of_reviving.proxy;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import javax.annotation.Nullable;
public interface IProxy { public interface IProxy {
@Nullable
MinecraftServer getServer(); MinecraftServer getServer();
@Nullable
Player getClientPlayer(); Player getClientPlayer();
Level getClientWorld();
@Nullable
Level getClientLevel();
} }

View File

@ -1,43 +1,40 @@
package dev.micle.totemofreviving.proxy; package dev.micle.totem_of_reviving.proxy;
import dev.micle.totemofreviving.network.NetworkManager; import dev.micle.totem_of_reviving.setup.Config;
import dev.micle.totemofreviving.setup.Config; import dev.micle.totem_of_reviving.setup.Registration;
import dev.micle.totemofreviving.setup.Registration;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level; import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist; import net.neoforged.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn; import net.neoforged.api.distmarker.OnlyIn;
import net.minecraftforge.common.MinecraftForge; import net.neoforged.bus.api.IEventBus;
import net.minecraftforge.event.AddReloadListenerEvent; import net.neoforged.fml.ModContainer;
import net.minecraftforge.event.server.ServerStartedEvent; import net.neoforged.fml.event.lifecycle.*;
import net.minecraftforge.event.server.ServerStoppingEvent; import net.neoforged.neoforge.common.NeoForge;
import net.minecraftforge.eventbus.api.IEventBus; import net.neoforged.neoforge.event.AddReloadListenerEvent;
import net.minecraftforge.fml.event.lifecycle.*; import net.neoforged.neoforge.event.server.ServerStartedEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import net.neoforged.neoforge.event.server.ServerStoppingEvent;
public class Proxy implements IProxy { public class Proxy implements IProxy {
// Initialize variables // Initialize variables
private static MinecraftServer server = null; private static MinecraftServer server = null;
// Common setup // Common setup
public Proxy() { public Proxy(IEventBus modEventBus, ModContainer modContainer) {
// Initialize setup // Initialize setup
Registration.register(); Registration.register(modEventBus);
Config.init(); Config.init(modContainer);
NetworkManager.init();
// Register mod event bus listeners // Register mod event bus listeners
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(Proxy::setup); modEventBus.addListener(Proxy::setup);
modEventBus.addListener(Proxy::imcEnqueue); modEventBus.addListener(Proxy::imcEnqueue);
modEventBus.addListener(Proxy::imcProcess); modEventBus.addListener(Proxy::imcProcess);
// Register event bus listeners // Register event bus listeners
MinecraftForge.EVENT_BUS.addListener(Proxy::onAddReloadListeners); NeoForge.EVENT_BUS.addListener(Proxy::onAddReloadListeners);
MinecraftForge.EVENT_BUS.addListener(Proxy::serverStarted); NeoForge.EVENT_BUS.addListener(Proxy::serverStarted);
MinecraftForge.EVENT_BUS.addListener(Proxy::serverStopping); NeoForge.EVENT_BUS.addListener(Proxy::serverStopping);
} }
private static void setup(FMLCommonSetupEvent event) {} private static void setup(FMLCommonSetupEvent event) {}
@ -67,15 +64,15 @@ public class Proxy implements IProxy {
} }
@Override @Override
public Level getClientWorld() { public Level getClientLevel() {
return null; return null;
} }
// Client setup // Client setup
public static class Client extends Proxy { public static class Client extends Proxy {
public Client() { public Client(IEventBus modEventBus, ModContainer modContainer) {
super(modEventBus, modContainer);
// Register mod event bus listeners // Register mod event bus listeners
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(Client::setup); modEventBus.addListener(Client::setup);
modEventBus.addListener(Client::postSetup); modEventBus.addListener(Client::postSetup);
} }
@ -92,16 +89,16 @@ public class Proxy implements IProxy {
@Override @Override
@OnlyIn(Dist.CLIENT) @OnlyIn(Dist.CLIENT)
public Level getClientWorld() { public Level getClientLevel() {
return Minecraft.getInstance().level; return Minecraft.getInstance().level;
} }
} }
// Server setup // Server setup
public static class Server extends Proxy { public static class Server extends Proxy {
public Server() { public Server(IEventBus modEventBus, ModContainer modContainer) {
super(modEventBus, modContainer);
// Register mod event bus listeners // Register mod event bus listeners
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
modEventBus.addListener(Server::setup); modEventBus.addListener(Server::setup);
} }

View File

@ -0,0 +1,97 @@
package dev.micle.totem_of_reviving.setup;
import dev.micle.totem_of_reviving.item.totem.DiamondTotemItem;
import dev.micle.totem_of_reviving.item.totem.IronTotemItem;
import dev.micle.totem_of_reviving.item.totem.NetheriteTotemItem;
import dev.micle.totem_of_reviving.item.totem.StrawTotemItem;
import net.neoforged.fml.ModContainer;
import net.neoforged.fml.config.ModConfig;
import net.neoforged.neoforge.common.ModConfigSpec;
import java.util.Objects;
public final class Config {
public static void init(ModContainer modContainer) {
modContainer.registerConfig(ModConfig.Type.SERVER, Server.SPEC);
}
public static class Server {
private static final ModConfigSpec 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 {
ModConfigSpec.Builder builder = new ModConfigSpec.Builder();
STRAW_TOTEM_CONFIG = new TotemConfig(builder, StrawTotemItem.getName(), -1, 3,
1, false, false, 1);
IRON_TOTEM_CONFIG = new TotemConfig(builder, IronTotemItem.getName(), -1, 3,
0.5, false, false, 2);
DIAMOND_TOTEM_CONFIG = new TotemConfig(builder, DiamondTotemItem.getName(), -1, 6,
0.67, true, false, 3);
NETHERITE_TOTEM_CONFIG = new TotemConfig(builder, NetheriteTotemItem.getName(), 1, 1,
1, false, 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 ModConfigSpec.IntValue CHARGE_COST;
private final ModConfigSpec.IntValue CHARGE_COST_LIMIT;
private final ModConfigSpec.DoubleValue CHARGE_COST_MULTIPLIER;
private final ModConfigSpec.BooleanValue CAN_REVIVE_MORE_EXPENSIVE_TARGETS;
private final ModConfigSpec.BooleanValue CAN_REVIVE_ACROSS_DIMENSIONS;
private final ModConfigSpec.IntValue DURABILITY;
public TotemConfig(ModConfigSpec.Builder builder, String name, int chargeCost,
int chargeCostLimit, double chargeCostMultiplier, boolean canReviveMoreExpensiveTargets,
boolean canReviveAcrossDimensions, int durability) {
builder.push(name);
CHARGE_COST = builder
.comment("""
The amount of charges required to revive a player.
Set to -1 for dynamic cost that scales with a player's deaths.
""")
.defineInRange("chargeCost", chargeCost, -1, Integer.MAX_VALUE);
CHARGE_COST_LIMIT = builder
.comment("DYNAMIC COST REQUIRED. The max amount of charges the totem can hold at once.")
.defineInRange("chargeCostLimit", chargeCostLimit, 1, Integer.MAX_VALUE);
CHARGE_COST_MULTIPLIER = builder
.comment("""
DYNAMIC COST REQUIRED. charge_cost = player_deaths * charge_cost_multiplier.
Note: The resulting cost will always be at least 1.
""")
.defineInRange("chargeCostMultiplier", chargeCostMultiplier, 0.01, 100);
CAN_REVIVE_MORE_EXPENSIVE_TARGETS = builder
.comment("DYNAMIC COST REQUIRED. Allows players with a higher cost to be revived as long as the totem is fully charged.")
.define("canReviveMoreExpensiveTargets", canReviveMoreExpensiveTargets);
CAN_REVIVE_ACROSS_DIMENSIONS = builder
.comment("Allows players in different dimensions to be revived.")
.define("canReviveAcrossDimensions", canReviveAcrossDimensions);
DURABILITY = builder
.comment("""
The durability of the totem.
Set to 0 to make the totem unbreakable.
""")
.defineInRange("durability", durability, 0, Integer.MAX_VALUE);
builder.pop();
}
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(); }
public int getConfigHash() { return Objects.hash(getDurability()); }
}
}

View File

@ -0,0 +1,27 @@
package dev.micle.totem_of_reviving.setup;
import dev.micle.totem_of_reviving.util.LangAsset;
import net.minecraft.world.item.CreativeModeTab;
import net.neoforged.neoforge.registries.DeferredHolder;
public class ModCreativeModeTabs {
public static DeferredHolder<CreativeModeTab, CreativeModeTab> MAIN = Registration.CREATIVE_MODE_TABS.register("main",
() -> CreativeModeTab.builder()
.title(LangAsset.ITEM_GROUP_MAIN.getComponent())
.icon(ModItems.STRAW_TOTEM.get()::getDefaultInstance)
.displayItems((itemDisplayParameters, output) -> {
output.accept(ModItems.STRAW_TOTEM.get());
output.accept(ModItems.IRON_TOTEM.get());
output.accept(ModItems.DIAMOND_TOTEM.get());
output.accept(ModItems.NETHERITE_TOTEM.get());
output.accept(ModItems.STRAW_CHARGE.get());
output.accept(ModItems.IRON_CHARGE.get());
output.accept(ModItems.DIAMOND_CHARGE.get());
output.accept(ModItems.NETHERITE_CHARGE.get());
})
.build()
);
public static void register() {}
}

View File

@ -0,0 +1,24 @@
package dev.micle.totem_of_reviving.setup;
import dev.micle.totem_of_reviving.component.TotemConfigHashData;
import dev.micle.totem_of_reviving.component.TotemData;
import net.minecraft.core.component.DataComponentType;
import net.neoforged.neoforge.registries.DeferredHolder;
public class ModDataComponents {
public static final DeferredHolder<DataComponentType<?>, DataComponentType<TotemData>> TOTEM_DATA = Registration.DATA_COMPONENTS.registerComponentType(
"totem_data",
builder -> builder
.persistent(TotemData.CODEC)
.networkSynchronized(TotemData.STREAM_CODEC)
);
public static final DeferredHolder<DataComponentType<?>, DataComponentType<TotemConfigHashData>> TOTEM_CONFIG_HASH_DATA = Registration.DATA_COMPONENTS.registerComponentType(
"totem_config_hash_data",
builder -> builder
.persistent(TotemConfigHashData.CODEC)
.networkSynchronized(TotemConfigHashData.STREAM_CODEC)
);
public static void register() {}
}

View File

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

View File

@ -0,0 +1,30 @@
package dev.micle.totem_of_reviving.setup;
import dev.micle.totem_of_reviving.TotemOfReviving;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.item.CreativeModeTab;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.neoforge.registries.DeferredRegister;
public class Registration {
// Initialize variables
public static final DeferredRegister.DataComponents DATA_COMPONENTS =
DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, TotemOfReviving.MOD_ID);
public static final DeferredRegister.Items ITEMS =
DeferredRegister.createItems(TotemOfReviving.MOD_ID);
public static final DeferredRegister<CreativeModeTab> CREATIVE_MODE_TABS =
DeferredRegister.create(Registries.CREATIVE_MODE_TAB, TotemOfReviving.MOD_ID);
public static void register(IEventBus modEventBus) {
DATA_COMPONENTS.register(modEventBus);
ModDataComponents.register();
ITEMS.register(modEventBus);
ModItems.register();
CREATIVE_MODE_TABS.register(modEventBus);
ModCreativeModeTabs.register();
}
}

View File

@ -0,0 +1,31 @@
package dev.micle.totem_of_reviving.util;
import net.minecraft.ChatFormatting;
import net.minecraft.client.KeyMapping;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.MutableComponent;
import java.util.ArrayList;
import java.util.List;
public final class ComponentHelper {
public static MutableComponent addIndentToComponent(Component component, int indentLevel) {
List<Component> components = new ArrayList<>();
components.add(Component.literal(" ".repeat(indentLevel)));
components.add(component);
return (MutableComponent) ComponentUtils.formatList(components, Component.empty());
}
public static MutableComponent createKeyText(boolean isEnclosed, ChatFormatting[] textFormat, ChatFormatting[] keyFormat, KeyMapping...keys) {
List<Component> textComponents = new ArrayList<>();
textComponents.add(isEnclosed ? Component.literal("[").withStyle(textFormat) : Component.empty());
for (int i = 0; i < keys.length; i++) {
if (i > 0) textComponents.add(Component.literal(" + ").withStyle(textFormat));
textComponents.add(Component.literal(keys[i].getKey().getDisplayName().getString()).withStyle(keyFormat));
}
textComponents.add(isEnclosed ? Component.literal("]").withStyle(textFormat) : Component.empty());
return (MutableComponent) ComponentUtils.formatList(textComponents, Component.empty());
}
}

View File

@ -0,0 +1,58 @@
package dev.micle.totem_of_reviving.util;
import dev.micle.totem_of_reviving.TotemOfReviving;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.contents.TranslatableContents;
public enum LangAsset {
ITEM_GROUP_MAIN("itemGroup", "main"),
ITEM_STRAW_TOTEM("item", "straw_totem"),
ITEM_IRON_TOTEM("item", "iron_totem"),
ITEM_DIAMOND_TOTEM("item", "diamond_totem"),
ITEM_NETHERITE_TOTEM("item", "netherite_totem"),
ITEM_STRAW_CHARGE("item", "straw_charge"),
ITEM_IRON_CHARGE("item", "iron_charge"),
ITEM_DIAMOND_CHARGE("item", "diamond_charge"),
ITEM_NETHERITE_CHARGE("item", "netherite_charge"),
TOOLTIP_TOTEM_TARGET("tooltip", "totem_target"),
TOOLTIP_TOTEM_TARGET_COST("tooltip", "totem_target_cost"),
TOOLTIP_TOTEM_CHARGES("tooltip", "totem_charges"),
TOOLTIP_TOTEM_DURABILITY("tooltip", "totem_durability"),
TOOLTIP_TOTEM_DYNAMIC_COST("tooltip", "totem_dynamic_cost"),
TOOLTIP_TOTEM_STATIC_COST("tooltip", "totem_static_cost"),
TOOLTIP_TOTEM_CAN_REVIVE_MORE_EXPENSIVE_TARGETS("tooltip", "totem_can_revive_more_expensive_targets"),
TOOLTIP_TOTEM_CAN_REVIVE_ACROSS_DIMENSIONS("tooltip", "totem_can_revive_across_dimensions"),
TOOLTIP_TOTEM_REVIVE_INSTRUCTION("tooltip", "totem_revive_instruction"),
TOOLTIP_TOTEM_CHARGE_INSTRUCTION("tooltip", "totem_charge_instruction"),
TOOLTIP_TOTEM_CHANGE_TARGET_INSTRUCTION("tooltip", "totem_change_target_instructions"),
TOOLTIP_CHARGE("tooltip", "charge"),
TOOLTIP_ADVANCED_TOOLTIP_HIDDEN("tooltip", "advanced_tooltip_hidden"),
TOOLTIP_ADVANCED_TOOLTIP_SHOWN("tooltip", "advanced_tooltip_shown"),
GENERAL_NA("general", "na"),
GENERAL_UNBREAKABLE("general", "unbreakable"),
MESSAGE_UNABLE_TO_FIND_PLAYER("message", "unable_to_find_player"),
MESSAGE_PLAYER_IS_NOT_DEAD("message", "player_is_not_dead"),
MESSAGE_PLAYER_IS_IN_ANOTHER_DIMENSION("message", "player_is_in_another_dimension"),
MESSAGE_UNABLE_TO_GET_PLAYER_WORLD("message", "unable_to_get_player_world"),
MESSAGE_NOT_ENOUGH_CHARGE("message", "not_enough_charge"),
MESSAGE_UNABLE_TO_GET_YOUR_WORLD("message", "unable_to_get_your_world"),
MESSAGE_SUCCESSFULLY_REVIVED_TARGET("message", "successfully_revived_target"),
MESSAGE_NOW_TARGETING("message", "now_targeting");
private final String category;
private final String key;
private LangAsset(String category, String key) {
this.category = category;
this.key = key;
}
public MutableComponent getComponent() {
return getComponent(TranslatableContents.NO_ARGS);
}
public MutableComponent getComponent(Object ...args) {
return Component.translatable(String.format("%s.%s.%s", category, TotemOfReviving.MOD_ID, key), args);
}
}

View File

@ -1,47 +0,0 @@
package dev.micle.totemofreviving;
import dev.micle.totemofreviving.proxy.IProxy;
import dev.micle.totemofreviving.proxy.Proxy;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.CreativeModeTabs;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.ModContainer;
import net.minecraftforge.fml.ModList;
import net.minecraftforge.fml.common.Mod;
import java.util.Optional;
@Mod(TotemOfReviving.MOD_ID)
public final class TotemOfReviving {
public static final String MOD_ID = "totemofreviving";
public static CreativeModeTab CREATIVE_TAB = CreativeModeTabs.getDefaultTab();
private static IProxy proxy;
public TotemOfReviving() {
proxy = DistExecutor.safeRunForDist(
() -> Proxy.Client::new,
() -> Proxy.Server::new
);
}
public static ResourceLocation createResourceLocation(String name) {
if (name.contains(":")) {
throw new IllegalArgumentException("Name contains namespace");
}
return new ResourceLocation(MOD_ID, name);
}
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 IProxy getProxy() {
return proxy;
}
}

View File

@ -1,22 +0,0 @@
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.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@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(event.includeServer(), new ModItemModelProvider(generator, existingFileHelper));
generator.addProvider(event.includeServer(), new ModRecipeProvider(generator));
}
}

View File

@ -1,33 +0,0 @@
package dev.micle.totemofreviving.event.common;
import dev.micle.totemofreviving.TotemOfReviving;
import dev.micle.totemofreviving.setup.ModItems;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.event.CreativeModeTabEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@Mod.EventBusSubscriber(modid = TotemOfReviving.MOD_ID)
public class OnCreativeModeTabRegisterEventHandler {
@SubscribeEvent
public static void creativeModeTabRegisterEvent(CreativeModeTabEvent.Register event) {
System.out.println("HERE!");
TotemOfReviving.CREATIVE_TAB = event.registerCreativeModeTab(
TotemOfReviving.createResourceLocation("creative_mode_tab_main"), builder -> builder
.icon(() -> new ItemStack(ModItems.STRAW_TOTEM.get()))
.title(Component.translatable(String.format("tabs.%s.main_tab", TotemOfReviving.MOD_ID)))
.displayItems((featureFlags, output) -> {
output.accept(ModItems.STRAW_TOTEM.get());
output.accept(ModItems.IRON_TOTEM.get());
output.accept(ModItems.DIAMOND_TOTEM.get());
output.accept(ModItems.NETHERITE_TOTEM.get());
output.accept(ModItems.STRAW_CHARGE.get());
output.accept(ModItems.IRON_CHARGE.get());
output.accept(ModItems.DIAMOND_CHARGE.get());
output.accept(ModItems.NETHERITE_CHARGE.get());
})
);
}
}

View File

@ -1,34 +0,0 @@
package dev.micle.totemofreviving.item.charge;
import dev.micle.totemofreviving.setup.Config;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Rarity;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import 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 Properties().stacksTo(64).rarity(rarity));
}
@Override
@OnlyIn(Dist.CLIENT)
@ParametersAreNonnullByDefault
public void appendHoverText(ItemStack stack, @Nullable Level world, List<Component> tooltip, TooltipFlag tooltipFlag) {
tooltip.add(Component.literal(ChatFormatting.WHITE + "Used for charging its corresponding totem."));
super.appendHoverText(stack, world, tooltip, tooltipFlag);
}
}

Some files were not shown because too many files have changed in this diff Show More