From 98941b84b952697f060e89899864cb7bb7da08d3 Mon Sep 17 00:00:00 2001 From: marston Date: Mon, 26 Jan 2026 18:37:37 -0500 Subject: [PATCH 1/5] Backport Random Loot 2 to Minecraft 1.12.2 Forge - Convert from NeoForge 1.21.11 to Forge 1.12.2 (14.23.5.2860) - Replace DataComponents with NBT-based storage (LootNBT.java) - Port all 39 modifiers with 1.12.2 API translations - Implement dynamic texture system with ItemPropertyGetter - Add anvil recipe handler for trait modification (30 XP cost) - Add loot table injection for dungeon chests - Update build system to RetroFuturaGradle 1.4.1 - Fix stat tracking for goodness progression - Convert lang files from JSON to .lang format --- build.gradle | 216 +--- gradle.properties | 43 +- gradle/wrapper/gradle-wrapper.properties | 4 +- run.sh | 1 + settings.gradle | 11 +- .../dev/marston/randomloot/ClientProxy.java | 69 ++ .../dev/marston/randomloot/CommonProxy.java | 20 + .../java/dev/marston/randomloot/Config.java | 112 +- .../java/dev/marston/randomloot/GenWiki.java | 538 --------- .../marston/randomloot/ModLootModifiers.java | 23 - .../dev/marston/randomloot/RandomLoot.java | 118 +- .../component/ModDataComponents.java | 34 - .../randomloot/component/ToolModifier.java | 67 -- .../marston/randomloot/items/ModItems.java | 60 +- .../randomloot/loot/CaseLootModifier.java | 66 - .../dev/marston/randomloot/loot/LootCase.java | 157 +-- .../dev/marston/randomloot/loot/LootItem.java | 1060 +++++++--------- .../dev/marston/randomloot/loot/LootNBT.java | 228 ++++ .../randomloot/loot/LootTableHandler.java | 64 + .../marston/randomloot/loot/LootUtils.java | 1068 +++++------------ .../marston/randomloot/loot/ModTemplate.java | 60 - .../loot/modifiers/BlockBreakModifier.java | 17 +- .../loot/modifiers/ChargeTracker.java | 46 +- .../loot/modifiers/DummyContainer.java | 84 +- .../loot/modifiers/EntityHurtModifier.java | 14 +- .../loot/modifiers/HoldModifier.java | 15 +- .../randomloot/loot/modifiers/Modifier.java | 205 ++-- .../loot/modifiers/ModifierRegistry.java | 211 ++-- .../loot/modifiers/StatsModifier.java | 12 +- .../randomloot/loot/modifiers/Unbreaking.java | 132 +- .../loot/modifiers/UseModifier.java | 42 +- .../loot/modifiers/breakers/Attracting.java | 70 +- .../loot/modifiers/breakers/Excavator.java | 77 +- .../loot/modifiers/breakers/Explode.java | 40 +- .../loot/modifiers/breakers/Learning.java | 53 +- .../loot/modifiers/breakers/Melting.java | 124 +- .../loot/modifiers/breakers/Prospector.java | 104 +- .../loot/modifiers/breakers/Veiny.java | 93 +- .../loot/modifiers/holders/Aquatic.java | 49 +- .../loot/modifiers/holders/Effect.java | 75 +- .../loot/modifiers/holders/Hasty.java | 61 +- .../loot/modifiers/holders/Healing.java | 57 +- .../loot/modifiers/holders/OreFinder.java | 109 +- .../loot/modifiers/holders/Rainy.java | 60 +- .../modifiers/holders/TreasureFinder.java | 109 +- .../loot/modifiers/hurter/Bezerk.java | 43 +- .../loot/modifiers/hurter/Charging.java | 65 +- .../loot/modifiers/hurter/Combo.java | 60 +- .../loot/modifiers/hurter/Critical.java | 47 +- .../loot/modifiers/hurter/Draining.java | 36 +- .../loot/modifiers/hurter/Fire.java | 38 +- .../loot/modifiers/hurter/Frozen.java | 76 +- .../loot/modifiers/hurter/HurtEffect.java | 64 +- .../loot/modifiers/hurter/Nemesis.java | 65 +- .../loot/modifiers/hurter/Overgrown.java | 69 +- .../loot/modifiers/hurter/Scorched.java | 51 +- .../loot/modifiers/hurter/Soulbound.java | 57 +- .../loot/modifiers/stats/Busted.java | 30 +- .../loot/modifiers/users/DirtPlace.java | 121 +- .../loot/modifiers/users/FireBall.java | 63 +- .../loot/modifiers/users/FirePlace.java | 120 +- .../loot/modifiers/users/TorchPlace.java | 155 +-- .../loot/modifiers/users/VoidTouched.java | 100 +- .../recipes/AnvilRecipeHandler.java | 148 +++ .../randomloot/recipes/ModCraftingHelper.java | 42 - .../marston/randomloot/recipes/Recipies.java | 26 - .../recipes/TextureChangeRecipe.java | 102 -- .../recipes/TraitAdditionRecipe.java | 185 --- .../assets/randomloot/items/case.json | 6 - .../assets/randomloot/items/mod_add.json | 6 - .../assets/randomloot/items/mod_sub.json | 6 - .../assets/randomloot/items/tool.json | 650 ---------- .../assets/randomloot/lang/en_us.json | 6 - .../assets/randomloot/lang/en_us.lang | 2 + .../assets/randomloot/models/item/tool.json | 30 + .../loot_modifiers/global_loot_modifiers.json | 7 - .../randomloot/recipe/texture_change.json | 3 - .../randomloot/recipe/trait_absorption.json | 8 - .../data/randomloot/recipe/trait_aquatic.json | 8 - .../randomloot/recipe/trait_attracting.json | 8 - .../data/randomloot/recipe/trait_bezerk.json | 8 - .../randomloot/recipe/trait_blinding.json | 8 - .../data/randomloot/recipe/trait_busted.json | 8 - .../data/randomloot/recipe/trait_charged.json | 8 - .../data/randomloot/recipe/trait_combo.json | 8 - .../randomloot/recipe/trait_critical.json | 8 - .../randomloot/recipe/trait_detecting.json | 8 - .../randomloot/recipe/trait_dirt_place.json | 8 - .../randomloot/recipe/trait_excavator.json | 8 - .../data/randomloot/recipe/trait_explode.json | 8 - .../data/randomloot/recipe/trait_filling.json | 8 - .../randomloot/recipe/trait_fire_place.json | 8 - .../recipe/trait_fire_resistance.json | 8 - .../recipe/trait_flame_thrower.json | 8 - .../data/randomloot/recipe/trait_flaming.json | 8 - .../data/randomloot/recipe/trait_frozen.json | 8 - .../data/randomloot/recipe/trait_hasty.json | 8 - .../randomloot/recipe/trait_learning.json | 8 - .../data/randomloot/recipe/trait_living.json | 8 - .../data/randomloot/recipe/trait_melting.json | 8 - .../randomloot/recipe/trait_necrotic.json | 8 - .../data/randomloot/recipe/trait_nemesis.json | 8 - .../randomloot/recipe/trait_overgrown.json | 8 - .../data/randomloot/recipe/trait_poison.json | 8 - .../randomloot/recipe/trait_prospector.json | 8 - .../data/randomloot/recipe/trait_rainy.json | 8 - .../randomloot/recipe/trait_regeneration.json | 8 - .../randomloot/recipe/trait_resistance.json | 8 - .../randomloot/recipe/trait_scorched.json | 8 - .../randomloot/recipe/trait_soulbound.json | 8 - .../data/randomloot/recipe/trait_spawner.json | 8 - .../randomloot/recipe/trait_torch_place.json | 8 - .../randomloot/recipe/trait_unbreaking.json | 8 - .../data/randomloot/recipe/trait_veiny.json | 8 - .../randomloot/recipe/trait_void_touched.json | 8 - .../data/randomloot/recipe/trait_wither.json | 8 - src/main/resources/mcmod.info | 16 + src/main/resources/pack.mcmeta | 6 + .../templates/META-INF/neoforge.mods.toml | 93 -- 119 files changed, 3065 insertions(+), 5719 deletions(-) create mode 100755 run.sh create mode 100644 src/main/java/dev/marston/randomloot/ClientProxy.java create mode 100644 src/main/java/dev/marston/randomloot/CommonProxy.java delete mode 100644 src/main/java/dev/marston/randomloot/GenWiki.java delete mode 100644 src/main/java/dev/marston/randomloot/ModLootModifiers.java delete mode 100644 src/main/java/dev/marston/randomloot/component/ModDataComponents.java delete mode 100644 src/main/java/dev/marston/randomloot/component/ToolModifier.java delete mode 100644 src/main/java/dev/marston/randomloot/loot/CaseLootModifier.java create mode 100644 src/main/java/dev/marston/randomloot/loot/LootNBT.java create mode 100644 src/main/java/dev/marston/randomloot/loot/LootTableHandler.java delete mode 100644 src/main/java/dev/marston/randomloot/loot/ModTemplate.java create mode 100644 src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java delete mode 100644 src/main/java/dev/marston/randomloot/recipes/ModCraftingHelper.java delete mode 100644 src/main/java/dev/marston/randomloot/recipes/Recipies.java delete mode 100644 src/main/java/dev/marston/randomloot/recipes/TextureChangeRecipe.java delete mode 100644 src/main/java/dev/marston/randomloot/recipes/TraitAdditionRecipe.java delete mode 100644 src/main/resources/assets/randomloot/items/case.json delete mode 100644 src/main/resources/assets/randomloot/items/mod_add.json delete mode 100644 src/main/resources/assets/randomloot/items/mod_sub.json delete mode 100644 src/main/resources/assets/randomloot/items/tool.json delete mode 100644 src/main/resources/assets/randomloot/lang/en_us.json create mode 100644 src/main/resources/assets/randomloot/lang/en_us.lang delete mode 100644 src/main/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json delete mode 100644 src/main/resources/data/randomloot/recipe/texture_change.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_absorption.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_aquatic.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_attracting.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_bezerk.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_blinding.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_busted.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_charged.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_combo.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_critical.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_detecting.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_dirt_place.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_excavator.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_explode.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_filling.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_fire_place.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_fire_resistance.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_flame_thrower.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_flaming.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_frozen.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_hasty.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_learning.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_living.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_melting.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_necrotic.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_nemesis.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_overgrown.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_poison.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_prospector.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_rainy.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_regeneration.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_resistance.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_scorched.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_soulbound.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_spawner.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_torch_place.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_unbreaking.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_veiny.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_void_touched.json delete mode 100644 src/main/resources/data/randomloot/recipe/trait_wither.json create mode 100644 src/main/resources/mcmod.info create mode 100644 src/main/resources/pack.mcmeta delete mode 100644 src/main/templates/META-INF/neoforge.mods.toml diff --git a/build.gradle b/build.gradle index 8119705..28d40a6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,189 +1,67 @@ plugins { - id 'java-library' - id 'maven-publish' - id 'net.neoforged.moddev' version '2.0.131' - id 'idea' + id 'com.gtnewhorizons.retrofuturagradle' version '1.4.1' } -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 -} - -version = mod_version -group = mod_group_id - -repositories { - mavenLocal() -} - -base { - archivesName = mod_id -} - -// Mojang ships Java 21 to end users starting in 1.20.5, so mods should target Java 21. -java.toolchain.languageVersion = JavaLanguageVersion.of(21) - -neoForge { - // Specify the version of NeoForge to use. - version = project.neo_version +version = project.mod_version +group = project.mod_group_id +archivesBaseName = project.mod_id - parchment { - mappingsVersion = project.parchment_mappings_version - minecraftVersion = project.parchment_minecraft_version - } - - // 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 { - client { - client() - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id - } - - server { - server() - programArgument '--nogui' - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id - } - - // 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 { - clientData() - - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // gameDirectory = project.file('run-data') - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. - programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() - } - - // 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 { - // define mod <-> source bindings - // 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) - } +// Use Java 17 but target Java 8 +java { + toolchain { + languageVersion.set(JavaLanguageVersion.of(17)) } + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 + withSourcesJar() } -// Include resources generated by data generators. -sourceSets.main.resources { srcDir 'src/generated/resources' } +minecraft { + mcVersion = project.minecraft_version + mcpMappingChannel = 'stable' + mcpMappingVersion = '39' +} -// Sets up a dependency configuration called 'localRuntime'. -// This configuration should be used instead of 'runtimeOnly' to declare -// a dependency that will be present for runtime testing but that is -// "optional", meaning it will not be pulled by dependents of this mod. -configurations { - runtimeClasspath.extendsFrom localRuntime +repositories { + mavenCentral() } dependencies { - // 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}" - - // Example mod dependency using a mod jar from ./libs with a flat dir repository - // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar - // The group id is ignored when searching -- in this case, it is "blank" - // implementation "blank:coolmod-${mc_version}:${coolmod_version}" - - // 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 + // No additional dependencies needed } -// 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. -var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) { - 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 - expand replaceProperties - from "src/main/templates" - into "build/generated/sources/modMetadata" +processResources { + inputs.property "version", project.version + inputs.property "mcversion", project.minecraft_version + inputs.property "modid", project.mod_id + inputs.property "modname", project.mod_name + inputs.property "moddescription", project.mod_description + inputs.property "modauthors", project.mod_authors + + filesMatching('mcmod.info') { + expand 'version': project.version, + 'mcversion': project.minecraft_version, + 'modid': project.mod_id, + 'modname': project.mod_name, + 'moddescription': project.mod_description, + 'modauthors': project.mod_authors + } } -// Include the output of "generateModMetadata" as an input directory for the build -// this works with both building through Gradle and the IDE. -sourceSets.main.resources.srcDir generateModMetadata -// To avoid having to run "generateModMetadata" manually, make it run on every project reload -neoForge.ideSyncTask generateModMetadata -// Example configuration to allow publishing using the maven-publish plugin -publishing { - publications { - register('mavenJava', MavenPublication) { - from components.java - } - } - repositories { - maven { - url "file://${project.projectDir}/repo" - } +jar { + manifest { + attributes([ + "Specification-Title": project.mod_id, + "Specification-Vendor": project.mod_authors, + "Specification-Version": "1", + "Implementation-Title": project.mod_name, + "Implementation-Version": "${version}", + "Implementation-Vendor": project.mod_authors, + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) } } 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 - } + options.encoding = 'UTF-8' } diff --git a/gradle.properties b/gradle.properties index b933169..133a45a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,45 +1,16 @@ -# Sets default memory used for gradle commands. Can be overridden by user or command line properties. -org.gradle.jvmargs=-Xmx1G +# Sets default memory used for gradle commands +org.gradle.jvmargs=-Xmx3G org.gradle.daemon=true -org.gradle.parallel=true -org.gradle.caching=true -org.gradle.configuration-cache=true -#read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment -# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started -parchment_minecraft_version=1.21.4 -parchment_mappings_version=2025.01.05 -# Environment Properties -# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge -# The Minecraft version must agree with the Neo version to get a valid artifact -minecraft_version=1.21.11 -# The Minecraft version range can use any release version of Minecraft as bounds. -# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly -# as they do not follow standard versioning conventions. -minecraft_version_range=[1.21.11] -# The Neo version must agree with the Minecraft version to get a valid artifact -neo_version=21.11.34-beta -# The Neo version range can use any version of Neo as bounds -neo_version_range=[21.11.25-beta,) -# The loader version range can only use the major version of FML as bounds -loader_version_range=[1,) +# Minecraft/Forge versions +minecraft_version=1.12.2 +forge_version=14.23.5.2860 ## Mod Properties - -# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} -# Must match the String constant located in the main mod class annotated with @Mod. mod_id=randomloot -# The human-readable display name for the mod. mod_name=Random Loot 2 -# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=All Rights Reserved -# The mod version. See https://semver.org/ -mod_version=1.1.0 -# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. -# This should match the base package used for the mod sources. -# See https://maven.apache.org/guides/mini/guide-naming-conventions.html +mod_version=1.0.0-1.12.2 mod_group_id=dev.marston.randomloot -# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. mod_authors=Marston Connell -# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. -mod_description=An RPG style loot system built from the ground up to make Minecraft loot feel more personal. \ No newline at end of file +mod_description=An RPG style loot system built from the ground up to make Minecraft loot feel more personal. diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index cea7a79..e1adfb4 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,7 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.12-bin.zip -networkTimeout=10000 -validateDistributionUrl=true +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..d5984d1 --- /dev/null +++ b/run.sh @@ -0,0 +1 @@ +JAVA_HOME="$HOME/.jdks/zulu8.78.0.19-ca-jdk8.0.412-macosx_x64" arch -x86_64 ./gradlew runClient diff --git a/settings.gradle b/settings.gradle index 90ae98f..f9de53b 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,11 +1,16 @@ pluginManagement { repositories { - mavenLocal() + maven { + name = 'GTNH Maven' + url = 'https://nexus.gtnewhorizons.com/repository/public/' + } gradlePluginPortal() - maven { url = 'https://maven.neoforged.net/releases' } + mavenCentral() } } plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0' + id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0' } + +rootProject.name = 'randomloot' diff --git a/src/main/java/dev/marston/randomloot/ClientProxy.java b/src/main/java/dev/marston/randomloot/ClientProxy.java new file mode 100644 index 0000000..9121de7 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/ClientProxy.java @@ -0,0 +1,69 @@ +package dev.marston.randomloot; + +import dev.marston.randomloot.items.ModItems; +import dev.marston.randomloot.loot.LootNBT; +import net.minecraft.client.renderer.block.model.ModelResourceLocation; +import net.minecraft.item.Item; +import net.minecraft.util.ResourceLocation; +import net.minecraftforge.client.event.ModelRegistryEvent; +import net.minecraftforge.client.model.ModelLoader; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.relauncher.Side; + +@Mod.EventBusSubscriber(modid = RandomLoot.MODID, value = Side.CLIENT) +public class ClientProxy extends CommonProxy { + + @Override + public void preInit(FMLPreInitializationEvent event) { + super.preInit(event); + } + + @Override + public void init(FMLInitializationEvent event) { + super.init(event); + registerItemPropertyOverrides(); + } + + @SubscribeEvent + public static void registerModels(ModelRegistryEvent event) { + registerModel(ModItems.TOOL, 0, "tool"); + registerModel(ModItems.CASE, 0, "case"); + } + + private static void registerModel(Item item, int meta, String name) { + ModelLoader.setCustomModelResourceLocation(item, meta, + new ModelResourceLocation(new ResourceLocation(RandomLoot.MODID, name), "inventory")); + } + + private void registerItemPropertyOverrides() { + // Register custom property for dynamic texture selection + // Encoding matches tool.json overrides: + // 0.1xxx = pickaxe, 0.2xxx = shovel, 0.3xxx = axe, 0.4xxx = sword + ModItems.TOOL.addPropertyOverride( + new ResourceLocation(RandomLoot.MODID, "cosmetic"), + (stack, world, entity) -> { + if (stack.isEmpty() || !stack.hasTagCompound()) { + return 0.0f; + } + int toolType = LootNBT.getToolTypeOrdinal(stack); + int texture = LootNBT.getTexture(stack); + + // Map tool type ordinal to JSON encoding + // PICKAXE=0->0.1, SHOVEL=1->0.2, AXE=2->0.3, SWORD=3->0.4 + float base; + switch (toolType) { + case 0: base = 0.1f; break; // PICKAXE + case 1: base = 0.2f; break; // SHOVEL + case 2: base = 0.3f; break; // AXE + case 3: base = 0.4f; break; // SWORD + default: base = 0.0f; break; + } + + return base + texture * 0.0001f; + } + ); + } +} diff --git a/src/main/java/dev/marston/randomloot/CommonProxy.java b/src/main/java/dev/marston/randomloot/CommonProxy.java new file mode 100644 index 0000000..15f8382 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/CommonProxy.java @@ -0,0 +1,20 @@ +package dev.marston.randomloot; + +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; + +public class CommonProxy { + + public void preInit(FMLPreInitializationEvent event) { + // Common pre-initialization + } + + public void init(FMLInitializationEvent event) { + // Common initialization + } + + public void postInit(FMLPostInitializationEvent event) { + // Common post-initialization + } +} diff --git a/src/main/java/dev/marston/randomloot/Config.java b/src/main/java/dev/marston/randomloot/Config.java index 70d3639..55b973a 100644 --- a/src/main/java/dev/marston/randomloot/Config.java +++ b/src/main/java/dev/marston/randomloot/Config.java @@ -2,90 +2,62 @@ import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.Identifier; -import net.minecraft.world.item.Item; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.event.config.ModConfigEvent; -import net.neoforged.neoforge.common.ModConfigSpec; +import net.minecraftforge.common.config.Configuration; +import java.io.File; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -// An example config class. This is not required, but it's a good idea to have one to keep your config organized. -// Demonstrates how to use Neo's config APIs -@EventBusSubscriber(modid = RandomLoot.MODID) -public class Config -{ - private static final ModConfigSpec.Builder BUILDER = new ModConfigSpec.Builder(); +public class Config { + private static Configuration config; - private static ModConfigSpec.DoubleValue CASE_CHANCE; + // Loot chances + public static double CaseChance = 0.25; - private static ModConfigSpec.DoubleValue MOD_CHANCE; + // Misc + public static double Goodness = 1.0; - private static ModConfigSpec.DoubleValue GOODNESS; - - static final ModConfigSpec SPEC = build(); - - public static ModConfigSpec build() { - init(); - return BUILDER.build(); - } - - public static double CaseChance; - public static double ModChance; - public static double Goodness; - - private static Map MODIFIERS_ENABLED; + // Modifier toggles private static Map ModsEnabled = new HashMap<>(); - public static void init() { - - BUILDER.push("Loot Chances"); - CASE_CHANCE = BUILDER.comment("chance to find a case in a chest.").defineInRange("caseChance", 0.25, 0.0, 1.0); - MOD_CHANCE = BUILDER.comment("chance to find a modifier template in a chest.").defineInRange("modChance", 0.15, - 0.0, 1.0); - BUILDER.pop(); - - BUILDER.push("Modifiers Enabled"); - MODIFIERS_ENABLED = new HashMap(); - - for (Map.Entry entry : ModifierRegistry.getModifiers().entrySet()) { - String key = entry.getKey(); - Modifier mod = entry.getValue(); - - MODIFIERS_ENABLED.put(key, - BUILDER.comment("should the " + mod.name() + " trait be enabled").define(key + "_enabled", true)); + public static void init(File configFile) { + if (config == null) { + config = new Configuration(configFile); + loadConfig(); } - BUILDER.pop(); + } - BUILDER.push("Misc"); - GOODNESS = BUILDER.comment("rate of tool improvement per player").defineInRange("goodness_rate", 1.0, 0.01, - 10.0); - BUILDER.pop(); + private static void loadConfig() { + try { + config.load(); + + // Loot Chances category + CaseChance = config.getFloat("caseChance", "loot_chances", 0.25f, 0.0f, 1.0f, + "Chance to find a case in a chest"); + + // Misc category + Goodness = config.getFloat("goodness_rate", "misc", 1.0f, 0.01f, 10.0f, + "Rate of tool improvement per player"); + + // Modifiers Enabled category + for (Map.Entry entry : ModifierRegistry.getModifiers().entrySet()) { + String key = entry.getKey(); + Modifier mod = entry.getValue(); + boolean enabled = config.getBoolean(key + "_enabled", "modifiers_enabled", true, + "Should the " + mod.name() + " trait be enabled"); + ModsEnabled.put(key, enabled); + } + + } catch (Exception e) { + RandomLoot.LOGGER.error("Error loading config", e); + } finally { + if (config.hasChanged()) { + config.save(); + } + } } public static boolean traitEnabled(String tagName) { return ModsEnabled.getOrDefault(tagName, true); } - - @SubscribeEvent - static void onLoad(final ModConfigEvent event) { - CaseChance = CASE_CHANCE.get(); - ModChance = MOD_CHANCE.get(); - Goodness = GOODNESS.get(); - - ModsEnabled = new HashMap(); - for (Map.Entry entry : MODIFIERS_ENABLED.entrySet()) { - String key = entry.getKey(); - ModConfigSpec.BooleanValue val = entry.getValue(); - - ModsEnabled.put(key, val.get()); - } - - } } diff --git a/src/main/java/dev/marston/randomloot/GenWiki.java b/src/main/java/dev/marston/randomloot/GenWiki.java deleted file mode 100644 index 99b5214..0000000 --- a/src/main/java/dev/marston/randomloot/GenWiki.java +++ /dev/null @@ -1,538 +0,0 @@ -package dev.marston.randomloot; - -import com.google.gson.Gson; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import dev.marston.randomloot.loot.NameGenerator; -import dev.marston.randomloot.loot.modifiers.Modifier; -import dev.marston.randomloot.loot.modifiers.ModifierRegistry; -import net.minecraft.resources.Identifier; - -import java.io.*; -import java.util.*; - -public class GenWiki { - - private static void write(String s, FileWriter f) throws IOException { - f.write(s + "\n"); - } - - private static String stripItemName(String name) { - Identifier loc = Identifier.tryParse(name); - return loc.getPath(); - } - - private static void writeMod(Modifier m, FileWriter f) throws IOException { - String tag = m.tagName(); - String recipe = "n/a"; - int count = 1; - try { - recipe = readRecipe(tag); - count = readCount(tag); - } catch (Exception e) { - RandomLoot.LOGGER.warn("failed to find recipe for " + tag + "."); - } - write("### " + m.name(), f); - - write("**id:** `" + tag + "` | **crafting:** `" + recipe + "` ![" + stripItemName(recipe) - + "](https://raw.githubusercontent.com/anish-shanbhag/minecraft-api/master/public/images/items/" - + stripItemName(recipe) + ".png)", f); - write("", f); - write("**Decription:** " + m.description(), f); - } - - private static void writeMods(Set mods, FileWriter f) throws IOException { - List sortedList = new ArrayList<>(mods); - sortedList.sort(Comparator.comparing(Modifier::name)); - - for (Modifier modifier : sortedList) { - writeMod(modifier, f); - } - } - - private static void writeModifiers(FileWriter f) throws IOException { - - write("# Modifiers", f); - write("This is a full list of modifiers in the game and a description of what they do.", f); - - write("## Breakers", f); - write("These effects are applied when breaking blocks.", f); - writeMods(ModifierRegistry.BREAKERS, f); - - write("## Holders", f); - write("These effects are applied when holding the tool.", f); - writeMods(ModifierRegistry.HOLDERS, f); - - write("## Users", f); - write("These effects are applied when right clicking.", f); - writeMods(ModifierRegistry.USERS, f); - - write("## Hurters", f); - write("These effects are applied when hurting enemies.", f); - writeMods(ModifierRegistry.HURTERS, f); - - write("## Stats", f); - write("These effects are used to calculate stats for tools.", f); - writeMods(ModifierRegistry.STATS, f); - - write("## Misc.", f); - write("These effects are general and don't fit into any other categories.", f); - writeMods(ModifierRegistry.MISC, f); - } - - private static void writeConfig(FileWriter f) throws IOException { - write("# Configuration Guide", f); - write("", f); - write("This document describes all configuration options available for Random Loot.", f); - write("", f); - - write("## Loot Chances", f); - write("", f); - write("These settings control how often Random Loot items appear in structure chests.", f); - write("", f); - write("| Option | Default | Range | Description |", f); - write("|--------|---------|-------|-------------|", f); - write("| `caseChance` | 0.25 | 0.0-1.0 | Chance to find a Loot Case in a chest |", f); - write("| `modChance` | 0.15 | 0.0-1.0 | Chance to find a Trait Template in a chest |", f); - write("", f); - - write("## Progression", f); - write("", f); - write("These settings affect how tools improve over time.", f); - write("", f); - write("| Option | Default | Range | Description |", f); - write("|--------|---------|-------|-------------|", f); - write("| `goodness_rate` | 1.0 | 0.01-10.0 | Multiplier for tool improvement rate per player |", f); - write("", f); - - write("## Modifier Toggles", f); - write("", f); - write("Each modifier can be individually enabled or disabled. Set to `false` to disable a modifier.", f); - write("", f); - write("| Config Option | Modifier | Description |", f); - write("|---------------|----------|-------------|", f); - - List> sortedMods = new ArrayList<>(ModifierRegistry.getModifiers().entrySet()); - sortedMods.sort(Comparator.comparing(Map.Entry::getKey)); - - for (Map.Entry entry : sortedMods) { - String key = entry.getKey(); - Modifier mod = entry.getValue(); - write("| `" + key + "_enabled` | [" + mod.name() + "](MODIFIERS.md#" + mod.name().toLowerCase().replace(" ", "-") + ") | " + mod.description() + " |", f); - } - write("", f); - } - - private static void writeProgression(FileWriter f) throws IOException { - write("# Tool Progression", f); - write("", f); - write("This document explains how Random Loot tools improve over time.", f); - write("", f); - - write("## Tool Stats (Goodness)", f); - write("", f); - write("Each tool has a \"goodness\" value that determines its base stats. Higher goodness means:", f); - write("- Higher mining/digging speed", f); - write("- More attack damage", f); - write("- More durability", f); - write("", f); - write("**Speed Formula:** `(goodness / 2) + 6`", f); - write("", f); - write("**Damage Formula:** `goodness + 1` (modified by tool type)", f); - write("- Pickaxe: 50% damage", f); - write("- Axe: 120% damage", f); - write("- Shovel: 60% damage", f); - write("- Sword: 100% damage", f); - write("", f); - write("**Durability Formula:** `(goodness + 10) × 80`", f); - write("", f); - - write("## Leveling System", f); - write("", f); - write("Tools gain XP from mining blocks and attacking enemies. Each level grants a **10% stat boost**.", f); - write("", f); - write("**XP Required per Level:** `500 × 2^level`", f); - write("", f); - write("| Level | XP Required | Total XP | Stat Multiplier |", f); - write("|-------|-------------|----------|-----------------|", f); - for (int i = 0; i <= 10; i++) { - int xpRequired = (int) (500 * Math.pow(2, i)); - int totalXP = 0; - for (int j = 0; j < i; j++) { - totalXP += (int) (500 * Math.pow(2, j)); - } - double multiplier = Math.pow(1.1, i); - write(String.format("| %d | %,d | %,d | %.2fx |", i, xpRequired, totalXP, multiplier), f); - } - write("", f); - - write("## Progression Curve", f); - write("", f); - write("The more cases you open, the better your new tools become. Goodness is calculated as:", f); - write("", f); - write("**Goodness Formula:** `√(cases_opened + 1) × goodness_rate`", f); - write("", f); - write("**Starting Traits:** `floor(goodness / 2)`", f); - write("", f); - write("| Cases Opened | Goodness | Starting Traits |", f); - write("|--------------|----------|-----------------|", f); - int[] caseCounts = {0, 1, 5, 10, 25, 50, 100, 200, 500, 1000}; - for (int count : caseCounts) { - double goodness = Math.sqrt(count + 1); - int traits = (int) Math.floor(goodness / 2.0); - write(String.format("| %d | %.2f | %d |", count, goodness, traits), f); - } - write("", f); - - write("## Tool Types", f); - write("", f); - write("Random Loot generates four types of tools, each with multiple texture variants:", f); - write("", f); - write("| Tool Type | Texture Variants | Primary Use |", f); - write("|-----------|------------------|-------------|", f); - write("| Pickaxe | 18 | Mining stone and ores |", f); - write("| Axe | 14 | Chopping wood |", f); - write("| Shovel | 9 | Digging dirt and sand |", f); - write("| Sword | 50 | Combat |", f); - write("", f); - } - - private static void writeNames(FileWriter f) throws IOException { - write("# Name Generation", f); - write("", f); - write("This document explains how Random Loot tool names are generated.", f); - write("", f); - - write("## Name Structure", f); - write("", f); - write("Tool names follow this pattern:", f); - write("```", f); - write("[Adjective] [Prefix][Suffix]", f); - write("```", f); - write("", f); - write("Example: \"Blazing Fytenblade\" or \"Frozen Halbedda\"", f); - write("", f); - - write("## Base Names", f); - write("", f); - write("### Prefixes", f); - write("", f); - writeStringArray(NameGenerator.Prefixes, f); - write("", f); - - write("### Suffixes", f); - write("", f); - writeStringArray(NameGenerator.Suffixes, f); - write("", f); - - write("## Temperature-Based Adjectives", f); - write("", f); - write("The adjective is chosen based on the biome temperature where the tool is created.", f); - write("", f); - - write("### Hot Biomes (temp ≥ 1.0)", f); - write("", f); - writeStringArray(NameGenerator.HotAdj, f); - write("", f); - - write("### Cold Biomes (temp ≤ 0.1)", f); - write("", f); - writeStringArray(NameGenerator.ColdAdj, f); - write("", f); - - write("### Temperate Biomes (0.1 < temp < 1.0)", f); - write("", f); - writeStringArray(NameGenerator.TemperateAdj, f); - write("", f); - - write("### Rainy Weather", f); - write("", f); - write("If it's raining when the tool is created, these adjectives are used instead:", f); - write("", f); - writeStringArray(NameGenerator.RainingAdj, f); - write("", f); - - write("## Forger Names", f); - write("", f); - write("Each tool's lore mentions a forger. The forger name is based on biome temperature.", f); - write("", f); - - write("### Hot Biome Forgers", f); - write("", f); - writeStringArray(NameGenerator.HotNames, f); - write("", f); - - write("### Cold Biome Forgers", f); - write("", f); - writeStringArray(NameGenerator.ColdNames, f); - write("", f); - - write("### Temperate Biome Forgers", f); - write("", f); - writeStringArray(NameGenerator.TemperateNames, f); - write("", f); - - write("## Example", f); - write("", f); - write("A tool created in a desert (hot biome) might be named:", f); - write("- **\"Scorched Kitmer\"** - forged by Blazicus", f); - write("", f); - write("A tool created in a snowy tundra (cold biome) might be named:", f); - write("- **\"Frigid Halwam\"** - forged by Boreas", f); - write("", f); - } - - private static void writeStringArray(String[] array, FileWriter f) throws IOException { - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < array.length; i++) { - sb.append("`").append(array[i]).append("`"); - if (i < array.length - 1) { - sb.append(", "); - } - } - write(sb.toString(), f); - } - - private static void writeBiomes(FileWriter f) throws IOException { - write("# Biome-Specific Traits", f); - write("", f); - write("Some traits in Random Loot are tied to specific biomes. These special traits can only appear on tools generated in matching biomes, and can only be added via smithing table to tools that originated from compatible biomes.", f); - write("", f); - - write("## How It Works", f); - write("", f); - write("When you open a Loot Case, the tool remembers:", f); - write("- The **biome** you were standing in", f); - write("- The **temperature** of that biome", f); - write("- The **dimension** you were in (Overworld, Nether, or End)", f); - write("", f); - write("This information determines which biome-specific traits can appear on the tool, both at creation and when crafting.", f); - write("", f); - - write("## Biome-Restricted Traits", f); - write("", f); - write("| Trait | Biome Requirement | Details |", f); - write("|-------|-------------------|---------|", f); - write("| [Aquatic](MODIFIERS.md#aquatic) | Ocean or River biomes | Water breathing + Haste underwater |", f); - write("| [Frozen](MODIFIERS.md#frozen) | Cold biomes (temp <= 0.15) | Slowness on hit, frost walker |", f); - write("| [Scorched](MODIFIERS.md#scorched) | Hot biomes (temp >= 1.0) or Nether | Fire damage, fire resistance |", f); - write("| [Overgrown](MODIFIERS.md#overgrown) | Jungle, Swamp, or Bamboo biomes | Arthropod damage, poison immunity |", f); - write("| [Void-Touched](MODIFIERS.md#void-touched) | The End dimension only | Teleport on right-click |", f); - write("", f); - write("See [MODIFIERS.md](MODIFIERS.md) for full effect descriptions and crafting recipes.", f); - write("", f); - - write("## Crafting Restrictions", f); - write("", f); - write("When using the Smithing Table to add a biome-specific trait, the recipe will only work if the tool was originally created in a compatible biome. A tool created in the desert cannot have the Frozen trait added to it, even with a Smithing Table.", f); - write("", f); - - write("## Tips", f); - write("", f); - write("- **Explore different biomes** to collect tools with different trait possibilities", f); - write("- **Nether tools** can have Scorched trait naturally", f); - write("- **End tools** are the only way to get Void-Touched", f); - write("- **Biome data is permanent** - you cannot change a tool's origin biome", f); - write("", f); - - write("## Biome Temperature Reference", f); - write("", f); - write("| Temperature | Biome Examples |", f); - write("|-------------|----------------|", f); - write("| <= 0.15 (Cold) | Snowy Plains, Ice Spikes, Frozen Ocean, Grove |", f); - write("| 0.15 - 1.0 (Temperate) | Plains, Forest, Taiga, Ocean, Mountains |", f); - write("| >= 1.0 (Hot) | Desert, Badlands, Savanna, Jungle |", f); - write("", f); - write("*Note: The Nether counts as \"hot\" for Scorched regardless of specific biome temperature.*", f); - write("", f); - } - - private static void writeLoot(FileWriter f) throws IOException { - write("# Loot & Crafting Guide", f); - write("", f); - write("This document explains where to find Random Loot items and how to craft with them.", f); - write("", f); - - write("## Finding Loot Cases", f); - write("", f); - write("Loot Cases spawn in structure chests throughout your world:", f); - write("- Dungeons", f); - write("- Mineshafts", f); - write("- Desert Temples", f); - write("- Jungle Temples", f); - write("- Strongholds", f); - write("- Villages", f); - write("- Woodland Mansions", f); - write("- End Cities", f); - write("- And any other structure with loot chests!", f); - write("", f); - write("Default spawn chance: **25%** (configurable in [CONFIG.md](CONFIG.md))", f); - write("", f); - - write("## Using Loot Cases", f); - write("", f); - write("**Right-click** with a Loot Case in hand to open it and receive a random tool.", f); - write("", f); - write("The tool's quality depends on how many cases you've opened - see [PROGRESSION.md](PROGRESSION.md) for details.", f); - write("", f); - - write("### Dispenser Automation", f); - write("", f); - write("Loot Cases can be placed in **Dispensers** for automated opening:", f); - write("- The dispenser will open the case and eject a tool", f); - write("- **Note:** Tools created by dispensers don't benefit from player progression", f); - write("- Dispenser tools will always have base stats (as if 0 cases opened)", f); - write("", f); - - write("## Finding Trait Templates", f); - write("", f); - write("Trait Templates also spawn in structure chests.", f); - write("", f); - write("Default spawn chance: **15%** (configurable in [CONFIG.md](CONFIG.md))", f); - write("", f); - - write("## Trait Templates", f); - write("", f); - write("There are two types of Trait Templates:", f); - write("", f); - write("| Template | Function |", f); - write("|----------|----------|", f); - write("| Addition Template | Add a new trait to a tool |", f); - write("| Subtraction Template | Remove a trait from a tool |", f); - write("", f); - write("**Right-click** with a template to toggle between Addition and Subtraction modes.", f); - write("", f); - - write("### Using the Smithing Table", f); - write("", f); - write("To add or remove traits:", f); - write("", f); - write("1. Open a **Smithing Table**", f); - write("2. Place a **Trait Template** in the template slot", f); - write("3. Place your **Random Tool** in the base slot", f); - write("4. Place the **required item** for the trait in the addition slot", f); - write("5. Preview and take your modified tool", f); - write("", f); - - write("## Trait Recipes", f); - write("", f); - write("Each trait requires a specific item to add or remove. See [MODIFIERS.md](MODIFIERS.md) for the full list.", f); - write("", f); - write("| Trait | Required Item | Count |", f); - write("|-------|---------------|-------|", f); - - File recipeDir = new File("../src/main/resources/data/randomloot/recipe/"); - File[] recipeFiles = recipeDir.listFiles((dir, name) -> name.startsWith("trait_") && name.endsWith(".json")); - - if (recipeFiles != null) { - Arrays.sort(recipeFiles); - for (File recipeFile : recipeFiles) { - try { - String traitName = recipeFile.getName().replace("trait_", "").replace(".json", ""); - FileReader reader = new FileReader(recipeFile); - Gson gson = new Gson(); - BufferedReader bufferedReader = new BufferedReader(reader); - JsonObject obj = gson.fromJson(bufferedReader, JsonObject.class); - JsonObject item = obj.get("item").getAsJsonObject(); - String itemId = item.get("id").getAsString(); - int count = 1; - if (item.has("count")) { - count = item.get("count").getAsInt(); - } - String displayName = traitName.substring(0, 1).toUpperCase() + traitName.substring(1).replace("_", " "); - write("| " + displayName + " | `" + itemId + "` | " + count + " |", f); - bufferedReader.close(); - } catch (Exception e) { - RandomLoot.LOGGER.warn("Failed to read recipe: " + recipeFile.getName()); - } - } - } - write("", f); - } - - public static void genWiki() { - - String isProdEnv = System.getenv("RL_PROD"); - if (isProdEnv == null) { - return; - } - - String isProd = isProdEnv.strip(); - - if (isProd.contains("false")) { - RandomLoot.LOGGER.info("Creating wiki..."); - - try { - FileWriter modifiersWriter = new FileWriter("../MODIFIERS.md"); - writeModifiers(modifiersWriter); - modifiersWriter.close(); - RandomLoot.LOGGER.info("Generated MODIFIERS.md"); - - FileWriter configWriter = new FileWriter("../CONFIG.md"); - writeConfig(configWriter); - configWriter.close(); - RandomLoot.LOGGER.info("Generated CONFIG.md"); - - FileWriter progressionWriter = new FileWriter("../PROGRESSION.md"); - writeProgression(progressionWriter); - progressionWriter.close(); - RandomLoot.LOGGER.info("Generated PROGRESSION.md"); - - FileWriter namesWriter = new FileWriter("../NAMES.md"); - writeNames(namesWriter); - namesWriter.close(); - RandomLoot.LOGGER.info("Generated NAMES.md"); - - FileWriter lootWriter = new FileWriter("../LOOT.md"); - writeLoot(lootWriter); - lootWriter.close(); - RandomLoot.LOGGER.info("Generated LOOT.md"); - - FileWriter biomesWriter = new FileWriter("../BIOMES.md"); - writeBiomes(biomesWriter); - biomesWriter.close(); - RandomLoot.LOGGER.info("Generated BIOMES.md"); - - RandomLoot.LOGGER.info("Wiki generation complete!"); - } catch (IOException e) { - e.printStackTrace(); - } - } - - } - - public static String readRecipe(String trait) throws FileNotFoundException { - FileReader reader = new FileReader( - "../src/main/resources/data/randomloot/recipe/trait_" + trait + ".json"); - Gson gson = new Gson(); - BufferedReader bufferedReader = new BufferedReader(reader); - - JsonObject obj; - obj = gson.fromJson(bufferedReader, JsonObject.class); - - JsonElement item = obj.get("item"); - - JsonObject itemObj = item.getAsJsonObject(); - - return itemObj.get("id").getAsString(); - - } - - public static int readCount(String trait) throws FileNotFoundException { - FileReader reader = new FileReader( - "../src/main/resources/data/randomloot/recipe/trait_" + trait + ".json"); - Gson gson = new Gson(); - BufferedReader bufferedReader = new BufferedReader(reader); - - JsonObject obj; - obj = gson.fromJson(bufferedReader, JsonObject.class); - - JsonElement item = obj.get("item"); - - JsonObject itemObj = item.getAsJsonObject(); - - return itemObj.get("count").getAsInt(); - - } - -} \ No newline at end of file diff --git a/src/main/java/dev/marston/randomloot/ModLootModifiers.java b/src/main/java/dev/marston/randomloot/ModLootModifiers.java deleted file mode 100644 index 8084e0b..0000000 --- a/src/main/java/dev/marston/randomloot/ModLootModifiers.java +++ /dev/null @@ -1,23 +0,0 @@ -package dev.marston.randomloot; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import dev.marston.randomloot.loot.CaseLootModifier; -import net.minecraft.core.registries.BuiltInRegistries; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.common.loot.IGlobalLootModifier; -import net.neoforged.neoforge.registries.DeferredRegister; -import net.neoforged.neoforge.registries.NeoForgeRegistries; - -import java.util.function.Supplier; - -public class ModLootModifiers { - public static final DeferredRegister> GLOBAL_LOOT_MODIFIER_SERIALIZERS = DeferredRegister.create(NeoForgeRegistries.Keys.GLOBAL_LOOT_MODIFIER_SERIALIZERS, RandomLoot.MODID); - - public static final Supplier> CASE_LOOT_MODIFIER = - GLOBAL_LOOT_MODIFIER_SERIALIZERS.register("case_item", () -> CaseLootModifier.CODEC); - - public static void register(IEventBus bus) { - GLOBAL_LOOT_MODIFIER_SERIALIZERS.register(bus); - } -} diff --git a/src/main/java/dev/marston/randomloot/RandomLoot.java b/src/main/java/dev/marston/randomloot/RandomLoot.java index 4bfbc9e..12fd7d5 100644 --- a/src/main/java/dev/marston/randomloot/RandomLoot.java +++ b/src/main/java/dev/marston/randomloot/RandomLoot.java @@ -1,93 +1,51 @@ package dev.marston.randomloot; -import com.mojang.logging.LogUtils; -import dev.marston.randomloot.component.ModDataComponents; -import dev.marston.randomloot.items.ModItems; -import dev.marston.randomloot.loot.LootUtils; -import dev.marston.randomloot.recipes.Recipies; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.Identifier; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.ModContainer; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.common.Mod; -import net.neoforged.fml.config.ModConfig; -import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent; -import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; -import net.neoforged.neoforge.client.event.RegisterRangeSelectItemModelPropertyEvent; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.server.ServerStartingEvent; -import org.slf4j.Logger; - -// The value here should match an entry in the META-INF/neoforge.mods.toml file -@Mod(RandomLoot.MODID) -public class RandomLoot -{ - // Define mod id in a common place for everything to reference +import dev.marston.randomloot.loot.LootTableHandler; +import dev.marston.randomloot.recipes.AnvilRecipeHandler; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.Mod.EventHandler; +import net.minecraftforge.fml.common.SidedProxy; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +@Mod(modid = RandomLoot.MODID, name = RandomLoot.NAME, version = RandomLoot.VERSION) +public class RandomLoot { public static final String MODID = "randomloot"; - // Directly reference a slf4j logger - public static final Logger LOGGER = LogUtils.getLogger(); - // Create a Deferred Register to hold Blocks which will all be registered under the "randomloot" namespace - - - // The constructor for the mod class is the first code that is run when your mod is loaded. - // FML will recognize some parameter types like IEventBus or ModContainer and pass them in automatically. - public RandomLoot(IEventBus modEventBus, ModContainer modContainer) - { - modEventBus.addListener(this::commonSetup); + public static final String NAME = "Random Loot 2"; + public static final String VERSION = "1.0.0"; - ModDataComponents.register(modEventBus); + public static final Logger LOGGER = LogManager.getLogger(MODID); - ModItems.register(modEventBus); - Recipies.register(modEventBus); - ModLootModifiers.register(modEventBus); + @SidedProxy(clientSide = "dev.marston.randomloot.ClientProxy", serverSide = "dev.marston.randomloot.CommonProxy") + public static CommonProxy proxy; - NeoForge.EVENT_BUS.register(this); - modEventBus.addListener(ModItems::addCreative); + @Mod.Instance(MODID) + public static RandomLoot instance; - modContainer.registerConfig(ModConfig.Type.COMMON, Config.SPEC); - - GenWiki.genWiki(); + @EventHandler + public void preInit(FMLPreInitializationEvent event) { + LOGGER.info("Random Loot 2 Pre-Initialization"); + Config.init(event.getSuggestedConfigurationFile()); + proxy.preInit(event); } - private void commonSetup(final FMLCommonSetupEvent event) - { + @EventHandler + public void init(FMLInitializationEvent event) { + LOGGER.info("Random Loot 2 Initialization"); + proxy.init(event); + + // Register event handlers + MinecraftForge.EVENT_BUS.register(new AnvilRecipeHandler()); + MinecraftForge.EVENT_BUS.register(new LootTableHandler()); } - // You can use SubscribeEvent and let the Event Bus discover methods to call - @SubscribeEvent - public void onServerStarting(ServerStartingEvent event) - { - // Do something when the server starts - LOGGER.info("HELLO from server starting"); + @EventHandler + public void postInit(FMLPostInitializationEvent event) { + LOGGER.info("Random Loot 2 Post-Initialization"); + proxy.postInit(event); } - - // In some client class where the event is registered to the mod event bus - - - // You can use EventBusSubscriber to automatically register all static methods in the class annotated with @SubscribeEvent - @EventBusSubscriber(modid = MODID, value = Dist.CLIENT) - public static class ClientModEvents - { - @SubscribeEvent - public static void registerRangeProperties(RegisterRangeSelectItemModelPropertyEvent event) { - event.register( - // The name to reference as the type - Identifier.fromNamespaceAndPath(MODID, "cosmetic"), - // The map codec - LootUtils.TextureProperty.MAP_CODEC - ); - } - - @SubscribeEvent - public static void onClientSetup(FMLClientSetupEvent event) - { - // Some client setup code - LOGGER.info("HELLO FROM CLIENT SETUP"); - } - } - - } diff --git a/src/main/java/dev/marston/randomloot/component/ModDataComponents.java b/src/main/java/dev/marston/randomloot/component/ModDataComponents.java deleted file mode 100644 index 5d5d56d..0000000 --- a/src/main/java/dev/marston/randomloot/component/ModDataComponents.java +++ /dev/null @@ -1,34 +0,0 @@ -package dev.marston.randomloot.component; - -import com.mojang.serialization.Codec; -import dev.marston.randomloot.RandomLoot; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.core.registries.Registries; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.registries.DeferredHolder; -import net.neoforged.neoforge.registries.DeferredRegister; - -import java.util.List; -import java.util.function.UnaryOperator; - - -public class ModDataComponents { - public static final DeferredRegister> DATA_COMPONENT_TYPES = - DeferredRegister.createDataComponents(Registries.DATA_COMPONENT_TYPE, RandomLoot.MODID); - public static final Codec> LIST_CODEC = ToolModifier.CODEC.listOf(); - - public static final DeferredHolder, DataComponentType> TOOL_MODIFIER = register("tool_mod", - builder -> builder.persistent(ToolModifier.CODEC)); - public static final DeferredHolder, DataComponentType>> TOOL_MODIFIERS = register("tool_mods", - builder -> builder.persistent(LIST_CODEC)); - - private static DeferredHolder, DataComponentType> register(String name, - UnaryOperator> builderOperator) { - return DATA_COMPONENT_TYPES.register(name, () -> builderOperator.apply(DataComponentType.builder()).build()); - } - - - public static void register(IEventBus eventBus) { - DATA_COMPONENT_TYPES.register(eventBus); - } -} diff --git a/src/main/java/dev/marston/randomloot/component/ToolModifier.java b/src/main/java/dev/marston/randomloot/component/ToolModifier.java deleted file mode 100644 index 2f017b9..0000000 --- a/src/main/java/dev/marston/randomloot/component/ToolModifier.java +++ /dev/null @@ -1,67 +0,0 @@ -package dev.marston.randomloot.component; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import net.minecraft.nbt.CompoundTag; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; - - -public class ToolModifier { - - private static final int MAX_MODIFIERS = 256; - - @Override - public boolean equals(Object obj) { - if (obj == null) { - return false; - } - if (obj.getClass() != ToolModifier.class) { - return false; - } - ToolModifier t = (ToolModifier) obj; - - return t.tags.equals(this.tags); - } - - @Override - public int hashCode() { - return Objects.hash(tags); - } - - private final Map tags; - - public Map getTags() { - return new HashMap<>(this.tags); - } - - public ToolModifier(Map tagIn) { - // Enforce size limit and make immutable - if (tagIn.size() > MAX_MODIFIERS) { - this.tags = Collections.unmodifiableMap(new HashMap<>()); - } else { - this.tags = Collections.unmodifiableMap(new HashMap<>(tagIn)); - } - } - - public static final Codec CODEC = RecordCodecBuilder.create( - builder -> builder.group( - Codec.unboundedMap(Codec.STRING, CompoundTag.CODEC) - .xmap( - m -> m.size() <= MAX_MODIFIERS ? m : new HashMap(), - m -> m - ) - .fieldOf("tags") - .forGetter(ToolModifier::getTags) - ) - .apply(builder, ToolModifier::new) - ); - - - - - -} diff --git a/src/main/java/dev/marston/randomloot/items/ModItems.java b/src/main/java/dev/marston/randomloot/items/ModItems.java index b515ca3..87a15a1 100644 --- a/src/main/java/dev/marston/randomloot/items/ModItems.java +++ b/src/main/java/dev/marston/randomloot/items/ModItems.java @@ -1,40 +1,36 @@ package dev.marston.randomloot.items; import dev.marston.randomloot.RandomLoot; -import dev.marston.randomloot.component.ModDataComponents; -import dev.marston.randomloot.component.ToolModifier; import dev.marston.randomloot.loot.LootCase; import dev.marston.randomloot.loot.LootItem; -import dev.marston.randomloot.loot.ModTemplate; -import net.minecraft.world.item.CreativeModeTabs; -import net.minecraft.world.item.Item; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; -import net.neoforged.neoforge.registries.DeferredItem; -import net.neoforged.neoforge.registries.DeferredRegister; - -import java.util.HashMap; - +import net.minecraft.creativetab.CreativeTabs; +import net.minecraft.item.Item; +import net.minecraftforge.event.RegistryEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.registry.GameRegistry; + +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) public class ModItems { - public static final DeferredRegister.Items ITEMS = DeferredRegister.createItems(RandomLoot.MODID); - - - public static DeferredItem TOOL = ITEMS.registerItem("tool", p -> new LootItem(p.component(ModDataComponents.TOOL_MODIFIER.get(), new ToolModifier(new HashMap<>())).enchantable(15))); - public static DeferredItem CASE = ITEMS.registerItem("case", LootCase::new); - public static DeferredItem MOD_ADD = ITEMS.registerItem("mod_add", p -> new ModTemplate(p, true)); - public static DeferredItem MOD_SUB = ITEMS.registerItem("mod_sub", p -> new ModTemplate(p, false)); - - - public static void register(IEventBus eventBus) { - ITEMS.register(eventBus); - } - - public static void addCreative(BuildCreativeModeTabContentsEvent event) { - if (event.getTabKey() == CreativeModeTabs.TOOLS_AND_UTILITIES) { - event.accept(TOOL); - event.accept(CASE); - } + + @GameRegistry.ObjectHolder(RandomLoot.MODID + ":tool") + public static LootItem TOOL; + + @GameRegistry.ObjectHolder(RandomLoot.MODID + ":case") + public static LootCase CASE; + + @SubscribeEvent + public static void registerItems(RegistryEvent.Register event) { + LootItem tool = new LootItem(); + tool.setRegistryName(RandomLoot.MODID, "tool"); + tool.setTranslationKey(RandomLoot.MODID + ".tool"); + tool.setCreativeTab(CreativeTabs.TOOLS); + + LootCase lootCase = new LootCase(); + lootCase.setRegistryName(RandomLoot.MODID, "case"); + lootCase.setTranslationKey(RandomLoot.MODID + ".case"); + lootCase.setCreativeTab(CreativeTabs.TOOLS); + + event.getRegistry().registerAll(tool, lootCase); } } - - diff --git a/src/main/java/dev/marston/randomloot/loot/CaseLootModifier.java b/src/main/java/dev/marston/randomloot/loot/CaseLootModifier.java deleted file mode 100644 index b2d0f9a..0000000 --- a/src/main/java/dev/marston/randomloot/loot/CaseLootModifier.java +++ /dev/null @@ -1,66 +0,0 @@ -package dev.marston.randomloot.loot; - -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import dev.marston.randomloot.Config; -import dev.marston.randomloot.items.ModItems; -import it.unimi.dsi.fastutil.objects.ObjectArrayList; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.storage.loot.LootContext; -import net.minecraft.world.level.storage.loot.predicates.LootItemCondition; -import net.neoforged.neoforge.common.loot.IGlobalLootModifier; -import net.neoforged.neoforge.common.loot.LootModifier; -import org.jetbrains.annotations.NotNull; - -public class CaseLootModifier extends LootModifier { - private final Item item; - - // See below for how the codec works. - public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(inst -> - LootModifier.codecStart(inst).and( - BuiltInRegistries.ITEM.byNameCodec().fieldOf("item").forGetter(e -> e.item) - ).apply(inst, CaseLootModifier::new) - ); - - // First constructor parameter is the list of conditions. The rest is our extra properties. - public CaseLootModifier(LootItemCondition[] conditions, Item itemIn) { - super(conditions); - this.item = itemIn; - } - - // Return our codec here. - @Override - public @NotNull MapCodec codec() { - return CODEC; - } - - - @Override - protected @NotNull ObjectArrayList doApply(ObjectArrayList generatedLoot, - LootContext context) { - - String path = context.getQueriedLootTableId().getPath(); - - if (!path.contains("chest")) { - return generatedLoot; - } - - double chance; - if (item == ModItems.CASE.asItem()) { - chance = Config.CaseChance; - } else if (item == ModItems.MOD_ADD.asItem()) { - chance = Config.ModChance; - } else { - return generatedLoot; - } - - if (context.getRandom().nextDouble() < chance) { - generatedLoot.add(new ItemStack(item)); - } - - return generatedLoot; - } -} \ No newline at end of file diff --git a/src/main/java/dev/marston/randomloot/loot/LootCase.java b/src/main/java/dev/marston/randomloot/loot/LootCase.java index e03254c..4759975 100644 --- a/src/main/java/dev/marston/randomloot/loot/LootCase.java +++ b/src/main/java/dev/marston/randomloot/loot/LootCase.java @@ -1,106 +1,65 @@ package dev.marston.randomloot.loot; -import dev.marston.randomloot.items.ModItems; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.core.Direction; -import net.minecraft.core.Position; -import net.minecraft.core.dispenser.BlockSource; -import net.minecraft.core.dispenser.DefaultDispenseItemBehavior; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.stats.StatType; -import net.minecraft.stats.Stats; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.DispenserBlock; -import org.jetbrains.annotations.NotNull; +import net.minecraft.client.util.ITooltipFlag; +import dev.marston.randomloot.items.ModItems; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.stats.StatList; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; + +import javax.annotation.Nullable; +import java.util.List; public class LootCase extends Item { - public static void initDispenser() { - DispenserBlock.registerBehavior(ModItems.CASE.get(), new DefaultDispenseItemBehavior() { - public @NotNull ItemStack execute(@NotNull BlockSource source, @NotNull ItemStack stack) { - Direction direction = source.state().getValue(DispenserBlock.FACING); - Position position = DispenserBlock.getDispensePosition(source); - - ItemStack tool = LootUtils.genTool(null, source.level()); // generate tool and give it to the player - - spawnTool(source.level(), tool, 6, direction, position); - - return ItemStack.EMPTY; - } - }); - } - - public static void spawnTool(Level level, ItemStack stack, int speed, Direction direction, Position pos) { - double d0 = pos.x(); - double d1 = pos.y(); - double d2 = pos.z(); - if (direction.getAxis() == Direction.Axis.Y) { - d1 -= 0.125D; - } else { - d1 -= 0.15625D; - } - - ItemEntity itementity = new ItemEntity(level, d0, d1, d2, stack); - double d3 = level.random.nextDouble() * 0.1D + 0.2D; - itementity.setDeltaMovement( - level.random.triangle((double) direction.getStepX() * d3, 0.0172275D * (double) speed), - level.random.triangle(0.2D, 0.0172275D * (double) speed), - level.random.triangle((double) direction.getStepZ() * d3, 0.0172275D * (double) speed)); - level.addFreshEntity(itementity); - } - - public LootCase(Properties p) { - super(p.stacksTo(1)); - } - - @Override - public boolean isFoil(@NotNull ItemStack stack) { - return true; - } - - @Override - public @NotNull InteractionResult use(@NotNull Level level, Player player, @NotNull InteractionHand hand) { - ItemStack lootCase = player.getItemInHand(hand); - - if (player instanceof ServerPlayer sPlayer) { - StatType itemUsed = Stats.ITEM_USED; - - sPlayer.getStats().increment(sPlayer, itemUsed.get(ModItems.CASE.get()), 1); - } - - Modifier.TrackEntityParticle(level, player, ParticleTypes.CLOUD); - - - - if (!level.isClientSide()) { - assert player instanceof ServerPlayer; - LootUtils.generateTool((ServerPlayer) player, level); // generate tool and give it to the player - } - - player.awardStat(Stats.ITEM_USED.get(this)); - if (!player.getAbilities().instabuild) { - lootCase.shrink(1); - } - - return InteractionResult.SUCCESS; - } - -// @Override -// public void appendHoverText(ItemStack stack, @Nullable Level level, List tipList, TooltipFlag flag) { -// -// MutableComponent comp = Component.empty(); -// comp.append("Right-click for loot!"); -// comp = comp.withStyle(ChatFormatting.GRAY); -// -// tipList.add(comp); -// -// } - + public LootCase() { + super(); + this.setMaxStackSize(1); + } + + @Override + @SideOnly(Side.CLIENT) + public boolean hasEffect(ItemStack stack) { + return true; // Enchanted glow effect + } + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack lootCase = player.getHeldItem(hand); + + // Spawn particles around player + Modifier.TrackEntityParticle(world, player, EnumParticleTypes.CLOUD); + + if (!world.isRemote && player instanceof EntityPlayerMP) { + EntityPlayerMP serverPlayer = (EntityPlayerMP) player; + + // Increment the case usage stat BEFORE generating (so first case = count 0) + serverPlayer.addStat(StatList.getObjectUseStats(ModItems.CASE)); + + LootUtils.generateTool(serverPlayer, world); + } + + // Consume the case unless in creative mode + if (!player.capabilities.isCreativeMode) { + lootCase.shrink(1); + } + + return new ActionResult<>(EnumActionResult.SUCCESS, lootCase); + } + + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + tooltip.add(TextFormatting.GRAY + "Right-click for loot!"); + } } diff --git a/src/main/java/dev/marston/randomloot/loot/LootItem.java b/src/main/java/dev/marston/randomloot/loot/LootItem.java index 4d06e94..e419a7d 100644 --- a/src/main/java/dev/marston/randomloot/loot/LootItem.java +++ b/src/main/java/dev/marston/randomloot/loot/LootItem.java @@ -1,644 +1,456 @@ package dev.marston.randomloot.loot; -import com.mojang.serialization.MapCodec; +import com.google.common.collect.Multimap; import dev.marston.randomloot.Config; -import dev.marston.randomloot.RandomLoot; -import dev.marston.randomloot.items.ModItems; import dev.marston.randomloot.loot.modifiers.*; -import net.minecraft.ChatFormatting; -import net.minecraft.client.gui.screens.Screen; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperty; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.core.component.DataComponentMap; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.stats.StatType; -import net.minecraft.stats.Stats; -import net.minecraft.core.Holder; -import net.minecraft.tags.BlockTags; -import net.minecraft.tags.TagKey; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.EquipmentSlotGroup; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.ai.attributes.AttributeModifier; -import net.minecraft.world.entity.ai.attributes.Attributes; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.component.ItemAttributeModifiers; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.server.level.ServerLevel; -import net.neoforged.neoforge.common.ItemAbilities; -import net.neoforged.neoforge.common.ItemAbility; -import net.minecraft.world.item.component.TooltipDisplay; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.function.Consumer; - -public class LootItem extends Item { - - public enum ToolType { - PICKAXE, SHOVEL, AXE, SWORD, NULL; - - @Override - public String toString() { - return switch (this) { - case PICKAXE -> "Pickaxe"; - case SHOVEL -> "Shovel"; - case AXE -> "Axe"; - case SWORD -> "Sword"; - default -> "Null"; - }; - } - } - - - public LootItem(Properties p) { - super(p.stacksTo(1).durability(100)); - } - - public static float getDigSpeed(ItemStack stack, ToolType type) { - - float statMod = 1.0f; - - List mods = LootUtils.getModifiers(stack); - - for (Modifier mod : mods) { - if (mod instanceof StatsModifier ehm) { - if (!Config.traitEnabled(mod.tagName())) { - continue; - } - - statMod *= ehm.getStats(stack); - } - } - - if (type.equals(ToolType.SWORD)) { - return 1.0f; - } - - float speed = (LootUtils.getStats(stack) / 2.0f) + 6.0f; - return speed * statMod; - } - - public static float getAttackSpeed(ItemStack stack, ToolType type) { - - float speed = 0.0f; - - switch (type) { - case PICKAXE: - speed = -2.8F; - break; - case AXE: - speed = -3.0F; - break; - case SHOVEL: - speed = -3.0F; - break; - case SWORD: - speed = -2.4F; - break; - default: - break; - } - - return speed; - } - - public static float getAttackDamage(ItemStack stack, ToolType type) { - - float damage = (LootUtils.getStats(stack)) + 1.0f; - - switch (type) { - case PICKAXE: - damage = damage * 0.5f; - break; - case AXE: - damage = damage * 1.2f; - break; - case SHOVEL: - damage = damage * 0.6f; - break; - default: - break; - } - - return damage; - } - - @Override - public float getDestroySpeed(@NotNull ItemStack stack, @NotNull BlockState block) { - - ToolType type = LootUtils.getToolType(stack); - - TagKey blocks = null; - - if (type == ToolType.PICKAXE) { - blocks = BlockTags.MINEABLE_WITH_PICKAXE; - } else if (type == ToolType.AXE) { - blocks = BlockTags.MINEABLE_WITH_AXE; - } else if (type == ToolType.SHOVEL) { - blocks = BlockTags.MINEABLE_WITH_SHOVEL; - } else if (type == ToolType.SWORD) { - Block blockType = block.getBlock(); - - // Cobwebs - instant break (vanilla sword behavior) - if (blockType == Blocks.COBWEB) { - return 15.0f; - } - - // Bamboo - instant break (vanilla sword behavior) - if (blockType == Blocks.BAMBOO || blockType == Blocks.BAMBOO_SAPLING) { - return 100.0f; - } - - // Leaves - faster than fists (vanilla sword behavior) - if (block.is(BlockTags.LEAVES)) { - return 1.5f; - } - - return 1.0f; - } else { - return 1.0f; - } - - return block.is(blocks) ? getDigSpeed(stack, type) : 1.0F; - } - - - @Override - public boolean isCombineRepairable(ItemStack stack) { - return false; - } - - - - @Override - public boolean isCorrectToolForDrops(ItemStack stack, BlockState state) { - - ToolType type = LootUtils.getToolType(stack); - - TagKey blocks = null; - - if (type == ToolType.PICKAXE) { - blocks = BlockTags.MINEABLE_WITH_PICKAXE; - } else if (type == ToolType.SHOVEL) { - blocks = BlockTags.MINEABLE_WITH_SHOVEL; - } else if (type == ToolType.AXE) { - blocks = BlockTags.MINEABLE_WITH_AXE; - } else { - return false; - } - - return state.is(blocks); - } - - - @Override - public @NotNull ItemAttributeModifiers getDefaultAttributeModifiers(ItemStack stack) { - - ToolType tt = LootUtils.getToolType(stack); - - float attack = getAttackDamage(stack, tt); - float speed = getAttackSpeed(stack, tt); - - return ItemAttributeModifiers.builder().add( - Attributes.ATTACK_DAMAGE, new AttributeModifier(Item.BASE_ATTACK_DAMAGE_ID, attack, AttributeModifier.Operation.ADD_VALUE), EquipmentSlotGroup.MAINHAND) - .add(Attributes.ATTACK_SPEED, new AttributeModifier(Item.BASE_ATTACK_SPEED_ID, speed, AttributeModifier.Operation.ADD_VALUE), - EquipmentSlotGroup.MAINHAND).build(); - } - - @Override - public boolean canPerformAction(ItemStack stack, ItemAbility itemAbility) { - ToolType type = LootUtils.getToolType(stack); - - if (type == ToolType.AXE) { - return itemAbility == ItemAbilities.AXE_STRIP || - itemAbility == ItemAbilities.AXE_SCRAPE || - itemAbility == ItemAbilities.AXE_WAX_OFF; - } - if (type == ToolType.SHOVEL) { - return itemAbility == ItemAbilities.SHOVEL_FLATTEN; - } - return false; - } - - @Override - public void hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { - - ToolType type = LootUtils.getToolType(itemstack); - - if (type == ToolType.AXE || type == ToolType.SWORD) { - LootUtils.addXp(itemstack, hurter, 1); - } - - List mods = LootUtils.getModifiers(itemstack); - - boolean shouldSkipBreak = false; - for (Modifier mod : mods) { - if (mod instanceof EntityHurtModifier ehm) { - if (!Config.traitEnabled(mod.tagName())) { - continue; - } - - if (ehm.hurtEnemy(itemstack, hurtee, hurter)) { - shouldSkipBreak = true; - } - } - - if (mod instanceof Unbreaking unbreaking) { - if (!Config.traitEnabled(mod.tagName())) { - continue; - } - - if (unbreaking.test(hurtee.level())) { - shouldSkipBreak = true; - } - } - } - if (!shouldSkipBreak) { - itemstack.hurtAndBreak(1, hurter, EquipmentSlot.MAINHAND); - } - } - -// @Override -// public boolean canApplyAtEnchantingTable(ItemStack stack, Enchantment enchantment) { -// -// if (enchantment.category.equals(EnchantmentCategory.BREAKABLE)) { // all these items are breakable so we can -// // enchant them first! -// return true; -// } -// -// ToolType type = LootUtils.getToolType(stack); -// if (enchantment.category.equals(EnchantmentCategory.DIGGER)) { -// if (type == ToolType.AXE || type == ToolType.SHOVEL || type == ToolType.PICKAXE) { -// return true; -// } -// } -// -// if (enchantment.category.equals(EnchantmentCategory.WEAPON)) { -// if (type == ToolType.AXE || type == ToolType.SWORD) { -// return true; -// } -// } -// -// return enchantment.category.canEnchant(stack.getItem()); -// } - - @Override - public boolean mineBlock(@NotNull ItemStack stack, Level level, @NotNull BlockState blockState, @NotNull BlockPos pos, @NotNull LivingEntity player) { - if (!level.isClientSide() && blockState.getDestroySpeed(level, pos) != 0.0F) { - - List mods = LootUtils.getModifiers(stack); - - boolean shouldSkipBreak = false; - for (Modifier mod : mods) { - - if (mod instanceof BlockBreakModifier bbm) { +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.util.ITooltipFlag; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.SharedMonsterAttributes; +import net.minecraft.entity.ai.attributes.AttributeModifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.inventory.EntityEquipmentSlot; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.ActionResult; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.relauncher.Side; +import net.minecraftforge.fml.relauncher.SideOnly; +import org.lwjgl.input.Keyboard; + +import javax.annotation.Nullable; +import java.util.Comparator; +import java.util.List; + +public class LootItem extends Item { + + public enum ToolType { + PICKAXE, SHOVEL, AXE, SWORD, NULL; + + @Override + public String toString() { + switch (this) { + case PICKAXE: return "Pickaxe"; + case SHOVEL: return "Shovel"; + case AXE: return "Axe"; + case SWORD: return "Sword"; + default: return "Null"; + } + } + } + + public LootItem() { + super(); + this.setMaxStackSize(1); + this.setMaxDamage(100); // Will be overridden by getMaxDamage() + } + + public static float getDigSpeed(ItemStack stack, ToolType type) { + float statMod = 1.0f; + + List mods = LootNBT.getModifiers(stack); + for (Modifier mod : mods) { + if (mod instanceof StatsModifier) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + StatsModifier sm = (StatsModifier) mod; + statMod *= sm.getStats(stack); + } + } + + if (type.equals(ToolType.SWORD)) { + return 1.0f; + } + + float speed = (LootUtils.getStats(stack) / 2.0f) + 6.0f; + return speed * statMod; + } + + public static float getAttackSpeed(ItemStack stack, ToolType type) { + float speed = 0.0f; + + switch (type) { + case PICKAXE: + speed = -2.8F; + break; + case AXE: + speed = -3.0F; + break; + case SHOVEL: + speed = -3.0F; + break; + case SWORD: + speed = -2.4F; + break; + default: + break; + } + + return speed; + } + + public static float getAttackDamage(ItemStack stack, ToolType type) { + float damage = (LootUtils.getStats(stack)) + 1.0f; + + switch (type) { + case PICKAXE: + damage = damage * 0.5f; + break; + case AXE: + damage = damage * 1.2f; + break; + case SHOVEL: + damage = damage * 0.6f; + break; + default: + break; + } + + return damage; + } + + @Override + public float getDestroySpeed(ItemStack stack, IBlockState state) { + ToolType type = LootUtils.getToolType(stack); + Material material = state.getMaterial(); + Block block = state.getBlock(); + + if (type == ToolType.PICKAXE) { + if (material == Material.ROCK || material == Material.IRON || material == Material.ANVIL) { + return getDigSpeed(stack, type); + } + } else if (type == ToolType.AXE) { + if (material == Material.WOOD || material == Material.PLANTS || material == Material.VINE) { + return getDigSpeed(stack, type); + } + } else if (type == ToolType.SHOVEL) { + if (material == Material.GROUND || material == Material.GRASS || + material == Material.SAND || material == Material.SNOW || + material == Material.CRAFTED_SNOW || material == Material.CLAY) { + return getDigSpeed(stack, type); + } + } else if (type == ToolType.SWORD) { + // Cobwebs - instant break + if (block == Blocks.WEB) { + return 15.0f; + } + // Leaves - faster + if (material == Material.LEAVES) { + return 1.5f; + } + return 1.0f; + } + + return 1.0f; + } + + @Override + public boolean canHarvestBlock(IBlockState state) { + // Swords can harvest cobwebs + Block block = state.getBlock(); + return block == Blocks.WEB; + } + + @Override + public boolean canHarvestBlock(IBlockState state, ItemStack stack) { + ToolType type = LootUtils.getToolType(stack); + Material material = state.getMaterial(); + Block block = state.getBlock(); + + if (type == ToolType.PICKAXE) { + return material == Material.ROCK || material == Material.IRON || material == Material.ANVIL; + } else if (type == ToolType.SHOVEL) { + return material == Material.GROUND || material == Material.GRASS || + material == Material.SAND || material == Material.SNOW || + material == Material.CRAFTED_SNOW || material == Material.CLAY; + } else if (type == ToolType.AXE) { + return material == Material.WOOD || material == Material.PLANTS || material == Material.VINE; + } else if (type == ToolType.SWORD) { + return block == Blocks.WEB; + } + + return false; + } + + @Override + public int getHarvestLevel(ItemStack stack, String toolClass, @Nullable EntityPlayer player, @Nullable IBlockState blockState) { + ToolType type = LootUtils.getToolType(stack); + + // Return diamond-level harvest level for matching tool types + if (type == ToolType.PICKAXE && toolClass.equals("pickaxe")) { + return 3; // Diamond level + } + if (type == ToolType.AXE && toolClass.equals("axe")) { + return 3; + } + if (type == ToolType.SHOVEL && toolClass.equals("shovel")) { + return 3; + } + + return -1; + } + + @Override + public Multimap getAttributeModifiers(EntityEquipmentSlot slot, ItemStack stack) { + Multimap multimap = super.getAttributeModifiers(slot, stack); + + if (slot == EntityEquipmentSlot.MAINHAND) { + ToolType tt = LootUtils.getToolType(stack); + float attack = getAttackDamage(stack, tt); + float speed = getAttackSpeed(stack, tt); + + multimap.put(SharedMonsterAttributes.ATTACK_DAMAGE.getName(), + new AttributeModifier(ATTACK_DAMAGE_MODIFIER, "Weapon modifier", attack, 0)); + multimap.put(SharedMonsterAttributes.ATTACK_SPEED.getName(), + new AttributeModifier(ATTACK_SPEED_MODIFIER, "Weapon modifier", speed, 0)); + } + + return multimap; + } + + @Override + public boolean hitEntity(ItemStack stack, EntityLivingBase target, EntityLivingBase attacker) { + ToolType type = LootUtils.getToolType(stack); + + if (type == ToolType.AXE || type == ToolType.SWORD) { + LootUtils.addXp(stack, attacker, 1); + } + + List mods = LootNBT.getModifiers(stack); + + boolean shouldSkipBreak = false; + for (Modifier mod : mods) { + if (mod instanceof EntityHurtModifier) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + EntityHurtModifier ehm = (EntityHurtModifier) mod; + if (ehm.hurtEnemy(stack, target, attacker)) { + shouldSkipBreak = true; + } + } + if (mod instanceof Unbreaking) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + Unbreaking unbreaking = (Unbreaking) mod; + if (unbreaking.test(target.world)) { + shouldSkipBreak = true; + } + } + } + + if (!shouldSkipBreak) { + stack.damageItem(1, attacker); + } + + return true; + } + + @Override + public boolean onBlockDestroyed(ItemStack stack, World world, IBlockState state, BlockPos pos, EntityLivingBase player) { + if (!world.isRemote && state.getBlockHardness(world, pos) != 0.0F) { + List mods = LootNBT.getModifiers(stack); + + boolean shouldSkipBreak = false; + for (Modifier mod : mods) { + if (mod instanceof BlockBreakModifier) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + BlockBreakModifier bbm = (BlockBreakModifier) mod; if (bbm.startBreak(stack, pos, player)) { - shouldSkipBreak = true; - } - } - - if (mod instanceof Unbreaking unbreaking) { - if (!Config.traitEnabled(mod.tagName())) { - continue; - } - - if (unbreaking.test(level)) { - shouldSkipBreak = true; - } - - } - } - - if (!shouldSkipBreak) { - stack.hurtAndBreak(1, player,EquipmentSlot.MAINHAND); - } - - LootUtils.addXp(stack, player, 1); - - } - - return true; - } - - - - @Override - public int getMaxDamage(@NotNull ItemStack stack) { - float stats = (LootUtils.getStats(stack) + 10.0f) * 80.0f; - - return (int) stats; - } - - @Override - public @NotNull InteractionResult useOn(UseOnContext ctx) { - - ItemStack itemstack = ctx.getItemInHand(); - ToolType type = LootUtils.getToolType(itemstack); - List mods = LootUtils.getModifiers(itemstack); - - // First, try UseModifier abilities - for (Modifier mod : mods) { - - if (mod instanceof UseModifier um) { - if (!Config.traitEnabled(mod.tagName())) { - continue; - } - - InteractionResult result = um.use(ctx); - if (result.consumesAction()) { - return result; // Modifier consumed the action - } - } - - } - - // No modifier consumed - try vanilla tool behaviors - if (type == ToolType.AXE) { - InteractionResult result = tryAxeActions(ctx); - if (result.consumesAction()) return result; - } - - if (type == ToolType.SHOVEL) { - InteractionResult result = tryShovelFlatten(ctx); - if (result.consumesAction()) return result; - } - - return InteractionResult.PASS; - } - - private InteractionResult tryAxeActions(UseOnContext ctx) { - Level level = ctx.getLevel(); - BlockPos pos = ctx.getClickedPos(); - BlockState state = level.getBlockState(pos); - Player player = ctx.getPlayer(); - ItemStack stack = ctx.getItemInHand(); - - // Try stripping logs - BlockState stripped = state.getToolModifiedState(ctx, ItemAbilities.AXE_STRIP, false); - if (stripped != null) { - level.playSound(player, pos, SoundEvents.AXE_STRIP, SoundSource.BLOCKS, 1.0F, 1.0F); - if (!level.isClientSide()) { - level.setBlock(pos, stripped, 11); - level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, stripped)); - stack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND); - } - return InteractionResult.SUCCESS; - } - - // Try scraping oxidation - BlockState scraped = state.getToolModifiedState(ctx, ItemAbilities.AXE_SCRAPE, false); - if (scraped != null) { - level.playSound(player, pos, SoundEvents.AXE_SCRAPE, SoundSource.BLOCKS, 1.0F, 1.0F); - if (!level.isClientSide()) { - level.setBlock(pos, scraped, 11); - level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, scraped)); - stack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND); - } - return InteractionResult.SUCCESS; - } - - // Try removing wax - BlockState unwaxed = state.getToolModifiedState(ctx, ItemAbilities.AXE_WAX_OFF, false); - if (unwaxed != null) { - level.playSound(player, pos, SoundEvents.AXE_WAX_OFF, SoundSource.BLOCKS, 1.0F, 1.0F); - if (!level.isClientSide()) { - level.setBlock(pos, unwaxed, 11); - level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, unwaxed)); - stack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND); - } - return InteractionResult.SUCCESS; - } - - return InteractionResult.PASS; - } - - private InteractionResult tryShovelFlatten(UseOnContext ctx) { - if (ctx.getClickedFace() != Direction.UP) return InteractionResult.PASS; - - Level level = ctx.getLevel(); - BlockPos pos = ctx.getClickedPos(); - - if (!level.getBlockState(pos.above()).isAir()) return InteractionResult.PASS; - - BlockState flattened = level.getBlockState(pos).getToolModifiedState(ctx, ItemAbilities.SHOVEL_FLATTEN, false); - if (flattened != null) { - Player player = ctx.getPlayer(); - level.playSound(player, pos, SoundEvents.SHOVEL_FLATTEN, SoundSource.BLOCKS, 1.0F, 1.0F); - if (!level.isClientSide()) { - level.setBlock(pos, flattened, 11); - level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(player, flattened)); - ctx.getItemInHand().hurtAndBreak(1, player, EquipmentSlot.MAINHAND); - } - return InteractionResult.SUCCESS; - } - return InteractionResult.PASS; - } - - @Override - public @NotNull InteractionResult use(@NotNull Level level, Player player, @NotNull InteractionHand hand) { - ItemStack toolItem = player.getItemInHand(hand); - - boolean used = false; - - List mods = LootUtils.getModifiers(toolItem); - - for (Modifier mod : mods) { - - if (mod instanceof UseModifier um) { - if (!Config.traitEnabled(mod.tagName())) { - continue; - } - - if (um.useAnywhere()) { - used = used || um.use(level, player, hand); - } - } - - } - - if (used) { - if (player instanceof ServerPlayer sPlayer) { - StatType itemUsed = Stats.ITEM_USED; - - sPlayer.getStats().increment(sPlayer, itemUsed.get(ModItems.TOOL.get()), 1); - } - - player.awardStat(Stats.ITEM_USED.get(this)); - - return InteractionResult.SUCCESS; - } - - return InteractionResult.PASS; - } + shouldSkipBreak = true; + } + } + + if (mod instanceof Unbreaking) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + Unbreaking unbreaking = (Unbreaking) mod; + if (unbreaking.test(world)) { + shouldSkipBreak = true; + } + } + } - private MutableComponent makeComp(String text, ChatFormatting color) { - MutableComponent comp = Component.empty(); - comp.append(text); - comp = comp.withStyle(color); + if (!shouldSkipBreak) { + stack.damageItem(1, player); + } - return comp; - } + LootUtils.addXp(stack, player, 1); + } + + return true; + } + + @Override + public int getMaxDamage(ItemStack stack) { + float stats = (LootUtils.getStats(stack) + 10.0f) * 80.0f; + return (int) stats; + } + + @Override + public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, + EnumFacing facing, float hitX, float hitY, float hitZ) { + ItemStack stack = player.getHeldItem(hand); + List mods = LootNBT.getModifiers(stack); + + // Try UseModifier abilities + for (Modifier mod : mods) { + if (mod instanceof UseModifier) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + UseModifier um = (UseModifier) mod; + EnumActionResult result = um.use(player, world, pos, hand, facing, hitX, hitY, hitZ); + if (result != EnumActionResult.PASS) { + return result; + } + } + } + + // TODO: Add vanilla axe stripping and shovel path making for 1.12.2 + // These features were added in later versions + + return EnumActionResult.PASS; + } + + @Override + public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { + ItemStack stack = player.getHeldItem(hand); + List mods = LootNBT.getModifiers(stack); + + boolean used = false; + for (Modifier mod : mods) { + if (mod instanceof UseModifier) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + UseModifier um = (UseModifier) mod; + if (um.useAnywhere()) { + used = used || um.use(world, player, hand); + } + } + } - private void newLine(Consumer tipList) { - tipList.accept(makeComp("", ChatFormatting.GRAY)); - } + if (used) { + return new ActionResult<>(EnumActionResult.SUCCESS, stack); + } - @Override - public void appendHoverText(ItemStack item, TooltipContext pContext, TooltipDisplay display, Consumer tipList, TooltipFlag pTooltipFlag) { - Level level = pContext.level(); + return new ActionResult<>(EnumActionResult.PASS, stack); + } - // Check if shift/ctrl are held using InputConstants - long window = net.minecraft.client.Minecraft.getInstance().getWindow().handle(); - boolean show = org.lwjgl.glfw.GLFW.glfwGetKey(window, org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_SHIFT) == org.lwjgl.glfw.GLFW.GLFW_PRESS - || org.lwjgl.glfw.GLFW.glfwGetKey(window, org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_SHIFT) == org.lwjgl.glfw.GLFW.GLFW_PRESS; + @Override + @SideOnly(Side.CLIENT) + public void addInformation(ItemStack stack, @Nullable World world, List tooltip, ITooltipFlag flag) { + boolean shift = Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT); + boolean ctrl = Keyboard.isKeyDown(Keyboard.KEY_LCONTROL) || Keyboard.isKeyDown(Keyboard.KEY_RCONTROL); - boolean showDescription = org.lwjgl.glfw.GLFW.glfwGetKey(window, org.lwjgl.glfw.GLFW.GLFW_KEY_LEFT_CONTROL) == org.lwjgl.glfw.GLFW.GLFW_PRESS - || org.lwjgl.glfw.GLFW.glfwGetKey(window, org.lwjgl.glfw.GLFW.GLFW_KEY_RIGHT_CONTROL) == org.lwjgl.glfw.GLFW.GLFW_PRESS; + ToolType tt = LootUtils.getToolType(stack); - ToolType tt = LootUtils.getToolType(item); + if (shift) { + tooltip.add(TextFormatting.BLUE + tt.toString()); + } - if (show) { - tipList.accept(makeComp(tt.toString(), ChatFormatting.BLUE)); - } + String lore = LootNBT.getLore(stack); + if (!lore.isEmpty()) { + tooltip.add(TextFormatting.GRAY + lore); + } - MutableComponent desc = makeComp(LootUtils.getItemLore(item), ChatFormatting.GRAY); - tipList.accept(desc); + if (shift) { + tooltip.add(""); + int itemLevel = LootNBT.getLevel(stack); + tooltip.add(TextFormatting.GRAY + "Level: " + itemLevel); + tooltip.add(TextFormatting.GRAY + "XP: " + LootNBT.getXP(stack) + " / " + LootUtils.getMaxXP(itemLevel)); + } - if (show) { - newLine(tipList); - int itemLevel = LootUtils.getLevel(item); - tipList.accept(makeComp("Level: " + itemLevel, ChatFormatting.GRAY)); - tipList.accept(makeComp("XP: " + LootUtils.getXP(item) + " / " + LootUtils.getMaxXP(itemLevel), - ChatFormatting.GRAY)); - } + tooltip.add(""); - newLine(tipList); + List mods = LootNBT.getModifiers(stack); + mods.sort(Comparator.comparing(Modifier::tagName)); - List mods = LootUtils.getModifiers(item); - mods.sort(new Comparator() { - @Override - public int compare(final Modifier object1, final Modifier object2) { - return object1.tagName().compareTo(object2.tagName()); + for (Modifier modifier : mods) { + if (!Config.traitEnabled(modifier.tagName())) { + continue; } - }); - - for (Modifier modifier : mods) { - if (!Config.traitEnabled(modifier.tagName())) { - continue; - } - // Wrapper to bridge List interface to Consumer - List tempList = new ArrayList<>(); - modifier.writeToLore(tempList, show); - tempList.forEach(tipList); - if (show) { - Component details = modifier.writeDetailsToLore(level); - - if (details != null) { - MutableComponent detailComp = makeComp(" - ", ChatFormatting.GRAY); - detailComp.append(details); - tipList.accept(detailComp); - } - } - if (showDescription) { - MutableComponent detailComp = makeComp("", ChatFormatting.GRAY); - detailComp.append(modifier.description()); - tipList.accept(detailComp); - } - } - - if (show) { - newLine(tipList); - - float digSpeed = LootItem.getDigSpeed(item, tt); - tipList.accept(makeComp(String.format("Speed: %.2f", digSpeed), ChatFormatting.GRAY)); - - float attackDamage = LootItem.getAttackDamage(item, tt); - tipList.accept(makeComp(String.format("Damage: %.2f", attackDamage), ChatFormatting.GRAY)); - - } - - if (!show && !showDescription) { - newLine(tipList); - MutableComponent comp = Component.empty(); - comp.append("[Shift for more]"); - comp = comp.withStyle(ChatFormatting.GRAY); - tipList.accept(comp); - MutableComponent descComp = Component.empty(); - descComp.append("[Ctrl for trait info]"); - descComp = descComp.withStyle(ChatFormatting.GRAY); - tipList.accept(descComp); - - } - } - - @Override - public void inventoryTick(ItemStack stack, ServerLevel level, Entity holder, EquipmentSlot slot) { - - // Only trigger for mainhand slot (replacing the old 'holding' boolean check) - if (slot == EquipmentSlot.MAINHAND) { - - List mods = LootUtils.getModifiers(stack); - - for (Modifier mod : mods) { - - if (mod instanceof HoldModifier hodlMod) { - - hodlMod.hold(stack, level, holder); - } - - } - } - - } - - @Override - public boolean isPrimaryItemFor(ItemStack stack, Holder enchantment) { - ToolType type = LootUtils.getToolType(stack); - String enchantPath = enchantment.getRegisteredName(); - - // Universal enchantments - all tools (Unbreaking, Mending) - if (enchantPath.contains("unbreaking") || enchantPath.contains("mending")) { - return true; - } - - // Mining enchantments - pickaxe, axe, shovel only (Efficiency, Fortune, Silk Touch) - if (enchantPath.contains("efficiency") || enchantPath.contains("fortune") || enchantPath.contains("silk_touch")) { - return type == ToolType.PICKAXE || type == ToolType.AXE || type == ToolType.SHOVEL; - } - - // Weapon enchantments - sword and axe (Sharpness, Smite, Bane, Knockback, Fire Aspect, Looting) - if (enchantPath.contains("sharpness") || enchantPath.contains("smite") || enchantPath.contains("bane_of_arthropods") || - enchantPath.contains("knockback") || enchantPath.contains("fire_aspect") || enchantPath.contains("looting")) { - return type == ToolType.SWORD || type == ToolType.AXE; - } - - // Sword-only enchantments (Sweeping Edge) - if (enchantPath.contains("sweeping")) { - return type == ToolType.SWORD; - } - - return false; - } - + modifier.writeToLore(tooltip, shift); + if (shift) { + String details = modifier.writeDetailsToLore(world); + if (details != null) { + tooltip.add(TextFormatting.GRAY + " - " + details); + } + } + if (ctrl) { + tooltip.add(TextFormatting.GRAY + modifier.description()); + } + } + + if (shift) { + tooltip.add(""); + float digSpeed = LootItem.getDigSpeed(stack, tt); + tooltip.add(TextFormatting.GRAY + String.format("Speed: %.2f", digSpeed)); + float attackDamage = LootItem.getAttackDamage(stack, tt); + tooltip.add(TextFormatting.GRAY + String.format("Damage: %.2f", attackDamage)); + } + + if (!shift && !ctrl) { + tooltip.add(""); + tooltip.add(TextFormatting.GRAY + "[Shift for more]"); + tooltip.add(TextFormatting.GRAY + "[Ctrl for trait info]"); + } + } + + @Override + public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean isSelected) { + if (isSelected && !world.isRemote) { + List mods = LootNBT.getModifiers(stack); + + for (Modifier mod : mods) { + if (mod instanceof HoldModifier) { + if (!Config.traitEnabled(mod.tagName())) { + continue; + } + HoldModifier holdMod = (HoldModifier) mod; + holdMod.hold(stack, world, entity); + } + } + } + } + + @Override + public String getItemStackDisplayName(ItemStack stack) { + String name = LootNBT.getToolName(stack); + if (name != null && !name.isEmpty() && !name.equals("Random Tool")) { + return name; + } + return super.getItemStackDisplayName(stack); + } + + @Override + public boolean getIsRepairable(ItemStack toRepair, ItemStack repair) { + return false; + } + + @Override + public boolean isEnchantable(ItemStack stack) { + return true; + } + + @Override + public int getItemEnchantability(ItemStack stack) { + return 15; + } } diff --git a/src/main/java/dev/marston/randomloot/loot/LootNBT.java b/src/main/java/dev/marston/randomloot/loot/LootNBT.java new file mode 100644 index 0000000..bda81e7 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/loot/LootNBT.java @@ -0,0 +1,228 @@ +package dev.marston.randomloot.loot; + +import dev.marston.randomloot.loot.modifiers.Modifier; +import dev.marston.randomloot.loot.modifiers.ModifierRegistry; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; + +import java.util.ArrayList; +import java.util.List; + +/** + * NBT storage utility for Random Loot tools. + * Replaces the DataComponent system from 1.21+ + * + * NBT Structure: + * randomloot (compound) + * ├── modifiers (compound) - each modifier's serialized data + * ├── XP (compound) - {level, xp} + * ├── info (compound) - {type, biomeTemp, biomeKey, dimension, ownerUUID} + * ├── itemStats (compound) - {goodness} + * ├── cosmetics (compound) - {texture} + * └── itemLore (string) + */ +public class LootNBT { + + public static final String ROOT_TAG = "randomloot"; + public static final String MODIFIERS_TAG = "modifiers"; + public static final String XP_TAG = "XP"; + public static final String INFO_TAG = "info"; + public static final String STATS_TAG = "itemStats"; + public static final String COSMETICS_TAG = "cosmetics"; + public static final String LORE_TAG = "itemLore"; + + // ========== Root Tag Management ========== + + public static NBTTagCompound getOrCreateRootTag(ItemStack stack) { + if (!stack.hasTagCompound()) { + stack.setTagCompound(new NBTTagCompound()); + } + NBTTagCompound rootTag = stack.getTagCompound(); + if (!rootTag.hasKey(ROOT_TAG)) { + rootTag.setTag(ROOT_TAG, new NBTTagCompound()); + } + return rootTag.getCompoundTag(ROOT_TAG); + } + + public static NBTTagCompound getRootTag(ItemStack stack) { + if (!stack.hasTagCompound()) { + return new NBTTagCompound(); + } + return stack.getTagCompound().getCompoundTag(ROOT_TAG); + } + + public static boolean hasRootTag(ItemStack stack) { + return stack.hasTagCompound() && stack.getTagCompound().hasKey(ROOT_TAG); + } + + // ========== Modifiers ========== + + public static NBTTagCompound getModifiersTag(ItemStack stack) { + return getRootTag(stack).getCompoundTag(MODIFIERS_TAG); + } + + public static void setModifiersTag(ItemStack stack, NBTTagCompound modifiers) { + getOrCreateRootTag(stack).setTag(MODIFIERS_TAG, modifiers); + } + + public static List getModifiers(ItemStack stack) { + List modifiers = new ArrayList<>(); + NBTTagCompound modsTag = getModifiersTag(stack); + + for (String key : modsTag.getKeySet()) { + Modifier mod = ModifierRegistry.loadModifier(key, modsTag.getCompoundTag(key)); + if (mod != null) { + modifiers.add(mod); + } + } + return modifiers; + } + + public static void addModifier(ItemStack stack, Modifier modifier) { + NBTTagCompound modsTag = getModifiersTag(stack); + modsTag.setTag(modifier.tagName(), modifier.toNBT()); + setModifiersTag(stack, modsTag); + } + + public static void removeModifier(ItemStack stack, String tagName) { + NBTTagCompound modsTag = getModifiersTag(stack); + modsTag.removeTag(tagName); + setModifiersTag(stack, modsTag); + } + + public static boolean hasModifier(ItemStack stack, String tagName) { + return getModifiersTag(stack).hasKey(tagName); + } + + public static void updateModifier(ItemStack stack, Modifier modifier) { + NBTTagCompound modsTag = getModifiersTag(stack); + modsTag.setTag(modifier.tagName(), modifier.toNBT()); + setModifiersTag(stack, modsTag); + } + + // ========== XP/Level ========== + + public static int getLevel(ItemStack stack) { + return getRootTag(stack).getCompoundTag(XP_TAG).getInteger("level"); + } + + public static void setLevel(ItemStack stack, int level) { + NBTTagCompound xpTag = getOrCreateRootTag(stack).getCompoundTag(XP_TAG); + xpTag.setInteger("level", level); + getOrCreateRootTag(stack).setTag(XP_TAG, xpTag); + } + + public static int getXP(ItemStack stack) { + return getRootTag(stack).getCompoundTag(XP_TAG).getInteger("xp"); + } + + public static void setXP(ItemStack stack, int xp) { + NBTTagCompound xpTag = getOrCreateRootTag(stack).getCompoundTag(XP_TAG); + xpTag.setInteger("xp", xp); + getOrCreateRootTag(stack).setTag(XP_TAG, xpTag); + } + + // ========== Tool Info ========== + + public static NBTTagCompound getInfoTag(ItemStack stack) { + return getRootTag(stack).getCompoundTag(INFO_TAG); + } + + public static void setInfoTag(ItemStack stack, NBTTagCompound info) { + getOrCreateRootTag(stack).setTag(INFO_TAG, info); + } + + public static int getToolTypeOrdinal(ItemStack stack) { + return getInfoTag(stack).getInteger("type"); + } + + public static void setToolType(ItemStack stack, int typeOrdinal) { + NBTTagCompound info = getInfoTag(stack); + info.setInteger("type", typeOrdinal); + setInfoTag(stack, info); + } + + public static String getBiomeKey(ItemStack stack) { + NBTTagCompound info = getInfoTag(stack); + return info.hasKey("biomeKey") ? info.getString("biomeKey") : null; + } + + public static float getBiomeTemp(ItemStack stack) { + return getInfoTag(stack).getFloat("biomeTemp"); + } + + public static String getDimension(ItemStack stack) { + NBTTagCompound info = getInfoTag(stack); + return info.hasKey("dimension") ? info.getString("dimension") : "minecraft:overworld"; + } + + public static void setBiomeData(ItemStack stack, String biomeKey, float temp, String dimension) { + NBTTagCompound info = getInfoTag(stack); + info.setString("biomeKey", biomeKey); + info.setFloat("biomeTemp", temp); + info.setString("dimension", dimension); + setInfoTag(stack, info); + } + + public static String getOwnerUUID(ItemStack stack) { + NBTTagCompound info = getInfoTag(stack); + return info.hasKey("ownerUUID") ? info.getString("ownerUUID") : null; + } + + public static void setOwnerUUID(ItemStack stack, String uuid) { + NBTTagCompound info = getInfoTag(stack); + info.setString("ownerUUID", uuid); + setInfoTag(stack, info); + } + + // ========== Stats ========== + + public static float getGoodness(ItemStack stack) { + NBTTagCompound stats = getRootTag(stack).getCompoundTag(STATS_TAG); + return stats.hasKey("goodness") ? stats.getFloat("goodness") : 0.0f; + } + + public static void setGoodness(ItemStack stack, float goodness) { + NBTTagCompound stats = getRootTag(stack).getCompoundTag(STATS_TAG); + stats.setFloat("goodness", goodness); + getOrCreateRootTag(stack).setTag(STATS_TAG, stats); + } + + // ========== Cosmetics ========== + + public static int getTexture(ItemStack stack) { + return getRootTag(stack).getCompoundTag(COSMETICS_TAG).getInteger("texture"); + } + + public static void setTexture(ItemStack stack, int texture) { + NBTTagCompound cosmetics = getRootTag(stack).getCompoundTag(COSMETICS_TAG); + cosmetics.setInteger("texture", texture); + getOrCreateRootTag(stack).setTag(COSMETICS_TAG, cosmetics); + } + + // ========== Lore ========== + + public static String getLore(ItemStack stack) { + NBTTagCompound root = getRootTag(stack); + return root.hasKey(LORE_TAG) ? root.getString(LORE_TAG) : ""; + } + + public static void setLore(ItemStack stack, String lore) { + getOrCreateRootTag(stack).setString(LORE_TAG, lore); + } + + // ========== Display Name ========== + + public static String getToolName(ItemStack stack) { + NBTTagCompound info = getInfoTag(stack); + return info.hasKey("name") ? info.getString("name") : "Random Tool"; + } + + public static void setToolName(ItemStack stack, String name) { + NBTTagCompound info = getInfoTag(stack); + info.setString("name", name); + setInfoTag(stack, info); + // Also set the actual display name + stack.setStackDisplayName(name); + } +} diff --git a/src/main/java/dev/marston/randomloot/loot/LootTableHandler.java b/src/main/java/dev/marston/randomloot/loot/LootTableHandler.java new file mode 100644 index 0000000..1bef9d8 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/loot/LootTableHandler.java @@ -0,0 +1,64 @@ +package dev.marston.randomloot.loot; + +import dev.marston.randomloot.Config; +import dev.marston.randomloot.RandomLoot; +import dev.marston.randomloot.items.ModItems; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.storage.loot.LootEntry; +import net.minecraft.world.storage.loot.LootEntryItem; +import net.minecraft.world.storage.loot.LootPool; +import net.minecraft.world.storage.loot.RandomValueRange; +import net.minecraft.world.storage.loot.conditions.LootCondition; +import net.minecraft.world.storage.loot.conditions.RandomChance; +import net.minecraft.world.storage.loot.functions.LootFunction; +import net.minecraftforge.event.LootTableLoadEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +/** + * Handles injection of loot cases into vanilla loot tables. + */ +public class LootTableHandler { + + @SubscribeEvent + public void onLootTableLoad(LootTableLoadEvent event) { + String name = event.getName().toString(); + + // Add to dungeon, temple, and other chest loot tables + if (shouldInjectLoot(name)) { + LootPool casePool = createCasePool(); + event.getTable().addPool(casePool); + } + } + + private boolean shouldInjectLoot(String tableName) { + // Inject into most chest-based loot tables + return tableName.contains("chests/") || + tableName.contains("chest") || + tableName.equals("minecraft:gameplay/fishing/treasure"); + } + + private LootPool createCasePool() { + // Create condition for random chance based on config + LootCondition[] conditions = new LootCondition[] { + new RandomChance((float) Config.CaseChance) + }; + + // Create entry for the case item + LootEntry caseEntry = new LootEntryItem( + ModItems.CASE, + 1, // weight + 0, // quality + new LootFunction[0], // functions + new LootCondition[0], // conditions + RandomLoot.MODID + ":case_entry" + ); + + return new LootPool( + new LootEntry[] { caseEntry }, + conditions, + new RandomValueRange(0, 1), // rolls + new RandomValueRange(0, 0), // bonus rolls + RandomLoot.MODID + "_case_pool" + ); + } +} diff --git a/src/main/java/dev/marston/randomloot/loot/LootUtils.java b/src/main/java/dev/marston/randomloot/loot/LootUtils.java index 8380dcf..f35b187 100644 --- a/src/main/java/dev/marston/randomloot/loot/LootUtils.java +++ b/src/main/java/dev/marston/randomloot/loot/LootUtils.java @@ -1,862 +1,344 @@ package dev.marston.randomloot.loot; -import com.google.gson.JsonObject; -import com.mojang.serialization.DataResult; -import com.mojang.serialization.MapCodec; import dev.marston.randomloot.Config; import dev.marston.randomloot.RandomLoot; -import dev.marston.randomloot.component.ModDataComponents; -import dev.marston.randomloot.component.ToolModifier; import dev.marston.randomloot.items.ModItems; import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BiomeRestrictedModifier; import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; -import net.minecraft.ChatFormatting; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.renderer.item.properties.numeric.RangeSelectItemModelProperty; -import net.minecraft.core.Holder; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.core.component.DataComponentType; -import net.minecraft.core.component.DataComponents; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; -import net.minecraft.network.chat.TextColor; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.stats.StatType; -import net.minecraft.stats.Stats; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.ItemOwner; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.biome.Biome; -import org.apache.logging.log4j.core.tools.picocli.CommandLine; -import org.jetbrains.annotations.Nullable; - -import java.util.*; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.stats.StatList; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundCategory; +import net.minecraft.world.World; +import net.minecraft.world.biome.Biome; + +import java.util.ArrayList; +import java.util.List; import java.util.Map.Entry; public class LootUtils { - public record TextureProperty() implements RangeSelectItemModelProperty { - public static final MapCodec MAP_CODEC = MapCodec.unit(new TextureProperty()); - - @Override - public float get(ItemStack stack, @Nullable ClientLevel level, @Nullable ItemOwner owner, int seed) { - return LootUtils.getTexture(stack); - } - - @Override - public MapCodec type() { - return MAP_CODEC; - } - } - - private static int PICKAXE_COUNT = 18; - private static int AXE_COUNT = 14; - private static int SHOVEL_COUNT = 9; - private static int SWORD_COUNT = 50; - - public static ItemStack CloneItem(ItemStack stack) { - ItemStack copy = new ItemStack(ModItems.TOOL.asItem()); - - @Nullable ToolModifier mods = stack.get(ModDataComponents.TOOL_MODIFIER); - if (mods == null) { - return copy; - } - - // Build the new map first, then create ToolModifier with it - Map newTags = new HashMap<>(); - Map tags = mods.getTags(); - tags.forEach((s, compoundTag) -> { - newTags.put(s, compoundTag.copy()); - }); - - ToolModifier copyMods = new ToolModifier(newTags); - copy.set(ModDataComponents.TOOL_MODIFIER, copyMods); - - copy.set(DataComponents.CUSTOM_NAME, stack.get(DataComponents.CUSTOM_NAME)); - - return copy; - } - - public static void addLoreLine(ListTag lore, String text, String color) { - JsonObject value = new JsonObject(); - - value.addProperty("text", text); - value.addProperty("color", color); - value.addProperty("italic", false); - - StringTag nbtName = StringTag.valueOf(value.toString()); - - lore.add(nbtName); - } - - public static void setItemName(ItemStack stack, String name, String color) { - MutableComponent comp = Component.literal(name); - RandomLoot.LOGGER.info("COLOR: " + color); - - Style style = Style.EMPTY; - style = style.withItalic(false); - DataResult col = TextColor.parseColor(color); - style = style.withColor(col.getOrThrow()); - - comp = comp.withStyle(style); - - stack.set(DataComponents.CUSTOM_NAME, comp); - } - - public static void setItemLore(ItemStack stack, String lore) { - CompoundTag tag = getOrCreateTagElement(stack, "itemLore"); - - tag.putString("itemLore", lore); - - addTagElement(stack, "itemLore", tag); - } - - public static String getItemLore(ItemStack stack) { - CompoundTag tag = getOrCreateTagElement(stack, "itemLore"); - return tag.getStringOr("itemLore", ""); - } - - public static int getMaxXP(int level) { - int starting = 500; + private static int PICKAXE_COUNT = 18; + private static int AXE_COUNT = 14; + private static int SHOVEL_COUNT = 9; + private static int SWORD_COUNT = 50; + public static int getMaxXP(int level) { + int starting = 500; return (int) (starting * Math.pow(2, level)); - } - - public static ItemStack levelUp(ItemStack item, LivingEntity holder) { - - float stats = getStats(item); - stats = stats * 1.1f; - setStats(item, stats); - - holder.level().playSound(null, holder.getX(), holder.getY(), holder.getZ(), SoundEvents.PLAYER_LEVELUP, - holder.getSoundSource(), 1.0f, 1.0f); - - return item; - } - - public static CompoundTag getOrCreateTagElement(ItemStack stack, String tagName) { + } - @Nullable ToolModifier mods = stack.get(ModDataComponents.TOOL_MODIFIER); - if (mods == null) { - return new CompoundTag(); - } + public static ItemStack levelUp(ItemStack item, EntityLivingBase holder) { + float stats = getStats(item); + stats = stats * 1.1f; + setStats(item, stats); - Map tags = mods.getTags(); - CompoundTag tag = tags.get(tagName); - if (tag == null) { - tag = new CompoundTag(); - } - return tag; - } + holder.world.playSound(null, holder.posX, holder.posY, holder.posZ, + SoundEvents.ENTITY_PLAYER_LEVELUP, SoundCategory.PLAYERS, 1.0f, 1.0f); + return item; + } + public static void addXp(ItemStack item, EntityLivingBase holder, int amount) { + int level = LootNBT.getLevel(item); + int xp = LootNBT.getXP(item); - public static void addTagElement(ItemStack stack, String tagName, CompoundTag tag) { + xp += amount; - @Nullable ToolModifier mods = stack.get(ModDataComponents.TOOL_MODIFIER); - if (mods == null) { - mods = new ToolModifier(new HashMap<>()); - } + int max = getMaxXP(level); - Map tags = mods.getTags(); - HashMap mutTags = new HashMap<>(tags); - - mutTags.put(tagName, tag); - - mods = new ToolModifier(mutTags); - - stack.set(ModDataComponents.TOOL_MODIFIER, mods); - } - - public static void removeTagKey(ItemStack stack, String tagName) { - @Nullable ToolModifier mods = stack.get(ModDataComponents.TOOL_MODIFIER); - if (mods == null) { - mods = new ToolModifier(new HashMap<>()); - } - - Map tags = mods.getTags(); - - - HashMap mutTags = new HashMap<>(tags); - - mutTags.remove(tagName); - - mods = new ToolModifier(mutTags); - - stack.set(ModDataComponents.TOOL_MODIFIER, mods); - } - - public static void addXp(ItemStack item, LivingEntity holder, int amount) { - - CompoundTag tag = getOrCreateTagElement(item,"XP"); - - int level = tag.getIntOr("level", 0); - - int xp = tag.getIntOr("xp", 0); - - xp += amount; + while (xp >= max) { + xp = xp - max; + level++; + levelUp(item, holder); + } - int max = getMaxXP(level); + LootNBT.setLevel(item, level); + LootNBT.setXP(item, xp); + } - while (xp >= max) { - xp = xp - max; - level++; - levelUp(item, holder); - } + public static float getStats(ItemStack stack) { + return LootNBT.getGoodness(stack); + } - tag.putInt("level", level); - tag.putInt("xp", xp); + public static void setStats(ItemStack stack, float goodness) { + LootNBT.setGoodness(stack, goodness); + } - addTagElement(item,"XP", tag); + public static ToolType getToolType(ItemStack item) { + int typeOrdinal = LootNBT.getToolTypeOrdinal(item); + if (typeOrdinal < 0 || typeOrdinal >= ToolType.values().length) { + return ToolType.NULL; + } + return ToolType.values()[typeOrdinal]; + } + + public static ItemStack setToolType(ItemStack item, ToolType type) { + LootNBT.setToolType(item, type.ordinal()); + return item; + } + + public static void addModifier(ItemStack item, Modifier mod) { + // Check if modifier already exists and can level + List existing = LootNBT.getModifiers(item); + for (Modifier m : existing) { + if (m.tagName().equals(mod.tagName())) { + if (m.canLevel()) { + m.levelUp(); + LootNBT.updateModifier(item, m); + } + return; + } + } + + // Add new modifier + LootNBT.addModifier(item, mod.clone()); + } + + public static void updateModifier(ItemStack item, Modifier mod) { + LootNBT.updateModifier(item, mod); + } + + public static ItemStack removeModifier(ItemStack item, Modifier mod) { + LootNBT.removeModifier(item, mod.tagName()); + return item; + } + + private static void storeBiomeData(ItemStack lootItem, World world, EntityPlayer player) { + float temp = 0.7f; + String biomeKey = "unknown"; + String dimension = "minecraft:overworld"; + + if (player != null) { + Biome biome = world.getBiome(player.getPosition()); + temp = biome.getDefaultTemperature(); + + ResourceLocation biomeRL = biome.getRegistryName(); + if (biomeRL != null) { + biomeKey = biomeRL.toString(); + } - } + // Get dimension + dimension = "minecraft:" + world.provider.getDimensionType().getName(); + } - public static int getLevel(ItemStack item) { + LootNBT.setBiomeData(lootItem, biomeKey, temp, dimension); + RandomLoot.LOGGER.info("Tool generated in biome: {} with temp: {} in dimension: {}", biomeKey, temp, dimension); + } - CompoundTag tag = getOrCreateTagElement(item,"XP"); + private static String biomeKeyToReadableName(String biomeKey) { + if (biomeKey == null || biomeKey.isEmpty() || biomeKey.equals("unknown")) { + return "an Unknown Biome"; + } - return tag.getIntOr("level", 0); - } + // Remove namespace (minecraft:desert -> desert) + String biomeName = biomeKey.contains(":") ? biomeKey.substring(biomeKey.indexOf(":") + 1) : biomeKey; - public static int getXP(ItemStack item) { + // Replace underscores with spaces and capitalize each word + String[] words = biomeName.split("_"); + StringBuilder result = new StringBuilder(); + for (String word : words) { + if (word.isEmpty()) continue; + if (result.length() > 0) result.append(" "); + result.append(Character.toUpperCase(word.charAt(0))).append(word.substring(1)); + } - CompoundTag tag = getOrCreateTagElement(item,"XP"); + return "a " + result.toString(); + } - return tag.getIntOr("xp", 0); - } + private static void generateLore(ItemStack lootItem, World world, EntityPlayer player) { + float temp = LootNBT.getBiomeTemp(lootItem); - public static ItemStack setLevelAndXP(ItemStack item, int level, int xp) { + String name = "a machine"; + if (player != null) { + name = player.getName(); + } - CompoundTag tag = getOrCreateTagElement(item,"XP"); + String forger = NameGenerator.generateForger(temp); + String biomeKey = LootNBT.getBiomeKey(lootItem); + String biomeName = biomeKeyToReadableName(biomeKey); - tag.putInt("level", level); - tag.putInt("xp", xp); + String loreText = "Discovered by " + name + " in " + biomeName + ", forged by " + forger + "."; + LootNBT.setLore(lootItem, loreText); - addTagElement(item,"XP", tag); + // Generate and set the tool name + String toolName = NameGenerator.generateNameWPrefix(temp, world.isRaining()); + LootNBT.setToolName(lootItem, toolName); + } - return item; - } + public static void generateNewTrait(ItemStack stack, ToolType type) { + List mods = LootNBT.getModifiers(stack); + ArrayList allowedMods = new ArrayList<>(); - public static List getModifiers(ItemStack item) { + RandomLoot.LOGGER.info("=== Generating trait for {} ===", type); - ArrayList tags = new ArrayList(); + for (Entry entry : ModifierRegistry.getModifiers().entrySet()) { + Modifier newMod = entry.getValue(); - CompoundTag modifiers = getOrCreateTagElement(item,Modifier.MODTAG); + if (!Config.traitEnabled(newMod.tagName())) { + continue; + } - Set mods = modifiers.keySet(); + // Filter by biome restrictions + if (newMod instanceof BiomeRestrictedModifier) { + BiomeRestrictedModifier biomeRestricted = (BiomeRestrictedModifier) newMod; + String biomeKey = LootNBT.getBiomeKey(stack); + float temp = LootNBT.getBiomeTemp(stack); + String dimension = LootNBT.getDimension(stack); - for (String string : mods) { - CompoundTag modTag = modifiers.getCompoundOrEmpty(string); + if (!biomeRestricted.canSpawnInBiome(biomeKey, temp, dimension)) { + continue; + } + } - Modifier finalModifier = ModifierRegistry.loadModifier(string, modTag); - if (finalModifier == null) { + if (!newMod.forTool(type)) { continue; } - if (!Config.traitEnabled(finalModifier.tagName())) { - continue; - } - tags.add(finalModifier); + boolean compatible = true; + for (Modifier modifier : mods) { + if (modifier.tagName().equals(newMod.tagName())) { + if (!modifier.canLevel()) { + compatible = false; + break; + } + } + + if (!modifier.compatible(newMod)) { + compatible = false; + break; + } + } + if (compatible) { + allowedMods.add(newMod); + } } - return tags; - } - - public static void addModifier(ItemStack item, Modifier mod) { - - CompoundTag modifiers = getOrCreateTagElement(item,Modifier.MODTAG); - CompoundTag newTag = mod.toNBT(); - - boolean oldModFound = modifiers.contains(mod.tagName()); // does that tag already exist on the tool? - - if (!oldModFound) { // tag doesn't exist so we're adding a new trait. - - modifiers.put(mod.tagName(), newTag); - removeTagKey(item,Modifier.MODTAG); - addTagElement(item,Modifier.MODTAG, modifiers); - return; - - } - - CompoundTag oldmod = modifiers.getCompoundOrEmpty(mod.tagName()); - Modifier oldModifier = mod.fromNBT(oldmod); - - if (!oldModifier.canLevel()) { - return; - } - - oldModifier.levelUp(); - modifiers.put(oldModifier.tagName(), oldModifier.toNBT()); - - removeTagKey(item,Modifier.MODTAG); - addTagElement(item,Modifier.MODTAG, modifiers); - - } - - public static void updateModifier(ItemStack item, Modifier mod) { - - CompoundTag modifiers = getOrCreateTagElement(item,Modifier.MODTAG); - - boolean oldModFound = modifiers.contains(mod.tagName()); // does that tag already exist on the tool? - - if (!oldModFound) { // tag doesn't exist so we're adding a new trait. - return; - } - - modifiers.put(mod.tagName(), mod.toNBT()); - - removeTagKey(item,Modifier.MODTAG); - addTagElement(item,Modifier.MODTAG, modifiers); - } - - public static ItemStack removeModifier(ItemStack item, Modifier mod) { - - CompoundTag modifiers = getOrCreateTagElement(item,Modifier.MODTAG); - - modifiers.remove(mod.tagName()); - - removeTagKey(item,Modifier.MODTAG); - addTagElement(item,Modifier.MODTAG, modifiers); - - return item; - } - - public static void setStats(ItemStack stack, float goodness) { - CompoundTag statTag = getOrCreateTagElement(stack,"itemStats"); - - statTag.putFloat("goodness", goodness); - - addTagElement(stack,"itemStats", statTag); - } - - public static float getStats(ItemStack stack) { - CompoundTag statTag = getOrCreateTagElement(stack,"itemStats"); - - return statTag.getFloatOr("goodness", 0f); - } - - public static void setBiomeTemperature(ItemStack stack, float temperature) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - infoTag.putFloat("biomeTemp", temperature); - addTagElement(stack, "info", infoTag); - } - - public static float getBiomeTemperature(ItemStack stack) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - return infoTag.getFloatOr("biomeTemp", 0.7f); - } - - public static void setBiomeKey(ItemStack stack, String biomeKey) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - infoTag.putString("biomeKey", biomeKey); - addTagElement(stack, "info", infoTag); - } - - public static String getBiomeKey(ItemStack stack) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - return infoTag.getStringOr("biomeKey", ""); - } - - public static void setDimension(ItemStack stack, String dimension) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - infoTag.putString("dimension", dimension); - addTagElement(stack, "info", infoTag); - } - - public static String getDimension(ItemStack stack) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - return infoTag.getStringOr("dimension", "minecraft:overworld"); - } - - public static void setOwnerUUID(ItemStack stack, String uuid) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - infoTag.putString("ownerUUID", uuid); - addTagElement(stack, "info", infoTag); - } + int size = allowedMods.size(); + if (size == 0) { + return; + } - public static String getOwnerUUID(ItemStack stack) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - return infoTag.getStringOr("ownerUUID", ""); - } + int choice = (int) (Math.random() * size); + Modifier m = allowedMods.get(choice); - public static void setOwnerName(ItemStack stack, String name) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - infoTag.putString("ownerName", name); - addTagElement(stack, "info", infoTag); - } + RandomLoot.LOGGER.info("SELECTED: {}", m.tagName()); + addModifier(stack, m); + } - public static String getOwnerName(ItemStack stack) { - CompoundTag infoTag = getOrCreateTagElement(stack, "info"); - return infoTag.getStringOr("ownerName", ""); - } + public static void generateInitialTraits(ItemStack stack, ToolType type, int count) { + for (int i = 0; i < count; i++) { + generateNewTrait(stack, type); + } + } - public static void setTexture(ItemStack stack, int texture) { - CompoundTag cosmeticTag = getOrCreateTagElement(stack,"cosmetics"); + public static int getToolMaxTextures(ItemStack stack) { + ToolType m = getToolType(stack); - cosmeticTag.putInt("texture", texture); - - addTagElement(stack,"cosmetics", cosmeticTag); - } - - public static float getTexture(ItemStack stack) { - CompoundTag cosmeticTag = getOrCreateTagElement(stack,"cosmetics"); - - int texture = cosmeticTag.getIntOr("texture", 0); - - float index = ((float) texture) / 10000.0f; - - ToolType type = getToolType(stack); - - switch (type) { - - case PICKAXE: - index += 0.1f; - break; - case SHOVEL: - index += 0.2f; - break; - case AXE: - index += 0.3f; - break; - case SWORD: - index += 0.4f; - break; - case NULL: - default: - break; - - } - - return index; - } - - public static int getTextureIndex(ItemStack stack) { - CompoundTag cosmeticTag = getOrCreateTagElement(stack,"cosmetics"); - - return cosmeticTag.getIntOr("texture", 0); - } - - private static void storeBiomeData(ItemStack lootItem, Level level, Player player) { - float temp = 0.7f; - - if (player != null) { - Holder biome = level.getBiome(player.blockPosition()); - Biome b = biome.value(); - temp = b.getBaseTemperature(); - } - - setBiomeTemperature(lootItem, temp); - - // Store biome key for modifier filtering - if (player != null) { - final float finalTemp = temp; // Capture for lambda - Holder biomeHolder = level.getBiome(player.blockPosition()); - - // Get biome key from registry - String biomeKey = "unknown"; - Registry biomeRegistry = level.registryAccess().lookupOrThrow(Registries.BIOME); - - // Try unwrapKey first - if (biomeHolder.unwrapKey().isPresent()) { - biomeKey = biomeHolder.unwrapKey().get().identifier().toString(); - RandomLoot.LOGGER.info("Got biome key from unwrapKey: {}", biomeKey); - } else { - // Fallback: search registry for this biome - RandomLoot.LOGGER.warn("Biome key not available via unwrapKey, searching registry..."); - Biome biome = biomeHolder.value(); - for (var entry : biomeRegistry.entrySet()) { - if (entry.getValue() == biome) { - biomeKey = entry.getKey().identifier().toString(); - RandomLoot.LOGGER.info("Found biome key via registry search: {}", biomeKey); - break; - } - } - } - - setBiomeKey(lootItem, biomeKey); - RandomLoot.LOGGER.info("Tool generated in biome: {} with temp: {}", biomeKey, finalTemp); - - // Store dimension - String dim = level.dimension().identifier().toString(); - setDimension(lootItem, dim); - RandomLoot.LOGGER.info("Tool generated in dimension: {}", dim); - } - } - - private static String biomeKeyToReadableName(String biomeKey) { - if (biomeKey == null || biomeKey.isEmpty() || biomeKey.equals("unknown")) { - return "an Unknown Biome"; - } - - // Remove namespace (minecraft:desert -> desert) - String biomeName = biomeKey.contains(":") ? biomeKey.substring(biomeKey.indexOf(":") + 1) : biomeKey; - - // Replace underscores with spaces and capitalize each word - String[] words = biomeName.split("_"); - StringBuilder result = new StringBuilder(); - for (String word : words) { - if (word.isEmpty()) continue; // Skip empty strings from split - if (result.length() > 0) result.append(" "); - result.append(Character.toUpperCase(word.charAt(0))).append(word.substring(1)); - } - - return "a " + result.toString(); - } - - private static void generateLore(ItemStack lootItem, Level level, Player player) { - String nameColor = "#50ab4b"; - float temp = getBiomeTemperature(lootItem); // Get stored temperature - - if (player != null) { - if (level.dimension().equals(Level.NETHER)) { - nameColor = "#FF8C19"; - } else if (level.dimension().equals(Level.END)) { - nameColor = "#C419FF"; - } - } - - LootUtils.setItemName(lootItem, NameGenerator.generateNameWPrefix(temp, level.isRaining()), nameColor); - - String forger = NameGenerator.generateForger(temp); - - String name = "a machine"; - if (player != null) { - name = player.getDisplayName().getString(); - } - - // Get biome name for lore - String biomeKey = getBiomeKey(lootItem); - String biomeName = biomeKeyToReadableName(biomeKey); - - String loreText = "Discovered by " + name + " in " + biomeName + ", forged by " + forger + "."; - - LootUtils.setItemLore(lootItem, loreText); - - } - - public static ToolType getToolType(ItemStack item) { - CompoundTag toolType = getOrCreateTagElement(item,"info"); - String type = toolType.getStringOr("type", ""); - if (type.isEmpty()) { - return ToolType.NULL; - } - return ToolType.valueOf(type); - } - - public static ItemStack setToolType(ItemStack item, ToolType type) { - CompoundTag toolInfo = getOrCreateTagElement(item,"info"); - toolInfo.putString("type", type.name()); - addTagElement(item,"info", toolInfo); - return item; - } - - public static void generateNewTrait(ItemStack stack, ToolType type) { - - List mods = getModifiers(stack); - - ArrayList allowedMods = new ArrayList(); - - RandomLoot.LOGGER.info("=== Generating trait for {} ===", type); - - for (Entry entry : ModifierRegistry.getModifiers().entrySet()) { - Modifier newMod = entry.getValue(); - - if (!Config.traitEnabled(newMod.tagName())) { - RandomLoot.LOGGER.info(" {} - SKIP (disabled in config)", newMod.tagName()); - continue; - } - - // Filter by biome restrictions (for natural spawning only) - if (newMod instanceof BiomeRestrictedModifier biomeRestricted) { - String biomeKey = getBiomeKey(stack); - float temp = getBiomeTemperature(stack); - String dimension = getDimension(stack); + switch (m) { + case PICKAXE: return PICKAXE_COUNT; + case AXE: return AXE_COUNT; + case SHOVEL: return SHOVEL_COUNT; + case SWORD: return SWORD_COUNT; + default: return 0; + } + } - boolean canSpawn = biomeRestricted.canSpawnInBiome(biomeKey, temp, dimension); - RandomLoot.LOGGER.info(" {} - biome: {}, temp: {}, dim: {}, canSpawn: {}", - newMod.tagName(), biomeKey, temp, dimension, canSpawn); + public static ItemStack genTool(EntityPlayer player, World world) { + ItemStack lootItem = new ItemStack(ModItems.TOOL); - if (!canSpawn) { - RandomLoot.LOGGER.info(" {} - SKIP (biome restriction)", newMod.tagName()); - continue; // Skip this modifier if biome doesn't match - } - } + if (world.isRemote) { + return ItemStack.EMPTY; + } - if (!newMod.forTool(type)) { - RandomLoot.LOGGER.info(" {} - SKIP (wrong tool type)", newMod.tagName()); - continue; - } + // Calculate goodness based on cases opened + int count = 0; + if (player != null && player instanceof EntityPlayerMP) { + EntityPlayerMP serverPlayer = (EntityPlayerMP) player; + count = serverPlayer.getStatFile().readStat(StatList.getObjectUseStats(ModItems.CASE)); + } - boolean compatible = true; + float goodness = (float) (Math.sqrt(count + 1) * Config.Goodness); + int traits = (int) (Math.floor(goodness / 2.0f)); + + RandomLoot.LOGGER.info("Generating tool: count={}, goodness={}, traits={}", count, goodness, traits); + + LootNBT.setGoodness(lootItem, goodness); + + // Random tool type + int toolType = (int) (Math.random() * 4); + ToolType m; + switch (toolType) { + case 0: m = ToolType.PICKAXE; break; + case 1: m = ToolType.AXE; break; + case 2: m = ToolType.SHOVEL; break; + case 3: m = ToolType.SWORD; break; + default: m = ToolType.PICKAXE; + } - for (Modifier modifier : mods) { + int textureCount; + switch (m) { + case PICKAXE: textureCount = PICKAXE_COUNT; break; + case AXE: textureCount = AXE_COUNT; break; + case SHOVEL: textureCount = SHOVEL_COUNT; break; + case SWORD: textureCount = SWORD_COUNT; break; + default: textureCount = 0; + } - if (modifier.tagName().equals(newMod.tagName())) { - if (!modifier.canLevel()) { - RandomLoot.LOGGER.info(" {} - SKIP (already has max level)", newMod.tagName()); - compatible = false; - break; - } - } + setToolType(lootItem, m); - if (!modifier.compatible(newMod)) { - RandomLoot.LOGGER.info(" {} - SKIP (incompatible with {})", newMod.tagName(), modifier.tagName()); - compatible = false; - break; - } - - } + // Store biome data BEFORE generating traits + storeBiomeData(lootItem, world, player); - if (compatible) { - RandomLoot.LOGGER.info(" {} - ALLOWED", newMod.tagName()); - allowedMods.add(newMod); - } + // Store owner data for Soulbound modifier + if (player != null) { + LootNBT.setOwnerUUID(lootItem, player.getUniqueID().toString()); + } - } + generateInitialTraits(lootItem, m, traits); + generateLore(lootItem, world, player); - int size = allowedMods.size(); + LootNBT.setTexture(lootItem, (int) (Math.random() * textureCount)); - RandomLoot.LOGGER.info("Total allowed modifiers: {}", size); + return lootItem; + } - if (size == 0) { - RandomLoot.LOGGER.info("No modifiers available - skipping trait generation"); - return; - } - - int choice = (int) (Math.random() * size); - - Modifier m = allowedMods.get(choice); - - RandomLoot.LOGGER.info("SELECTED: {}", m.tagName()); - - addModifier(stack, m); - - } - - public static void generateInitialTraits(ItemStack stack, ToolType type, int count) { - for (int i = 0; i < count; i++) { - generateNewTrait(stack, getToolType(stack)); - } - } - - public static int getToolMaxTextures(ItemStack stack) { - ToolType m = getToolType(stack); - - return switch (m) { - case PICKAXE: { - yield PICKAXE_COUNT; - } - case AXE: { - yield AXE_COUNT; - } - case SHOVEL: { - yield SHOVEL_COUNT; - } - case SWORD: { - yield SWORD_COUNT; - } - default: - yield 0; - }; - - } - - public static int addToolTextures(ItemStack stack, int count) { - int max = getToolMaxTextures(stack); - - if (max == 0) { - return 0; - } - - int current = getTextureIndex(stack); - - int newTexture = (current + count) % max; - - return newTexture; - - } - - public static void addTexture(ItemStack stack, int count) { - setTexture(stack, addToolTextures(stack, count)); - } - - public static ItemStack genTool(Player player, Level level) { - ItemStack lootItem = new ItemStack(ModItems.TOOL.get()); - - /** - * We want to be able to make the loot get better over time for players. This is - * pretty trivial with the statistics of a player since we can just check how - * many cases they've opened. The more cases they've opened, the better their - * tools will be. We do this on a SQRT curve to ensure that tools get better - * over time without getting out of hand. Since the tools level pretty closely - * to this curve we can expect that users won't constantly feel like they should - * use the same tool since it's already leveled up to be better than what these - * new tools start at. But at the same time, players won't feel sad abandoning - * their old tools in favor of these new ones since they're comparable AND these - * new ones have a clean XP slate so they can level faster again. - */ - int count = 0; - if (level.isClientSide()) { - return ItemStack.EMPTY; - } - - if (player != null) { - ServerPlayer sPlayer = (ServerPlayer) player; - StatType itemUsed = Stats.ITEM_USED; - count = sPlayer.getStats().getValue(itemUsed.get(ModItems.CASE.get())); - } - - float goodness = (float) (Math.sqrt(count + 1) * Config.Goodness); // keeping track of items stats through a - // "goodness" curve - - int traits = (int) (Math.floor(goodness / 2.0f)); // how many traits the tool should be created with - - LootUtils.setStats(lootItem, goodness); - - int toolType = (int) (Math.random() * 4); - ToolType m = switch (toolType) { - case 0: { - yield ToolType.PICKAXE; - } - case 1: { - yield ToolType.AXE; - } - case 2: { - yield ToolType.SHOVEL; - } - case 3: { - yield ToolType.SWORD; - } - default: { - yield ToolType.PICKAXE; - } - }; - - int textureCount = switch (m) { - case PICKAXE: { - yield PICKAXE_COUNT; - } - case AXE: { - yield AXE_COUNT; - } - case SHOVEL: { - yield SHOVEL_COUNT; - } - case SWORD: { - yield SWORD_COUNT; - } - default: - yield 0; - }; - - lootItem = setToolType(lootItem, m); - - // Store biome data BEFORE generating traits (so biome-restricted modifiers work) - storeBiomeData(lootItem, level, player); - - // Store owner data for Soulbound modifier - if (player != null) { - setOwnerUUID(lootItem, player.getStringUUID()); - setOwnerName(lootItem, player.getDisplayName().getString()); - } - - generateInitialTraits(lootItem, m, traits); - - generateLore(lootItem, level, player); - - LootUtils.setTexture(lootItem, (int) (Math.random() * textureCount)); - - return lootItem; - } - - public static boolean generateTool(ServerPlayer player, Level level) { - - ItemStack lootItem = genTool(player, level); - - boolean added = player.getInventory().add(lootItem); - if (!added) { - ItemEntity dropItem = new ItemEntity(EntityType.ITEM, level); - dropItem.setItem(lootItem); - dropItem.setPos(player.position()); - - level.addFreshEntity(dropItem); - } - return true; - } - - public static String roman(int input) { - if (input < 1 || input > 3999) - return "Invalid Roman Number Value"; - StringBuilder s = new StringBuilder(); - while (input >= 1000) { - s.append("M"); - input -= 1000; - } - while (input >= 900) { - s.append("CM"); - input -= 900; - } - while (input >= 500) { - s.append("D"); - input -= 500; - } - while (input >= 400) { - s.append("CD"); - input -= 400; - } - while (input >= 100) { - s.append("C"); - input -= 100; - } - while (input >= 90) { - s.append("XC"); - input -= 90; - } - while (input >= 50) { - s.append("L"); - input -= 50; - } - while (input >= 40) { - s.append("XL"); - input -= 40; - } - while (input >= 10) { - s.append("X"); - input -= 10; - } - while (input >= 9) { - s.append("IX"); - input -= 9; - } - while (input >= 5) { - s.append("V"); - input -= 5; - } - while (input >= 4) { - s.append("IV"); - input -= 4; - } - while (input >= 1) { - s.append("I"); - input -= 1; - } - return s.toString(); - - } + public static boolean generateTool(EntityPlayerMP player, World world) { + ItemStack lootItem = genTool(player, world); + boolean added = player.inventory.addItemStackToInventory(lootItem); + if (!added) { + EntityItem dropItem = new EntityItem(world, player.posX, player.posY, player.posZ, lootItem); + world.spawnEntity(dropItem); + } + return true; + } + + public static String roman(int input) { + if (input < 1 || input > 3999) + return "Invalid Roman Number Value"; + StringBuilder s = new StringBuilder(); + while (input >= 1000) { s.append("M"); input -= 1000; } + while (input >= 900) { s.append("CM"); input -= 900; } + while (input >= 500) { s.append("D"); input -= 500; } + while (input >= 400) { s.append("CD"); input -= 400; } + while (input >= 100) { s.append("C"); input -= 100; } + while (input >= 90) { s.append("XC"); input -= 90; } + while (input >= 50) { s.append("L"); input -= 50; } + while (input >= 40) { s.append("XL"); input -= 40; } + while (input >= 10) { s.append("X"); input -= 10; } + while (input >= 9) { s.append("IX"); input -= 9; } + while (input >= 5) { s.append("V"); input -= 5; } + while (input >= 4) { s.append("IV"); input -= 4; } + while (input >= 1) { s.append("I"); input -= 1; } + return s.toString(); + } } diff --git a/src/main/java/dev/marston/randomloot/loot/ModTemplate.java b/src/main/java/dev/marston/randomloot/loot/ModTemplate.java deleted file mode 100644 index 08f7115..0000000 --- a/src/main/java/dev/marston/randomloot/loot/ModTemplate.java +++ /dev/null @@ -1,60 +0,0 @@ -package dev.marston.randomloot.loot; - -import dev.marston.randomloot.items.ModItems; -import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; - -public class ModTemplate extends Item { - - final boolean add; - - public ModTemplate(Properties p, boolean additional) { - super(p.stacksTo(1)); - this.add = additional; - } - - @Override - public boolean isFoil(ItemStack stack) { - return true; - } - - @Override - public InteractionResult use(Level level, Player player, InteractionHand hand) { - ItemStack template = player.getItemInHand(hand); - - Modifier.TrackEntityParticle(level, player, ParticleTypes.CLOUD); - - if (!level.isClientSide()) { - - ItemStack s; - - if (this.add) { - s = new ItemStack(ModItems.MOD_SUB.get()); - } else { - s = new ItemStack(ModItems.MOD_ADD.get()); - } - - player.setItemInHand(hand, s); - } - - return InteractionResult.SUCCESS; - } - -// @Override -// public void appendHoverText(ItemStack stack, @Nullable Level level, List tipList, TooltipFlag flag) { -// -// MutableComponent comp = Component.empty(); -// comp.append("Right-click to change function"); -// comp = comp.withStyle(ChatFormatting.GRAY); -// -// tipList.add(comp); -// -// } - -} diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/BlockBreakModifier.java b/src/main/java/dev/marston/randomloot/loot/modifiers/BlockBreakModifier.java index b5620b4..cad497e 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/BlockBreakModifier.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/BlockBreakModifier.java @@ -1,10 +1,17 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; public interface BlockBreakModifier extends Modifier { - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity player); - + /** + * Called when a block is about to be broken with this tool. + * + * @param itemstack The tool being used + * @param pos The position of the block being broken + * @param player The entity breaking the block + * @return true to skip normal block breaking, false to continue + */ + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase player); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/ChargeTracker.java b/src/main/java/dev/marston/randomloot/loot/modifiers/ChargeTracker.java index 1ab6b32..765f602 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/ChargeTracker.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/ChargeTracker.java @@ -1,6 +1,6 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.world.level.Level; +import net.minecraft.world.World; /** * Utility class for tracking charge-based modifier mechanics. @@ -8,30 +8,30 @@ */ public final class ChargeTracker { - private ChargeTracker() { - } + private ChargeTracker() { + } - /** - * Calculates the charge level based on time elapsed since last trigger. - * - * @param level The world level (for game time) - * @param lastTriggered The game time when the charge was last reset - * @param chargeTime The number of seconds to fully charge (multiplied by 20 for ticks) - * @return A value from 0.0 to 1.0 representing charge percentage - */ - public static float getCharge(Level level, long lastTriggered, int chargeTime) { - if (level == null) { - return 0.0f; - } + /** + * Calculates the charge level based on time elapsed since last trigger. + * + * @param world The world (for game time) + * @param lastTriggered The game time when the charge was last reset + * @param chargeTime The number of seconds to fully charge (multiplied by 20 for ticks) + * @return A value from 0.0 to 1.0 representing charge percentage + */ + public static float getCharge(World world, long lastTriggered, int chargeTime) { + if (world == null) { + return 0.0f; + } - long time = level.getGameTime(); - long diff = time - lastTriggered; + long time = world.getTotalWorldTime(); + long diff = time - lastTriggered; - float rate = (float) diff / (float) (chargeTime * 20); - if (rate > 1.0f) { - rate = 1.0f; - } + float rate = (float) diff / (float) (chargeTime * 20); + if (rate > 1.0f) { + rate = 1.0f; + } - return rate; - } + return rate; + } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/DummyContainer.java b/src/main/java/dev/marston/randomloot/loot/modifiers/DummyContainer.java index 3b01a71..8a7644b 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/DummyContainer.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/DummyContainer.java @@ -1,10 +1,12 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.world.Container; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.inventory.IInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; -public class DummyContainer implements Container { +public class DummyContainer implements IInventory { ItemStack item; @@ -17,13 +19,12 @@ public DummyContainer() { } @Override - public void clearContent() { + public void clear() { item = ItemStack.EMPTY; - } @Override - public int getContainerSize() { + public int getSizeInventory() { return 1; } @@ -33,36 +34,87 @@ public boolean isEmpty() { } @Override - public ItemStack getItem(int _index) { + public ItemStack getStackInSlot(int index) { return item; } @Override - public ItemStack removeItem(int _x, int _y) { - item = ItemStack.EMPTY; - return item; + public ItemStack decrStackSize(int index, int count) { + if (item.isEmpty()) { + return ItemStack.EMPTY; + } + ItemStack result = item.splitStack(count); + if (item.isEmpty()) { + item = ItemStack.EMPTY; + } + return result; } @Override - public ItemStack removeItemNoUpdate(int _index) { + public ItemStack removeStackFromSlot(int index) { + ItemStack result = item; item = ItemStack.EMPTY; - return item; + return result; } @Override - public void setItem(int _index, ItemStack stack) { + public void setInventorySlotContents(int index, ItemStack stack) { item = stack; } @Override - public void setChanged() { + public int getInventoryStackLimit() { + return 64; + } + + @Override + public void markDirty() { + } + + @Override + public boolean isUsableByPlayer(EntityPlayer player) { + return true; + } + @Override + public void openInventory(EntityPlayer player) { } @Override - public boolean stillValid(Player p_18946_) { + public void closeInventory(EntityPlayer player) { + } + @Override + public boolean isItemValidForSlot(int index, ItemStack stack) { return true; } + @Override + public int getField(int id) { + return 0; + } + + @Override + public void setField(int id, int value) { + } + + @Override + public int getFieldCount() { + return 0; + } + + @Override + public String getName() { + return "DummyContainer"; + } + + @Override + public boolean hasCustomName() { + return false; + } + + @Override + public ITextComponent getDisplayName() { + return new TextComponentString(getName()); + } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/EntityHurtModifier.java b/src/main/java/dev/marston/randomloot/loot/modifiers/EntityHurtModifier.java index 933e976..3885463 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/EntityHurtModifier.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/EntityHurtModifier.java @@ -1,8 +1,16 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; public interface EntityHurtModifier extends Modifier { - boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter); + /** + * Called when an entity is hit with this tool. + * + * @param itemstack The tool being used + * @param hurtee The entity being hit + * @param hurter The entity doing the hitting + * @return true to skip durability damage, false to continue normally + */ + boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/HoldModifier.java b/src/main/java/dev/marston/randomloot/loot/modifiers/HoldModifier.java index 56ba311..67527e1 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/HoldModifier.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/HoldModifier.java @@ -1,9 +1,16 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.item.ItemStack; +import net.minecraft.world.World; public interface HoldModifier extends Modifier { - public void hold(ItemStack stack, Level level, Entity holder); + /** + * Called every tick when this tool is held in the player's hand. + * + * @param stack The tool being held + * @param world The world + * @param holder The entity holding the tool + */ + public void hold(ItemStack stack, World world, Entity holder); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/Modifier.java b/src/main/java/dev/marston/randomloot/loot/modifiers/Modifier.java index 492d127..0f6b22a 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/Modifier.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/Modifier.java @@ -1,97 +1,128 @@ package dev.marston.randomloot.loot.modifiers; import dev.marston.randomloot.loot.LootItem.ToolType; -import net.minecraft.ChatFormatting; -import net.minecraft.core.particles.ParticleOptions; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; import java.util.List; import java.util.Random; public interface Modifier { - public static MutableComponent makeComp(String text, ChatFormatting color) { - MutableComponent comp = Component.empty(); - comp.append(text); - comp = comp.withStyle(color); - - return comp; - } - - public static MutableComponent makeComp(String text, String color) { - MutableComponent comp = Component.empty(); - comp.append(text); - comp = comp.withStyle(ChatFormatting.getByName(color)); - - return comp; - } - - public static MutableComponent makeComp(Component compIn) { - MutableComponent comp = Component.empty(); - comp.append(compIn); - return comp; - } - - public static void TrackEntityParticle(Level level, Entity e, ParticleOptions particleType) { - if (!level.isClientSide()) { - Random r = new Random(); - - ServerLevel sl = ((ServerLevel) level); - - for (int i = 0; i < 32; ++i) { - double d0 = (double) (r.nextFloat() * 2.0F - 1.0F); - double d1 = (double) (r.nextFloat() * 2.0F - 1.0F); - double d2 = (double) (r.nextFloat() * 2.0F - 1.0F); - if (!(d0 * d0 + d1 * d1 + d2 * d2 > 1.0D)) { - double d3 = e.getX(d0 / 4.0D); - double d4 = e.getY(0.5D + d1 / 4.0D); - double d5 = e.getZ(d2 / 4.0D); - sl.sendParticles(particleType, d3, d4, d5, 1, d0, d1 + 0.2D, d2, 0.0D); - } - } - - } - } - - public static final String MODTAG = "modifiers"; - - static final String NAME = "name"; - - public String tagName(); - - public void writeToLore(List list, boolean shift); - - public String description(); - - public String name(); - - public String color(); - - public Modifier clone(); - - public CompoundTag toNBT(); - - public Modifier fromNBT(CompoundTag tag); - - public boolean forTool(ToolType type); - - default Component writeDetailsToLore(Level level) { - return null; - } - - default boolean compatible(Modifier mod) { - return true; - } - - default boolean canLevel() { - return false; - } - - default void levelUp() { - } + public static final String MODTAG = "modifiers"; + static final String NAME = "name"; + + /** + * Spawn particles around an entity + */ + public static void TrackEntityParticle(World world, Entity e, EnumParticleTypes particleType) { + if (!world.isRemote && world instanceof WorldServer) { + Random r = new Random(); + WorldServer ws = (WorldServer) world; + + for (int i = 0; i < 32; ++i) { + double d0 = (double) (r.nextFloat() * 2.0F - 1.0F); + double d1 = (double) (r.nextFloat() * 2.0F - 1.0F); + double d2 = (double) (r.nextFloat() * 2.0F - 1.0F); + if (!(d0 * d0 + d1 * d1 + d2 * d2 > 1.0D)) { + double d3 = e.posX + d0 * e.width / 4.0D; + double d4 = e.posY + e.height / 2.0D + d1 * e.height / 4.0D; + double d5 = e.posZ + d2 * e.width / 4.0D; + ws.spawnParticle(particleType, d3, d4, d5, 1, d0, d1 + 0.2D, d2, 0.0D); + } + } + } + } + + /** + * Format text with color + */ + public static String formatText(String text, TextFormatting color) { + return color + text + TextFormatting.RESET; + } + + /** + * Format text with color name + */ + public static String formatText(String text, String colorName) { + TextFormatting color = TextFormatting.getValueByName(colorName); + if (color == null) color = TextFormatting.WHITE; + return color + text + TextFormatting.RESET; + } + + /** + * The internal tag name used for NBT storage + */ + public String tagName(); + + /** + * Write lore text to the list for tooltip display + */ + public void writeToLore(List list, boolean shift); + + /** + * Short description of what this modifier does + */ + public String description(); + + /** + * Display name of the modifier + */ + public String name(); + + /** + * Color name for display (lowercase, e.g., "gold", "aqua") + */ + public String color(); + + /** + * Create a copy of this modifier + */ + public Modifier clone(); + + /** + * Serialize to NBT + */ + public NBTTagCompound toNBT(); + + /** + * Deserialize from NBT + */ + public Modifier fromNBT(NBTTagCompound tag); + + /** + * Check if this modifier is compatible with the given tool type + */ + public boolean forTool(ToolType type); + + /** + * Write additional details to lore (called when shift is held) + */ + default String writeDetailsToLore(World world) { + return null; + } + + /** + * Check if this modifier is compatible with another modifier + */ + default boolean compatible(Modifier mod) { + return true; + } + + /** + * Check if this modifier can level up + */ + default boolean canLevel() { + return false; + } + + /** + * Level up this modifier + */ + default void levelUp() { + } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/ModifierRegistry.java b/src/main/java/dev/marston/randomloot/loot/modifiers/ModifierRegistry.java index c7a7069..ecadae6 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/ModifierRegistry.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/ModifierRegistry.java @@ -3,118 +3,121 @@ import dev.marston.randomloot.loot.modifiers.breakers.*; import dev.marston.randomloot.loot.modifiers.holders.*; import dev.marston.randomloot.loot.modifiers.hurter.*; -import dev.marston.randomloot.loot.modifiers.hurter.Soulbound; import dev.marston.randomloot.loot.modifiers.stats.Busted; import dev.marston.randomloot.loot.modifiers.users.DirtPlace; import dev.marston.randomloot.loot.modifiers.users.FireBall; import dev.marston.randomloot.loot.modifiers.users.FirePlace; import dev.marston.randomloot.loot.modifiers.users.VoidTouched; import dev.marston.randomloot.loot.modifiers.users.TorchPlace; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.effect.MobEffects; +import net.minecraft.init.MobEffects; +import net.minecraft.nbt.NBTTagCompound; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; +import java.util.*; public class ModifierRegistry { - private static final HashMap Modifiers = new HashMap<>(); - private static final HashMap ModifierEnabled = new HashMap<>(); - - public static Map getModifiers() { - return Collections.unmodifiableMap(Modifiers); - } - - public static Map getModifierEnabled() { - return Collections.unmodifiableMap(ModifierEnabled); - } - - public static Modifier getModifier(String name) { - return Modifiers.get(name); - } - - public static Modifier EXPLODE = register(new Explode()); - public static Modifier LEARNING = register(new Learning()); - public static Modifier ATTRACTING = register(new Attracting()); - public static Modifier VEINY = register(new Veiny()); - public static Modifier MELTING = register(new Melting()); - public static Modifier EXCAVATOR = register(new Excavator()); - public static Modifier PROSPECTOR = register(new Prospector()); - - public static Modifier TORCH_PLACE = register(new TorchPlace()); - public static Modifier DIRT_PLACE = register(new DirtPlace()); - public static Modifier FIRE_PLACE = register(new FirePlace()); - public static Modifier FIRE_BALL = register(new FireBall()); - - public static Modifier FLAMING = register(new Fire()); - public static Modifier CRITICAL = register(new Critical()); - public static Modifier CHARGING = register(new Charging()); - public static Modifier COMBO = register(new Combo()); - public static Modifier DRAINING = register(new Draining()); - public static Modifier POISONOUS = register(new HurtEffect("Poisonous", "poison", 5, MobEffects.POISON)); - public static Modifier WITHERING = register(new HurtEffect("Withering", "wither", 3, MobEffects.WITHER)); - public static Modifier BLINDING = register(new HurtEffect("Blinding", "blinding", 4, MobEffects.BLINDNESS)); - public static Modifier BEZERK = register(new Bezerk()); - public static Modifier NEMESIS = register(new Nemesis()); - public static Modifier SOULBOUND = register(new Soulbound()); - - // Biome-restricted modifiers - public static Modifier AQUATIC = register(new Aquatic()); - public static Modifier SCORCHED = register(new Scorched()); - public static Modifier FROZEN = register(new Frozen()); - public static Modifier OVERGROWN = register(new Overgrown()); - public static Modifier VOID_TOUCHED = register(new VoidTouched()); - - public static Modifier HASTY = register(new Hasty()); - public static Modifier FILLING = register(new Effect("Filling", "filling", 2, MobEffects.SATURATION)); - public static Modifier ABSORBTION = register(new Effect("Appley", "absorption", 10, MobEffects.ABSORPTION)); - public static Modifier REGENERATING = register(new Effect("Healing", "regeneration", 3, MobEffects.REGENERATION)); - public static Modifier RESISTANT = register(new Effect("Resistant", "resistance", 1, MobEffects.RESISTANCE)); - public static Modifier FIRE_RESISTANT = register( - new Effect("Heat Resistant", "fire_resistance", 1, MobEffects.FIRE_RESISTANCE)); - public static Modifier RAINY = register(new Rainy()); - public static Modifier ORE_FINDER = register(new OreFinder()); - public static Modifier SPAWNER_FINDER = register(new TreasureFinder()); - public static Modifier LIVING = register(new Healing()); - - public static Modifier BUSTED = register(new Busted()); - - public static Modifier UNBREAKING = register(new Unbreaking()); - - public static final Set BREAKERS = Set.of(EXPLODE, LEARNING, ATTRACTING, VEINY, MELTING, EXCAVATOR, PROSPECTOR); - public static final Set USERS = Set.of(TORCH_PLACE, DIRT_PLACE, FIRE_PLACE, FIRE_BALL, VOID_TOUCHED); - public static final Set HURTERS = Set.of(CRITICAL, CHARGING, FLAMING, COMBO, DRAINING, POISONOUS, - WITHERING, BLINDING, BEZERK, NEMESIS, SOULBOUND, SCORCHED, FROZEN, OVERGROWN); - public static final Set HOLDERS = Set.of(HASTY, ABSORBTION, FILLING, RAINY, ORE_FINDER, SPAWNER_FINDER, - LIVING, REGENERATING, RESISTANT, FIRE_RESISTANT, AQUATIC); - - public static final Set STATS = Set.of(BUSTED); - - public static final Set MISC = Set.of(UNBREAKING); - - public static Modifier register(Modifier modifier) { - - String tagName = modifier.tagName(); - - if (Modifiers.containsKey(tagName)) { - throw new IllegalStateException("Cannot register modifier twice: " + tagName); - } - - Modifiers.put(tagName, modifier); - ModifierEnabled.put(tagName, true); - - return modifier; - } - - public static Modifier loadModifier(String name, CompoundTag tag) { - Modifier m = Modifiers.get(name); - if (m == null) { - return null; - } - - return m.fromNBT(tag); - } - + private static final HashMap Modifiers = new HashMap<>(); + private static final HashMap ModifierEnabled = new HashMap<>(); + + public static Map getModifiers() { + return Collections.unmodifiableMap(Modifiers); + } + + public static Map getModifierEnabled() { + return Collections.unmodifiableMap(ModifierEnabled); + } + + public static Modifier getModifier(String name) { + return Modifiers.get(name); + } + + // Breakers + public static Modifier EXPLODE = register(new Explode()); + public static Modifier LEARNING = register(new Learning()); + public static Modifier ATTRACTING = register(new Attracting()); + public static Modifier VEINY = register(new Veiny()); + public static Modifier MELTING = register(new Melting()); + public static Modifier EXCAVATOR = register(new Excavator()); + public static Modifier PROSPECTOR = register(new Prospector()); + + // Users + public static Modifier TORCH_PLACE = register(new TorchPlace()); + public static Modifier DIRT_PLACE = register(new DirtPlace()); + public static Modifier FIRE_PLACE = register(new FirePlace()); + public static Modifier FIRE_BALL = register(new FireBall()); + + // Hurters + public static Modifier FLAMING = register(new Fire()); + public static Modifier CRITICAL = register(new Critical()); + public static Modifier CHARGING = register(new Charging()); + public static Modifier COMBO = register(new Combo()); + public static Modifier DRAINING = register(new Draining()); + public static Modifier POISONOUS = register(new HurtEffect("Poisonous", "poison", 5, MobEffects.POISON)); + public static Modifier WITHERING = register(new HurtEffect("Withering", "wither", 3, MobEffects.WITHER)); + public static Modifier BLINDING = register(new HurtEffect("Blinding", "blinding", 4, MobEffects.BLINDNESS)); + public static Modifier BEZERK = register(new Bezerk()); + public static Modifier NEMESIS = register(new Nemesis()); + public static Modifier SOULBOUND = register(new Soulbound()); + + // Biome-restricted modifiers + public static Modifier AQUATIC = register(new Aquatic()); + public static Modifier SCORCHED = register(new Scorched()); + public static Modifier FROZEN = register(new Frozen()); + public static Modifier OVERGROWN = register(new Overgrown()); + public static Modifier VOID_TOUCHED = register(new VoidTouched()); + + // Holders + public static Modifier HASTY = register(new Hasty()); + public static Modifier FILLING = register(new Effect("Filling", "filling", 2, MobEffects.SATURATION)); + public static Modifier ABSORBTION = register(new Effect("Appley", "absorption", 10, MobEffects.ABSORPTION)); + public static Modifier REGENERATING = register(new Effect("Healing", "regeneration", 3, MobEffects.REGENERATION)); + public static Modifier RESISTANT = register(new Effect("Resistant", "resistance", 1, MobEffects.RESISTANCE)); + public static Modifier FIRE_RESISTANT = register( + new Effect("Heat Resistant", "fire_resistance", 1, MobEffects.FIRE_RESISTANCE)); + public static Modifier RAINY = register(new Rainy()); + public static Modifier ORE_FINDER = register(new OreFinder()); + public static Modifier SPAWNER_FINDER = register(new TreasureFinder()); + public static Modifier LIVING = register(new Healing()); + + // Stats + public static Modifier BUSTED = register(new Busted()); + + // Misc + public static Modifier UNBREAKING = register(new Unbreaking()); + + // Category sets (Java 8 compatible) + public static final Set BREAKERS = new HashSet<>(Arrays.asList( + EXPLODE, LEARNING, ATTRACTING, VEINY, MELTING, EXCAVATOR, PROSPECTOR)); + public static final Set USERS = new HashSet<>(Arrays.asList( + TORCH_PLACE, DIRT_PLACE, FIRE_PLACE, FIRE_BALL, VOID_TOUCHED)); + public static final Set HURTERS = new HashSet<>(Arrays.asList( + CRITICAL, CHARGING, FLAMING, COMBO, DRAINING, POISONOUS, + WITHERING, BLINDING, BEZERK, NEMESIS, SOULBOUND, SCORCHED, FROZEN, OVERGROWN)); + public static final Set HOLDERS = new HashSet<>(Arrays.asList( + HASTY, ABSORBTION, FILLING, RAINY, ORE_FINDER, SPAWNER_FINDER, + LIVING, REGENERATING, RESISTANT, FIRE_RESISTANT, AQUATIC)); + public static final Set STATS = new HashSet<>(Collections.singletonList(BUSTED)); + public static final Set MISC = new HashSet<>(Collections.singletonList(UNBREAKING)); + + public static Modifier register(Modifier modifier) { + String tagName = modifier.tagName(); + + if (Modifiers.containsKey(tagName)) { + throw new IllegalStateException("Cannot register modifier twice: " + tagName); + } + + Modifiers.put(tagName, modifier); + ModifierEnabled.put(tagName, true); + + return modifier; + } + + public static Modifier loadModifier(String name, NBTTagCompound tag) { + Modifier m = Modifiers.get(name); + if (m == null) { + return null; + } + + return m.fromNBT(tag); + } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/StatsModifier.java b/src/main/java/dev/marston/randomloot/loot/modifiers/StatsModifier.java index de43897..1f65c21 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/StatsModifier.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/StatsModifier.java @@ -1,8 +1,14 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.world.item.ItemStack; +import net.minecraft.item.ItemStack; public interface StatsModifier extends Modifier { - public float getStats(ItemStack itemstack); - + /** + * Get the stat modifier value for this modifier. + * Positive values increase stats, negative values decrease them. + * + * @param itemstack The tool + * @return The stat modifier value + */ + public float getStats(ItemStack itemstack); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/Unbreaking.java b/src/main/java/dev/marston/randomloot/loot/modifiers/Unbreaking.java index 356ddf5..51a8b19 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/Unbreaking.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/Unbreaking.java @@ -2,95 +2,95 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.LootUtils; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.level.Level; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; +import java.util.Random; public class Unbreaking implements Modifier { - final String name; - int level; + final String name; + int level; - final static String LEVEL = "trait_level"; + final static String LEVEL = "trait_level"; - public Unbreaking(String name, int level) { - this.name = name; - this.level = level; - } + public Unbreaking(String name, int level) { + this.name = name; + this.level = level; + } - public Unbreaking() { - this("Unbreaking", 0); - } + public Unbreaking() { + this("Unbreaking", 0); + } - public String tagName() { - return "unbreaking"; - } + public String tagName() { + return "unbreaking"; + } - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - list.add(comp); - } + public void writeToLore(List list, boolean shift) { + list.add(Modifier.formatText(this.name(), this.color())); + } - public String description() { - return "This tool has a " + String.format("%.0f", chance() * 100) + "% chance of not taking damage."; - } + public String description() { + return "This tool has a " + String.format("%.0f", chance() * 100) + "% chance of not taking damage."; + } - public String name() { - if (this.level == 0) { - return this.name; - } + public String name() { + if (this.level == 0) { + return this.name; + } - if (!this.canLevel()) { - return "Unbreakable"; - } + if (!this.canLevel()) { + return "Unbreakable"; + } - return this.name + " " + LootUtils.roman(this.level + 1); - } + return this.name + " " + LootUtils.roman(this.level + 1); + } - public String color() { - return ChatFormatting.AQUA.getName(); - } + public String color() { + return TextFormatting.AQUA.getFriendlyName(); + } - public Modifier clone() { - return new Unbreaking(this.name, this.level); - } + public Modifier clone() { + return new Unbreaking(this.name, this.level); + } - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); - return tag; - } + return tag; + } - public Modifier fromNBT(CompoundTag tag) { - return new Unbreaking(tag.getStringOr(NAME, "Unbreaking"), tag.getIntOr(LEVEL, 0)); - } + public Modifier fromNBT(NBTTagCompound tag) { + String n = tag.hasKey(NAME) ? tag.getString(NAME) : "Unbreaking"; + int l = tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0; + return new Unbreaking(n, l); + } - public boolean forTool(ToolType type) { - return true; - } + public boolean forTool(ToolType type) { + return true; + } - public boolean canLevel() { - return this.level < 4; - } + public boolean canLevel() { + return this.level < 4; + } - public void levelUp() { - this.level++; - } + public void levelUp() { + this.level++; + } - private float chance() { - return 0.2f * (float) (this.level + 1); - } + private float chance() { + return 0.2f * (float) (this.level + 1); + } - public boolean test(Level level) { - float f = level.getRandom().nextFloat(); - - return f <= chance(); - } + public boolean test(World world) { + Random r = new Random(); + float f = r.nextFloat(); + return f <= chance(); + } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/UseModifier.java b/src/main/java/dev/marston/randomloot/loot/modifiers/UseModifier.java index 2eadb5d..8f6f6fb 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/UseModifier.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/UseModifier.java @@ -1,15 +1,41 @@ package dev.marston.randomloot.loot.modifiers; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public interface UseModifier extends Modifier { - public InteractionResult use(UseOnContext ctx); + /** + * Called when the player right-clicks on a block with this tool. + * + * @param player The player using the tool + * @param world The world + * @param pos The position of the block clicked + * @param hand The hand holding the tool + * @param facing The face of the block clicked + * @param hitX Hit X position on block face + * @param hitY Hit Y position on block face + * @param hitZ Hit Z position on block face + * @return The action result + */ + public EnumActionResult use(EntityPlayer player, World world, BlockPos pos, EnumHand hand, + EnumFacing facing, float hitX, float hitY, float hitZ); - public boolean use(Level level, Player player, InteractionHand hand); + /** + * Called when the player right-clicks in the air with this tool. + * + * @param world The world + * @param player The player using the tool + * @param hand The hand holding the tool + * @return true if the action was handled, false otherwise + */ + public boolean use(World world, EntityPlayer player, EnumHand hand); - public boolean useAnywhere(); + /** + * Whether this modifier's use action works anywhere (in air), not just on blocks. + */ + public boolean useAnywhere(); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Attracting.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Attracting.java index 372521c..cc4d6ea 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Attracting.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Attracting.java @@ -3,21 +3,17 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; public class Attracting implements BlockBreakModifier { @@ -40,26 +36,32 @@ public Modifier clone() { } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity player) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase player) { - Level level = player.level(); + World world = player.world; - if (level.isClientSide()) { + if (world.isRemote) { return false; } - ServerLevel serverLevel = (ServerLevel) level; - AABB box = new AABB(pos.east().south().below().getCenter(), pos.west().north().above().getCenter()); + final WorldServer serverWorld = (WorldServer) world; + AxisAlignedBB box = new AxisAlignedBB( + pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, + pos.getX() + 2, pos.getY() + 2, pos.getZ() + 2); + + final double playerX = player.posX; + final double playerY = player.posY; + final double playerZ = player.posZ; // Schedule execution after a short delay to allow block drops to spawn - // Then submit to server thread for thread-safe execution - CompletableFuture.delayedExecutor(100, TimeUnit.MILLISECONDS).execute(() -> { - serverLevel.getServer().execute(() -> { - List items = level.getEntities(null, box); + serverWorld.addScheduledTask(() -> { + // Schedule for next tick to allow drops to spawn + serverWorld.addScheduledTask(() -> { + List items = world.getEntitiesWithinAABB(Entity.class, box); for (Entity entity : items) { - if (entity.getType() == EntityType.ITEM) { - entity.setPos(player.position()); + if (entity instanceof EntityItem) { + entity.setPosition(playerX, playerY, playerZ); } } }); @@ -69,20 +71,22 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity player } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Attracting(tag.getStringOr(NAME, "Magnetic"), tag.getFloatOr(POWER, 2.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Attracting( + tag.hasKey(NAME) ? tag.getString(NAME) : "Magnetic", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 2.0f); } @Override @@ -106,10 +110,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Excavator.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Excavator.java index 1101211..dad8af5 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Excavator.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Excavator.java @@ -4,18 +4,15 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.ArrayList; import java.util.List; @@ -36,28 +33,28 @@ public Modifier clone() { return new Excavator(); } - private List get3x3Positions(BlockPos center, ServerPlayer player) { + private List get3x3Positions(BlockPos center, EntityPlayerMP player) { List positions = new ArrayList<>(); - Direction facing = player.getDirection(); - float pitch = player.getXRot(); + EnumFacing facing = player.getHorizontalFacing(); + float pitch = player.rotationPitch; if (Math.abs(pitch) > 45) { // Looking up or down -> horizontal plane (X-Z) for (int x = -1; x <= 1; x++) { for (int z = -1; z <= 1; z++) { if (x == 0 && z == 0) continue; // Skip center - positions.add(center.offset(x, 0, z)); + positions.add(center.add(x, 0, z)); } } } else { // Looking horizontally -> vertical plane perpendicular to facing - if (facing == Direction.NORTH || facing == Direction.SOUTH) { + if (facing == EnumFacing.NORTH || facing == EnumFacing.SOUTH) { // Mine in X-Y plane for (int x = -1; x <= 1; x++) { for (int y = -1; y <= 1; y++) { if (x == 0 && y == 0) continue; // Skip center - positions.add(center.offset(x, y, 0)); + positions.add(center.add(x, y, 0)); } } } else { @@ -65,7 +62,7 @@ private List get3x3Positions(BlockPos center, ServerPlayer player) { for (int z = -1; z <= 1; z++) { for (int y = -1; y <= 1; y++) { if (z == 0 && y == 0) continue; // Skip center - positions.add(center.offset(0, y, z)); + positions.add(center.add(0, y, z)); } } } @@ -75,21 +72,21 @@ private List get3x3Positions(BlockPos center, ServerPlayer player) { } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity p) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase p) { - if (!(p instanceof ServerPlayer)) { + if (!(p instanceof EntityPlayerMP)) { return false; } - ServerPlayer player = (ServerPlayer) p; + EntityPlayerMP player = (EntityPlayerMP) p; - if (!player.isCrouching()) { + if (!player.isSneaking()) { return false; } - Level level = player.level(); + World world = player.world; - if (level.isClientSide()) { + if (world.isRemote) { return false; } @@ -97,42 +94,42 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity p) { List positions = get3x3Positions(pos, player); for (BlockPos blockPos : positions) { - BlockState state = level.getBlockState(blockPos); + IBlockState state = world.getBlockState(blockPos); // Skip air and unharvestable blocks - if (state.isAir()) { + if (state.getBlock().isAir(state, world, blockPos)) { continue; } - if (!state.canHarvestBlock(level, blockPos, player)) { + if (!state.getBlock().canHarvestBlock(world, blockPos, player)) { continue; } - if (!li.isCorrectToolForDrops(itemstack, state)) { + if (!li.canHarvestBlock(state, itemstack)) { continue; } // Break the block with drops - state.getBlock().playerDestroy(level, player, blockPos, state, null, itemstack); - level.removeBlock(blockPos, false); + state.getBlock().harvestBlock(world, player, blockPos, state, null, itemstack); + world.setBlockToAir(blockPos); // Apply durability damage for each block - itemstack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND); + itemstack.damageItem(1, player); } return false; } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Excavator(tag.getStringOr(NAME, "Excavator")); + public Modifier fromNBT(NBTTagCompound tag) { + return new Excavator(tag.hasKey(NAME) ? tag.getString(NAME) : "Excavator"); } @Override @@ -147,7 +144,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GREEN.name(); + return TextFormatting.GREEN.getFriendlyName(); } @Override @@ -156,8 +153,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Explode.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Explode.java index 22e4254..c31e303 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Explode.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Explode.java @@ -3,15 +3,11 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Explosion; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.Level.ExplosionInteraction; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import java.util.List; @@ -36,30 +32,32 @@ public Modifier clone() { } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity player) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase player) { - Level l = player.level(); + World world = player.world; - l.explode(player, Explosion.getDefaultDamageSource(l, player), null, pos.getX(), pos.getY() + 0.5, pos.getZ(), power, false, ExplosionInteraction.TNT); + world.createExplosion(player, pos.getX(), pos.getY() + 0.5, pos.getZ(), power, true); return false; } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Explode(tag.getStringOr(NAME, "Explosive"), tag.getFloatOr(POWER, 4.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Explode( + tag.hasKey(NAME) ? tag.getString(NAME) : "Explosive", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 4.0f); } @Override @@ -83,10 +81,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Learning.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Learning.java index e790b6f..8098c63 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Learning.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Learning.java @@ -4,15 +4,13 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -42,19 +40,19 @@ public Modifier clone() { } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity entity) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase entity) { - if (!(entity instanceof Player)) { + if (!(entity instanceof EntityPlayer)) { return false; } - Player player = (Player) entity; + EntityPlayer player = (EntityPlayer) entity; this.count++; while (count >= max) { count = count - max; - player.giveExperiencePoints(this.points); + player.addExperience(this.points); } LootUtils.updateModifier(itemstack, this); @@ -62,20 +60,23 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity entity } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putInt(COUNT, count); - tag.putInt(POINTS, points); - tag.putString(NAME, name); + tag.setInteger(COUNT, count); + tag.setInteger(POINTS, points); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Learning(tag.getStringOr(NAME, "Learning"), tag.getIntOr(COUNT, 0), tag.getIntOr(POINTS, 3)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Learning( + tag.hasKey(NAME) ? tag.getString(NAME) : "Learning", + tag.hasKey(COUNT) ? tag.getInteger(COUNT) : 0, + tag.hasKey(POINTS) ? tag.getInteger(POINTS) : 3); } @Override @@ -99,20 +100,16 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override - public Component writeDetailsToLore(Level level) { - + public String writeDetailsToLore(World world) { float amt = ((float) count) / ((float) max) * 100; String perc = String.format("%.0f%% Learned", amt); - - return Modifier.makeComp(perc, ChatFormatting.GRAY); + return Modifier.formatText(perc, TextFormatting.GRAY); } @Override diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java index e52d0ea..ec4dab8 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java @@ -3,24 +3,18 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.*; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.AABB; - -import java.util.Collection; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.item.ItemStack; +import net.minecraft.item.crafting.FurnaceRecipes; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + import java.util.List; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; public class Melting implements BlockBreakModifier { @@ -43,72 +37,58 @@ public Modifier clone() { } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity player) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase player) { - Level level = player.level(); + World world = player.world; - if (level.isClientSide()) { + if (world.isRemote) { return false; } - ServerLevel serverLevel = (ServerLevel) level; - AABB box = new AABB(pos.east().south().below().getCenter(), pos.west().north().above().getCenter()); + final WorldServer serverWorld = (WorldServer) world; + AxisAlignedBB box = new AxisAlignedBB( + pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, + pos.getX() + 2, pos.getY() + 2, pos.getZ() + 2); // Schedule execution after a short delay to allow block drops to spawn - // Then submit to server thread for thread-safe execution - CompletableFuture.delayedExecutor(50, TimeUnit.MILLISECONDS).execute(() -> { - serverLevel.getServer().execute(() -> { - List items = level.getEntities(null, box); - - for (Entity entity : items) { - if (entity.getType() != EntityType.ITEM) { - continue; - } - - ItemEntity i = (ItemEntity) entity; - if (i.getAge() > 10) { - continue; - } - - ItemStack stack = i.getItem(); - - RecipeManager manager = serverLevel.recipeAccess(); + serverWorld.addScheduledTask(() -> { + // Schedule for next tick to allow drops to spawn + serverWorld.addScheduledTask(() -> { + List items = world.getEntitiesWithinAABB(Entity.class, box); - Collection> recipes = manager.getRecipes(); - List smeltingRecipes = recipes.stream() - .map(RecipeHolder::value) - .filter(r -> r.getType() == RecipeType.SMELTING) - .filter(r -> r instanceof SingleItemRecipe) - .map(r -> (SingleItemRecipe) r) - .toList(); + for (Entity entity : items) { + if (!(entity instanceof EntityItem)) { + continue; + } - for (SingleItemRecipe recipe : smeltingRecipes) { - if (!recipe.matches(new SingleRecipeInput(stack), level)) { + EntityItem i = (EntityItem) entity; + if (i.getAge() > 10) { continue; } - ItemStack result = recipe.assemble(new SingleRecipeInput(stack), null); + ItemStack stack = i.getItem(); + ItemStack result = FurnaceRecipes.instance().getSmeltingResult(stack); if (result.isEmpty()) { continue; } - // Capture motion before modifying original item - var motion = i.getDeltaMovement(); - - ItemEntity k = new ItemEntity(level, i.getX(), i.getY(), i.getZ(), result); + // Copy the result with correct count + ItemStack newResult = result.copy(); + newResult.setCount(stack.getCount()); - i.setPos(i.position().x, -1, i.position().z); - i.kill(serverLevel); + // Create new item entity + EntityItem k = new EntityItem(world, i.posX, i.posY, i.posZ, newResult); + k.motionX = i.motionX; + k.motionY = i.motionY; + k.motionZ = i.motionZ; - level.addFreshEntity(k); + // Remove old item + i.setDead(); - // Set motion after spawn to prevent it being reset - k.setDeltaMovement(motion); - - break; + // Spawn new item + world.spawnEntity(k); } - } }); }); @@ -116,20 +96,22 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity player } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Melting(tag.getStringOr(NAME, "Melting"), tag.getFloatOr(POWER, 1.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Melting( + tag.hasKey(NAME) ? tag.getString(NAME) : "Melting", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 1.0f); } @Override @@ -153,10 +135,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Prospector.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Prospector.java index 1b89f91..158ff19 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Prospector.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Prospector.java @@ -4,28 +4,19 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.Registries; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.Identifier; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.tags.BlockTags; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.item.ItemEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.storage.loot.LootParams; -import net.minecraft.world.level.storage.loot.LootTable; -import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets; -import net.minecraft.world.level.storage.loot.parameters.LootContextParams; -import net.minecraft.world.phys.Vec3; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityItem; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; +import net.minecraft.world.storage.loot.LootContext; +import net.minecraft.world.storage.loot.LootTable; import java.util.List; import java.util.Random; @@ -42,9 +33,7 @@ public class Prospector implements BlockBreakModifier { private static final float BASE_CHANCE = 0.03f; private static final float CHANCE_PER_LEVEL = 0.01f; - private static final ResourceKey LOOT_TABLE = ResourceKey.create( - Registries.LOOT_TABLE, - Identifier.fromNamespaceAndPath("randomloot", "prospector_drops")); + private static final ResourceLocation LOOT_TABLE = new ResourceLocation("randomloot", "prospector_drops"); public Prospector(String name, int level, int totalFinds) { this.name = name; @@ -62,28 +51,27 @@ public Modifier clone() { return new Prospector(); } - private boolean isStoneBlock(BlockState state) { - return state.is(BlockTags.BASE_STONE_OVERWORLD) || state.is(BlockTags.BASE_STONE_NETHER); + private boolean isStoneBlock(net.minecraft.block.state.IBlockState state) { + net.minecraft.block.Block block = state.getBlock(); + return block == net.minecraft.init.Blocks.STONE || + block == net.minecraft.init.Blocks.COBBLESTONE || + block == net.minecraft.init.Blocks.NETHERRACK; } - private List getDropsFromLootTable(ServerLevel serverLevel, BlockPos pos) { - LootTable lootTable = serverLevel.getServer().reloadableRegistries().getLootTable(LOOT_TABLE); - - LootParams params = new LootParams.Builder(serverLevel) - .withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)) - .create(LootContextParamSets.EMPTY); - - return lootTable.getRandomItems(params); + private List getDropsFromLootTable(WorldServer serverLevel, BlockPos pos) { + LootTable lootTable = serverLevel.getLootTableManager().getLootTableFromLocation(LOOT_TABLE); + LootContext.Builder builder = new LootContext.Builder(serverLevel); + return lootTable.generateLootForPools(serverLevel.rand, builder.build()); } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity entity) { - Level level = entity.level(); - if (level.isClientSide()) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase entity) { + World world = entity.world; + if (world.isRemote) { return false; } - BlockState state = level.getBlockState(pos); + net.minecraft.block.state.IBlockState state = world.getBlockState(pos); if (!isStoneBlock(state)) { return false; } @@ -94,19 +82,19 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity entity return false; } - ServerLevel serverLevel = (ServerLevel) level; + WorldServer serverLevel = (WorldServer) world; List drops = getDropsFromLootTable(serverLevel, pos); for (ItemStack drop : drops) { if (!drop.isEmpty()) { - ItemEntity itemEntity = new ItemEntity(level, + EntityItem itemEntity = new EntityItem(world, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, drop); - level.addFreshEntity(itemEntity); + world.spawnEntity(itemEntity); } } if (!drops.isEmpty()) { - level.playSound(null, pos, SoundEvents.EXPERIENCE_ORB_PICKUP, SoundSource.BLOCKS, 0.5f, 1.2f); + world.playSound(null, pos, SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, SoundCategory.BLOCKS, 0.5f, 1.2f); this.totalFinds++; LootUtils.updateModifier(itemstack, this); } @@ -115,20 +103,20 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity entity } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); - tag.putInt(TOTAL_FINDS, totalFinds); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); + tag.setInteger(TOTAL_FINDS, totalFinds); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { + public Modifier fromNBT(NBTTagCompound tag) { return new Prospector( - tag.getStringOr(NAME, "Prospector"), - tag.getIntOr(LEVEL, 1), - tag.getIntOr(TOTAL_FINDS, 0)); + tag.hasKey(NAME) ? tag.getString(NAME) : "Prospector", + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 1, + tag.hasKey(TOTAL_FINDS) ? tag.getInteger(TOTAL_FINDS) : 0); } @Override @@ -146,7 +134,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GOLD.getName(); + return TextFormatting.GOLD.getFriendlyName(); } @Override @@ -156,17 +144,17 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @Override - public Component writeDetailsToLore(Level level) { + public String writeDetailsToLore(World world) { if (totalFinds == 0) { - return Modifier.makeComp("No minerals found yet", ChatFormatting.GRAY); + return Modifier.formatText("No minerals found yet", TextFormatting.GRAY); } - return Modifier.makeComp(totalFinds + " minerals found", ChatFormatting.GRAY); + return Modifier.formatText(totalFinds + " minerals found", TextFormatting.GRAY); } @Override diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Veiny.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Veiny.java index 410804e..ecb22d3 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Veiny.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Veiny.java @@ -4,19 +4,16 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.HashSet; import java.util.Iterator; @@ -43,25 +40,25 @@ public Modifier clone() { return new Veiny(); } - private void removeBlock(ItemStack itemstack, BlockPos pos, ServerPlayer player, Level level, BlockState state) { - if (!state.canHarvestBlock(level, pos, player)) { + private void removeBlock(ItemStack itemstack, BlockPos pos, EntityPlayerMP player, World world, IBlockState state) { + if (!state.getBlock().canHarvestBlock(world, pos, player)) { return; } - state.getBlock().playerDestroy(level, player, pos, state, null, itemstack); - level.removeBlock(pos, false); + state.getBlock().harvestBlock(world, player, pos, state, null, itemstack); + world.setBlockToAir(pos); } - public void checkAndBreak(ItemStack itemstack, BlockPos pos, Player player, Level level, int index, Block blockType, + public void checkAndBreak(ItemStack itemstack, BlockPos pos, EntityPlayer player, World world, int index, Block blockType, Set tobreak) { if (index > power) { return; } - BlockState startingState = level.getBlockState(pos); + IBlockState startingState = world.getBlockState(pos); - if (!startingState.is(blockType)) { + if (startingState.getBlock() != blockType) { return; } @@ -71,39 +68,39 @@ public void checkAndBreak(ItemStack itemstack, BlockPos pos, Player player, Leve int dex = index + 1; - checkAndBreak(itemstack, pos.above(), player, level, dex, blockType, tobreak); - checkAndBreak(itemstack, pos.below(), player, level, dex, blockType, tobreak); - checkAndBreak(itemstack, pos.east(), player, level, dex, blockType, tobreak); - checkAndBreak(itemstack, pos.west(), player, level, dex, blockType, tobreak); - checkAndBreak(itemstack, pos.north(), player, level, dex, blockType, tobreak); - checkAndBreak(itemstack, pos.south(), player, level, dex, blockType, tobreak); + checkAndBreak(itemstack, pos.up(), player, world, dex, blockType, tobreak); + checkAndBreak(itemstack, pos.down(), player, world, dex, blockType, tobreak); + checkAndBreak(itemstack, pos.east(), player, world, dex, blockType, tobreak); + checkAndBreak(itemstack, pos.west(), player, world, dex, blockType, tobreak); + checkAndBreak(itemstack, pos.north(), player, world, dex, blockType, tobreak); + checkAndBreak(itemstack, pos.south(), player, world, dex, blockType, tobreak); } @Override - public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity p) { + public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase p) { - if (!(p instanceof ServerPlayer)) { + if (!(p instanceof EntityPlayerMP)) { return false; } - ServerPlayer player = (ServerPlayer) p; + EntityPlayerMP player = (EntityPlayerMP) p; - if (!player.isCrouching()) { + if (!player.isSneaking()) { return false; } - Level l = player.level(); + World world = player.world; - if (l.isClientSide()) { + if (world.isRemote) { return false; } - BlockState state = l.getBlockState(pos); + IBlockState state = world.getBlockState(pos); LootItem li = (LootItem) itemstack.getItem(); - if (!li.isCorrectToolForDrops(itemstack, state)) { + if (!li.canHarvestBlock(state, itemstack)) { return false; } @@ -111,34 +108,36 @@ public boolean startBreak(ItemStack itemstack, BlockPos pos, LivingEntity p) { Set toBreak = new HashSet(); - checkAndBreak(itemstack, pos, player, l, 0, b, toBreak); + checkAndBreak(itemstack, pos, player, world, 0, b, toBreak); for (Iterator iterator = toBreak.iterator(); iterator.hasNext();) { BlockPos blockPos = iterator.next(); - removeBlock(itemstack, blockPos, player, l, l.getBlockState(blockPos)); + removeBlock(itemstack, blockPos, player, world, world.getBlockState(blockPos)); - itemstack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND); + itemstack.damageItem(1, player); } return false; } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Veiny(tag.getStringOr(NAME, "Veiny"), tag.getFloatOr(POWER, 5.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Veiny( + tag.hasKey(NAME) ? tag.getString(NAME) : "Veiny", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 5.0f); } @Override @@ -153,7 +152,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_GREEN.name(); + return TextFormatting.DARK_GREEN.getFriendlyName(); } @Override @@ -163,10 +162,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Aquatic.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Aquatic.java index 6f549fb..6563a83 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Aquatic.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Aquatic.java @@ -5,16 +5,14 @@ import dev.marston.randomloot.loot.modifiers.BiomeRestrictedModifier; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -39,16 +37,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Aquatic(tag.getStringOr(NAME, "Aquatic"), tag.getIntOr(LEVEL, 0)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Aquatic( + tag.hasKey(NAME) ? tag.getString(NAME) : "Aquatic", + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0); } @Override @@ -66,7 +66,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.AQUA.getName(); + return TextFormatting.AQUA.getFriendlyName(); } @Override @@ -75,8 +75,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -86,15 +86,16 @@ public boolean forTool(ToolType type) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - if (!(holder instanceof LivingEntity living)) return; + public void hold(ItemStack stack, World world, Entity holder) { + if (!(holder instanceof EntityLivingBase)) return; + EntityLivingBase living = (EntityLivingBase) holder; // Water breathing - living.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 40, 0, false, false)); + living.addPotionEffect(new PotionEffect(MobEffects.WATER_BREATHING, 40, 0, false, false)); // Extra haste when underwater - if (living.isUnderWater()) { - living.addEffect(new MobEffectInstance(MobEffects.HASTE, 40, this.level + 1, true, false)); + if (living.isInWater()) { + living.addPotionEffect(new PotionEffect(MobEffects.HASTE, 40, this.level + 1, true, false)); } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Effect.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Effect.java index 0062e53..97de39b 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Effect.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Effect.java @@ -4,18 +4,14 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.core.Holder; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -25,10 +21,10 @@ public class Effect implements HoldModifier { private int power; private String tagname; private final static String POWER = "power"; - private Holder effect; + private Potion effect; private int duration; - public Effect(String name, String tagname, int power, int duration, Holder effect) { + public Effect(String name, String tagname, int power, int duration, Potion effect) { this.name = name; this.effect = effect; this.power = 0; @@ -36,7 +32,7 @@ public Effect(String name, String tagname, int power, int duration, Holder effect) { + public Effect(String name, String tagname, int duration, Potion effect) { this(name, tagname, 0, duration, effect); } @@ -45,19 +41,24 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); - tag.putInt(POWER, power); + tag.setString(NAME, name); + tag.setInteger(POWER, power); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Effect(tag.getStringOr(NAME, this.name), this.tagname, tag.getIntOr(POWER, 0), this.duration, this.effect); + public Modifier fromNBT(NBTTagCompound tag) { + return new Effect( + tag.hasKey(NAME) ? tag.getString(NAME) : this.name, + this.tagname, + tag.hasKey(POWER) ? tag.getInteger(POWER) : 0, + this.duration, + this.effect); } @Override @@ -75,25 +76,21 @@ public String tagName() { @Override public String color() { - int color = effect.value().getColor(); - ChatFormatting format = ChatFormatting.getById(color); - if (format == null) { - return ChatFormatting.LIGHT_PURPLE.getName(); - } - return format.getName(); + int color = effect.getLiquidColor(); + // Convert potion color to a reasonable TextFormatting + // This is approximate - potion colors don't map directly to TextFormatting + return TextFormatting.LIGHT_PURPLE.getFriendlyName(); } @Override public String description() { - return "While holding the tool, get the " + I18n.get(effect.value().getDisplayName().getString()).toLowerCase() + " " - + LootUtils.roman(this.power + 1) + " effect."; + return "While holding the tool, get the " + effect.getName().toLowerCase() + + " " + LootUtils.roman(this.power + 1) + " effect."; } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -103,17 +100,17 @@ public boolean forTool(ToolType type) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - MobEffectInstance eff = new MobEffectInstance(effect, duration * 20, this.power, false, false); + public void hold(ItemStack stack, World world, Entity holder) { + PotionEffect eff = new PotionEffect(effect, duration * 20, this.power, false, false); - if (!(holder instanceof LivingEntity)) { + if (!(holder instanceof EntityLivingBase)) { return; } - LivingEntity livingHolder = (LivingEntity) holder; - boolean alreadyHasEffect = livingHolder.hasEffect(effect); + EntityLivingBase livingHolder = (EntityLivingBase) holder; + boolean alreadyHasEffect = livingHolder.isPotionActive(effect); if (!alreadyHasEffect) { - livingHolder.addEffect(eff); + livingHolder.addPotionEffect(eff); } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Hasty.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Hasty.java index fe9b84c..975a536 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Hasty.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Hasty.java @@ -4,17 +4,15 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -44,22 +42,25 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); + tag.setString(NAME, name); - tag.putInt(POWER, power); + tag.setInteger(POWER, power); - tag.putInt(LEVEL, level); + tag.setInteger(LEVEL, level); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Hasty(tag.getStringOr(NAME, "Hasty"), tag.getIntOr(POWER, 0), tag.getIntOr(LEVEL, 0)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Hasty( + tag.hasKey(NAME) ? tag.getString(NAME) : "Hasty", + tag.hasKey(POWER) ? tag.getInteger(POWER) : 0, + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0); } @Override @@ -80,7 +81,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.BLUE.getName(); + return TextFormatting.BLUE.getFriendlyName(); } @Override @@ -89,10 +90,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -102,16 +101,16 @@ public boolean forTool(ToolType type) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - MobEffectInstance haste = new MobEffectInstance(MobEffects.HASTE, 2, power, true, false); + public void hold(ItemStack stack, World world, Entity holder) { + PotionEffect haste = new PotionEffect(MobEffects.HASTE, 2, power, true, false); - if (holder instanceof LivingEntity) { - LivingEntity le = (LivingEntity) holder; - le.addEffect(haste); + if (holder instanceof EntityLivingBase) { + EntityLivingBase le = (EntityLivingBase) holder; + le.addPotionEffect(haste); } - if (holder instanceof Player) { - Player p = (Player) holder; - p.addEffect(haste); + if (holder instanceof EntityPlayer) { + EntityPlayer p = (EntityPlayer) holder; + p.addPotionEffect(haste); } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Healing.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Healing.java index f8f9a3c..a1b3503 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Healing.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Healing.java @@ -3,14 +3,13 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -35,20 +34,22 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Healing(tag.getStringOr(NAME, "Living"), tag.getFloatOr(POWER, 0.005f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Healing( + tag.hasKey(NAME) ? tag.getString(NAME) : "Living", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 0.005f); } @Override @@ -63,7 +64,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GREEN.getName(); + return TextFormatting.GREEN.getFriendlyName(); } @Override @@ -72,10 +73,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -85,27 +84,23 @@ public boolean forTool(ToolType type) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { + public void hold(ItemStack stack, World world, Entity holder) { - float f = level.getRandom().nextFloat(); + float f = world.rand.nextFloat(); if (f < power) { - if (stack.getDamageValue() == 0) { + if (stack.getItemDamage() == 0) { return; } - stack.setDamageValue(Math.max(stack.getDamageValue() - 1, 0)); + stack.setItemDamage(Math.max(stack.getItemDamage() - 1, 0)); if (f < power / 5) { - MutableComponent comp = Component.empty(); - - comp.append("pssst..."); - comp = comp.withStyle(ChatFormatting.GRAY); - comp = comp.withStyle(ChatFormatting.ITALIC); + String text = TextFormatting.GRAY + "" + TextFormatting.ITALIC + "pssst..."; - if (holder instanceof Player) { - Player p = (Player) holder; - p.displayClientMessage(comp, false); + if (holder instanceof EntityPlayer) { + EntityPlayer p = (EntityPlayer) holder; + p.sendMessage(new TextComponentString(text)); } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/OreFinder.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/OreFinder.java index 4179b46..f573c0d 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/OreFinder.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/OreFinder.java @@ -4,30 +4,27 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.monster.Shulker; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.phys.AABB; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.event.server.ServerStoppingEvent; -import net.neoforged.neoforge.event.tick.ServerTickEvent; +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.EntityShulker; +import net.minecraft.init.Blocks; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.event.world.WorldEvent; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; -@EventBusSubscriber(modid = RandomLoot.MODID) +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) public class OreFinder implements HoldModifier { private String name; @@ -39,7 +36,7 @@ public class OreFinder implements HoldModifier { static int maxShulkerLife = 10; // Thread-safe lists for concurrent access between tick events and hold() - private static final List shulkers = new CopyOnWriteArrayList<>(); + private static final List shulkers = new CopyOnWriteArrayList<>(); private static final List timings = new CopyOnWriteArrayList<>(); public OreFinder(String name, float power) { @@ -57,20 +54,22 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new OreFinder(tag.getStringOr(NAME, "Detecting"), tag.getFloatOr(POWER, 4.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new OreFinder( + tag.hasKey(NAME) ? tag.getString(NAME) : "Detecting", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 4.0f); } @Override @@ -85,7 +84,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.WHITE.getName(); + return TextFormatting.WHITE.getFriendlyName(); } @Override @@ -94,10 +93,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -107,15 +104,19 @@ public boolean forTool(ToolType type) { } @SubscribeEvent - public static void serverStop(ServerStoppingEvent event) { - for (Shulker shulker : shulkers) { - shulker.setPos(0, -256, 0); + public static void serverStop(WorldEvent.Unload event) { + for (EntityShulker shulker : shulkers) { + shulker.setPosition(0, -256, 0); shulker.setHealth(0); } + shulkers.clear(); + timings.clear(); } @SubscribeEvent - public static void tickEvent(ServerTickEvent.Post event) { + public static void tickEvent(TickEvent.ServerTickEvent event) { + if (event.phase != TickEvent.Phase.END) return; + time++; time = time % maxTime; @@ -128,11 +129,11 @@ public static void tickEvent(ServerTickEvent.Post event) { int tick = timings.get(i) + 1; timings.set(i, tick); - Shulker sh = shulkers.get(i); + EntityShulker sh = shulkers.get(i); if (tick > maxShulkerLife - || sh.level().getBlockState(sh.blockPosition()).getBlock().equals(Blocks.AIR)) { - sh.setPos(0, -256, 0); + || sh.world.getBlockState(sh.getPosition()).getBlock() == Blocks.AIR) { + sh.setPosition(0, -256, 0); sh.setHealth(0); shulkers.remove(i); timings.remove(i); @@ -142,23 +143,23 @@ public static void tickEvent(ServerTickEvent.Post event) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { + public void hold(ItemStack stack, World world, Entity holder) { int size = 10; for (int i = -size; i < size; i++) { for (int j = -size; j < size; j++) { for (int k = -size; k < size; k++) { - BlockPos p = new BlockPos((int) (holder.getX() + i), (int) (holder.getY() + j), - (int) (holder.getZ() + k)); - Block b = level.getBlockState(p).getBlock(); - name = b.getName().getString(); + BlockPos p = new BlockPos((int) (holder.posX + i), (int) (holder.posY + j), + (int) (holder.posZ + k)); + Block b = world.getBlockState(p).getBlock(); + String blockName = b.getLocalizedName(); - if (name.toLowerCase().contains("ore")) { + if (blockName.toLowerCase().contains("ore")) { - List entitiesInBlock = level.getEntities(null, new AABB(p)); + List entitiesInBlock = world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(p)); if (!entitiesInBlock.isEmpty()) { boolean isShulker = false; for (Entity entity : entitiesInBlock) { - if (entity.getType() == EntityType.SHULKER) { + if (entity instanceof EntityShulker) { isShulker = true; break; } @@ -168,15 +169,15 @@ public void hold(ItemStack stack, Level level, Entity holder) { } } - Shulker se = new Shulker(EntityType.SHULKER, level); - se.setGlowingTag(true); - se.setInvulnerable(true); + EntityShulker se = new EntityShulker(world); + se.setGlowing(true); + se.setEntityInvulnerable(true); se.setInvisible(true); - se.setPos(p.getX(), p.getY(), p.getZ()); - se.setNoAi(true); + se.setPosition(p.getX(), p.getY(), p.getZ()); + se.setNoAI(true); - level.addFreshEntity(se); - se.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200, 0, false, false)); + world.spawnEntity(se); + se.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, 1200, 0, false, false)); shulkers.add(se); timings.add(-1); diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Rainy.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Rainy.java index ac53eec..a9d39a6 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Rainy.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/Rainy.java @@ -3,17 +3,15 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -38,20 +36,22 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Rainy(tag.getStringOr(NAME, "Rainy"), tag.getFloatOr(POWER, 4.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Rainy( + tag.hasKey(NAME) ? tag.getString(NAME) : "Rainy", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 4.0f); } @Override @@ -66,7 +66,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.BLUE.getName(); + return TextFormatting.BLUE.getFriendlyName(); } @Override @@ -75,10 +75,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -88,17 +86,17 @@ public boolean forTool(ToolType type) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - if (level.isRainingAt(holder.blockPosition())) { - MobEffectInstance haste = new MobEffectInstance(MobEffects.HASTE, 3, 2, false, false); + public void hold(ItemStack stack, World world, Entity holder) { + if (world.isRainingAt(holder.getPosition())) { + PotionEffect haste = new PotionEffect(MobEffects.HASTE, 3, 2, false, false); - if (holder instanceof LivingEntity) { - LivingEntity le = (LivingEntity) holder; - le.addEffect(haste); + if (holder instanceof EntityLivingBase) { + EntityLivingBase le = (EntityLivingBase) holder; + le.addPotionEffect(haste); } - if (holder instanceof Player) { - Player p = (Player) holder; - p.addEffect(haste); + if (holder instanceof EntityPlayer) { + EntityPlayer p = (EntityPlayer) holder; + p.addPotionEffect(haste); } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/TreasureFinder.java b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/TreasureFinder.java index 788f1f2..0b3c556 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/holders/TreasureFinder.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/holders/TreasureFinder.java @@ -4,30 +4,27 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.monster.Shulker; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.phys.AABB; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.event.server.ServerStoppingEvent; -import net.neoforged.neoforge.event.tick.ServerTickEvent; +import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.EntityShulker; +import net.minecraft.init.Blocks; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; +import net.minecraftforge.event.world.WorldEvent; import java.util.ArrayList; import java.util.List; -@EventBusSubscriber(modid = RandomLoot.MODID) +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) public class TreasureFinder implements HoldModifier { private String name; @@ -40,7 +37,7 @@ public class TreasureFinder implements HoldModifier { static boolean locked = false; - private static ArrayList shulkers = new ArrayList(); + private static ArrayList shulkers = new ArrayList(); private static ArrayList timings = new ArrayList(); public TreasureFinder(String name, float power) { @@ -58,20 +55,22 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putFloat(POWER, power); + tag.setFloat(POWER, power); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new TreasureFinder(tag.getStringOr(NAME, "Tomb Raider"), tag.getFloatOr(POWER, 4.0f)); + public Modifier fromNBT(NBTTagCompound tag) { + return new TreasureFinder( + tag.hasKey(NAME) ? tag.getString(NAME) : "Tomb Raider", + tag.hasKey(POWER) ? tag.getFloat(POWER) : 4.0f); } @Override @@ -86,7 +85,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_AQUA.getName(); + return TextFormatting.DARK_AQUA.getFriendlyName(); } @Override @@ -95,10 +94,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -108,15 +105,19 @@ public boolean forTool(ToolType type) { } @SubscribeEvent - public static void serverStop(ServerStoppingEvent event) { - for (Shulker shulker : shulkers) { - shulker.setPos(0, -256, 0); + public static void serverStop(WorldEvent.Unload event) { + for (EntityShulker shulker : shulkers) { + shulker.setPosition(0, -256, 0); shulker.setHealth(0); } + shulkers.clear(); + timings.clear(); } @SubscribeEvent - public static void tickEvent(ServerTickEvent.Post event) { + public static void tickEvent(TickEvent.ServerTickEvent event) { + if (event.phase != TickEvent.Phase.END) return; + locked = true; time++; @@ -126,13 +127,15 @@ public static void tickEvent(ServerTickEvent.Post event) { int off = 0; for (int i = 0; i < shulkers.size(); i++) { int iOff = i - off; + if (iOff >= timings.size() || iOff >= shulkers.size()) break; + int tick = timings.get(iOff) + 1; timings.set(iOff, tick); - Shulker sh = shulkers.get(iOff); + EntityShulker sh = shulkers.get(iOff); if (tick > maxShulkerLife - || sh.level().getBlockState(sh.blockPosition()).getBlock().equals(Blocks.AIR)) { - shulkers.get(iOff).setPos(0, -64, 0); + || sh.world.getBlockState(sh.getPosition()).getBlock() == Blocks.AIR) { + shulkers.get(iOff).setPosition(0, -64, 0); shulkers.get(iOff).setHealth(0); shulkers.remove(iOff); timings.remove(iOff); @@ -145,7 +148,7 @@ public static void tickEvent(ServerTickEvent.Post event) { } @Override - public void hold(ItemStack stack, Level level, Entity holder) { + public void hold(ItemStack stack, World world, Entity holder) { if (locked) { return; } @@ -155,17 +158,17 @@ public void hold(ItemStack stack, Level level, Entity holder) { for (int i = -size; i < size; i++) { for (int j = -size; j < size; j++) { for (int k = -size; k < size; k++) { - BlockPos p = new BlockPos((int) (holder.getX() + i), (int) (holder.getY() + j), - (int) (holder.getZ() + k)); - Block b = level.getBlockState(p).getBlock(); + BlockPos p = new BlockPos((int) (holder.posX + i), (int) (holder.posY + j), + (int) (holder.posZ + k)); + Block b = world.getBlockState(p).getBlock(); - if (b == Blocks.SPAWNER) { + if (b == Blocks.MOB_SPAWNER) { - List entitiesInBlock = level.getEntities(null, new AABB(p)); + List entitiesInBlock = world.getEntitiesWithinAABB(Entity.class, new AxisAlignedBB(p)); if (!entitiesInBlock.isEmpty()) { boolean isShulker = false; for (Entity entity : entitiesInBlock) { - if (entity.getType() == EntityType.SHULKER) { + if (entity instanceof EntityShulker) { isShulker = true; break; } @@ -175,16 +178,16 @@ public void hold(ItemStack stack, Level level, Entity holder) { } } - Shulker se = new Shulker(EntityType.SHULKER, level); - se.setGlowingTag(true); + EntityShulker se = new EntityShulker(world); + se.setGlowing(true); - se.setInvulnerable(true); + se.setEntityInvulnerable(true); se.setInvisible(true); - se.setPos(p.getX(), p.getY(), p.getZ()); - se.setNoAi(true); + se.setPosition(p.getX(), p.getY(), p.getZ()); + se.setNoAI(true); - level.addFreshEntity(se); - se.addEffect(new MobEffectInstance(MobEffects.INVISIBILITY, 1200, 0, false, false)); + world.spawnEntity(se); + se.addPotionEffect(new PotionEffect(MobEffects.INVISIBILITY, 1200, 0, false, false)); shulkers.add(se); timings.add(-1); diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Bezerk.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Bezerk.java index bc854c1..62f60e7 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Bezerk.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Bezerk.java @@ -5,14 +5,13 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -32,18 +31,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Bezerk(tag.getStringOr(NAME, "Bezerk")); + public Modifier fromNBT(NBTTagCompound tag) { + return new Bezerk(tag.hasKey(NAME) ? tag.getString(NAME) : "Bezerk"); } @Override @@ -58,7 +57,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GOLD.getName(); + return TextFormatting.GOLD.getFriendlyName(); } @Override @@ -67,11 +66,9 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override @@ -80,7 +77,7 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { float dmg = LootItem.getAttackDamage(itemstack, LootUtils.getToolType(itemstack)); float maxHealth = hurter.getMaxHealth(); @@ -90,13 +87,13 @@ public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity float amt = dmg * 0.05f * (ratio - 1); - if (hurter instanceof Player) { - Player p = (Player) hurter; - hurtee.hurt(hurter.damageSources().playerAttack(p), amt); + if (hurter instanceof EntityPlayer) { + EntityPlayer p = (EntityPlayer) hurter; + hurtee.attackEntityFrom(DamageSource.causePlayerDamage(p), amt); return false; } - hurtee.hurt(hurter.damageSources().mobAttack(hurter), amt); + hurtee.attackEntityFrom(DamageSource.causeMobDamage(hurter), amt); return false; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Charging.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Charging.java index ce3a78d..9e8a968 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Charging.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Charging.java @@ -6,16 +6,13 @@ import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierConstants; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LightningBolt; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.effect.EntityLightningBolt; +import net.minecraft.entity.player.EntityPlayerMP; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -41,19 +38,22 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putInt(ModifierConstants.POINTS, points); - tag.putString(ModifierConstants.NAME, name); - tag.putLong(ModifierConstants.CHARGED, charged); + tag.setInteger(ModifierConstants.POINTS, points); + tag.setString(ModifierConstants.NAME, name); + tag.setLong(ModifierConstants.CHARGED, charged); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Charging(tag.getStringOr(ModifierConstants.NAME, "Charged"), tag.getIntOr(ModifierConstants.POINTS, 10), tag.getLongOr(ModifierConstants.CHARGED, 0L)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Charging( + tag.hasKey(ModifierConstants.NAME) ? tag.getString(ModifierConstants.NAME) : "Charged", + tag.hasKey(ModifierConstants.POINTS) ? tag.getInteger(ModifierConstants.POINTS) : 10, + tag.hasKey(ModifierConstants.CHARGED) ? tag.getLong(ModifierConstants.CHARGED) : 0L); } @Override @@ -68,7 +68,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.YELLOW.getName(); + return TextFormatting.YELLOW.getFriendlyName(); } @Override @@ -78,19 +78,19 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @Override - public Component writeDetailsToLore(Level level) { - if (level != null) { - float charge = ChargeTracker.getCharge(level, charged, points); + public String writeDetailsToLore(World world) { + if (world != null) { + float charge = ChargeTracker.getCharge(world, charged, points); String perc = String.format("%.0f%% Charged", charge * 100.0f); - return Modifier.makeComp(perc, ChatFormatting.GREEN); + return Modifier.formatText(perc, TextFormatting.GREEN); } return null; @@ -102,21 +102,16 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { - Level level = hurtee.level(); + World world = hurtee.world; - long time = level.getGameTime(); + long time = world.getTotalWorldTime(); - if (ChargeTracker.getCharge(level, charged, points) >= 1.0f) { - LightningBolt lb = new LightningBolt(EntityType.LIGHTNING_BOLT, level); - lb.setPos(hurtee.position()); - if (hurter instanceof ServerPlayer) { - lb.setCause((ServerPlayer) hurter); - } + if (ChargeTracker.getCharge(world, charged, points) >= 1.0f) { + EntityLightningBolt lb = new EntityLightningBolt(world, hurtee.posX, hurtee.posY, hurtee.posZ, false); - - level.addFreshEntity(lb); + world.spawnEntity(lb); this.charged = time; LootUtils.updateModifier(itemstack, this); diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Combo.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Combo.java index 7dcdf2f..5ebb81e 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Combo.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Combo.java @@ -7,14 +7,13 @@ import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierConstants; -import net.minecraft.ChatFormatting; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -40,19 +39,22 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putInt(ModifierConstants.POINTS, points); - tag.putString(ModifierConstants.NAME, name); - tag.putLong(ModifierConstants.CHARGED, charged); + tag.setInteger(ModifierConstants.POINTS, points); + tag.setString(ModifierConstants.NAME, name); + tag.setLong(ModifierConstants.CHARGED, charged); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Combo(tag.getStringOr(ModifierConstants.NAME, "Dexterous"), tag.getIntOr(ModifierConstants.POINTS, 2), tag.getLongOr(ModifierConstants.CHARGED, 0L)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Combo( + tag.hasKey(ModifierConstants.NAME) ? tag.getString(ModifierConstants.NAME) : "Dexterous", + tag.hasKey(ModifierConstants.POINTS) ? tag.getInteger(ModifierConstants.POINTS) : 2, + tag.hasKey(ModifierConstants.CHARGED) ? tag.getLong(ModifierConstants.CHARGED) : 0L); } @Override @@ -67,7 +69,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.YELLOW.getName(); + return TextFormatting.YELLOW.getFriendlyName(); } @Override @@ -76,24 +78,22 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override - public Component writeDetailsToLore(Level level) { - if (level != null) { - float charge = ChargeTracker.getCharge(level, charged, points); + public String writeDetailsToLore(World world) { + if (world != null) { + float charge = ChargeTracker.getCharge(world, charged, points); String s = "Not Ready"; if (charge < 1.0f) { s = "Ready"; } - return Modifier.makeComp(s, ChatFormatting.RED); + return Modifier.formatText(s, TextFormatting.RED); } return null; @@ -105,19 +105,19 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { - Level level = hurtee.level(); + World world = hurtee.world; - long time = level.getGameTime(); + long time = world.getTotalWorldTime(); - if (ChargeTracker.getCharge(level, charged, points) < 1.0f) { + if (ChargeTracker.getCharge(world, charged, points) < 1.0f) { float damage = LootItem.getAttackDamage(itemstack, LootUtils.getToolType(itemstack)); - hurtee.hurt(hurter.damageSources().mobAttack(hurtee), damage * 0.25f); + hurtee.attackEntityFrom(DamageSource.causeMobDamage(hurtee), damage * 0.25f); - Modifier.TrackEntityParticle(level, hurtee, ParticleTypes.CRIT); + Modifier.TrackEntityParticle(world, hurtee, EnumParticleTypes.CRIT); } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Critical.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Critical.java index 7066327..c12e71a 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Critical.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Critical.java @@ -5,15 +5,14 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -33,18 +32,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Critical(tag.getStringOr(NAME, "Critical")); + public Modifier fromNBT(NBTTagCompound tag) { + return new Critical(tag.hasKey(NAME) ? tag.getString(NAME) : "Critical"); } @Override @@ -59,7 +58,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GOLD.getName(); + return TextFormatting.GOLD.getFriendlyName(); } @Override @@ -68,11 +67,9 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override @@ -81,20 +78,20 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { float dmg = LootItem.getAttackDamage(itemstack, LootUtils.getToolType(itemstack)); float amt = dmg * 0.5f; - Modifier.TrackEntityParticle(hurtee.level(), hurtee, ParticleTypes.CRIT); + Modifier.TrackEntityParticle(hurtee.world, hurtee, EnumParticleTypes.CRIT); - if (hurter instanceof Player) { - Player p = (Player) hurter; - hurtee.hurt(hurter.damageSources().playerAttack(p), amt); + if (hurter instanceof EntityPlayer) { + EntityPlayer p = (EntityPlayer) hurter; + hurtee.attackEntityFrom(DamageSource.causePlayerDamage(p), amt); return false; } - hurtee.hurt(hurter.damageSources().mobAttack(hurter), amt); + hurtee.attackEntityFrom(DamageSource.causeMobDamage(hurter), amt); return false; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Draining.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Draining.java index 7946465..4f955b3 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Draining.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Draining.java @@ -5,13 +5,11 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -35,19 +33,21 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putInt(POINTS, points); - tag.putString(NAME, name); + tag.setInteger(POINTS, points); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Draining(tag.getStringOr(NAME, "Necrotic"), tag.getIntOr(POINTS, 2)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Draining( + tag.hasKey(NAME) ? tag.getString(NAME) : "Necrotic", + tag.hasKey(POINTS) ? tag.getInteger(POINTS) : 2); } @Override @@ -65,7 +65,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.RED.getName(); + return TextFormatting.RED.getFriendlyName(); } @Override @@ -78,11 +78,9 @@ public float drain() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override @@ -91,7 +89,7 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { float damage = LootItem.getAttackDamage(itemstack, LootUtils.getToolType(itemstack)); hurter.heal(damage * drain()); diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Fire.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Fire.java index d76d67a..364172d 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Fire.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Fire.java @@ -4,13 +4,11 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -34,19 +32,21 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putInt(POINTS, points); - tag.putString(NAME, name); + tag.setInteger(POINTS, points); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Fire(tag.getStringOr(NAME, "Flaming"), tag.getIntOr(POINTS, 2)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Fire( + tag.hasKey(NAME) ? tag.getString(NAME) : "Flaming", + tag.hasKey(POINTS) ? tag.getInteger(POINTS) : 2); } @Override @@ -64,7 +64,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.RED.getName(); + return TextFormatting.RED.getFriendlyName(); } @Override @@ -73,11 +73,9 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override @@ -86,8 +84,8 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { - hurtee.setRemainingFireTicks(points * 20); + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { + hurtee.setFire(points); return false; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Frozen.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Frozen.java index dc86868..352faf6 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Frozen.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Frozen.java @@ -6,21 +6,19 @@ import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.LiquidBlock; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.block.BlockLiquid; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -45,16 +43,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Frozen(tag.getStringOr(NAME, "Frozen"), tag.getIntOr(LEVEL, 0)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Frozen( + tag.hasKey(NAME) ? tag.getString(NAME) : "Frozen", + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0); } @Override @@ -72,18 +72,18 @@ public String tagName() { @Override public String color() { - return ChatFormatting.AQUA.getName(); + return TextFormatting.AQUA.getFriendlyName(); } @Override public String description() { int radius = 3 + this.level; - return "Slows enemies on hit. Creates " + radius + " block radius of frosted ice on water."; + return "Slows enemies on hit. Creates " + radius + " block radius of ice on water."; } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -93,25 +93,26 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { int duration = 3 * 20; - hurtee.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, duration, this.level + 1, false, true)); + hurtee.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, duration, this.level + 1, false, true)); return false; } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - if (!(holder instanceof Player player)) return; + public void hold(ItemStack stack, World world, Entity holder) { + if (!(holder instanceof EntityPlayer)) return; + EntityPlayer player = (EntityPlayer) holder; // Check every 2 ticks for smoother ice generation - if (level.getGameTime() % 2 != 0) return; + if (world.getTotalWorldTime() % 2 != 0) return; - BlockPos centerPos = player.blockPosition().below(); + BlockPos centerPos = player.getPosition().down(); // Radius scales with level: 3.0, 4.0, 5.0 double radius = 3.0 + this.level; - // Create circular pattern of frosted ice (like Frost Walker but wider) + // Create circular pattern of ice (like Frost Walker but wider) int radiusInt = (int) Math.ceil(radius); for (int xOffset = -radiusInt; xOffset <= radiusInt; xOffset++) { for (int zOffset = -radiusInt; zOffset <= radiusInt; zOffset++) { @@ -121,12 +122,13 @@ public void hold(ItemStack stack, Level level, Entity holder) { continue; // Skip blocks outside the circle } - BlockPos pos = centerPos.offset(xOffset, 0, zOffset); - BlockState below = level.getBlockState(pos); + BlockPos pos = centerPos.add(xOffset, 0, zOffset); + IBlockState below = world.getBlockState(pos); - // Create frosted ice on water surface (mimic Frost Walker) - if (below.is(Blocks.WATER) && below.getValue(LiquidBlock.LEVEL) == 0) { - level.setBlockAndUpdate(pos, Blocks.FROSTED_ICE.defaultBlockState()); + // Create ice on water surface (mimic Frost Walker) + if (below.getBlock() == Blocks.WATER && below.getValue(BlockLiquid.LEVEL) == 0) { + // Use packed ice instead of frosted ice (1.12.2 doesn't have frosted ice) + world.setBlockState(pos, Blocks.ICE.getDefaultState()); } } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/HurtEffect.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/HurtEffect.java index 82ce5a8..f605e58 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/HurtEffect.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/HurtEffect.java @@ -4,17 +4,13 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.core.Holder; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.Potion; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -24,10 +20,10 @@ public class HurtEffect implements EntityHurtModifier { private int power; private String tagname; private final static String POWER = "power"; - private Holder effect; + private Potion effect; private int duration; - public HurtEffect(String name, String tagname, int power, int duration, Holder effect) { + public HurtEffect(String name, String tagname, int power, int duration, Potion effect) { this.name = name; this.effect = effect; this.power = power; @@ -35,7 +31,7 @@ public HurtEffect(String name, String tagname, int power, int duration, Holder effect) { + public HurtEffect(String name, String tagname, int duration, Potion effect) { this(name, tagname, 0, duration, effect); } @@ -44,19 +40,24 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); - tag.putInt(POWER, power); + tag.setString(NAME, name); + tag.setInteger(POWER, power); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new HurtEffect(tag.getStringOr(NAME, this.name), this.tagname, tag.getIntOr(POWER, 0), this.duration, this.effect); + public Modifier fromNBT(NBTTagCompound tag) { + return new HurtEffect( + tag.hasKey(NAME) ? tag.getString(NAME) : this.name, + this.tagname, + tag.hasKey(POWER) ? tag.getInteger(POWER) : 0, + this.duration, + this.effect); } @Override @@ -74,25 +75,20 @@ public String tagName() { @Override public String color() { - int color = effect.value().getColor(); - ChatFormatting format = ChatFormatting.getById(color); - if (format == null) { - return ChatFormatting.LIGHT_PURPLE.getName(); - } - return format.getName(); + int color = effect.getLiquidColor(); + // Convert potion color to a reasonable TextFormatting + return TextFormatting.LIGHT_PURPLE.getFriendlyName(); } @Override public String description() { - return "When attacking with tool, apply the " + I18n.get(effect.value().getDisplayName().getString()).toLowerCase() + return "When attacking with tool, apply the " + effect.getName().toLowerCase() + " " + LootUtils.roman(this.power + 1) + " effect to the target for " + this.duration + " seconds."; } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -102,10 +98,10 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { - MobEffectInstance eff = new MobEffectInstance(effect, duration * 20, power, false, false); + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { + PotionEffect eff = new PotionEffect(effect, duration * 20, power, false, false); - hurtee.addEffect(eff); + hurtee.addPotionEffect(eff); return false; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Nemesis.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Nemesis.java index e2b90ca..a5cf5a8 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Nemesis.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Nemesis.java @@ -5,14 +5,14 @@ import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.EntityList; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.HashMap; import java.util.List; @@ -43,30 +43,32 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); - CompoundTag killCountsTag = new CompoundTag(); + NBTTagCompound killCountsTag = new NBTTagCompound(); for (Map.Entry entry : killCounts.entrySet()) { - killCountsTag.putInt(entry.getKey(), entry.getValue()); + killCountsTag.setInteger(entry.getKey(), entry.getValue()); } - tag.put(KILL_COUNTS, killCountsTag); + tag.setTag(KILL_COUNTS, killCountsTag); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - String name = tag.getStringOr(NAME, "Nemesis"); - int level = tag.getIntOr(LEVEL, 1); + public Modifier fromNBT(NBTTagCompound tag) { + String name = tag.hasKey(NAME) ? tag.getString(NAME) : "Nemesis"; + int level = tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 1; Map killCounts = new HashMap<>(); - CompoundTag killCountsTag = tag.getCompoundOrEmpty(KILL_COUNTS); - for (String key : killCountsTag.keySet()) { - killCounts.put(key, killCountsTag.getIntOr(key, 0)); + if (tag.hasKey(KILL_COUNTS)) { + NBTTagCompound killCountsTag = tag.getCompoundTag(KILL_COUNTS); + for (String key : killCountsTag.getKeySet()) { + killCounts.put(key, killCountsTag.getInteger(key)); + } } return new Nemesis(name, level, killCounts); @@ -87,7 +89,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_RED.getName(); + return TextFormatting.DARK_RED.getFriendlyName(); } @Override @@ -145,22 +147,22 @@ private String getEntityDisplayName(String registryName) { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @Override - public Component writeDetailsToLore(Level level) { + public String writeDetailsToLore(World world) { String mostKilled = getMostKilledEntity(); if (mostKilled == null) { - return Modifier.makeComp("No nemesis yet", ChatFormatting.GRAY); + return Modifier.formatText("No nemesis yet", TextFormatting.GRAY); } String entityName = getEntityDisplayName(mostKilled); int bonusPercent = (int) (bonusDamagePercent() * 100); - return Modifier.makeComp(entityName + " +" + bonusPercent + "%", ChatFormatting.GRAY); + return Modifier.formatText(entityName + " +" + bonusPercent + "%", TextFormatting.GRAY); } @Override @@ -169,20 +171,21 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { // Only track kills on server side - if (hurtee.level().isClientSide()) { + if (hurtee.world.isRemote) { return false; } - String entityKey = EntityType.getKey(hurtee.getType()).toString(); + ResourceLocation entityRL = EntityList.getKey(hurtee); + String entityKey = entityRL != null ? entityRL.toString() : "unknown"; String mostKilled = getMostKilledEntity(); // Apply bonus damage if attacking most-killed type if (mostKilled != null && mostKilled.equals(entityKey)) { float baseDamage = LootItem.getAttackDamage(itemstack, LootUtils.getToolType(itemstack)); float bonusDamage = baseDamage * bonusDamagePercent(); - hurtee.hurt(hurter.damageSources().mobAttack(hurter), bonusDamage); + hurtee.attackEntityFrom(DamageSource.causeMobDamage(hurter), bonusDamage); } // Track kill if the entity is dead diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Overgrown.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Overgrown.java index d713a46..887572f 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Overgrown.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Overgrown.java @@ -6,17 +6,19 @@ import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.monster.EntityCaveSpider; +import net.minecraft.entity.monster.EntityEndermite; +import net.minecraft.entity.monster.EntitySilverfish; +import net.minecraft.entity.monster.EntitySpider; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.DamageSource; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -41,16 +43,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Overgrown(tag.getStringOr(NAME, "Overgrown"), tag.getIntOr(LEVEL, 0)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Overgrown( + tag.hasKey(NAME) ? tag.getString(NAME) : "Overgrown", + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0); } @Override @@ -68,7 +72,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GREEN.getName(); + return TextFormatting.GREEN.getFriendlyName(); } @Override @@ -78,8 +82,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -89,28 +93,27 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { - EntityType type = hurtee.getType(); - boolean isArthropod = type == EntityType.SPIDER || - type == EntityType.CAVE_SPIDER || - type == EntityType.SILVERFISH || - type == EntityType.ENDERMITE || - type == EntityType.BEE; + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { + boolean isArthropod = hurtee instanceof EntitySpider || + hurtee instanceof EntityCaveSpider || + hurtee instanceof EntitySilverfish || + hurtee instanceof EntityEndermite; if (isArthropod) { float bonusDamage = 2.5f + (this.level * 2.5f); - hurtee.hurt(hurter.damageSources().mobAttack(hurter), bonusDamage); - hurtee.addEffect(new MobEffectInstance(MobEffects.SLOWNESS, 60, this.level)); + hurtee.attackEntityFrom(DamageSource.causeMobDamage(hurter), bonusDamage); + hurtee.addPotionEffect(new PotionEffect(MobEffects.SLOWNESS, 60, this.level)); } return false; } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - if (!(holder instanceof LivingEntity living)) return; - if (living.hasEffect(MobEffects.POISON)) { - living.removeEffect(MobEffects.POISON); + public void hold(ItemStack stack, World world, Entity holder) { + if (!(holder instanceof EntityLivingBase)) return; + EntityLivingBase living = (EntityLivingBase) holder; + if (living.isPotionActive(MobEffects.POISON)) { + living.removePotionEffect(MobEffects.POISON); } } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Scorched.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Scorched.java index 0d3b1dd..7e8df89 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Scorched.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Scorched.java @@ -6,16 +6,14 @@ import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.HoldModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.effect.MobEffectInstance; -import net.minecraft.world.effect.MobEffects; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.init.MobEffects; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.potion.PotionEffect; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -40,16 +38,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Scorched(tag.getStringOr(NAME, "Scorched"), tag.getIntOr(LEVEL, 0)); + public Modifier fromNBT(NBTTagCompound tag) { + return new Scorched( + tag.hasKey(NAME) ? tag.getString(NAME) : "Scorched", + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0); } @Override @@ -67,7 +67,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.GOLD.getName(); + return TextFormatting.GOLD.getFriendlyName(); } @Override @@ -77,8 +77,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -88,16 +88,17 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { - int fireDuration = (4 + (this.level * 2)) * 20; - hurtee.setRemainingFireTicks(fireDuration); + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { + int fireDuration = 4 + (this.level * 2); + hurtee.setFire(fireDuration); return false; } @Override - public void hold(ItemStack stack, Level level, Entity holder) { - if (!(holder instanceof LivingEntity living)) return; - living.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 60, 0, false, false)); + public void hold(ItemStack stack, World world, Entity holder) { + if (!(holder instanceof EntityLivingBase)) return; + EntityLivingBase living = (EntityLivingBase) holder; + living.addPotionEffect(new PotionEffect(MobEffects.FIRE_RESISTANCE, 60, 0, false, false)); } @Override diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Soulbound.java b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Soulbound.java index 0362013..ee04a1e 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Soulbound.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/hurter/Soulbound.java @@ -5,24 +5,23 @@ import dev.marston.randomloot.items.ModItems; import dev.marston.randomloot.loot.LootItem; import dev.marston.randomloot.loot.LootItem.ToolType; +import dev.marston.randomloot.loot.LootNBT; import dev.marston.randomloot.loot.LootUtils; import dev.marston.randomloot.loot.modifiers.EntityHurtModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.neoforge.event.entity.player.PlayerEvent; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.DamageSource; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.event.entity.player.PlayerEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.List; -@EventBusSubscriber(modid = RandomLoot.MODID) +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) public class Soulbound implements EntityHurtModifier { private String name; @@ -40,15 +39,15 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Soulbound(tag.getStringOr(NAME, "Soulbound")); + public Modifier fromNBT(NBTTagCompound tag) { + return new Soulbound(tag.hasKey(NAME) ? tag.getString(NAME) : "Soulbound"); } @Override @@ -63,7 +62,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_PURPLE.getName(); + return TextFormatting.DARK_PURPLE.getFriendlyName(); } @Override @@ -72,8 +71,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -84,7 +83,7 @@ public boolean forTool(ToolType type) { } @Override - public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity hurter) { + public boolean hurtEnemy(ItemStack itemstack, EntityLivingBase hurtee, EntityLivingBase hurter) { // Only apply bonus damage for swords and axes ToolType type = LootUtils.getToolType(itemstack); if (!type.equals(ToolType.SWORD) && !type.equals(ToolType.AXE)) { @@ -99,7 +98,7 @@ public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity // Apply 15% bonus damage float baseDamage = LootItem.getAttackDamage(itemstack, type); float bonusDamage = baseDamage * 0.15f; - hurtee.hurt(hurtee.damageSources().mobAttack(hurter), bonusDamage); + hurtee.attackEntityFrom(DamageSource.causeMobDamage(hurter), bonusDamage); return false; } @@ -107,17 +106,17 @@ public boolean hurtEnemy(ItemStack itemstack, LivingEntity hurtee, LivingEntity /** * Check if the given entity is the original owner of the tool. */ - public static boolean isOwner(ItemStack stack, LivingEntity entity) { + public static boolean isOwner(ItemStack stack, EntityLivingBase entity) { if (entity == null) { return false; } - String ownerUUID = LootUtils.getOwnerUUID(stack); + String ownerUUID = LootNBT.getOwnerUUID(stack); if (ownerUUID.isEmpty()) { return false; } - return ownerUUID.equals(entity.getStringUUID()); + return ownerUUID.equals(entity.getUniqueID().toString()); } /** @@ -125,16 +124,16 @@ public static boolean isOwner(ItemStack stack, LivingEntity entity) { */ @SubscribeEvent public static void onBreakSpeed(PlayerEvent.BreakSpeed event) { - Player player = event.getEntity(); - ItemStack stack = player.getMainHandItem(); + EntityPlayer player = event.getEntityPlayer(); + ItemStack stack = player.getHeldItemMainhand(); // Check if holding a LootItem - if (!stack.is(ModItems.TOOL.get())) { + if (stack.getItem() != ModItems.TOOL) { return; } // Check if the tool has Soulbound modifier - List mods = LootUtils.getModifiers(stack); + List mods = LootNBT.getModifiers(stack); boolean hasSoulbound = false; for (Modifier mod : mods) { if (mod.tagName().equals("soulbound")) { diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/stats/Busted.java b/src/main/java/dev/marston/randomloot/loot/modifiers/stats/Busted.java index 29fc050..4218099 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/stats/Busted.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/stats/Busted.java @@ -3,12 +3,10 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.StatsModifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.level.Level; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -29,18 +27,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); + tag.setString(NAME, name); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new Busted(tag.getStringOr(NAME, "Busted")); + public Modifier fromNBT(NBTTagCompound tag) { + return new Busted(tag.hasKey(NAME) ? tag.getString(NAME) : "Busted"); } @Override @@ -57,7 +55,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.LIGHT_PURPLE.getName(); + return TextFormatting.LIGHT_PURPLE.getFriendlyName(); } @@ -67,10 +65,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); - + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -82,7 +78,7 @@ public boolean forTool(ToolType type) { @Override public float getStats(ItemStack itemstack) { float maxDamage = itemstack.getMaxDamage(); - float currentDamage = itemstack.getDamageValue(); + float currentDamage = itemstack.getItemDamage(); float ratio = currentDamage / maxDamage; diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/users/DirtPlace.java b/src/main/java/dev/marston/randomloot/loot/modifiers/users/DirtPlace.java index 47499f8..02da6a3 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/users/DirtPlace.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/users/DirtPlace.java @@ -5,27 +5,19 @@ import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; import dev.marston.randomloot.loot.modifiers.UseModifier; -import net.minecraft.ChatFormatting; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -49,19 +41,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(DAMAGE, damage); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(DAMAGE, damage); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { + public Modifier fromNBT(NBTTagCompound tag) { return new DirtPlace( - tag.getStringOr(NAME, NameGenerator.generateForger(0.5f) + "'s Grace"), - tag.getIntOr(DAMAGE, 1) - ); + tag.hasKey(NAME) ? tag.getString(NAME) : NameGenerator.generateForger(0.5f) + "'s Grace", + tag.hasKey(DAMAGE) ? tag.getInteger(DAMAGE) : 1); } @Override @@ -76,67 +67,39 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_GREEN.getName(); + return TextFormatting.DARK_GREEN.getFriendlyName(); } - private boolean canPlace(BlockPlaceContext ctx, BlockState state) { - Player player = ctx.getPlayer(); - CollisionContext collisionContext = player == null ? CollisionContext.empty() : CollisionContext.of(player); - return state.canSurvive(ctx.getLevel(), ctx.getClickedPos()) - && ctx.getLevel().isUnobstructed(state, ctx.getClickedPos(), collisionContext); - } - - private BlockState getPlacementState(BlockPlaceContext ctx) { - BlockState blockstate = Blocks.DIRT.getStateForPlacement(ctx); - return blockstate != null && canPlace(ctx, blockstate) ? blockstate : null; - } - - private InteractionResult place(BlockPlaceContext ctx) { - if (!ctx.canPlace()) { - return InteractionResult.FAIL; - } - - BlockState blockstate = getPlacementState(ctx); - if (blockstate == null) { - return InteractionResult.FAIL; - } + private EnumActionResult place(World world, EntityPlayer player, BlockPos pos, EnumFacing facing, EnumHand hand) { + BlockPos placePos = pos.offset(facing); + IBlockState targetState = world.getBlockState(placePos); - if (!ctx.getLevel().setBlock(ctx.getClickedPos(), blockstate, 11)) { - return InteractionResult.FAIL; + // Check if position is air or replaceable + if (!targetState.getBlock().isReplaceable(world, placePos)) { + return EnumActionResult.FAIL; } - BlockPos blockpos = ctx.getClickedPos(); - Level level = ctx.getLevel(); - Player player = ctx.getPlayer(); - ItemStack itemstack = ctx.getItemInHand(); - BlockState placedState = level.getBlockState(blockpos); - - if (placedState.is(blockstate.getBlock())) { - placedState.getBlock().setPlacedBy(level, blockpos, placedState, player, itemstack); - if (player instanceof ServerPlayer serverPlayer) { - CriteriaTriggers.PLACED_BLOCK.trigger(serverPlayer, blockpos, itemstack); - } - } + IBlockState dirtState = Blocks.DIRT.getDefaultState(); + world.setBlockState(placePos, dirtState, 11); - SoundType soundtype = placedState.getSoundType(level, blockpos, player); - level.playSound(player, blockpos, soundtype.getPlaceSound(), SoundSource.BLOCKS, + SoundType soundtype = dirtState.getBlock().getSoundType(dirtState, world, placePos, player); + world.playSound(player, placePos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); - level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(player, placedState)); - return InteractionResult.SUCCESS; + return EnumActionResult.SUCCESS; } @Override - public InteractionResult use(UseOnContext ctx) { - if (!ctx.getPlayer().isCrouching()) { - return InteractionResult.PASS; // Allow normal tool behaviors when not crouching + public EnumActionResult use(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + if (!player.isSneaking()) { + return EnumActionResult.PASS; // Allow normal tool behaviors when not crouching } - BlockPlaceContext bctx = new BlockPlaceContext(ctx); - InteractionResult result = place(bctx); + EnumActionResult result = place(world, player, pos, facing, hand); - if (result == InteractionResult.SUCCESS) { - ctx.getItemInHand().hurtAndBreak(this.damage, ctx.getPlayer(), EquipmentSlot.MAINHAND); + if (result == EnumActionResult.SUCCESS) { + ItemStack stack = player.getHeldItem(hand); + stack.damageItem(this.damage, player); } return result; @@ -149,8 +112,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -165,7 +128,7 @@ public boolean forTool(ToolType type) { } @Override - public boolean use(Level level, Player player, InteractionHand hand) { + public boolean use(World world, EntityPlayer player, EnumHand hand) { return true; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/users/FireBall.java b/src/main/java/dev/marston/randomloot/loot/modifiers/users/FireBall.java index af28073..b208903 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/users/FireBall.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/users/FireBall.java @@ -4,18 +4,17 @@ import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; import dev.marston.randomloot.loot.modifiers.UseModifier; -import net.minecraft.ChatFormatting; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.projectile.hurtingprojectile.LargeFireball; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.entity.projectile.EntityLargeFireball; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -39,19 +38,21 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); - tag.putInt(DAMAGE, damage); + tag.setString(NAME, name); + tag.setInteger(DAMAGE, damage); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new FireBall(tag.getStringOr(NAME, "Flame Thrower"), tag.getIntOr(DAMAGE, 20)); + public Modifier fromNBT(NBTTagCompound tag) { + return new FireBall( + tag.hasKey(NAME) ? tag.getString(NAME) : "Flame Thrower", + tag.hasKey(DAMAGE) ? tag.getInteger(DAMAGE) : 20); } @Override @@ -66,12 +67,12 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_RED.getName(); + return TextFormatting.DARK_RED.getFriendlyName(); } @Override - public InteractionResult use(UseOnContext ctx) { - return InteractionResult.PASS; + public EnumActionResult use(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + return EnumActionResult.PASS; } @Override @@ -80,11 +81,9 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override @@ -98,18 +97,20 @@ public boolean forTool(ToolType type) { } @Override - public boolean use(Level level, Player player, InteractionHand hand) { + public boolean use(World world, EntityPlayer player, EnumHand hand) { double d1 = 2.5D; - Vec3 vec3 = player.getLookAngle(); + Vec3d vec3 = player.getLookVec(); - LargeFireball largefireball = new LargeFireball(level, player, vec3, 1); + EntityLargeFireball largefireball = new EntityLargeFireball(world, player, vec3.x, vec3.y, vec3.z); + largefireball.explosionPower = 1; - largefireball.setPos(player.getX() + vec3.x * d1, player.getY(0.5D) + 0.5D, largefireball.getZ() + vec3.z * d1); + largefireball.setPosition(player.posX + vec3.x * d1, player.posY + player.getEyeHeight() + 0.5D, player.posZ + vec3.z * d1); - level.addFreshEntity(largefireball); + world.spawnEntity(largefireball); - player.getItemInHand(hand).hurtAndBreak(this.damage, player, EquipmentSlot.MAINHAND); + ItemStack stack = player.getHeldItem(hand); + stack.damageItem(this.damage, player); return true; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/users/FirePlace.java b/src/main/java/dev/marston/randomloot/loot/modifiers/users/FirePlace.java index 49cc727..3525569 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/users/FirePlace.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/users/FirePlace.java @@ -4,29 +4,19 @@ import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; import dev.marston.randomloot.loot.modifiers.UseModifier; -import net.minecraft.ChatFormatting; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.BaseFireBlock; -import net.minecraft.world.level.block.CampfireBlock; -import net.minecraft.world.level.block.CandleBlock; -import net.minecraft.world.level.block.CandleCakeBlock; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.state.properties.BlockStateProperties; -import net.minecraft.world.level.gameevent.GameEvent; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -50,19 +40,21 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { + public NBTTagCompound toNBT() { - CompoundTag tag = new CompoundTag(); + NBTTagCompound tag = new NBTTagCompound(); - tag.putString(NAME, name); - tag.putInt(DAMAGE, damage); + tag.setString(NAME, name); + tag.setInteger(DAMAGE, damage); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new FirePlace(tag.getStringOr(NAME, "Fire Starter"), tag.getIntOr(DAMAGE, 2)); + public Modifier fromNBT(NBTTagCompound tag) { + return new FirePlace( + tag.hasKey(NAME) ? tag.getString(NAME) : "Fire Starter", + tag.hasKey(DAMAGE) ? tag.getInteger(DAMAGE) : 2); } @Override @@ -77,54 +69,34 @@ public String tagName() { @Override public String color() { - return ChatFormatting.RED.getName(); - } - - private InteractionResult flintNSteel(UseOnContext ctx) { - Player player = ctx.getPlayer(); - Level level = ctx.getLevel(); - BlockPos blockpos = ctx.getClickedPos(); - BlockState blockstate = level.getBlockState(blockpos); - if (!CampfireBlock.canLight(blockstate) && !CandleBlock.canLight(blockstate) - && !CandleCakeBlock.canLight(blockstate)) { - BlockPos blockpos1 = blockpos.relative(ctx.getClickedFace()); - if (BaseFireBlock.canBePlacedAt(level, blockpos1, ctx.getHorizontalDirection())) { - level.playSound(player, blockpos1, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, - level.getRandom().nextFloat() * 0.4F + 0.8F); - BlockState blockstate1 = BaseFireBlock.getState(level, blockpos1); - level.setBlock(blockpos1, blockstate1, 11); - level.gameEvent(player, GameEvent.BLOCK_PLACE, blockpos); - ItemStack itemstack = ctx.getItemInHand(); - if (player instanceof ServerPlayer) { - CriteriaTriggers.PLACED_BLOCK.trigger((ServerPlayer) player, blockpos1, itemstack); - ctx.getItemInHand().hurtAndBreak(this.damage, ctx.getPlayer(), EquipmentSlot.MAINHAND); - } - - return InteractionResult.SUCCESS; - } else { - return InteractionResult.FAIL; - } - } else { - level.playSound(player, blockpos, SoundEvents.FLINTANDSTEEL_USE, SoundSource.BLOCKS, 1.0F, - level.getRandom().nextFloat() * 0.4F + 0.8F); - level.setBlock(blockpos, blockstate.setValue(BlockStateProperties.LIT, Boolean.valueOf(true)), 11); - level.gameEvent(player, GameEvent.BLOCK_CHANGE, blockpos); - if (player != null) { - ctx.getItemInHand().hurtAndBreak(1, player, EquipmentSlot.MAINHAND); - } - - return InteractionResult.SUCCESS; + return TextFormatting.RED.getFriendlyName(); + } + + private EnumActionResult flintNSteel(World world, EntityPlayer player, BlockPos pos, EnumFacing facing, EnumHand hand) { + BlockPos blockpos1 = pos.offset(facing); + IBlockState state = world.getBlockState(blockpos1); + + if (state.getBlock().isAir(state, world, blockpos1)) { + world.playSound(player, blockpos1, SoundEvents.ITEM_FLINTANDSTEEL_USE, SoundCategory.BLOCKS, 1.0F, + world.rand.nextFloat() * 0.4F + 0.8F); + world.setBlockState(blockpos1, Blocks.FIRE.getDefaultState(), 11); + + ItemStack stack = player.getHeldItem(hand); + stack.damageItem(this.damage, player); + + return EnumActionResult.SUCCESS; } + return EnumActionResult.FAIL; } @Override - public InteractionResult use(UseOnContext ctx) { + public EnumActionResult use(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { - if (!ctx.getPlayer().isCrouching()) { - return InteractionResult.PASS; // Allow axe stripping when not crouching + if (!player.isSneaking()) { + return EnumActionResult.PASS; // Allow axe stripping when not crouching } - return flintNSteel(ctx); + return flintNSteel(world, player, pos, facing, hand); } @@ -135,11 +107,9 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); - } @Override @@ -153,7 +123,7 @@ public boolean forTool(ToolType type) { } @Override - public boolean use(Level level, Player player, InteractionHand hand) { + public boolean use(World world, EntityPlayer player, EnumHand hand) { return true; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/users/TorchPlace.java b/src/main/java/dev/marston/randomloot/loot/modifiers/users/TorchPlace.java index 16a831c..6e35f17 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/users/TorchPlace.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/users/TorchPlace.java @@ -4,29 +4,20 @@ import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; import dev.marston.randomloot.loot.modifiers.UseModifier; -import net.minecraft.ChatFormatting; -import net.minecraft.advancements.CriteriaTriggers; -import net.minecraft.core.BlockPos; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.context.BlockPlaceContext; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.LevelReader; -import net.minecraft.world.level.block.Blocks; -import net.minecraft.world.level.block.SoundType; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.gameevent.GameEvent; -import net.minecraft.world.phys.shapes.CollisionContext; +import net.minecraft.block.Block; +import net.minecraft.block.SoundType; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.SoundCategory; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; import java.util.List; @@ -50,19 +41,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(DAMAGE, damage); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(DAMAGE, damage); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { + public Modifier fromNBT(NBTTagCompound tag) { return new TorchPlace( - tag.getStringOr(NAME, "Spelunking"), - tag.getIntOr(DAMAGE, 10) - ); + tag.hasKey(NAME) ? tag.getString(NAME) : "Spelunking", + tag.hasKey(DAMAGE) ? tag.getInteger(DAMAGE) : 10); } @Override @@ -77,91 +67,52 @@ public String tagName() { @Override public String color() { - return ChatFormatting.YELLOW.getName(); - } - - private boolean canPlace(LevelReader level, BlockState state, BlockPos pos) { - return state.canSurvive(level, pos); - } - - private BlockState getPlacementState(BlockPlaceContext ctx) { - // Try standing torch first, then wall torch based on placement direction - LevelReader level = ctx.getLevel(); - BlockPos blockpos = ctx.getClickedPos(); - - // Check each direction the player is looking at - for (Direction direction : ctx.getNearestLookingDirections()) { - BlockState torchState; - if (direction == Direction.DOWN) { - // Can't place torch pointing down - continue; - } else if (direction == Direction.UP) { - // Standing torch - torchState = Blocks.TORCH.getStateForPlacement(ctx); - } else { - // Wall torch - placed on the opposite face - torchState = Blocks.WALL_TORCH.getStateForPlacement(ctx); - } - - if (torchState != null && canPlace(level, torchState, blockpos)) { - // Check if the position is unobstructed - if (level.isUnobstructed(torchState, blockpos, CollisionContext.empty())) { - return torchState; - } - } - } - - return null; + return TextFormatting.YELLOW.getFriendlyName(); } - private InteractionResult place(UseOnContext ctx) { - BlockPlaceContext placeCtx = new BlockPlaceContext(ctx); + private EnumActionResult placeTorch(World world, EntityPlayer player, BlockPos pos, EnumFacing facing, EnumHand hand) { + BlockPos placePos = pos.offset(facing); + IBlockState targetState = world.getBlockState(placePos); - if (!placeCtx.canPlace()) { - return InteractionResult.FAIL; + // Check if position is air or replaceable + if (!targetState.getBlock().isReplaceable(world, placePos)) { + return EnumActionResult.FAIL; } - BlockState blockstate = getPlacementState(placeCtx); - if (blockstate == null) { - return InteractionResult.FAIL; + // Try to place standing torch first, then wall torch + IBlockState torchState = null; + if (facing == EnumFacing.UP) { + // Standing torch on top of block + torchState = Blocks.TORCH.getDefaultState(); + } else if (facing != EnumFacing.DOWN) { + // Wall torch on side of block + torchState = Blocks.TORCH.getStateForPlacement(world, placePos, facing, 0, 0, 0, 0, player, hand); } - Level level = placeCtx.getLevel(); - BlockPos blockpos = placeCtx.getClickedPos(); + if (torchState != null && torchState.getBlock().canPlaceBlockAt(world, placePos)) { + world.setBlockState(placePos, torchState, 11); - if (!level.setBlock(blockpos, blockstate, 11)) { - return InteractionResult.FAIL; - } + SoundType soundtype = torchState.getBlock().getSoundType(torchState, world, placePos, player); + world.playSound(player, placePos, soundtype.getPlaceSound(), SoundCategory.BLOCKS, + (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); - Player player = placeCtx.getPlayer(); - ItemStack itemstack = placeCtx.getItemInHand(); - BlockState placedState = level.getBlockState(blockpos); - - if (placedState.is(blockstate.getBlock())) { - placedState.getBlock().setPlacedBy(level, blockpos, placedState, player, itemstack); - if (player instanceof ServerPlayer serverPlayer) { - CriteriaTriggers.PLACED_BLOCK.trigger(serverPlayer, blockpos, itemstack); - } + return EnumActionResult.SUCCESS; } - SoundType soundtype = placedState.getSoundType(level, blockpos, player); - level.playSound(player, blockpos, soundtype.getPlaceSound(), SoundSource.BLOCKS, - (soundtype.getVolume() + 1.0F) / 2.0F, soundtype.getPitch() * 0.8F); - level.gameEvent(GameEvent.BLOCK_PLACE, blockpos, GameEvent.Context.of(player, placedState)); - - return InteractionResult.SUCCESS; + return EnumActionResult.FAIL; } @Override - public InteractionResult use(UseOnContext ctx) { - if (!ctx.getPlayer().isCrouching()) { - return InteractionResult.PASS; // Allow normal tool behaviors when not crouching + public EnumActionResult use(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + if (!player.isSneaking()) { + return EnumActionResult.PASS; // Allow normal tool behaviors when not crouching } - InteractionResult result = place(ctx); + EnumActionResult result = placeTorch(world, player, pos, facing, hand); - if (result == InteractionResult.SUCCESS) { - ctx.getItemInHand().hurtAndBreak(this.damage, ctx.getPlayer(), EquipmentSlot.MAINHAND); + if (result == EnumActionResult.SUCCESS) { + ItemStack stack = player.getHeldItem(hand); + stack.damageItem(this.damage, player); } return result; @@ -174,8 +125,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -190,7 +141,7 @@ public boolean forTool(ToolType type) { } @Override - public boolean use(Level level, Player player, InteractionHand hand) { + public boolean use(World world, EntityPlayer player, EnumHand hand) { return true; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/users/VoidTouched.java b/src/main/java/dev/marston/randomloot/loot/modifiers/users/VoidTouched.java index b792ca9..ab252e5 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/users/VoidTouched.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/users/VoidTouched.java @@ -6,22 +6,20 @@ import dev.marston.randomloot.loot.modifiers.Modifier; import dev.marston.randomloot.loot.modifiers.ModifierRegistry; import dev.marston.randomloot.loot.modifiers.UseModifier; -import net.minecraft.ChatFormatting; -import net.minecraft.core.BlockPos; -import net.minecraft.core.particles.ParticleTypes; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.entity.EquipmentSlot; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.phys.Vec3; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.init.SoundEvents; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.EnumParticleTypes; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; import java.util.List; @@ -46,16 +44,18 @@ public Modifier clone() { } @Override - public CompoundTag toNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString(NAME, name); - tag.putInt(LEVEL, level); + public NBTTagCompound toNBT() { + NBTTagCompound tag = new NBTTagCompound(); + tag.setString(NAME, name); + tag.setInteger(LEVEL, level); return tag; } @Override - public Modifier fromNBT(CompoundTag tag) { - return new VoidTouched(tag.getStringOr(NAME, "Void-Touched"), tag.getIntOr(LEVEL, 0)); + public Modifier fromNBT(NBTTagCompound tag) { + return new VoidTouched( + tag.hasKey(NAME) ? tag.getString(NAME) : "Void-Touched", + tag.hasKey(LEVEL) ? tag.getInteger(LEVEL) : 0); } @Override @@ -73,7 +73,7 @@ public String tagName() { @Override public String color() { - return ChatFormatting.DARK_PURPLE.getName(); + return TextFormatting.DARK_PURPLE.getFriendlyName(); } @Override @@ -83,8 +83,8 @@ public String description() { } @Override - public void writeToLore(List list, boolean shift) { - MutableComponent comp = Modifier.makeComp(this.name(), this.color()); + public void writeToLore(List list, boolean shift) { + String comp = Modifier.formatText(this.name(), this.color()); list.add(comp); } @@ -104,50 +104,52 @@ public boolean forTool(ToolType type) { } @Override - public InteractionResult use(UseOnContext ctx) { - return InteractionResult.PASS; + public EnumActionResult use(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing facing, float hitX, float hitY, float hitZ) { + return EnumActionResult.PASS; } @Override - public boolean use(Level level, Player player, InteractionHand hand) { - if (level.isClientSide()) return false; + public boolean use(World world, EntityPlayer player, EnumHand hand) { + if (world.isRemote) return false; float distance = 8.0f + (this.level * 4.0f); - Vec3 lookVec = player.getLookAngle(); - Vec3 destination = player.position().add( - lookVec.x * distance, - lookVec.y * distance, - lookVec.z * distance + Vec3d lookVec = player.getLookVec(); + Vec3d destination = new Vec3d( + player.posX + lookVec.x * distance, + player.posY + lookVec.y * distance, + player.posZ + lookVec.z * distance ); - BlockPos targetPos = BlockPos.containing(destination); - BlockPos safePos = findSafeTeleportLocation(level, targetPos); + BlockPos targetPos = new BlockPos(destination); + BlockPos safePos = findSafeTeleportLocation(world, targetPos); if (safePos != null) { - player.teleportTo(safePos.getX() + 0.5, safePos.getY(), safePos.getZ() + 0.5); + player.setPositionAndUpdate(safePos.getX() + 0.5, safePos.getY(), safePos.getZ() + 0.5); - if (level instanceof ServerLevel serverLevel) { - serverLevel.sendParticles(ParticleTypes.PORTAL, - player.getX(), player.getY() + 1, player.getZ(), + if (world instanceof WorldServer) { + WorldServer serverWorld = (WorldServer) world; + serverWorld.spawnParticle(EnumParticleTypes.PORTAL, + player.posX, player.posY + 1, player.posZ, 32, 0.5, 0.5, 0.5, 0.1); } - player.getItemInHand(hand).hurtAndBreak(10, player, EquipmentSlot.MAINHAND); - player.playSound(SoundEvents.ENDERMAN_TELEPORT, 1.0f, 1.0f); + ItemStack stack = player.getHeldItem(hand); + stack.damageItem(10, player); + player.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 1.0f, 1.0f); } return true; } - private BlockPos findSafeTeleportLocation(Level level, BlockPos target) { + private BlockPos findSafeTeleportLocation(World world, BlockPos target) { for (int yOffset = 0; yOffset >= -5; yOffset--) { - BlockPos checkPos = target.offset(0, yOffset, 0); - BlockState below = level.getBlockState(checkPos); - BlockState at = level.getBlockState(checkPos.above()); - BlockState above = level.getBlockState(checkPos.above(2)); + BlockPos checkPos = target.add(0, yOffset, 0); + IBlockState below = world.getBlockState(checkPos); + IBlockState at = world.getBlockState(checkPos.up()); + IBlockState above = world.getBlockState(checkPos.up(2)); - if (below.isSolid() && at.isAir() && above.isAir()) { - return checkPos.above(); + if (below.isFullBlock() && !at.isFullBlock() && !above.isFullBlock()) { + return checkPos.up(); } } return null; diff --git a/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java b/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java new file mode 100644 index 0000000..95c3f75 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java @@ -0,0 +1,148 @@ +package dev.marston.randomloot.recipes; + +import dev.marston.randomloot.loot.LootItem; +import dev.marston.randomloot.loot.LootNBT; +import dev.marston.randomloot.loot.modifiers.BiomeRestrictedModifier; +import dev.marston.randomloot.loot.modifiers.Modifier; +import dev.marston.randomloot.loot.modifiers.ModifierRegistry; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.AnvilUpdateEvent; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.HashMap; +import java.util.Map; + +/** + * Handles anvil recipes for adding traits to tools. + * All traits cost 30 XP levels. + */ +public class AnvilRecipeHandler { + + private static final int XP_COST = 30; + private static final Map TRAIT_RECIPES = new HashMap<>(); + + static { + // Initialize trait recipes + TRAIT_RECIPES.put(Items.ENDER_PEARL, "teleportuse"); + TRAIT_RECIPES.put(Items.BLAZE_POWDER, "scorched"); + TRAIT_RECIPES.put(Items.PRISMARINE_SHARD, "aquatic"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.PACKED_ICE), "frozen"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.VINE), "overgrown"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.TNT), "explode"); + TRAIT_RECIPES.put(Items.MAGMA_CREAM, "flaming"); + TRAIT_RECIPES.put(Items.GOLDEN_APPLE, "draining"); + TRAIT_RECIPES.put(Items.EXPERIENCE_BOTTLE, "learning"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.IRON_BLOCK), "attracting"); + TRAIT_RECIPES.put(Items.LAVA_BUCKET, "melting"); + TRAIT_RECIPES.put(Items.DIAMOND_PICKAXE, "excavator"); + TRAIT_RECIPES.put(Items.DIAMOND, "prospector"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.REDSTONE_BLOCK), "veiny"); + TRAIT_RECIPES.put(Items.COAL, "torchplace"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.DIRT), "dirtplace"); + TRAIT_RECIPES.put(Items.FLINT_AND_STEEL, "fireplace"); + TRAIT_RECIPES.put(Items.FIRE_CHARGE, "fireball"); + TRAIT_RECIPES.put(Items.DIAMOND_SWORD, "critical"); + TRAIT_RECIPES.put(Items.FERMENTED_SPIDER_EYE, "poison"); + TRAIT_RECIPES.put(Items.SKULL, "wither"); // Wither skeleton skull (meta 1) + TRAIT_RECIPES.put(Items.DYE, "blinding"); // Ink sac (meta 0) + TRAIT_RECIPES.put(Items.NETHER_STAR, "bezerk"); + TRAIT_RECIPES.put(Items.NAME_TAG, "nemesis"); + // Player head would be skull with meta 3 + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.PISTON), "charging"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.HOPPER), "combo"); + TRAIT_RECIPES.put(Items.SUGAR, "hasty"); + TRAIT_RECIPES.put(Items.GOLDEN_CARROT, "filling"); + // Enchanted golden apple - use regular golden apple for now + TRAIT_RECIPES.put(Items.GHAST_TEAR, "regeneration"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.OBSIDIAN), "resistance"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.MAGMA), "fire_resistance"); + TRAIT_RECIPES.put(Items.BUCKET, "rainy"); + TRAIT_RECIPES.put(Items.EMERALD, "orefinder"); + TRAIT_RECIPES.put(Items.ENDER_EYE, "spawnerfinder"); + // Heart of the Sea doesn't exist in 1.12.2, use prismarine crystals instead + TRAIT_RECIPES.put(Items.PRISMARINE_CRYSTALS, "living"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.DIAMOND_BLOCK), "unbreaking"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.SLIME_BLOCK), "busted"); + } + + @SubscribeEvent + public void onAnvilUpdate(AnvilUpdateEvent event) { + ItemStack tool = event.getLeft(); + ItemStack ingredient = event.getRight(); + + // Check if left item is a random loot tool + if (!(tool.getItem() instanceof LootItem)) { + return; + } + + // Check if we have a valid trait recipe + String traitName = getTraitForItem(ingredient); + if (traitName == null) { + return; + } + + // Check if tool already has this trait + if (LootNBT.hasModifier(tool, traitName)) { + return; + } + + // Get the modifier + Modifier modifier = ModifierRegistry.getModifier(traitName); + if (modifier == null) { + return; + } + + // Check tool type compatibility + int toolTypeOrdinal = LootNBT.getToolTypeOrdinal(tool); + LootItem.ToolType toolType = LootItem.ToolType.values()[toolTypeOrdinal]; + if (!modifier.forTool(toolType)) { + return; + } + + // Check biome restrictions + if (modifier instanceof BiomeRestrictedModifier) { + BiomeRestrictedModifier restricted = (BiomeRestrictedModifier) modifier; + String biomeKey = LootNBT.getBiomeKey(tool); + float biomeTemp = LootNBT.getBiomeTemp(tool); + String dimension = LootNBT.getDimension(tool); + + if (!restricted.canSpawnInBiome(biomeKey, biomeTemp, dimension)) { + return; // Biome restriction not met + } + } + + // Create output with added trait + ItemStack output = tool.copy(); + LootNBT.addModifier(output, modifier); + + event.setOutput(output); + event.setCost(XP_COST); + event.setMaterialCost(1); + } + + private String getTraitForItem(ItemStack stack) { + if (stack.isEmpty()) { + return null; + } + + Item item = stack.getItem(); + String trait = TRAIT_RECIPES.get(item); + + // Handle special cases with metadata + if (trait != null) { + // Ink sac specifically (dye meta 0) + if (item == Items.DYE && stack.getMetadata() != 0) { + return null; + } + // Wither skeleton skull (meta 1) + if (item == Items.SKULL && stack.getMetadata() != 1) { + return null; + } + } + + return trait; + } +} diff --git a/src/main/java/dev/marston/randomloot/recipes/ModCraftingHelper.java b/src/main/java/dev/marston/randomloot/recipes/ModCraftingHelper.java deleted file mode 100644 index 7ea2af2..0000000 --- a/src/main/java/dev/marston/randomloot/recipes/ModCraftingHelper.java +++ /dev/null @@ -1,42 +0,0 @@ -package dev.marston.randomloot.recipes; - -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.crafting.CraftingInput; - -import java.util.ArrayList; -import java.util.BitSet; -import java.util.List; -import java.util.function.Predicate; -public class ModCraftingHelper { - public static List findItems(CraftingInput inv, List> predicates) { - List res = new ArrayList<>(); - BitSet matchedSlots = new BitSet(inv.size()); - - for (var pred : predicates) { - boolean found = false; - for (int i = 0; i < inv.size(); i++) { - if (!matchedSlots.get(i)) { - ItemStack stack = inv.getItem(i); - if (pred.test(stack)) { - res.add(stack); - matchedSlots.set(i); - found = true; - break; - } - } - } - if (!found) return List.of(); - } - - // check any unmatched slots for extraneous items - for (int i = 0; i < inv.size(); i++) { - if (!matchedSlots.get(i) && !inv.getItem(i).isEmpty()) return List.of(); - } - - return res; - } - - public static boolean allPresent(CraftingInput inv, List> predicates) { - return findItems(inv, predicates).size() == predicates.size(); - } -} diff --git a/src/main/java/dev/marston/randomloot/recipes/Recipies.java b/src/main/java/dev/marston/randomloot/recipes/Recipies.java deleted file mode 100644 index ef5c762..0000000 --- a/src/main/java/dev/marston/randomloot/recipes/Recipies.java +++ /dev/null @@ -1,26 +0,0 @@ -package dev.marston.randomloot.recipes; - -import dev.marston.randomloot.RandomLoot; -import net.minecraft.core.Registry; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.Identifier; -import net.minecraft.world.item.crafting.*; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.registries.DeferredHolder; -import net.neoforged.neoforge.registries.DeferredRegister; - -import java.util.function.Supplier; - -public final class Recipies { - public static final DeferredRegister> RECIPE_SERIALIZERS = DeferredRegister.create(Registries.RECIPE_SERIALIZER, RandomLoot.MODID); - public static final Supplier> TEXTURE_CHANGE_SHAPELESS = RECIPE_SERIALIZERS.register("texture_change_recipe", () -> new CustomRecipe.Serializer<>(TextureChangeRecipe::new)); - - public static final Supplier> TRAIT_ADDITION_RECIPE = RECIPE_SERIALIZERS.register("trait_change", TraitAdditionRecipe.Serializer::new); - - public static void register(IEventBus eventBus) { - RandomLoot.LOGGER.info("REGISTERING RECIPES!"); - RECIPE_SERIALIZERS.register(eventBus); - } - -} diff --git a/src/main/java/dev/marston/randomloot/recipes/TextureChangeRecipe.java b/src/main/java/dev/marston/randomloot/recipes/TextureChangeRecipe.java deleted file mode 100644 index 55aeab4..0000000 --- a/src/main/java/dev/marston/randomloot/recipes/TextureChangeRecipe.java +++ /dev/null @@ -1,102 +0,0 @@ -package dev.marston.randomloot.recipes; - -import dev.marston.randomloot.items.ModItems; -import dev.marston.randomloot.loot.LootItem; -import dev.marston.randomloot.loot.LootUtils; -import net.minecraft.core.HolderLookup; -import net.minecraft.core.NonNullList; -import net.minecraft.world.item.AirItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.*; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; - -import java.util.List; -import java.util.function.Predicate; - -public class TextureChangeRecipe extends CustomRecipe { - private static final Item ingredient = Items.AMETHYST_SHARD; - private static final List> ITEM_PREDICATES = List.of( - stack -> stack.getItem() instanceof LootItem, - stack -> stack.getItem().equals(ingredient) - ); - private static final Ingredient CHANGE_TEXTURE_INGREDIENT = Ingredient.of(ingredient); - - - - public TextureChangeRecipe(CraftingBookCategory cat) { - super(cat); - } - - @Override - public boolean matches(CraftingInput container, Level level) { - if (container.ingredientCount() < 2) { - return false; - } - - boolean hasTool = false; - List items = container.items(); - - for (ItemStack item: items) { - if (item.isEmpty()) { - continue; - } - - if (item.getItem() instanceof LootItem) { - if (hasTool) { - return false; - } - hasTool = true; - continue; - } - - if (!CHANGE_TEXTURE_INGREDIENT.test(item)) { - return false; - } - } - - - return true; - } - - @Override - public @NotNull ItemStack assemble(@NotNull CraftingInput craftingInput, HolderLookup.Provider provider) { - int modCount = 0; - List stacks = craftingInput.items(); - - ItemStack result = ItemStack.EMPTY; - for (ItemStack item : stacks) { - if (item.isEmpty()) { - continue; - } - - if (item.getItem() instanceof LootItem) { - result = LootUtils.CloneItem(item); - continue; - } - - - if (CHANGE_TEXTURE_INGREDIENT.test(item)) { - modCount++; - } - - } - - if (result.isEmpty()) { - return ItemStack.EMPTY; - } - - LootUtils.addTexture(result, modCount); - - return result; - } - - @Override - public RecipeSerializer getSerializer() { - return Recipies.TEXTURE_CHANGE_SHAPELESS.get(); - } - - -} \ No newline at end of file diff --git a/src/main/java/dev/marston/randomloot/recipes/TraitAdditionRecipe.java b/src/main/java/dev/marston/randomloot/recipes/TraitAdditionRecipe.java deleted file mode 100644 index c670cc0..0000000 --- a/src/main/java/dev/marston/randomloot/recipes/TraitAdditionRecipe.java +++ /dev/null @@ -1,185 +0,0 @@ -package dev.marston.randomloot.recipes; - -import com.mojang.serialization.Codec; -import com.mojang.serialization.MapCodec; -import com.mojang.serialization.codecs.RecordCodecBuilder; -import java.util.List; -import java.util.Optional; -import javax.annotation.Nullable; - -import dev.marston.randomloot.RandomLoot; -import dev.marston.randomloot.items.ModItems; -import dev.marston.randomloot.loot.LootUtils; -import dev.marston.randomloot.loot.modifiers.BiomeRestrictedModifier; -import dev.marston.randomloot.loot.modifiers.Modifier; -import dev.marston.randomloot.loot.modifiers.ModifierRegistry; -import net.minecraft.core.HolderLookup; -import net.minecraft.network.RegistryFriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.Items; -import net.minecraft.world.item.crafting.*; -import net.minecraft.world.item.crafting.display.RecipeDisplay; -import net.minecraft.world.item.crafting.display.SlotDisplay; -import net.minecraft.world.item.crafting.display.SmithingRecipeDisplay; -import net.minecraft.world.level.Level; -import org.jetbrains.annotations.NotNull; - -public class TraitAdditionRecipe implements SmithingRecipe { - final ItemStack addition; - final Optional template; - final Optional base; - final String trait; - @Nullable - private PlacementInfo placementInfo; - - public TraitAdditionRecipe(ItemStack addition, String traitIn) { - this.addition = addition; - this.trait = traitIn; - this.base = Optional.of(Ingredient.of(ModItems.TOOL.asItem())); - this.template= Optional.of(Ingredient.of(ModItems.MOD_SUB.asItem(), ModItems.MOD_ADD.asItem())); - } - - @Override - public boolean matches(SmithingRecipeInput input, Level level) { - - if (!input.base().is(ModItems.TOOL.asItem())) { - return false; - } - - if (!this.addition.is(input.addition().getItem())) { - return false; - } - - // Check if we're adding a modifier (not removing) - if (input.template().is(ModItems.MOD_ADD.asItem())) { - // Get the modifier being added - Modifier modToAdd = ModifierRegistry.getModifier(this.trait); - - // If it's a biome-restricted modifier, check if the tool's biome matches - if (modToAdd instanceof BiomeRestrictedModifier biomeRestricted) { - ItemStack tool = input.base(); - String biomeKey = LootUtils.getBiomeKey(tool); - float temp = LootUtils.getBiomeTemperature(tool); - String dimension = LootUtils.getDimension(tool); - - boolean canAdd = biomeRestricted.canSpawnInBiome(biomeKey, temp, dimension); - - if (!canAdd) { - RandomLoot.LOGGER.info("Recipe blocked: {} cannot be added to tool from biome: {}, temp: {}, dim: {}", - this.trait, biomeKey, temp, dimension); - return false; - } - } - } - -// if (this.addition.getCount() > input.addition().getCount()) { -// return false; -// } - - return this.template.get().test(input.template()); - } - - private ItemStack getResult(SmithingRecipeInput input) { - - ItemStack tool = input.base(); - - ItemStack template = input.template(); - - ItemStack stack = LootUtils.CloneItem(tool); - - Modifier modToAdd = ModifierRegistry.getModifier(this.trait); - - if (modToAdd == null) { - RandomLoot.LOGGER.warn("Unknown modifier trait in recipe: {}", this.trait); - return stack; - } - - if (template.is(ModItems.MOD_ADD.asItem())) { - LootUtils.addModifier(stack, modToAdd); - } else if (template.is(ModItems.MOD_SUB.asItem())) { - LootUtils.removeModifier(stack, modToAdd); - } - - - return stack; - } - - - - - public ItemStack assemble(SmithingRecipeInput input, HolderLookup.Provider provider) { - return this.getResult(input); - } - - @Override - public Optional templateIngredient() { - return this.template; - } - - @Override - public Ingredient baseIngredient() { - return this.base.get(); - } - - @Override - public Optional additionIngredient() { - return Optional.of(Ingredient.of(this.addition.getItem())); - } - - @Override - public @NotNull RecipeSerializer getSerializer() { - return Recipies.TRAIT_ADDITION_RECIPE.get(); - } - - @Override - public PlacementInfo placementInfo() { - if (this.placementInfo == null) { - this.placementInfo = PlacementInfo.createFromOptionals(List.of(templateIngredient(), Optional.of(baseIngredient()), additionIngredient())); - } - - return this.placementInfo; - } - - @Override - public List display() { - return List.of( - new SmithingRecipeDisplay( - Ingredient.optionalIngredientToDisplay(templateIngredient()), - baseIngredient().display(), - Ingredient.optionalIngredientToDisplay(additionIngredient()), - baseIngredient().display(), - new SlotDisplay.ItemSlotDisplay(Items.SMITHING_TABLE) - ) - ); - } - - public static class Serializer implements RecipeSerializer { - private static final MapCodec CODEC = RecordCodecBuilder.mapCodec( - builder -> builder.group( - ItemStack.CODEC.fieldOf("item").forGetter(g -> g.addition), - Codec.STRING.fieldOf("trait").forGetter(g -> g.trait) - ) - .apply(builder, TraitAdditionRecipe::new) - ); - public static final StreamCodec STREAM_CODEC = StreamCodec.composite( - ItemStack.STREAM_CODEC, - c -> c.addition, - ByteBufCodecs.STRING_UTF8, - c -> c.trait, - TraitAdditionRecipe::new - ); - - @Override - public MapCodec codec() { - return CODEC; - } - - @Override - public StreamCodec streamCodec() { - return STREAM_CODEC; - } - } -} - diff --git a/src/main/resources/assets/randomloot/items/case.json b/src/main/resources/assets/randomloot/items/case.json deleted file mode 100644 index d75af1e..0000000 --- a/src/main/resources/assets/randomloot/items/case.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "randomloot:item/case" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/randomloot/items/mod_add.json b/src/main/resources/assets/randomloot/items/mod_add.json deleted file mode 100644 index 0c78d28..0000000 --- a/src/main/resources/assets/randomloot/items/mod_add.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "randomloot:item/mod_add" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/randomloot/items/mod_sub.json b/src/main/resources/assets/randomloot/items/mod_sub.json deleted file mode 100644 index e785f7e..0000000 --- a/src/main/resources/assets/randomloot/items/mod_sub.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "model": { - "type": "minecraft:model", - "model": "randomloot:item/mod_sub" - } -} \ No newline at end of file diff --git a/src/main/resources/assets/randomloot/items/tool.json b/src/main/resources/assets/randomloot/items/tool.json deleted file mode 100644 index b3876d8..0000000 --- a/src/main/resources/assets/randomloot/items/tool.json +++ /dev/null @@ -1,650 +0,0 @@ -{ - "model": { - "type": "minecraft:range_dispatch", - "property": "randomloot:cosmetic", - "scale": 1, - "fallback": { - "type": "minecraft:model", - "model": "randomloot:item/tool" - }, - "entries": [ - { - "threshold": 0.1, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/1" - } - }, - { - "threshold": 0.1001, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/2" - } - }, - { - "threshold": 0.1002, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/3" - } - }, - { - "threshold": 0.1003, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/4" - } - }, - { - "threshold": 0.1004, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/5" - } - }, - { - "threshold": 0.1005, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/6" - } - }, - { - "threshold": 0.1006, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/7" - } - }, - { - "threshold": 0.1007, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/8" - } - }, - { - "threshold": 0.1008, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/9" - } - }, - { - "threshold": 0.1009, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/10" - } - }, - { - "threshold": 0.101, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/11" - } - }, - { - "threshold": 0.1011, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/12" - } - }, - { - "threshold": 0.1012, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/13" - } - }, - { - "threshold": 0.1013, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/14" - } - }, - { - "threshold": 0.1014, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/15" - } - }, - { - "threshold": 0.1015, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/16" - } - }, - { - "threshold": 0.1016, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/17" - } - }, - { - "threshold": 0.1017, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/pickaxe/18" - } - }, - { - "threshold": 0.2, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/1" - } - }, - { - "threshold": 0.2001, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/2" - } - }, - { - "threshold": 0.2002, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/3" - } - }, - { - "threshold": 0.2003, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/4" - } - }, - { - "threshold": 0.2004, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/5" - } - }, - { - "threshold": 0.2005, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/6" - } - }, - { - "threshold": 0.2006, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/7" - } - }, - { - "threshold": 0.2007, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/8" - } - }, - { - "threshold": 0.2008, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/shovel/9" - } - }, - { - "threshold": 0.3, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/1" - } - }, - { - "threshold": 0.3001, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/2" - } - }, - { - "threshold": 0.3002, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/3" - } - }, - { - "threshold": 0.3003, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/4" - } - }, - { - "threshold": 0.3004, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/5" - } - }, - { - "threshold": 0.3005, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/6" - } - }, - { - "threshold": 0.3006, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/7" - } - }, - { - "threshold": 0.3007, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/8" - } - }, - { - "threshold": 0.3008, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/9" - } - }, - { - "threshold": 0.3009, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/10" - } - }, - { - "threshold": 0.301, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/11" - } - }, - { - "threshold": 0.3011, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/12" - } - }, - { - "threshold": 0.3012, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/13" - } - }, - { - "threshold": 0.3013, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/axe/14" - } - }, - { - "threshold": 0.4, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/1" - } - }, - { - "threshold": 0.4001, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/2" - } - }, - { - "threshold": 0.4002, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/3" - } - }, - { - "threshold": 0.4003, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/4" - } - }, - { - "threshold": 0.4004, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/5" - } - }, - { - "threshold": 0.4005, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/6" - } - }, - { - "threshold": 0.4006, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/7" - } - }, - { - "threshold": 0.4007, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/8" - } - }, - { - "threshold": 0.4008, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/9" - } - }, - { - "threshold": 0.4009, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/10" - } - }, - { - "threshold": 0.401, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/11" - } - }, - { - "threshold": 0.4011, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/12" - } - }, - { - "threshold": 0.4012, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/13" - } - }, - { - "threshold": 0.4013, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/14" - } - }, - { - "threshold": 0.4014, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/15" - } - }, - { - "threshold": 0.4015, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/16" - } - }, - { - "threshold": 0.4016, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/17" - } - }, - { - "threshold": 0.4017, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/18" - } - }, - { - "threshold": 0.4018, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/19" - } - }, - { - "threshold": 0.4019, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/20" - } - }, - { - "threshold": 0.402, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/21" - } - }, - { - "threshold": 0.4021, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/22" - } - }, - { - "threshold": 0.4022, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/23" - } - }, - { - "threshold": 0.4023, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/24" - } - }, - { - "threshold": 0.4024, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/25" - } - }, - { - "threshold": 0.4025, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/26" - } - }, - { - "threshold": 0.4026, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/27" - } - }, - { - "threshold": 0.4027, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/28" - } - }, - { - "threshold": 0.4028, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/29" - } - }, - { - "threshold": 0.4029, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/30" - } - }, - { - "threshold": 0.403, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/31" - } - }, - { - "threshold": 0.4031, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/32" - } - }, - { - "threshold": 0.4032, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/33" - } - }, - { - "threshold": 0.4033, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/34" - } - }, - { - "threshold": 0.4034, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/35" - } - }, - { - "threshold": 0.4035, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/36" - } - }, - { - "threshold": 0.4036, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/37" - } - }, - { - "threshold": 0.4037, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/38" - } - }, - { - "threshold": 0.4038, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/39" - } - }, - { - "threshold": 0.4039, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/40" - } - }, - { - "threshold": 0.404, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/41" - } - }, - { - "threshold": 0.4041, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/42" - } - }, - { - "threshold": 0.4042, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/43" - } - }, - { - "threshold": 0.4043, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/44" - } - }, - { - "threshold": 0.4044, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/45" - } - }, - { - "threshold": 0.4045, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/46" - } - }, - { - "threshold": 0.4046, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/47" - } - }, - { - "threshold": 0.4047, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/48" - } - }, - { - "threshold": 0.4048, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/49" - } - }, - { - "threshold": 0.4049, - "model": { - "type": "minecraft:model", - "model": "randomloot:item/tools/sword/50" - } - } - ] - } -} \ No newline at end of file diff --git a/src/main/resources/assets/randomloot/lang/en_us.json b/src/main/resources/assets/randomloot/lang/en_us.json deleted file mode 100644 index a165607..0000000 --- a/src/main/resources/assets/randomloot/lang/en_us.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "item.randomloot.tool": "Random Tool", - "item.randomloot.case": "Loot Case", - "item.randomloot.mod_add": "Trait Addition Template", - "item.randomloot.mod_sub": "Trait Subtraction Template" - } \ No newline at end of file diff --git a/src/main/resources/assets/randomloot/lang/en_us.lang b/src/main/resources/assets/randomloot/lang/en_us.lang new file mode 100644 index 0000000..4d40d89 --- /dev/null +++ b/src/main/resources/assets/randomloot/lang/en_us.lang @@ -0,0 +1,2 @@ +item.randomloot.tool.name=Random Tool +item.randomloot.case.name=Loot Case diff --git a/src/main/resources/assets/randomloot/models/item/tool.json b/src/main/resources/assets/randomloot/models/item/tool.json index e89e1b6..5053fda 100644 --- a/src/main/resources/assets/randomloot/models/item/tool.json +++ b/src/main/resources/assets/randomloot/models/item/tool.json @@ -238,6 +238,18 @@ }, "model": "randomloot:item/tools/axe/12" }, + { + "predicate": { + "randomloot:cosmetic": 0.3012 + }, + "model": "randomloot:item/tools/axe/13" + }, + { + "predicate": { + "randomloot:cosmetic": 0.3013 + }, + "model": "randomloot:item/tools/axe/14" + }, { "predicate": { "randomloot:cosmetic": 0.4 @@ -519,6 +531,24 @@ "randomloot:cosmetic": 0.4046 }, "model": "randomloot:item/tools/sword/47" + }, + { + "predicate": { + "randomloot:cosmetic": 0.4047 + }, + "model": "randomloot:item/tools/sword/48" + }, + { + "predicate": { + "randomloot:cosmetic": 0.4048 + }, + "model": "randomloot:item/tools/sword/49" + }, + { + "predicate": { + "randomloot:cosmetic": 0.4049 + }, + "model": "randomloot:item/tools/sword/50" } ] } \ No newline at end of file diff --git a/src/main/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json b/src/main/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json deleted file mode 100644 index af98026..0000000 --- a/src/main/resources/data/neoforge/loot_modifiers/global_loot_modifiers.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "replace": false, - "entries": [ - "randomloot:case_dungeon", - "randomloot:trait_dungeon" - ] - } \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/texture_change.json b/src/main/resources/data/randomloot/recipe/texture_change.json deleted file mode 100644 index a96c712..0000000 --- a/src/main/resources/data/randomloot/recipe/texture_change.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "type": "randomloot:texture_change_recipe" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_absorption.json b/src/main/resources/data/randomloot/recipe/trait_absorption.json deleted file mode 100644 index f7122ae..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_absorption.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:golden_apple" - }, - "trait": "absorption" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_aquatic.json b/src/main/resources/data/randomloot/recipe/trait_aquatic.json deleted file mode 100644 index 25656b3..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_aquatic.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:prismarine_shard" - }, - "trait": "aquatic" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_attracting.json b/src/main/resources/data/randomloot/recipe/trait_attracting.json deleted file mode 100644 index 4948961..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_attracting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:iron_block" - }, - "trait": "attracting" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_bezerk.json b/src/main/resources/data/randomloot/recipe/trait_bezerk.json deleted file mode 100644 index a20824c..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_bezerk.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 16, - "id": "minecraft:beef" - }, - "trait": "bezerk" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_blinding.json b/src/main/resources/data/randomloot/recipe/trait_blinding.json deleted file mode 100644 index 0bb5c50..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_blinding.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 24, - "id": "minecraft:carrot" - }, - "trait": "blinding" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_busted.json b/src/main/resources/data/randomloot/recipe/trait_busted.json deleted file mode 100644 index 54bb348..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_busted.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 3, - "id": "minecraft:cracked_stone_bricks" - }, - "trait": "busted" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_charged.json b/src/main/resources/data/randomloot/recipe/trait_charged.json deleted file mode 100644 index 877d96b..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_charged.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:lightning_rod" - }, - "trait": "charged" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_combo.json b/src/main/resources/data/randomloot/recipe/trait_combo.json deleted file mode 100644 index 0684f53..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_combo.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:chorus_fruit" - }, - "trait": "combo" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_critical.json b/src/main/resources/data/randomloot/recipe/trait_critical.json deleted file mode 100644 index de74bf8..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_critical.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:ghast_tear" - }, - "trait": "critical" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_detecting.json b/src/main/resources/data/randomloot/recipe/trait_detecting.json deleted file mode 100644 index 726e699..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_detecting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:spyglass" - }, - "trait": "detecting" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_dirt_place.json b/src/main/resources/data/randomloot/recipe/trait_dirt_place.json deleted file mode 100644 index 276fa72..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_dirt_place.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 64, - "id": "minecraft:dirt" - }, - "trait": "dirt_place" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_excavator.json b/src/main/resources/data/randomloot/recipe/trait_excavator.json deleted file mode 100644 index 7e7d730..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_excavator.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:piston" - }, - "trait": "excavator" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_explode.json b/src/main/resources/data/randomloot/recipe/trait_explode.json deleted file mode 100644 index e207a83..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_explode.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 8, - "id": "minecraft:tnt" - }, - "trait": "explode" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_filling.json b/src/main/resources/data/randomloot/recipe/trait_filling.json deleted file mode 100644 index c8b24bc..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_filling.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:cake" - }, - "trait": "filling" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_fire_place.json b/src/main/resources/data/randomloot/recipe/trait_fire_place.json deleted file mode 100644 index a2a013d..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_fire_place.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:flint_and_steel" - }, - "trait": "fire_place" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_fire_resistance.json b/src/main/resources/data/randomloot/recipe/trait_fire_resistance.json deleted file mode 100644 index 94c3ae8..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_fire_resistance.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:magma_cream" - }, - "trait": "fire_resistance" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_flame_thrower.json b/src/main/resources/data/randomloot/recipe/trait_flame_thrower.json deleted file mode 100644 index 35c4360..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_flame_thrower.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 12, - "id": "minecraft:fire_charge" - }, - "trait": "flame_thrower" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_flaming.json b/src/main/resources/data/randomloot/recipe/trait_flaming.json deleted file mode 100644 index 7c942b5..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_flaming.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:blaze_rod" - }, - "trait": "flaming" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_frozen.json b/src/main/resources/data/randomloot/recipe/trait_frozen.json deleted file mode 100644 index c70a041..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_frozen.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:packed_ice" - }, - "trait": "frozen" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_hasty.json b/src/main/resources/data/randomloot/recipe/trait_hasty.json deleted file mode 100644 index 5a5127b..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_hasty.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 16, - "id": "minecraft:sugar" - }, - "trait": "hasty" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_learning.json b/src/main/resources/data/randomloot/recipe/trait_learning.json deleted file mode 100644 index 57fa30c..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_learning.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 12, - "id": "minecraft:book" - }, - "trait": "learning" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_living.json b/src/main/resources/data/randomloot/recipe/trait_living.json deleted file mode 100644 index c7e73c2..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_living.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 4, - "id": "minecraft:moss_block" - }, - "trait": "living" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_melting.json b/src/main/resources/data/randomloot/recipe/trait_melting.json deleted file mode 100644 index 22027a6..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_melting.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:lava_bucket" - }, - "trait": "melting" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_necrotic.json b/src/main/resources/data/randomloot/recipe/trait_necrotic.json deleted file mode 100644 index cf66aa4..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_necrotic.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:wither_skeleton_skull" - }, - "trait": "necrotic" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_nemesis.json b/src/main/resources/data/randomloot/recipe/trait_nemesis.json deleted file mode 100644 index f9c570d..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_nemesis.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:ender_eye" - }, - "trait": "nemesis" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_overgrown.json b/src/main/resources/data/randomloot/recipe/trait_overgrown.json deleted file mode 100644 index c2a77b1..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_overgrown.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:vine" - }, - "trait": "overgrown" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_poison.json b/src/main/resources/data/randomloot/recipe/trait_poison.json deleted file mode 100644 index 011fe00..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_poison.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 4, - "id": "minecraft:poisonous_potato" - }, - "trait": "poison" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_prospector.json b/src/main/resources/data/randomloot/recipe/trait_prospector.json deleted file mode 100644 index 3a3a927..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_prospector.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:raw_gold" - }, - "trait": "prospector" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_rainy.json b/src/main/resources/data/randomloot/recipe/trait_rainy.json deleted file mode 100644 index a95bb52..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_rainy.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:cauldron" - }, - "trait": "rainy" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_regeneration.json b/src/main/resources/data/randomloot/recipe/trait_regeneration.json deleted file mode 100644 index a75734c..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_regeneration.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 8, - "id": "minecraft:glowstone" - }, - "trait": "regeneration" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_resistance.json b/src/main/resources/data/randomloot/recipe/trait_resistance.json deleted file mode 100644 index e1b7a82..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_resistance.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 5, - "id": "minecraft:turtle_scute" - }, - "trait": "resistance" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_scorched.json b/src/main/resources/data/randomloot/recipe/trait_scorched.json deleted file mode 100644 index 7885547..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_scorched.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:blaze_powder" - }, - "trait": "scorched" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_soulbound.json b/src/main/resources/data/randomloot/recipe/trait_soulbound.json deleted file mode 100644 index d2bcb90..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_soulbound.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:nether_star" - }, - "trait": "soulbound" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_spawner.json b/src/main/resources/data/randomloot/recipe/trait_spawner.json deleted file mode 100644 index 60ca14b..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_spawner.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 12, - "id": "minecraft:mossy_cobblestone" - }, - "trait": "spawner" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_torch_place.json b/src/main/resources/data/randomloot/recipe/trait_torch_place.json deleted file mode 100644 index 6886e2b..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_torch_place.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 64, - "id": "minecraft:torch" - }, - "trait": "torch_place" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_unbreaking.json b/src/main/resources/data/randomloot/recipe/trait_unbreaking.json deleted file mode 100644 index a615d42..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_unbreaking.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 8, - "id": "minecraft:obsidian" - }, - "trait": "unbreaking" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_veiny.json b/src/main/resources/data/randomloot/recipe/trait_veiny.json deleted file mode 100644 index f707b95..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_veiny.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:diamond_pickaxe" - }, - "trait": "veiny" -} \ No newline at end of file diff --git a/src/main/resources/data/randomloot/recipe/trait_void_touched.json b/src/main/resources/data/randomloot/recipe/trait_void_touched.json deleted file mode 100644 index c7148f3..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_void_touched.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:ender_pearl" - }, - "trait": "void_touched" -} diff --git a/src/main/resources/data/randomloot/recipe/trait_wither.json b/src/main/resources/data/randomloot/recipe/trait_wither.json deleted file mode 100644 index 9bc798f..0000000 --- a/src/main/resources/data/randomloot/recipe/trait_wither.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "type": "randomloot:trait_change", - "item": { - "count": 1, - "id": "minecraft:wither_rose" - }, - "trait": "wither" -} \ No newline at end of file diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info new file mode 100644 index 0000000..4f3f357 --- /dev/null +++ b/src/main/resources/mcmod.info @@ -0,0 +1,16 @@ +[ + { + "modid": "${modid}", + "name": "${modname}", + "description": "${moddescription}", + "version": "${version}", + "mcversion": "${mcversion}", + "url": "", + "updateUrl": "", + "authorList": ["${modauthors}"], + "credits": "", + "logoFile": "logo.png", + "screenshots": [], + "dependencies": [] + } +] diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100644 index 0000000..abf02e7 --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "Random Loot 2 resources", + "pack_format": 3 + } +} diff --git a/src/main/templates/META-INF/neoforge.mods.toml b/src/main/templates/META-INF/neoforge.mods.toml deleted file mode 100644 index 63ed2af..0000000 --- a/src/main/templates/META-INF/neoforge.mods.toml +++ /dev/null @@ -1,93 +0,0 @@ -# This is an example neoforge.mods.toml file. It contains the data relating to the loading mods. -# There are several mandatory fields (#mandatory), and many more that are optional (#optional). -# The overall format is standard TOML format, v0.5.0. -# Note that there are a couple of TOML lists in this file. -# Find more information on toml format here: https://github.com/toml-lang/toml -# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml -modLoader="javafml" #mandatory - -# A version range to match for said mod loader - for regular FML @Mod it will be the FML version. This is currently 2. -loaderVersion="${loader_version_range}" #mandatory - -# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. -# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. -license="${mod_license}" - -# A URL to refer people to when problems occur with this mod -#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional - -# A list of mods - how many allowed here is determined by the individual mod loader -[[mods]] #mandatory - -# The modid of the mod -modId="${mod_id}" #mandatory - -# The version number of the mod -version="${mod_version}" #mandatory - -# A display name for the mod -displayName="${mod_name}" #mandatory - -# A URL to query for updates for this mod. See the JSON update specification https://docs.neoforged.net/docs/misc/updatechecker/ -#updateJSONURL="https://change.me.example.invalid/updates.json" #optional - -# A URL for the "homepage" for this mod, displayed in the mod UI -#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional -displayURL="https://github.com/TheMarstonConnell/randomloot" #optional - -# A file name (in the root of the mod JAR) containing a logo for display -logoFile="logo.png" #optional - -# A text field displayed in the mod UI -#credits="" #optional - -# A text field displayed in the mod UI -authors="${mod_authors}" #optional - -# The description text for the mod (multi line!) (#mandatory) -description='''${mod_description}''' - -# The [[mixins]] block allows you to declare your mixin config to FML so that it gets loaded. -#[[mixins]] -#config="${mod_id}.mixins.json" - -# The [[accessTransformers]] block allows you to declare where your AT file is. -# If this block is omitted, a fallback attempt will be made to load an AT from META-INF/accesstransformer.cfg -#[[accessTransformers]] -#file="META-INF/accesstransformer.cfg" - -# The coremods config file path is not configurable and is always loaded from META-INF/coremods.json - -# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.${mod_id}]] #optional - # the modid of the dependency - modId="neoforge" #mandatory - # The type of the dependency. Can be one of "required", "optional", "incompatible" or "discouraged" (case insensitive). - # 'required' requires the mod to exist, 'optional' does not - # 'incompatible' will prevent the game from loading when the mod exists, and 'discouraged' will show a warning - type="required" #mandatory - # Optional field describing why the dependency is required or why it is incompatible - # reason="..." - # The version range of the dependency - versionRange="${neo_version_range}" #mandatory - # An ordering relationship for the dependency. - # BEFORE - This mod is loaded BEFORE the dependency - # AFTER - This mod is loaded AFTER the dependency - ordering="NONE" - # Side this dependency is applied on - BOTH, CLIENT, or SERVER - side="BOTH" - -# Here's another dependency -[[dependencies.${mod_id}]] - modId="minecraft" - type="required" - # This version range declares a minimum of the current minecraft version up to but not including the next major version - versionRange="${minecraft_version_range}" - ordering="NONE" - side="BOTH" - -# Features are specific properties of the game environment, that you may want to declare you require. This example declares -# that your mod requires GL version 3.2 or higher. Other features will be added. They are side aware so declaring this won't -# stop your mod loading on the server for example. -#[features.${mod_id}] -#openGLVersion="[3.2,)" From d2639f8c0b33dbe335c545d448fae5912be7bb54 Mon Sep 17 00:00:00 2001 From: marston Date: Mon, 26 Jan 2026 18:39:26 -0500 Subject: [PATCH 2/5] Fix Melting modifier timing issue Use HarvestDropsEvent to intercept drops before they spawn instead of trying to find dropped items after the fact. This ensures consistent smelting behavior. --- .../loot/modifiers/breakers/Melting.java | 80 +++++-------------- .../modifiers/breakers/MeltingHandler.java | 45 +++++++++++ 2 files changed, 63 insertions(+), 62 deletions(-) create mode 100644 src/main/java/dev/marston/randomloot/loot/modifiers/breakers/MeltingHandler.java diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java index ec4dab8..d1bd139 100644 --- a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/Melting.java @@ -3,16 +3,11 @@ import dev.marston.randomloot.loot.LootItem.ToolType; import dev.marston.randomloot.loot.modifiers.BlockBreakModifier; import dev.marston.randomloot.loot.modifiers.Modifier; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.entity.item.EntityItem; import net.minecraft.item.ItemStack; import net.minecraft.item.crafting.FurnaceRecipes; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.World; -import net.minecraft.world.WorldServer; import java.util.List; @@ -38,72 +33,33 @@ public Modifier clone() { @Override public boolean startBreak(ItemStack itemstack, BlockPos pos, EntityLivingBase player) { + // Melting is now handled via MeltingHandler event + // This method is kept for interface compliance but does nothing + return false; + } - World world = player.world; - - if (world.isRemote) { - return false; + /** + * Process drops for smelting - called from MeltingHandler event. + * Modifies the drop list in place, replacing items with their smelted versions. + */ + public static void processDrops(List drops) { + for (int i = 0; i < drops.size(); i++) { + ItemStack stack = drops.get(i); + ItemStack result = FurnaceRecipes.instance().getSmeltingResult(stack); + + if (!result.isEmpty()) { + ItemStack newResult = result.copy(); + newResult.setCount(stack.getCount()); + drops.set(i, newResult); + } } - - final WorldServer serverWorld = (WorldServer) world; - AxisAlignedBB box = new AxisAlignedBB( - pos.getX() - 1, pos.getY() - 1, pos.getZ() - 1, - pos.getX() + 2, pos.getY() + 2, pos.getZ() + 2); - - // Schedule execution after a short delay to allow block drops to spawn - serverWorld.addScheduledTask(() -> { - // Schedule for next tick to allow drops to spawn - serverWorld.addScheduledTask(() -> { - List items = world.getEntitiesWithinAABB(Entity.class, box); - - for (Entity entity : items) { - if (!(entity instanceof EntityItem)) { - continue; - } - - EntityItem i = (EntityItem) entity; - if (i.getAge() > 10) { - continue; - } - - ItemStack stack = i.getItem(); - ItemStack result = FurnaceRecipes.instance().getSmeltingResult(stack); - - if (result.isEmpty()) { - continue; - } - - // Copy the result with correct count - ItemStack newResult = result.copy(); - newResult.setCount(stack.getCount()); - - // Create new item entity - EntityItem k = new EntityItem(world, i.posX, i.posY, i.posZ, newResult); - k.motionX = i.motionX; - k.motionY = i.motionY; - k.motionZ = i.motionZ; - - // Remove old item - i.setDead(); - - // Spawn new item - world.spawnEntity(k); - } - }); - }); - - return false; } @Override public NBTTagCompound toNBT() { - NBTTagCompound tag = new NBTTagCompound(); - tag.setFloat(POWER, power); - tag.setString(NAME, name); - return tag; } diff --git a/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/MeltingHandler.java b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/MeltingHandler.java new file mode 100644 index 0000000..6cd9564 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/loot/modifiers/breakers/MeltingHandler.java @@ -0,0 +1,45 @@ +package dev.marston.randomloot.loot.modifiers.breakers; + +import dev.marston.randomloot.Config; +import dev.marston.randomloot.RandomLoot; +import dev.marston.randomloot.items.ModItems; +import dev.marston.randomloot.loot.LootNBT; +import dev.marston.randomloot.loot.modifiers.Modifier; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraftforge.event.world.BlockEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.util.List; + +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) +public class MeltingHandler { + + @SubscribeEvent + public static void onHarvestDrops(BlockEvent.HarvestDropsEvent event) { + EntityPlayer player = event.getHarvester(); + if (player == null) { + return; + } + + ItemStack heldItem = player.getHeldItemMainhand(); + if (heldItem.isEmpty() || heldItem.getItem() != ModItems.TOOL) { + return; + } + + // Check if tool has Melting modifier + List mods = LootNBT.getModifiers(heldItem); + boolean hasMelting = false; + for (Modifier mod : mods) { + if (mod instanceof Melting && Config.traitEnabled(mod.tagName())) { + hasMelting = true; + break; + } + } + + if (hasMelting) { + Melting.processDrops(event.getDrops()); + } + } +} From b6423f9fba47fba5a07513f40ab2242e6089803b Mon Sep 17 00:00:00 2001 From: marston Date: Mon, 26 Jan 2026 18:43:15 -0500 Subject: [PATCH 3/5] Fix anvil recipe handler not being registered Add @Mod.EventBusSubscriber annotation and make methods static so the event handler is properly registered with Forge. --- .../dev/marston/randomloot/recipes/AnvilRecipeHandler.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java b/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java index 95c3f75..af16213 100644 --- a/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java +++ b/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java @@ -1,5 +1,6 @@ package dev.marston.randomloot.recipes; +import dev.marston.randomloot.RandomLoot; import dev.marston.randomloot.loot.LootItem; import dev.marston.randomloot.loot.LootNBT; import dev.marston.randomloot.loot.modifiers.BiomeRestrictedModifier; @@ -10,6 +11,7 @@ import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.event.AnvilUpdateEvent; +import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import java.util.HashMap; @@ -19,6 +21,7 @@ * Handles anvil recipes for adding traits to tools. * All traits cost 30 XP levels. */ +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) public class AnvilRecipeHandler { private static final int XP_COST = 30; @@ -69,7 +72,7 @@ public class AnvilRecipeHandler { } @SubscribeEvent - public void onAnvilUpdate(AnvilUpdateEvent event) { + public static void onAnvilUpdate(AnvilUpdateEvent event) { ItemStack tool = event.getLeft(); ItemStack ingredient = event.getRight(); @@ -123,7 +126,7 @@ public void onAnvilUpdate(AnvilUpdateEvent event) { event.setMaterialCost(1); } - private String getTraitForItem(ItemStack stack) { + private static String getTraitForItem(ItemStack stack) { if (stack.isEmpty()) { return null; } From 99afbdb6fee1b0bf65df62642e2f25d2f979b7ff Mon Sep 17 00:00:00 2001 From: marston Date: Mon, 26 Jan 2026 18:47:05 -0500 Subject: [PATCH 4/5] Fix anvil recipe trait names to match ModifierRegistry Corrected tagNames: - teleportuse -> void_touched - torchplace -> torch_place - dirtplace -> dirt_place - fireplace -> fire_place - fireball -> flame_thrower - charging -> charged - orefinder -> detecting - spawnerfinder -> spawner - draining -> necrotic Added missing recipes for absorption and soulbound. --- .../recipes/AnvilRecipeHandler.java | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java b/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java index af16213..df26ba8 100644 --- a/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java +++ b/src/main/java/dev/marston/randomloot/recipes/AnvilRecipeHandler.java @@ -28,47 +28,46 @@ public class AnvilRecipeHandler { private static final Map TRAIT_RECIPES = new HashMap<>(); static { - // Initialize trait recipes - TRAIT_RECIPES.put(Items.ENDER_PEARL, "teleportuse"); + // Initialize trait recipes - tagNames must match ModifierRegistry exactly + TRAIT_RECIPES.put(Items.ENDER_PEARL, "void_touched"); TRAIT_RECIPES.put(Items.BLAZE_POWDER, "scorched"); TRAIT_RECIPES.put(Items.PRISMARINE_SHARD, "aquatic"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.PACKED_ICE), "frozen"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.VINE), "overgrown"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.TNT), "explode"); TRAIT_RECIPES.put(Items.MAGMA_CREAM, "flaming"); - TRAIT_RECIPES.put(Items.GOLDEN_APPLE, "draining"); + TRAIT_RECIPES.put(Items.GOLDEN_APPLE, "necrotic"); // Draining TRAIT_RECIPES.put(Items.EXPERIENCE_BOTTLE, "learning"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.IRON_BLOCK), "attracting"); TRAIT_RECIPES.put(Items.LAVA_BUCKET, "melting"); TRAIT_RECIPES.put(Items.DIAMOND_PICKAXE, "excavator"); TRAIT_RECIPES.put(Items.DIAMOND, "prospector"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.REDSTONE_BLOCK), "veiny"); - TRAIT_RECIPES.put(Items.COAL, "torchplace"); - TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.DIRT), "dirtplace"); - TRAIT_RECIPES.put(Items.FLINT_AND_STEEL, "fireplace"); - TRAIT_RECIPES.put(Items.FIRE_CHARGE, "fireball"); + TRAIT_RECIPES.put(Items.COAL, "torch_place"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.DIRT), "dirt_place"); + TRAIT_RECIPES.put(Items.FLINT_AND_STEEL, "fire_place"); + TRAIT_RECIPES.put(Items.FIRE_CHARGE, "flame_thrower"); TRAIT_RECIPES.put(Items.DIAMOND_SWORD, "critical"); TRAIT_RECIPES.put(Items.FERMENTED_SPIDER_EYE, "poison"); TRAIT_RECIPES.put(Items.SKULL, "wither"); // Wither skeleton skull (meta 1) TRAIT_RECIPES.put(Items.DYE, "blinding"); // Ink sac (meta 0) TRAIT_RECIPES.put(Items.NETHER_STAR, "bezerk"); TRAIT_RECIPES.put(Items.NAME_TAG, "nemesis"); - // Player head would be skull with meta 3 - TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.PISTON), "charging"); + TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.PISTON), "charged"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.HOPPER), "combo"); TRAIT_RECIPES.put(Items.SUGAR, "hasty"); TRAIT_RECIPES.put(Items.GOLDEN_CARROT, "filling"); - // Enchanted golden apple - use regular golden apple for now TRAIT_RECIPES.put(Items.GHAST_TEAR, "regeneration"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.OBSIDIAN), "resistance"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.MAGMA), "fire_resistance"); TRAIT_RECIPES.put(Items.BUCKET, "rainy"); - TRAIT_RECIPES.put(Items.EMERALD, "orefinder"); - TRAIT_RECIPES.put(Items.ENDER_EYE, "spawnerfinder"); - // Heart of the Sea doesn't exist in 1.12.2, use prismarine crystals instead + TRAIT_RECIPES.put(Items.EMERALD, "detecting"); // OreFinder + TRAIT_RECIPES.put(Items.ENDER_EYE, "spawner"); // TreasureFinder TRAIT_RECIPES.put(Items.PRISMARINE_CRYSTALS, "living"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.DIAMOND_BLOCK), "unbreaking"); TRAIT_RECIPES.put(Item.getItemFromBlock(Blocks.SLIME_BLOCK), "busted"); + TRAIT_RECIPES.put(Items.TOTEM_OF_UNDYING, "absorption"); // Appley effect + TRAIT_RECIPES.put(Items.BONE, "soulbound"); } @SubscribeEvent From 5feb061a2a4286360f15e74cc9bea0649ac5c0d7 Mon Sep 17 00:00:00 2001 From: marston Date: Tue, 27 Jan 2026 11:09:26 -0500 Subject: [PATCH 5/5] add legacy item migration for old 1.12 upgrades Register old item IDs (tools, cases, armor) so they don't disappear when players upgrade from the original 1.12 mod. When held in hand, legacy items convert to a case with a thank you message. --- .../marston/randomloot/items/LegacyItem.java | 21 ++++++ .../marston/randomloot/items/ModItems.java | 34 +++++++++ .../migration/LegacyMigrationHandler.java | 73 +++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 src/main/java/dev/marston/randomloot/items/LegacyItem.java create mode 100644 src/main/java/dev/marston/randomloot/migration/LegacyMigrationHandler.java diff --git a/src/main/java/dev/marston/randomloot/items/LegacyItem.java b/src/main/java/dev/marston/randomloot/items/LegacyItem.java new file mode 100644 index 0000000..be551ae --- /dev/null +++ b/src/main/java/dev/marston/randomloot/items/LegacyItem.java @@ -0,0 +1,21 @@ +package dev.marston.randomloot.items; + +import net.minecraft.item.Item; + +/** + * Placeholder item for legacy items from the old 1.12 Random Loot mod. + * These items exist only to catch old items when players upgrade. + * When held in hand, they are converted to cases via LegacyMigrationHandler. + */ +public class LegacyItem extends Item { + private final String legacyType; + + public LegacyItem(String legacyType) { + this.legacyType = legacyType; + this.setMaxStackSize(1); + } + + public String getLegacyType() { + return legacyType; + } +} diff --git a/src/main/java/dev/marston/randomloot/items/ModItems.java b/src/main/java/dev/marston/randomloot/items/ModItems.java index 87a15a1..9aece93 100644 --- a/src/main/java/dev/marston/randomloot/items/ModItems.java +++ b/src/main/java/dev/marston/randomloot/items/ModItems.java @@ -32,5 +32,39 @@ public static void registerItems(RegistryEvent.Register event) { lootCase.setCreativeTab(CreativeTabs.TOOLS); event.getRegistry().registerAll(tool, lootCase); + + // === LEGACY ITEMS (for old 1.12 migration) === + // These items exist to catch old items when players upgrade. + // When held in hand, they are converted to cases via LegacyMigrationHandler. + + // Legacy tools + event.getRegistry().register(createLegacyItem("sword")); + event.getRegistry().register(createLegacyItem("pickaxe")); + event.getRegistry().register(createLegacyItem("axe")); + event.getRegistry().register(createLegacyItem("shovel")); + event.getRegistry().register(createLegacyItem("rl_bow")); + + // Legacy cases + event.getRegistry().register(createLegacyItem("basic_case")); + event.getRegistry().register(createLegacyItem("golden_case")); + event.getRegistry().register(createLegacyItem("titan_case")); + + // Legacy armor - Heavy set + event.getRegistry().register(createLegacyItem("heavy_boots")); + event.getRegistry().register(createLegacyItem("heavy_legs")); + event.getRegistry().register(createLegacyItem("heavy_chest")); + event.getRegistry().register(createLegacyItem("heavy_helmet")); + + // Legacy armor - Titanium set + event.getRegistry().register(createLegacyItem("titanium_boots")); + event.getRegistry().register(createLegacyItem("titanium_legs")); + event.getRegistry().register(createLegacyItem("titanium_chest")); + event.getRegistry().register(createLegacyItem("titanium_helmet")); + } + + private static LegacyItem createLegacyItem(String name) { + LegacyItem item = new LegacyItem(name); + item.setRegistryName(RandomLoot.MODID, name); + return item; } } diff --git a/src/main/java/dev/marston/randomloot/migration/LegacyMigrationHandler.java b/src/main/java/dev/marston/randomloot/migration/LegacyMigrationHandler.java new file mode 100644 index 0000000..5d6ed66 --- /dev/null +++ b/src/main/java/dev/marston/randomloot/migration/LegacyMigrationHandler.java @@ -0,0 +1,73 @@ +package dev.marston.randomloot.migration; + +import dev.marston.randomloot.RandomLoot; +import dev.marston.randomloot.items.LegacyItem; +import dev.marston.randomloot.items.ModItems; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumHand; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextFormatting; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +/** + * Handles migration of legacy items from the old 1.12 Random Loot mod. + * When a player holds a legacy item in their hand, it is converted to a case. + */ +@Mod.EventBusSubscriber(modid = RandomLoot.MODID) +public class LegacyMigrationHandler { + + @SubscribeEvent + public static void onPlayerTick(TickEvent.PlayerTickEvent event) { + if (event.phase != TickEvent.Phase.END) { + return; + } + + EntityPlayer player = event.player; + if (player.world.isRemote) { + return; + } + + // Check main hand + ItemStack mainHand = player.getHeldItemMainhand(); + if (mainHand.getItem() instanceof LegacyItem) { + LegacyItem legacy = (LegacyItem) mainHand.getItem(); + convertLegacyItem(player, EnumHand.MAIN_HAND, legacy.getLegacyType()); + } + + // Check off hand + ItemStack offHand = player.getHeldItemOffhand(); + if (offHand.getItem() instanceof LegacyItem) { + LegacyItem legacy = (LegacyItem) offHand.getItem(); + convertLegacyItem(player, EnumHand.OFF_HAND, legacy.getLegacyType()); + } + } + + private static void convertLegacyItem(EntityPlayer player, EnumHand hand, String type) { + ItemStack newCase = new ItemStack(ModItems.CASE, 1); + player.setHeldItem(hand, newCase); + + String itemName = formatLegacyName(type); + String message = TextFormatting.GOLD + "Your legacy " + itemName + + " from an older version of Random Loot has been converted to a case. Thank you for playing!"; + player.sendMessage(new TextComponentString(message)); + + RandomLoot.LOGGER.info("Converted legacy {} for player {}", type, player.getName()); + } + + private static String formatLegacyName(String type) { + // Convert "heavy_boots" -> "Heavy Boots" + String[] words = type.split("_"); + StringBuilder result = new StringBuilder(); + for (String word : words) { + if (result.length() > 0) { + result.append(" "); + } + result.append(Character.toUpperCase(word.charAt(0))); + result.append(word.substring(1)); + } + return result.toString(); + } +}