diff --git a/.gitattributes b/.gitattributes index f811f6a..b7bbcc4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,5 @@ # Disable autocrlf on generated files, they always generate with LF # Add any extra files or paths here to make git stop saying they # are changed when only line endings change. -src/generated/**/.cache/cache text eol=lf +src/generated/**/.cache/* text eol=lf src/generated/**/*.json text eol=lf diff --git a/.github/README.md b/.github/README.md index de70948..92de502 100644 --- a/.github/README.md +++ b/.github/README.md @@ -31,7 +31,7 @@ Use the libs folder in the repositories section of your build scripts as follows ``` And then use the blank keyword to add the version inside your dependencies block ``` - implementation fg.deobf("blank:flib-${mc_version}:${flib_version}") + implementation "local.mods:flib:${minecraft_version}-${flib_version}" ``` And then your gradle.properties file will get the version number set that you are using ``` @@ -54,8 +54,8 @@ And then add a dependency at the bottom of your META-INF/mods.toml page ``` [[dependencies.examplemod]] modId="flib" - mandatory=true - versionRange="[0.0.0,)" + type="required" # was mandatory=true + versionRange="[1.0.0,)" ordering="NONE" side="BOTH" ``` diff --git a/.gitignore b/.gitignore index ff73fea..4b1853a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ bin *.launch .settings .metadata -.classpath +.cla* .project # idea @@ -16,11 +16,10 @@ out # gradle build .gradle +deploy.properties # other run logs libs - -# Files from Forge MDK -forge*changelog.txt +repo diff --git a/build.gradle b/build.gradle index ae49fd0..c96974d 100644 --- a/build.gradle +++ b/build.gradle @@ -1,153 +1,174 @@ plugins { - id 'eclipse' - id 'idea' + id 'java-library' id 'maven-publish' - id 'net.neoforged.gradle' version '[6.0.18,6.2)' + id 'net.neoforged.moddev' version '2.0.141' + id 'idea' } - -version = "${mc_version}-${mod_version}" +def localProps = new Properties() +def localFile = file("mod.properties") +localFile.withInputStream { localProps.load(it) } +localProps.each { k, v -> project.ext.set(k, v) } + +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 = "${minecraft_version}-${mod_version}" group = mod_group_id +sourceSets.main.resources { + // Include resources generated by data generators. + srcDir('src/generated/resources') + + // Exclude common development only resources from finalized outputs + exclude("**/*.bbmodel") // BlockBench project files + exclude("src/generated/**/.cache") // datagen cache files +} + + + +repositories { +// mavenLocal() + flatDir { dir 'libs' } + + maven { + name = "curios" + url = 'https://maven.theillusivec4.top/' + } + maven { url = 'https://maven.blamejared.com' } + maven { url = 'https://www.cursemaven.com' } +} + base { archivesName = mod_id } -// Mojang ships Java 17 to end users in 1.18+, so your mod should target Java 17. -java.toolchain.languageVersion = JavaLanguageVersion.of(17) -import net.minecraftforge.gradle.common.tasks.SignJar +// Mojang ships Java 21 to end users in 1.21.1, so mods should target Java 21. +// for intellij make sure to set JVM Navigate to Build, Execution, Deployment > Build Tools > Gradle +java.toolchain.languageVersion = JavaLanguageVersion.of(21) println "Java: ${System.getProperty 'java.version'}, JVM: ${System.getProperty 'java.vm.version'} (${System.getProperty 'java.vendor'}), Arch: ${System.getProperty 'os.arch'}" -minecraft { - // The mappings can be changed at any time and must be in the following format. - // Channel: Version: - // official MCVersion Official field/method names from Mojang mapping files - // parchment YYYY.MM.DD-MCVersion Open community-sourced parameter names and javadocs layered on top of official - // - // You must be aware of the Mojang license when using the 'official' or 'parchment' mappings. - // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md - // - // Parchment is an unofficial project maintained by ParchmentMC, separate from MinecraftForge - // Additional setup is needed to use their mappings: https://parchmentmc.org/docs/getting-started - // - // Use non-default mappings at your own risk. They may not always work. - // Simply re-run your setup task after changing the mappings to update your workspace. - mappings channel: mapping_channel, version: mapping_version - - // When true, this property will have all Eclipse/IntelliJ IDEA run configurations run the "prepareX" task for the given run configuration before launching the game. - // In most cases, it is not necessary to enable. - // enableEclipsePrepareRuns = true - // enableIdeaPrepareRuns = true - // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. - // It is REQUIRED to be set to true for this template to function. - // See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html - copyIdeResources = true - - // When true, this property will add the folder name of all declared run configurations to generated IDE run configurations. - // The folder name can be set on a run configuration using the "folderName" property. - // By default, the folder name of a run configuration is the name of the Gradle project containing it. - // generateRunFolders = true - - // This property enables access transformers for use in development. - // They will be applied to the Minecraft artifact. - // The access transformer file can be anywhere in the project. - // However, it must be at "META-INF/accesstransformer.cfg" in the final mod jar to be loaded by Forge. - // This default location is a best practice to automatically put the file in the right place in the final jar. - // See https://docs.minecraftforge.net/en/latest/advanced/accesstransformers/ for more information. - accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') +neoForge { + // Specify the version of NeoForge to use. + version = project.neo_version - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. - runs { - // applies to all the run configs below - configureEach { - workingDirectory project.file('run') - // 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. - property 'forge.logging.markers', 'REGISTRIES' + // This property allows configuring Gradle's ProcessResources task(s) to run on IDE output locations before launching the game. + // It is REQUIRED to be set to true for the 1.21.1 template to function correctly. + // ideConfigGenerated = true - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels - property 'forge.logging.console.level', 'debug' + // Other optional settings + // validateAccessTransformers = true - mods { - "${mod_id}" { - source sourceSets.main - } - } - } + parchment { + mappingsVersion = project.parchment_mappings_version + minecraftVersion = project.parchment_minecraft_version + } + 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. - property 'forge.enabledGameTestNamespaces', mod_id + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id } server { - property 'forge.enabledGameTestNamespaces', mod_id - args '--nogui' + 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 { - property 'forge.enabledGameTestNamespaces', mod_id + type = "gameTestServer" + systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id } data { - // example of overriding the workingDirectory set in configureEach above - workingDirectory project.file('run-data') + data() + + // 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. - args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/') + programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() } - } -} -// Include resources generated by data generators. -//sourceSets.main.resources { srcDir 'src/generated/resources' } + // applies to all the run configs above + configureEach { + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + systemProperty 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + logLevel = org.slf4j.event.Level.DEBUG -repositories { -// flatDir { dir 'libs' } + } + } - maven { - name = "curios" - url = 'https://maven.theillusivec4.top/' - } -// maven { url = 'https://maven.blamejared.com' } -// maven { url = 'https://modmaven.dev' } -// maven { url = 'https://www.cursemaven.com' } + 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) + } + } +} + +// 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 } + dependencies { - // Specify the version of Minecraft to use. - // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact. - // The "userdev" classifier will be requested and setup by ForgeGradle. - // If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"], - // then special handling is done to allow a setup of a vanilla dependency without the use of an external repository. - minecraft "net.neoforged:forge:${mc_version}-${neo_version}" - - // Example mod dependency with JEI - using fg.deobf() ensures the dependency is remapped to your development mappings - // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-common-api:${jei_version}") - // compileOnly fg.deobf("mezz.jei:jei-${mc_version}-forge-api:${jei_version}") - // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}-forge:${jei_version}") - - // runtimeOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${mc_version}") - // compileOnly fg.deobf("top.theillusivec4.curios:curios-forge:${curios_version}+${mc_version}:api") - - // implementation fg.deobf("com.blamejared.crafttweaker:CraftTweaker-forge-${mc_version}:${crafttweaker_version}") - - - + + // for other mods depending on THIS FLIB library, use + // implementation "local.mods:flib:${minecraft_version}-${flib_version}" + + + //these mods have API jars for compile as well as the full mod for local + compileOnly "mezz.jei:jei-${minecraft_version}-neoforge-api:${jei_version}" + localRuntime "mezz.jei:jei-${minecraft_version}-neoforge:${jei_version}" + + compileOnly "top.theillusivec4.curios:curios-neoforge:${curios_version}+${minecraft_version}" + localRuntime "top.theillusivec4.curios:curios-neoforge:${curios_version}+${minecraft_version}" + + // no APIs + compileOnly "vazkii.patchouli:Patchouli:${minecraft_version}-${patchouli_version}-NEOFORGE" + + compileOnly "com.blamejared.crafttweaker:CraftTweaker-neoforge-${minecraft_version}:${crafttweaker_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 + // This maps to ./libs/coolmod-${minecraft_version}-${coolmod_version}.jar // The group id is ignored when searching -- in this case, it is "blank" - // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + // implementation "blank:coolmod-${minecraft_version}:${coolmod_version}" + + // Example mod dependency using a file as dependency + // implementation files("libs/coolmod-${minecraft_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 @@ -156,76 +177,72 @@ dependencies { // This block of code expands all declared replace properties in the specified resource targets. // A missing property will result in an error. Properties are expanded using ${} Groovy notation. -// When "copyIdeResources" is enabled, this will also run before the game launches in IDE environments. -// See https://docs.gradle.org/current/dsl/org.gradle.language.jvm.tasks.ProcessResources.html -tasks.named('processResources', ProcessResources).configure { +var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) { var replaceProperties = [ - mod_id: mod_id, mod_name: mod_name, mod_license: mod_license, - mc_version: mc_version, mod_version: mod_version, - mod_authors: mod_authors, mod_description: mod_description, + minecraft_version : minecraft_version, + neo_version : neo_version, + loader_version_range : loader_version_range, + curse_slug : curse_slug, + mod_id : mod_id, + mod_name : mod_name, + mod_license : mod_license, + mod_version : mod_version, + mod_authors : mod_authors, + mod_description : mod_description ] inputs.properties replaceProperties - - filesMatching(['META-INF/mods.toml', 'pack.mcmeta']) { - expand replaceProperties + [project: project] - } + expand replaceProperties + from "src/main/templates" + into "build/generated/sources/modMetadata" } -// Example for how to get properties into the manifest for reading at runtime. -tasks.named('jar', Jar).configure { - manifest { - attributes([ - 'Specification-Title' : mod_id, - 'Specification-Vendor' : mod_authors, - 'Specification-Version' : '1', // We are version 1 of ourselves - 'Implementation-Title' : project.name, - 'Implementation-Version' : project.jar.archiveVersion, - 'Implementation-Vendor' : mod_authors, - 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") - ]) - } +// ??? +//sourceSets.main.resources.srcDir 'src/main/templates' + +// 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 +// Ensure standard processResources doesn't try to double-process the same files - // This is the preferred method to reobfuscate your jar file - finalizedBy 'reobfJar' -} -// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing: -// tasks.named('publish').configure { -// dependsOn 'reobfJar' -// } +//processResources { +// //from("src/main/resources") +// // 1. Tell Gradle what to do if it finds a duplicate (usually take the first one) +// duplicatesStrategy = DuplicatesStrategy.INCLUDE +// +// // 2. Ensure we aren't accidentally pulling the raw templates folder +// // into the final build (the generateModMetadata task handles this instead) +// exclude 'templates' +//} // Example configuration to allow publishing using the maven-publish plugin publishing { publications { register('mavenJava', MavenPublication) { - artifact jar + from components.java } } repositories { maven { - url "file://${project.projectDir}/mcmodsrepo" + // url "file://${project.projectDir}/repo" + // url uri("${project.projectDir}/repo") + url = uri("${project.projectDir}/repo") } } } -task signJar(type: SignJar, dependsOn: jar) { - - // findProperty allows us to reference the property without it existing. - // Using project.propName would cause the script to fail validation if - // the property did not exist. - keyStore = project.findProperty('keyStore') - alias = project.findProperty('keyStoreAlias') - storePass = project.findProperty('keyStorePass') - keyPass = project.findProperty('keyStoreKeyPass') - inputFile = jar.archivePath - outputFile = jar.archivePath -} - -task cleanJar { - delete 'build/libs' -} - +apply from: 'gradle/deploy.gradle' 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 + } +} diff --git a/gradle.properties b/gradle.properties index df54b8b..e1a0e8c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,30 +1,28 @@ # Sets default memory used for gradle commands. Can be overridden by user or command line properties. # This is required to provide enough memory for the Minecraft decompilation process. org.gradle.jvmargs=-Xmx3G -org.gradle.daemon=false +org.gradle.daemon=true +org.gradle.parallel=true +org.gradle.caching=true +org.gradle.configuration-cache=true + +#read more on this at https://github.com/neoforged/NeoGradle/blob/NG_7.0/README.md#apply-parchment-mappings +# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started +parchment_minecraft_version=1.21.1 +parchment_mappings_version=2024.11.17 # your properties # https://www.curseforge.com/minecraft/mc-mods/flib -mod_id=flib -curse_id=661261 -mod_version=0.0.15 - -mc_version=1.20.1 -neo_version=47.1.105 - - -mod_name=flib -mod_group_id=com.lothrazar.flib - -mod_license=SeeGithub -mod_authors=Lothrazar -mod_description=Future Library. Empowers many forge mods. +minecraft_version=1.21.1 +neo_version=21.1.222 -mapping_version=1.20.1 -mapping_channel=official +loader_version_range=[1,) +# flib_version=1.0.0 -#jei_version=15.0.0.23 -#curios_version=5.7.2 +patchouli_version=93 +jei_version=19.27.0.340 +curios_version=9.5.1 +crafttweaker_version=21.0.38 diff --git a/gradle/deploy.gradle b/gradle/deploy.gradle new file mode 100644 index 0000000..1b17f2a --- /dev/null +++ b/gradle/deploy.gradle @@ -0,0 +1,47 @@ +// --------------------------------------------------------------------------- +// deployLocal — copies the built JAR to every folder listed in deploy.properties +// deploy.properties is gitignored; each developer maintains their own copy. +// +// Runs automatically after 'publish' via finalizedBy. +// Can also be run standalone with: gradlew deployLocal +// (depends only on 'jar' so it won't trigger a full publish cycle standalone) +// --------------------------------------------------------------------------- +def deployProps = new Properties() +def deployFile = rootProject.file('deploy.properties') +if (deployFile.exists()) { + deployFile.withInputStream { deployProps.load(it) } +} + +tasks.register('deployLocal') { + description = 'Copies build jar to all destinations in deploy.properties' + group = 'distribution' + dependsOn 'jar' + + def jarFile = layout.buildDirectory.file("libs/${base.archivesName.get()}-${version}.jar") + + def destinations = deployProps.getProperty('destinations', '') + .split(',') + .collect { it.trim() } + .findAll { it } + + onlyIf { !destinations.isEmpty() } + + // doLast avoids configuration cache errors from project.copy() references + doLast { + def source = jarFile.get().asFile + destinations.each { dest -> + def destDir = new File(dest) + destDir.mkdirs() + java.nio.file.Files.copy( + source.toPath(), + new File(destDir, source.name).toPath(), + java.nio.file.StandardCopyOption.REPLACE_EXISTING + ) + logger.lifecycle("Deployed ${source.name} -> ${dest}") + } + } +} + +tasks.named('publish') { + finalizedBy 'deployLocal' +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 943f0cb..1b33c55 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 37aef8d..23449a2 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 65dcd68..23d15a9 100644 --- a/gradlew +++ b/gradlew @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. # +# SPDX-License-Identifier: Apache-2.0 +# ############################################################################## # @@ -55,7 +57,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -83,10 +85,8 @@ done # This is normally unused # shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -114,7 +114,7 @@ case "$( uname )" in #( NONSTOP* ) nonstop=true ;; esac -CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar +CLASSPATH="\\\"\\\"" # Determine the Java command to use to start the JVM. @@ -133,10 +133,13 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. @@ -144,7 +147,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac @@ -152,7 +155,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then '' | soft) :;; #( *) # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC3045 + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -197,16 +200,20 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ + -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ "$@" # Stop when "xargs" is not available. diff --git a/gradlew.bat b/gradlew.bat index 93e3f59..db3a6ac 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -13,6 +13,8 @@ @rem See the License for the specific language governing permissions and @rem limitations under the License. @rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem @if "%DEBUG%"=="" @echo off @rem ########################################################################## @@ -43,11 +45,11 @@ set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 if %ERRORLEVEL% equ 0 goto execute -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail @@ -57,22 +59,22 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe if exist "%JAVA_EXE%" goto execute -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 goto fail :execute @rem Setup the command line -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar +set CLASSPATH= @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* :end @rem End local scope for the variables with windows NT shell diff --git a/mod.properties b/mod.properties new file mode 100644 index 0000000..e0fa07c --- /dev/null +++ b/mod.properties @@ -0,0 +1,11 @@ + +mod_version=1.0.0-SNAPSHOT + +mod_id=flib +mod_license=MIT +mod_authors=Lothrazar +mod_description=mod +mod_name=FutureLibrary +mod_group_id=com.lothrazar.library +curse_slug=flib +curse_id=661261 diff --git a/scripts/clone.sh b/scripts/clone.sh new file mode 100644 index 0000000..2032bd3 --- /dev/null +++ b/scripts/clone.sh @@ -0,0 +1,112 @@ +#!/usr/bin/env bash +# this set -e tells bash to exit if a command such as git clone fails (nonzero) +set -e + +GITHUB="Lothrazar" +TEMP_DIR="/c/temp" +SOURCE_DIR="/c/Users/USER/eclipse-workspace/mc121/FLib" + +REPONAME="$1" +if [ -z "$REPONAME" ]; then + echo "Usage: clone.sh " + exit 1 +fi + +MC="1.21.1" +TARGET_DIR="/c/Users/USER/MyFiles/mc121/$REPONAME" +GIT_URL="git@github.com:${GITHUB}/${REPONAME}.git" +MOD_PROPS="$TARGET_DIR/mod.properties" +DEPLOY_PROPS="$TARGET_DIR/deploy.properties" +FLIB_VERSION="1.0.0-SNAPSHOT" + +echo +git clone "$GIT_URL" "$TARGET_DIR" +echo + +echo "✓ Cloned '$REPONAME' repository" + + +cd "$TARGET_DIR" + + +if [ ! -f "$MOD_PROPS" ]; then + + cat > "$MOD_PROPS" << EOF + +flib_version=$FLIB_VERSION + +EOF + + + echo "✓ mod.properties not found, template created" + + grep -E "^(mod_version|mod_id|mod_name|mod_license|mod_authors|mod_description|mod_group_id|curse_id|curse_slug)=" "$TARGET_DIR/gradle.properties" >> "$MOD_PROPS" || true + + echo "✓ Moved mod-specific properties into $MOD_PROPS" + +fi + +if [ ! -f "$DEPLOY_PROPS" ]; then + + cat > "$DEPLOY_PROPS" << EOF + +# CSV list of folders that will copy the release version to +# after the gradle publish task + +destinations=C:/temp + +EOF + echo "✓ deploy.properties not found, template created" +fi + +cp "$SOURCE_DIR/.gitignore" ./.gitignore +# gradle and other core shared files copied +cp -r "$SOURCE_DIR/gradle" ./ +cp "$SOURCE_DIR/gradle.properties" ./gradle.properties +cp "$SOURCE_DIR/settings.gradle" ./settings.gradle +cp "$SOURCE_DIR/build.gradle" ./build.gradle +cp "$SOURCE_DIR/gradlew" ./gradlew +cp "$SOURCE_DIR/gradlew.bat" ./gradlew.bat +echo "✓ Updated gradle" + +# rm legacy mods.toml if present (NeoForge uses templates -> neoforge.mods.toml) +rm -f ./src/main/resources/META-INF/mods.toml +echo "✓ Removed legacy mods.toml" + +# add the new template +cp -r "$SOURCE_DIR/src/main/templates" ./src/main/templates + +MODS_TOML="$TARGET_DIR/src/main/templates/META-INF/neoforge.mods.toml" +if [ -f "$MODS_TOML" ]; then + cat >> "$MODS_TOML" << 'EOF' + +[[dependencies.${mod_id}]] + modId="flib" + type="required" + versionRange="[0.1.0,)" + ordering="NONE" + side="BOTH" +EOF + + echo "✓ Appended flib dependency to neoforge.mods.toml" +fi + + + +mkdir -p "$TARGET_DIR/libs" +cp "/c/temp/flib-$MC-$FLIB_VERSION.jar" "$TARGET_DIR/libs/flib-$MC-$FLIB_VERSION.jar" + +echo "✓ Default library copied from temp" + +echo "✓ Source branch $(git rev-parse --abbrev-ref HEAD)" + +echo "! Verify mod.properties values and optional dependencies before building !" + +echo "! Update build.gradle dependencies as needed" + +echo + +git checkout -b port + +echo +# read -rp "Press Enter to close..." diff --git a/scripts/dist.sh b/scripts/dist.sh deleted file mode 100644 index 96859c1..0000000 --- a/scripts/dist.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/bash - -#./gradlew copyJar -# TODO loop on list lol -# cp -R build/libs/. c:/temp - -cp -R build/libs/. ../Cyclic/libs -cp -R build/libs/. ../RootsClassic/libs -cp -R build/libs/. ../Similsax-Transtructors/libs -cp -R build/libs/. ../SimpleTomb/libs -cp -R build/libs/. ../Storage-Network/libs -cp -R build/libs/. ../VeinCreeper/libs - -# cp -R build/libs/. ../Cyclic/libs -# cp -R build/libs/. ../ElementaryOres/libs -# cp -R build/libs/. ../PotatoBread/libs -# cp -R build/libs/. ../TinyLightBulbs/libs -# cp -R build/libs/. ../CustomGameRules/libs -# cp -R build/libs/. ../ForgeCreeperHeal/libs -# cp -R build/libs/. ../EnchantingRunes/libs -# cp -R build/libs/. ../ForgeTemplate/libs -# cp -R build/libs/. ../Scraps/libs -# cp -R build/libs/. ../SaplingGrowthControl/libs -# cp -R build/libs/. ../cobblestoney/libs -# cp -R build/libs/. ../absentbydesign/libs -# cp -R build/libs/. ../antibonemeal/libs -# cp -R build/libs/. ../BlockLayers/libs -# cp -R build/libs/. ../AutoRun/libs -# cp -R build/libs/. ../FragileTorches/libs -# cp -R build/libs/. ../GardenTools/libs -# cp -R build/libs/. ../GlassCutter/libs -# cp -R build/libs/. ../FragileTorches/libs -# cp -R build/libs/. ../HeartBalance/libs -# cp -R build/libs/. ../NoLogPunch/libs -# cp -R build/libs/. ../NoLavaBuild/libs -# cp -R build/libs/. ../stupidHorseStandStill/libs diff --git a/scripts/release.sh b/scripts/release.sh deleted file mode 100644 index f9ae4f1..0000000 --- a/scripts/release.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/bash - -./gradlew cleanJar build signJar - -./scripts/dist.sh diff --git a/scripts/setup.sh b/scripts/setup.sh deleted file mode 100644 index e7289d6..0000000 --- a/scripts/setup.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -./gradlew genEclipseRuns diff --git a/settings.gradle b/settings.gradle index 24584e9..7a488e3 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,13 +1,9 @@ pluginManagement { repositories { gradlePluginPortal() - maven { - name = 'NeoForged' - url = 'https://maven.neoforged.net/releases' - } } } plugins { - id 'org.gradle.toolchains.foojay-resolver-convention' version '0.5.0' -} \ No newline at end of file + id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' +} diff --git a/src/main/java/com/lothrazar/library/FutureLibMod.java b/src/main/java/com/lothrazar/library/FutureLibMod.java index f90dd29..3d87402 100644 --- a/src/main/java/com/lothrazar/library/FutureLibMod.java +++ b/src/main/java/com/lothrazar/library/FutureLibMod.java @@ -2,15 +2,15 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import com.lothrazar.library.cap.player.PlayerCapProvider; import com.lothrazar.library.events.FlibBlockEvents; import com.lothrazar.library.mod.CommandModule; import com.lothrazar.library.mod.ConfigModule; +import com.lothrazar.library.mod.FlibRegistrations; import com.lothrazar.library.mod.PacketRegistry; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.InterModComms; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.common.Mod; @Mod(FutureLibMod.MODID) public class FutureLibMod { @@ -18,21 +18,12 @@ public class FutureLibMod { public static final String MODID = "flib"; public static final Logger LOGGER = LogManager.getLogger(); - /** - * all "content" of the mod such as built in commands are in the 'library.mod' package, to keep it split up from the rest of the library code - */ - public FutureLibMod() { - new ConfigModule(); + public FutureLibMod(IEventBus modEventBus, ModContainer modContainer) { + new ConfigModule(modContainer); new CommandModule(); new FlibBlockEvents(); - IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus(); - bus.addListener(this::setup); - } - - private void setup(final FMLCommonSetupEvent event) { - PacketRegistry.setup(); - InterModComms.getMessages(MODID).forEach(x -> { - LOGGER.info("registration from " + x.senderModId() + " | " + x.messageSupplier().get()); - }); + PlayerCapProvider.ATTACHMENT_TYPES.register(modEventBus); + FlibRegistrations.register(modEventBus); + modEventBus.addListener(PacketRegistry::onRegisterPayloads); } } diff --git a/src/main/java/com/lothrazar/library/block/BlockFlib.java b/src/main/java/com/lothrazar/library/block/BlockFlib.java index 3fa249a..c3d754a 100644 --- a/src/main/java/com/lothrazar/library/block/BlockFlib.java +++ b/src/main/java/com/lothrazar/library/block/BlockFlib.java @@ -16,6 +16,7 @@ import net.minecraft.world.item.DyeColor; import net.minecraft.world.item.DyeItem; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Item; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; @@ -29,9 +30,9 @@ import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; +import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent.RightClickBlock; public class BlockFlib extends Block { @@ -166,13 +167,6 @@ public int getDirectSignal(BlockState blockState, BlockGetter blockAccess, Block return super.getDirectSignal(blockState, blockAccess, pos, side); } - @SuppressWarnings("deprecation") - @Override - public InteractionResult use(BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) { - // ItemStack heldStack = player.getItemInHand(hand); - return super.use(state, world, pos, player, hand, hit); - } - public void onRightClickBlock(RightClickBlock event, BlockState state) { if (me.rotateColour && event.getItemStack().getItem() instanceof DyeItem newColor) { @@ -212,10 +206,10 @@ public void setConnectedColour(Level world, BlockPos pos, DyeColor oldColour, Dy @Override @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, BlockGetter worldIn, List tooltip, TooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Item.TooltipContext context, List tooltip, TooltipFlag flagIn) { if (me.tooltip) { me.tooltipApply(this, tooltip); } - super.appendHoverText(stack, worldIn, tooltip, flagIn); + super.appendHoverText(stack, context, tooltip, flagIn); } } diff --git a/src/main/java/com/lothrazar/library/cap/CustomEnergyStorage.java b/src/main/java/com/lothrazar/library/cap/CustomEnergyStorage.java index 4946e4a..726e5da 100644 --- a/src/main/java/com/lothrazar/library/cap/CustomEnergyStorage.java +++ b/src/main/java/com/lothrazar/library/cap/CustomEnergyStorage.java @@ -1,15 +1,17 @@ package com.lothrazar.library.cap; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.energy.EnergyStorage; +import net.minecraft.nbt.IntTag; +import net.minecraft.nbt.Tag; +import net.neoforged.neoforge.energy.EnergyStorage; /** * For use with items, tile entities, etc. - * + * * @see cyclic */ -public class CustomEnergyStorage extends EnergyStorage implements INBTSerializable { +public class CustomEnergyStorage extends EnergyStorage { public static final String NBTENERGY = "energy"; @@ -22,21 +24,40 @@ public void setEnergy(int energyIn) { energyIn = 0; } if (energyIn > getMaxEnergyStored()) { - energyIn = getEnergyStored(); + energyIn = getMaxEnergyStored(); } this.energy = energyIn; } - @Override - public CompoundTag serializeNBT() { + /** + * Serialize energy to a CompoundTag (e.g. for block entity NBT). + * Use this instead of serializeNBT() when embedding energy inside a larger compound. + */ + public CompoundTag saveToTag() { CompoundTag tag = new CompoundTag(); tag.putInt(NBTENERGY, getEnergyStored()); return tag; } + /** + * Deserialize energy from a CompoundTag (e.g. from block entity NBT). + */ + public void loadFromTag(CompoundTag tag) { + setEnergy(tag.getInt(NBTENERGY)); + } + + // Override INBTSerializable from EnergyStorage with provider signatures @Override - public void deserializeNBT(net.minecraft.nbt.Tag nbt) { - CompoundTag real = (CompoundTag) nbt; - setEnergy(real.getInt(NBTENERGY)); + public IntTag serializeNBT(HolderLookup.Provider provider) { + return IntTag.valueOf(getEnergyStored()); + } + + @Override + public void deserializeNBT(HolderLookup.Provider provider, Tag nbt) { + if (nbt instanceof IntTag intNbt) { + setEnergy(intNbt.getAsInt()); + } else { + throw new IllegalArgumentException("Can not deserialize to an instance that isn't the default implementation"); + } } } diff --git a/src/main/java/com/lothrazar/library/cap/ItemStackHandlerEx.java b/src/main/java/com/lothrazar/library/cap/ItemStackHandlerEx.java index 5dd75ad..4af99e4 100644 --- a/src/main/java/com/lothrazar/library/cap/ItemStackHandlerEx.java +++ b/src/main/java/com/lothrazar/library/cap/ItemStackHandlerEx.java @@ -3,7 +3,7 @@ import java.util.ArrayList; import java.util.List; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.items.ItemStackHandler; +import net.neoforged.neoforge.items.ItemStackHandler; public class ItemStackHandlerEx extends ItemStackHandler { diff --git a/src/main/java/com/lothrazar/library/cap/ItemStackHandlerWrapper.java b/src/main/java/com/lothrazar/library/cap/ItemStackHandlerWrapper.java index 968a358..fa04fe3 100644 --- a/src/main/java/com/lothrazar/library/cap/ItemStackHandlerWrapper.java +++ b/src/main/java/com/lothrazar/library/cap/ItemStackHandlerWrapper.java @@ -1,14 +1,15 @@ package com.lothrazar.library.cap; -import java.util.stream.Stream; -import javax.annotation.Nullable; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.IItemHandlerModifiable; -import net.minecraftforge.items.ItemStackHandler; +import net.neoforged.neoforge.common.util.INBTSerializable; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.IItemHandlerModifiable; +import net.neoforged.neoforge.items.ItemStackHandler; + +import java.util.stream.Stream; /** * Wraps two {@link ItemStackHandler}s: Input and Output. Input's slots come first then the Output's slots come after. Items can only be inserted into Input. Items can only be extracted from Output. @@ -93,17 +94,17 @@ public void setStackInSlot(int slot, ItemStack stack) { } @Override - public CompoundTag serializeNBT() { + public CompoundTag serializeNBT(HolderLookup.Provider provider) { CompoundTag cmp = new CompoundTag(); - cmp.put(NBT_INPUT, input.serializeNBT()); - cmp.put(NBT_OUTPUT, output.serializeNBT()); + cmp.put(NBT_INPUT, input.serializeNBT(provider)); + cmp.put(NBT_OUTPUT, output.serializeNBT(provider)); return cmp; } @Override - public void deserializeNBT(CompoundTag nbt) { - input.deserializeNBT(nbt.getCompound(NBT_INPUT)); - output.deserializeNBT(nbt.getCompound(NBT_OUTPUT)); + public void deserializeNBT(HolderLookup.Provider provider, CompoundTag nbt) { + input.deserializeNBT(provider, nbt.getCompound(NBT_INPUT)); + output.deserializeNBT(provider, nbt.getCompound(NBT_OUTPUT)); } @FunctionalInterface @@ -130,7 +131,7 @@ public int[] getSlotsForFace(Direction direction) { /** * Support for non-capability interfaces like hoppers to support in-only and out-only. For use with WorldlyContainer.java */ - public boolean canPlaceItemThroughFace(int i, ItemStack itemStack, @Nullable Direction direction) { + public boolean canPlaceItemThroughFace(int i, ItemStack itemStack, Direction direction) { return i < this.input.getSlots(); } diff --git a/src/main/java/com/lothrazar/library/cap/item/CapabilityProviderEnergyStack.java b/src/main/java/com/lothrazar/library/cap/item/CapabilityProviderEnergyStack.java index e3dfc65..fad2e6b 100644 --- a/src/main/java/com/lothrazar/library/cap/item/CapabilityProviderEnergyStack.java +++ b/src/main/java/com/lothrazar/library/cap/item/CapabilityProviderEnergyStack.java @@ -1,43 +1,33 @@ package com.lothrazar.library.cap.item; import com.lothrazar.library.cap.CustomEnergyStorage; -import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.capabilities.ICapabilitySerializable; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.IEnergyStorage; -public class CapabilityProviderEnergyStack implements ICapabilitySerializable { +/** + * Simple energy storage wrapper for items. + * In NeoForge 1.21+, attach this to an item via RegisterCapabilitiesEvent: + * event.registerItem(Capabilities.EnergyStorage.ITEM, + * (stack, ctx) -> new CapabilityProviderEnergyStack(maxEnergy).getEnergyStorage(), myItem); + */ +public class CapabilityProviderEnergyStack { private static final String NBTENERGY = "energy"; - CustomEnergyStorage energy; - private LazyOptional energyCap = LazyOptional.of(() -> energy); + private final CustomEnergyStorage energy; public CapabilityProviderEnergyStack(int max) { energy = new CustomEnergyStorage(max, max); - energyCap = LazyOptional.of(() -> energy); } - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - if (cap == ForgeCapabilities.ENERGY) { - return energyCap.cast(); - } - return LazyOptional.empty(); + public CustomEnergyStorage getEnergyStorage() { + return energy; } - @Override public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - tag.put(NBTENERGY, energy.serializeNBT()); - return tag; + return energy.saveToTag(); } - @Override public void deserializeNBT(CompoundTag nbt) { - energy.deserializeNBT(nbt.getCompound(NBTENERGY)); + energy.loadFromTag(nbt); } @Override diff --git a/src/main/java/com/lothrazar/library/cap/item/EnergyCapabilityItemStack.java b/src/main/java/com/lothrazar/library/cap/item/EnergyCapabilityItemStack.java index 2392eb4..8be8fcd 100644 --- a/src/main/java/com/lothrazar/library/cap/item/EnergyCapabilityItemStack.java +++ b/src/main/java/com/lothrazar/library/cap/item/EnergyCapabilityItemStack.java @@ -1,63 +1,75 @@ package com.lothrazar.library.cap.item; -import com.lothrazar.library.cap.CustomEnergyStorage; -import net.minecraft.core.Direction; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.energy.IEnergyStorage; +import net.minecraft.world.item.component.CustomData; +import net.neoforged.neoforge.energy.IEnergyStorage; -public class EnergyCapabilityItemStack implements ICapabilityProvider { +/** + * IEnergyStorage that reads/writes energy to an ItemStack's CustomData component. + * In NeoForge 1.21+, register this via RegisterCapabilitiesEvent: + * event.registerItem(Capabilities.EnergyStorage.ITEM, + * (stack, ctx) -> new EnergyCapabilityItemStack(stack, maxEnergy), myItem); + */ +public class EnergyCapabilityItemStack implements IEnergyStorage { public static final String NBTENERGY = "energy"; - private LazyOptional energy = LazyOptional.of(this::createEnergy); - // private ItemStack stack; - private int max; - private ItemStack stack; - - private IEnergyStorage createEnergy() { - return new CustomEnergyStorage(max, max / 4) { - - @Override - public int getEnergyStored() { - if (stack.hasTag()) { - return stack.getTag().getInt(NBTENERGY); - } - else { - return super.getEnergyStored(); - } - } - - @Override - public void setEnergy(int energy) { - if (!stack.hasTag()) { - stack.setTag(new CompoundTag()); - } - stack.getTag().putInt(NBTENERGY, energy); - super.setEnergy(energy); - } - }; - } + private final ItemStack stack; + private final int max; public EnergyCapabilityItemStack(final ItemStack stack, int capacity) { - this.max = capacity; this.stack = stack; - energy = LazyOptional.of(this::createEnergy); + this.max = capacity; } @Override - public String toString() { - return "EnergyCapabilityItemStack [energy=" + energy + ", max=" + max + "]"; + public int receiveEnergy(int maxReceive, boolean simulate) { + if (!canReceive()) return 0; + int stored = getEnergyStored(); + int received = Math.min(max - stored, Math.min(max / 4, maxReceive)); + if (!simulate) setEnergyStored(stored + received); + return received; + } + + @Override + public int extractEnergy(int maxExtract, boolean simulate) { + if (!canExtract()) return 0; + int stored = getEnergyStored(); + int extracted = Math.min(stored, maxExtract); + if (!simulate) setEnergyStored(stored - extracted); + return extracted; + } + + @Override + public int getEnergyStored() { + CustomData data = stack.get(DataComponents.CUSTOM_DATA); + return data != null ? data.copyTag().getInt(NBTENERGY) : 0; + } + + @Override + public int getMaxEnergyStored() { + return max; + } + + @Override + public boolean canExtract() { + return true; } @Override - public LazyOptional getCapability(Capability capability, Direction facing) { - if (ForgeCapabilities.ENERGY == capability) { - return energy.cast(); - } - return LazyOptional.empty(); + public boolean canReceive() { + return true; + } + + private void setEnergyStored(int value) { + CompoundTag tag = stack.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + tag.putInt(NBTENERGY, Math.max(0, Math.min(value, max))); + stack.set(DataComponents.CUSTOM_DATA, CustomData.of(tag)); + } + + @Override + public String toString() { + return "EnergyCapabilityItemStack [energy=" + getEnergyStored() + ", max=" + max + "]"; } } diff --git a/src/main/java/com/lothrazar/library/cap/item/FluidHandlerCapabilityStack.java b/src/main/java/com/lothrazar/library/cap/item/FluidHandlerCapabilityStack.java index de46697..604aeb5 100644 --- a/src/main/java/com/lothrazar/library/cap/item/FluidHandlerCapabilityStack.java +++ b/src/main/java/com/lothrazar/library/cap/item/FluidHandlerCapabilityStack.java @@ -1,29 +1,28 @@ package com.lothrazar.library.cap.item; -import net.minecraft.core.Direction; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.fluids.capability.IFluidHandlerItem; -import net.minecraftforge.fluids.capability.templates.FluidHandlerItemStack; - -public class FluidHandlerCapabilityStack implements IFluidHandlerItem, ICapabilityProvider { - - public static final String FLUID_NBT_KEY = FluidHandlerItemStack.FLUID_NBT_KEY; - private final LazyOptional holder = LazyOptional.of(() -> this); +import net.minecraft.world.item.component.CustomData; +import net.minecraft.world.level.material.Fluid; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.capability.IFluidHandlerItem; + +/** + * IFluidHandlerItem that reads/writes a single fluid to an ItemStack's CustomData component. + * In NeoForge 1.21+, register this via RegisterCapabilitiesEvent: + * event.registerItem(Capabilities.FluidHandler.ITEM, + * (stack, ctx) -> new FluidHandlerCapabilityStack(stack, capacity), myItem); + */ +public class FluidHandlerCapabilityStack implements IFluidHandlerItem { + + public static final String FLUID_NBT_KEY = "Fluid"; protected ItemStack container; protected int capacity; - /** - * @param container - * The container itemStack, data is stored on it directly as NBT. - * @param capacity - * The maximum capacity of this fluid tank. - */ public FluidHandlerCapabilityStack(ItemStack container, int capacity) { this.container = container; this.capacity = capacity; @@ -34,21 +33,39 @@ public ItemStack getContainer() { return container; } + private CompoundTag getContainerTag() { + return container.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + } + + private void setContainerTag(CompoundTag tag) { + container.set(DataComponents.CUSTOM_DATA, CustomData.of(tag)); + } + public FluidStack getFluid() { - CompoundTag tagCompound = container.getTag(); - if (tagCompound == null || !tagCompound.contains(FLUID_NBT_KEY)) { + CompoundTag tag = getContainerTag(); + if (!tag.contains(FLUID_NBT_KEY)) { return FluidStack.EMPTY; } - return FluidStack.loadFluidStackFromNBT(tagCompound.getCompound(FLUID_NBT_KEY)); + CompoundTag fluidTag = tag.getCompound(FLUID_NBT_KEY); + ResourceLocation fluidId = ResourceLocation.tryParse(fluidTag.getString("id")); + int amount = fluidTag.getInt("amount"); + if (fluidId == null) return FluidStack.EMPTY; + Fluid fluid = BuiltInRegistries.FLUID.getOptional(fluidId).orElse(null); + if (fluid == null || fluid == Fluids.EMPTY) return FluidStack.EMPTY; + return new FluidStack(fluid, amount); } public void setFluid(FluidStack fluid) { - if (!container.hasTag()) { - container.setTag(new CompoundTag()); + CompoundTag tag = getContainerTag(); + if (fluid.isEmpty()) { + tag.remove(FLUID_NBT_KEY); + } else { + CompoundTag fluidTag = new CompoundTag(); + fluidTag.putString("id", BuiltInRegistries.FLUID.getKey(fluid.getFluid()).toString()); + fluidTag.putInt("amount", fluid.getAmount()); + tag.put(FLUID_NBT_KEY, fluidTag); } - CompoundTag fluidTag = new CompoundTag(); - fluid.writeToNBT(fluidTag); - container.getTag().put(FLUID_NBT_KEY, fluidTag); + setContainerTag(tag); } @Override @@ -85,9 +102,8 @@ public int fill(FluidStack resource, FluidAction doFill) { setFluid(filled); } return fillAmount; - } - else { - if (contained.isFluidEqual(resource)) { + } else { + if (FluidStack.isSameFluidSameComponents(contained, resource)) { int fillAmount = Math.min(capacity - contained.getAmount(), resource.getAmount()); if (doFill.execute() && fillAmount > 0) { contained.grow(fillAmount); @@ -101,7 +117,7 @@ public int fill(FluidStack resource, FluidAction doFill) { @Override public FluidStack drain(FluidStack resource, FluidAction action) { - if (container.getCount() != 1 || resource.isEmpty() || !resource.isFluidEqual(getFluid())) { + if (container.getCount() != 1 || resource.isEmpty() || !FluidStack.isSameFluidSameComponents(resource, getFluid())) { return FluidStack.EMPTY; } return drain(resource.getAmount(), action); @@ -123,8 +139,7 @@ public FluidStack drain(int maxDrain, FluidAction action) { contained.shrink(drainAmount); if (contained.isEmpty()) { setContainerToEmpty(); - } - else { + } else { setFluid(contained); } } @@ -139,19 +154,10 @@ public boolean canDrainFluidType(FluidStack fluid) { return true; } - /** - * Override this method for special handling. Can be used to swap out or destroy the container. - */ protected void setContainerToEmpty() { - container.removeTagKey(FLUID_NBT_KEY); - } - - @Override - public LazyOptional getCapability(Capability capability, Direction facing) { - if (ForgeCapabilities.FLUID_HANDLER_ITEM == capability) { - return holder.cast(); - } - return LazyOptional.empty(); + CompoundTag tag = getContainerTag(); + tag.remove(FLUID_NBT_KEY); + setContainerTag(tag); } @Override diff --git a/src/main/java/com/lothrazar/library/cap/player/PlayerCapProvider.java b/src/main/java/com/lothrazar/library/cap/player/PlayerCapProvider.java index 03e2e5c..a5118e7 100644 --- a/src/main/java/com/lothrazar/library/cap/player/PlayerCapProvider.java +++ b/src/main/java/com/lothrazar/library/cap/player/PlayerCapProvider.java @@ -1,49 +1,34 @@ package com.lothrazar.library.cap.player; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.common.capabilities.CapabilityToken; -import net.minecraftforge.common.capabilities.ICapabilityProvider; -import net.minecraftforge.common.util.INBTSerializable; -import net.minecraftforge.common.util.LazyOptional; - -public class PlayerCapProvider implements ICapabilityProvider, INBTSerializable { - - public static Capability PLAYERCAP = CapabilityManager.get(new CapabilityToken<>() { - //empty by design - }); - private PlayerCapabilityStorage playerMana = null; - private final LazyOptional opt = LazyOptional.of(this::createMe); - - private PlayerCapabilityStorage createMe() { - if (playerMana == null) { - playerMana = new PlayerCapabilityStorage(); - } - return playerMana; - } - - @Override - public LazyOptional getCapability(Capability cap) { - if (cap == PLAYERCAP) { - return opt.cast(); - } - return LazyOptional.empty(); - } - - @Override - public LazyOptional getCapability(Capability cap, Direction side) { - return getCapability(cap); - } - - @Override - public CompoundTag serializeNBT() { - return createMe().write(); - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - createMe().read(nbt); - } +import com.lothrazar.library.FutureLibMod; +import java.util.function.Supplier; +import net.minecraft.resources.ResourceLocation; +import net.neoforged.neoforge.attachment.AttachmentType; +import net.neoforged.neoforge.capabilities.EntityCapability; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; + +public class PlayerCapProvider { + + public static final DeferredRegister> ATTACHMENT_TYPES = + DeferredRegister.create(NeoForgeRegistries.Keys.ATTACHMENT_TYPES, FutureLibMod.MODID); + + /** + * Per-player mana storage, persists across death and dimension changes via AttachmentType serialization. + */ + public static final Supplier> PLAYER_MANA = + ATTACHMENT_TYPES.register("player_mana", () -> + AttachmentType.builder(() -> new PlayerCapabilityStorage()) + .serialize(PlayerCapabilityStorage.CODEC) + .build()); + + /** + * EntityCapability key for accessing player mana. + * Usage: player.getCapability(PlayerCapProvider.PLAYER_MANA_CAP) + * Returns null for non-player entities. + */ + public static final EntityCapability PLAYER_MANA_CAP = + EntityCapability.createVoid( + ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "player_mana"), + PlayerCapabilityStorage.class); } diff --git a/src/main/java/com/lothrazar/library/cap/player/PlayerCapabilityStorage.java b/src/main/java/com/lothrazar/library/cap/player/PlayerCapabilityStorage.java index 9b03adf..af55d48 100644 --- a/src/main/java/com/lothrazar/library/cap/player/PlayerCapabilityStorage.java +++ b/src/main/java/com/lothrazar/library/cap/player/PlayerCapabilityStorage.java @@ -1,17 +1,25 @@ package com.lothrazar.library.cap.player; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.nbt.CompoundTag; +import net.neoforged.neoforge.attachment.IAttachmentHolder; public class PlayerCapabilityStorage { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> + instance.group(Codec.INT.fieldOf("mana").forGetter(PlayerCapabilityStorage::getMana)) + .apply(instance, mana -> new PlayerCapabilityStorage(mana))); + int mana; - public PlayerCapabilityStorage(int readInt) { - mana = readInt; + public PlayerCapabilityStorage(int mana) { + this.mana = mana; } public PlayerCapabilityStorage() {} + @Deprecated // i think public PlayerCapabilityStorage(CompoundTag tag) { this.read(tag); } @@ -46,4 +54,4 @@ public void read(CompoundTag compound) { public String toString() { return "PlayerCapabilityStorage [mana=" + mana + "]"; } -} \ No newline at end of file +} diff --git a/src/main/java/com/lothrazar/library/config/ConfigTemplate.java b/src/main/java/com/lothrazar/library/config/ConfigTemplate.java deleted file mode 100644 index 92dad8f..0000000 --- a/src/main/java/com/lothrazar/library/config/ConfigTemplate.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.lothrazar.library.config; - -import com.electronwill.nightconfig.core.file.CommentedFileConfig; -import com.electronwill.nightconfig.core.io.WritingMode; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.common.ForgeConfigSpec.Builder; -import net.minecraftforge.fml.loading.FMLPaths; - -public abstract class ConfigTemplate { - - public CommentedFileConfig setup(final String modid) { - final CommentedFileConfig configData = CommentedFileConfig.builder(FMLPaths.CONFIGDIR.get().resolve(modid + ".toml")) - .sync() - .autosave() - .writingMode(WritingMode.REPLACE) - .build(); - configData.load(); - return configData; - } - - public static Builder builder() { - return new ForgeConfigSpec.Builder(); - } -} diff --git a/src/main/java/com/lothrazar/library/core/BlockPosDim.java b/src/main/java/com/lothrazar/library/core/BlockPosDim.java index 8f844c6..4d693db 100644 --- a/src/main/java/com/lothrazar/library/core/BlockPosDim.java +++ b/src/main/java/com/lothrazar/library/core/BlockPosDim.java @@ -5,7 +5,10 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.nbt.CompoundTag; +import com.google.gson.JsonParser; +import com.mojang.serialization.JsonOps; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.ComponentSerialization; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; @@ -46,8 +49,13 @@ public BlockPosDim(BlockPos pos, String dimension, CompoundTag stackTag) { // CompoundTag displayTag = stackTag.getCompound("display"); if (displayTag != null && displayTag.contains("Name", 8)) { - // - Component namec = Component.Serializer.fromJson(displayTag.getString("Name")); + String nameJson = displayTag.getString("Name"); + Component namec = ComponentSerialization.CODEC + .parse(JsonOps.INSTANCE, JsonParser.parseString(nameJson)) + .result() + .orElseGet(() -> Component.literal(nameJson)); + // TODO: is this a waste of overcomplication? should it just be name string? +// this.name = displayTag.getString("Name"); this.name = namec.getString(); } } diff --git a/src/main/java/com/lothrazar/library/core/IHasFluid.java b/src/main/java/com/lothrazar/library/core/IHasFluid.java index 4521acc..e2ddc05 100644 --- a/src/main/java/com/lothrazar/library/core/IHasFluid.java +++ b/src/main/java/com/lothrazar/library/core/IHasFluid.java @@ -1,6 +1,6 @@ package com.lothrazar.library.core; -import net.minecraftforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidStack; public interface IHasFluid { diff --git a/src/main/java/com/lothrazar/library/data/BlockStatePosWrapper.java b/src/main/java/com/lothrazar/library/data/BlockStatePosWrapper.java index 22262a8..8df2d95 100644 --- a/src/main/java/com/lothrazar/library/data/BlockStatePosWrapper.java +++ b/src/main/java/com/lothrazar/library/data/BlockStatePosWrapper.java @@ -24,7 +24,7 @@ public BlockStatePosWrapper(Level world, BlockPos chunkPosition, BlockState bloc this.blockPos = chunkPosition; BlockEntity te = world.getBlockEntity(chunkPosition); if (te != null) { - this.tileEntityTag = te.saveWithoutMetadata(); + this.tileEntityTag = te.saveWithoutMetadata(world.registryAccess()); } } @@ -44,7 +44,7 @@ public CompoundTag getTileEntityTag() { public void readFromNBT(CompoundTag tag, Level level) { this.blockState = NbtUtils.readBlockState(level.holderLookup(Registries.BLOCK), tag.getCompound("block")); - this.blockPos = NbtUtils.readBlockPos(tag.getCompound("pos")); + this.blockPos = NbtUtils.readBlockPos(tag,"pos").orElse(null); if (tag.contains("tileentity")) { this.tileEntityTag = tag.getCompound("tileentity"); } @@ -53,8 +53,7 @@ public void readFromNBT(CompoundTag tag, Level level) { public void writeToNBT(CompoundTag tag) { CompoundTag encoded = NbtUtils.writeBlockState(this.blockState); tag.put("block", encoded); - CompoundTag epos = NbtUtils.writeBlockPos(this.blockPos); - tag.put("pos", epos); + tag.put("pos", NbtUtils.writeBlockPos(this.blockPos)); if (this.tileEntityTag != null) { tag.put("tileentity", this.tileEntityTag); } diff --git a/src/main/java/com/lothrazar/library/data/RelativeShape.java b/src/main/java/com/lothrazar/library/data/RelativeShape.java index 078f1d3..202af1b 100644 --- a/src/main/java/com/lothrazar/library/data/RelativeShape.java +++ b/src/main/java/com/lothrazar/library/data/RelativeShape.java @@ -3,8 +3,10 @@ import java.util.ArrayList; import java.util.List; import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.component.CustomData; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; @@ -93,7 +95,8 @@ public static RelativeShape read(CompoundTag tag) { } public static RelativeShape read(ItemStack item) { - CompoundTag tag = item.getTag(); + CustomData data = item.get(DataComponents.CUSTOM_DATA); + CompoundTag tag = data != null ? data.copyTag() : null; return read(tag); } @@ -113,8 +116,9 @@ public CompoundTag write(CompoundTag tag) { } public void write(ItemStack shapeCard) { - CompoundTag tag = shapeCard.getOrCreateTag(); + CompoundTag tag = shapeCard.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); write(tag); + shapeCard.set(DataComponents.CUSTOM_DATA, CustomData.of(tag)); } public void setShape(List list) { diff --git a/src/main/java/com/lothrazar/library/dim/DimensionTransit.java b/src/main/java/com/lothrazar/library/dim/DimensionTransit.java deleted file mode 100644 index 7eaf0b2..0000000 --- a/src/main/java/com/lothrazar/library/dim/DimensionTransit.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.lothrazar.library.dim; - -import java.util.function.Function; -import com.lothrazar.library.core.BlockPosDim; -import com.lothrazar.library.util.LevelWorldUtil; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -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.level.portal.PortalInfo; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.util.ITeleporter; - -/** - * - * @see com/lothrazar/cyclic/world/ - */ -public class DimensionTransit implements ITeleporter { - - protected ServerLevel world; - private BlockPosDim target; - - public DimensionTransit(ServerLevel world, BlockPosDim target) { - this.world = world; - this.target = target; - } - - @Override - public PortalInfo getPortalInfo(Entity entity, ServerLevel destWorld, Function defaultPortalInfo) { - BlockPos myPos = moveToSafeCoords(destWorld, target.getPos()); - return new PortalInfo(new Vec3(myPos.getX() + 0.5F, myPos.getY() + 0.5F, myPos.getZ() + 0.5F), Vec3.ZERO, entity.getYRot(), entity.getXRot()); - } - - @SuppressWarnings("deprecation") - private BlockPos moveToSafeCoords(ServerLevel world, BlockPos pos) { - int tries = 10; - while (tries > 0) { - tries--; - if (world.getBlockState(pos).isSolid()) { - pos = pos.above(); - } - } - return pos; - } - - @Override - public Entity placeEntity(Entity newEntity, ServerLevel currentWorld, ServerLevel destWorld, float yaw, Function repositionEntity) { - if (newEntity instanceof LivingEntity) { - ((LivingEntity) newEntity).addEffect(new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 200, 200, false, false)); - ((LivingEntity) newEntity).addEffect(new MobEffectInstance(MobEffects.SLOW_FALLING, 20, 20, false, false)); - } - newEntity.fallDistance = 0; - return repositionEntity.apply(false); //Must be false or we fall on vanilla. thanks /Mrbysco/TelePastries/ - } - - public void teleport(Player player) { - if (!player.isCreative() && !player.level().isClientSide) { - player.addEffect(new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 200, 200, false, false)); - } - if (this.world != null) { - // ServerLevel dim = getTargetLevel(); - this.world.playSound(player, target.getX() + 0.5D, target.getY() + 0.5D, target.getZ() + 0.5D, SoundEvents.PORTAL_TRAVEL, SoundSource.MASTER, 0.25F, this.world.random.nextFloat() * 0.4F + 0.8F); - // player.changeDimension(dim, this); - } - } - - public ServerLevel getTargetLevel() { - return world == null ? null : world.getServer().getLevel(LevelWorldUtil.stringToDimension(target.getDimension())); - } -} diff --git a/src/main/java/com/lothrazar/library/enchant/EnchantmentFlib.java b/src/main/java/com/lothrazar/library/enchant/EnchantmentFlib.java index cadd86b..a72d649 100644 --- a/src/main/java/com/lothrazar/library/enchant/EnchantmentFlib.java +++ b/src/main/java/com/lothrazar/library/enchant/EnchantmentFlib.java @@ -1,80 +1,61 @@ package com.lothrazar.library.enchant; +import net.minecraft.core.Holder; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.item.enchantment.EnchantmentCategory; import net.minecraft.world.item.enchantment.EnchantmentHelper; -public abstract class EnchantmentFlib extends Enchantment { - - protected EnchantmentFlib(Rarity rarityIn, EnchantmentCategory typeIn, EquipmentSlot[] slots) { - super(rarityIn, typeIn, slots); +/** + * Utility helpers for working with enchantments. + * + * In Minecraft 1.21+, enchantments are data-driven and cannot be subclassed directly. + * Define enchantments as JSON data files and obtain their Holder via + * level.registryAccess().lookupOrThrow(Registries.ENCHANTMENT).getOrThrow(myKey) + */ +public class EnchantmentFlib { + + public static int getCurrentLevelTool(Holder enchantment, ItemStack stack) { + if (stack.isEmpty() || stack.getItem() == Items.ENCHANTED_BOOK) return -1; + return EnchantmentHelper.getTagEnchantmentLevel(enchantment, stack); } - public abstract boolean isEnabled(); - - public int getCurrentLevelTool(ItemStack stack) { - if (stack.isEmpty() == false && EnchantmentHelper.getEnchantments(stack).containsKey(this) - && stack.getItem() != Items.ENCHANTED_BOOK) { - return EnchantmentHelper.getEnchantments(stack).get(this); - } - return -1; + public static int getCurrentArmorLevelSlot(Holder enchantment, LivingEntity entity, EquipmentSlot type) { + ItemStack armor = entity.getItemBySlot(type); + if (armor.isEmpty()) return 0; + return EnchantmentHelper.getTagEnchantmentLevel(enchantment, armor); } - protected int getCurrentArmorLevelSlot(LivingEntity player, EquipmentSlot type) { - ItemStack armor = player.getItemBySlot(type); - int level = 0; - if (armor.isEmpty() == false && EnchantmentHelper.getEnchantments(armor) != null - && EnchantmentHelper.getEnchantments(armor).containsKey(this)) { - level = EnchantmentHelper.getEnchantments(armor).get(this); - } - return level; - } - - protected int getCurrentArmorLevel(LivingEntity player) { - EquipmentSlot[] armors = new EquipmentSlot[] { - EquipmentSlot.CHEST, EquipmentSlot.FEET, EquipmentSlot.HEAD, EquipmentSlot.LEGS - }; + public static int getCurrentArmorLevel(Holder enchantment, LivingEntity entity) { + EquipmentSlot[] armors = { EquipmentSlot.CHEST, EquipmentSlot.FEET, EquipmentSlot.HEAD, EquipmentSlot.LEGS }; int level = 0; for (EquipmentSlot slot : armors) { - ItemStack armor = player.getItemBySlot(slot); - if (armor.isEmpty() == false - && EnchantmentHelper.getEnchantments(armor) != null - && EnchantmentHelper.getEnchantments(armor).containsKey(this)) { - int newlevel = EnchantmentHelper.getEnchantments(armor).get(this); - if (newlevel > level) { - level = newlevel; - } - } + int slotLevel = getCurrentArmorLevelSlot(enchantment, entity, slot); + if (slotLevel > level) level = slotLevel; } return level; } - protected int getLevelAll(LivingEntity p) { - return Math.max(getCurrentArmorLevel(p), getCurrentLevelTool(p)); + public static int getLevelAll(Holder enchantment, LivingEntity entity) { + return Math.max(getCurrentArmorLevel(enchantment, entity), getCurrentLevelTool(enchantment, entity)); } - protected ItemStack getFirstArmorStackWithEnchant(LivingEntity player) { - if (player == null) { - return ItemStack.EMPTY; - } - for (ItemStack main : player.getArmorSlots()) { - if ((main.isEmpty() == false) && EnchantmentHelper.getEnchantments(main).containsKey(this)) { - return main; + public static ItemStack getFirstArmorStackWithEnchant(Holder enchantment, LivingEntity entity) { + if (entity == null) return ItemStack.EMPTY; + for (ItemStack armor : entity.getArmorSlots()) { + if (!armor.isEmpty() && EnchantmentHelper.getTagEnchantmentLevel(enchantment, armor) > 0) { + return armor; } } return ItemStack.EMPTY; } - protected int getCurrentLevelTool(LivingEntity player) { - if (player == null) { - return -1; - } - ItemStack main = player.getMainHandItem(); - ItemStack off = player.getOffhandItem(); - return Math.max(getCurrentLevelTool(main), getCurrentLevelTool(off)); + public static int getCurrentLevelTool(Holder enchantment, LivingEntity entity) { + if (entity == null) return -1; + ItemStack main = entity.getMainHandItem(); + ItemStack off = entity.getOffhandItem(); + return Math.max(getCurrentLevelTool(enchantment, main), getCurrentLevelTool(enchantment, off)); } } diff --git a/src/main/java/com/lothrazar/library/entity/BlockEntityFlib.java b/src/main/java/com/lothrazar/library/entity/BlockEntityFlib.java index f935ccf..5115839 100644 --- a/src/main/java/com/lothrazar/library/entity/BlockEntityFlib.java +++ b/src/main/java/com/lothrazar/library/entity/BlockEntityFlib.java @@ -6,8 +6,8 @@ import com.lothrazar.library.util.FakePlayerUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; +import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.Connection; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; import net.minecraft.network.protocol.game.ServerboundPlayerActionPacket; import net.minecraft.server.level.ServerLevel; @@ -17,7 +17,7 @@ import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.util.FakePlayer; +import net.neoforged.neoforge.common.util.FakePlayer; public abstract class BlockEntityFlib extends BlockEntity { @@ -26,15 +26,15 @@ public BlockEntityFlib(BlockEntityType type, BlockPos pos, BlockState state) } @Override - public void load(CompoundTag tag) { + public void loadAdditional(CompoundTag tag, HolderLookup.Provider registries) { // timer = tag.getInt("timer"); - super.load(tag); + super.loadAdditional(tag, registries); } @Override - public void saveAdditional(CompoundTag tag) { + public void saveAdditional(CompoundTag tag, HolderLookup.Provider registries) { // tag.putInt("timer", timer); - super.saveAdditional(tag); + super.saveAdditional(tag, registries); } public abstract void setField(int field, int value); @@ -52,16 +52,15 @@ public void setLitProperty(boolean lit) { } @Override - public CompoundTag getUpdateTag() { - CompoundTag syncData = super.getUpdateTag(); - this.saveAdditional(syncData); + public CompoundTag getUpdateTag(HolderLookup.Provider registries) { + CompoundTag syncData = super.getUpdateTag(registries); + this.saveAdditional(syncData, registries); return syncData; } @Override - public void onDataPacket(Connection net, ClientboundBlockEntityDataPacket pkt) { - this.load(pkt.getTag()); - super.onDataPacket(net, pkt); + public void handleUpdateTag(CompoundTag tag, HolderLookup.Provider registries) { + this.loadAdditional(tag, registries); } @Override diff --git a/src/main/java/com/lothrazar/library/events/CapabilityEvents.java b/src/main/java/com/lothrazar/library/events/CapabilityEvents.java index bce9744..b7968bd 100644 --- a/src/main/java/com/lothrazar/library/events/CapabilityEvents.java +++ b/src/main/java/com/lothrazar/library/events/CapabilityEvents.java @@ -3,62 +3,41 @@ import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.cap.player.PlayerCapProvider; import com.lothrazar.library.cap.player.PlayerCapabilityStorage; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; -import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; +import net.neoforged.neoforge.common.NeoForge; +import net.neoforged.neoforge.event.entity.player.PlayerEvent; /** - * NOT loaded by default load this into your event bus to pull in + * NOT loaded by default. Call {@link #register(IEventBus)} from inside your @Mod constructor to enable + * the FLib player mana capability. * - * - * Import @MinecraftForge and run - * - * MinecraftForge.EVENT_BUS.register(new CapabilityEvents()); - * - * inside of the event @FMLCommonSetupEvent + * Example: + * CapabilityEvents.register(modEventBus); */ public class CapabilityEvents { - public CapabilityEvents() { - MinecraftForge.EVENT_BUS.addGenericListener(Entity.class, CapabilityEvents::onAttachCapabilitiesPlayer); + public static void register(IEventBus modBus) { + NeoForge.EVENT_BUS.addListener(CapabilityEvents::onPlayerCloned); + modBus.addListener(CapabilityEvents::onRegisterCapabilities); + FutureLibMod.LOGGER.info("CapabilityEvents registered"); } - // When a player dies or teleports from the end capabilities are cleared. Using the PlayerEvent.Clone event - // we can detect this and copy our capability from the old player to the new one - @SubscribeEvent - public void onPlayerCloned(PlayerEvent.Clone event) { + public static void onPlayerCloned(PlayerEvent.Clone event) { if (event.isWasDeath()) { - // We need to copyFrom the capabilities - event.getOriginal().getCapability(PlayerCapProvider.PLAYERCAP).ifPresent(oldStore -> { - event.getEntity().getCapability(PlayerCapProvider.PLAYERCAP).ifPresent(newStore -> { - newStore.copyFrom(oldStore); - }); - }); + PlayerCapabilityStorage oldData = event.getOriginal().getData(PlayerCapProvider.PLAYER_MANA.get()); + event.getEntity().getData(PlayerCapProvider.PLAYER_MANA.get()).copyFrom(oldData); } } - @SubscribeEvent - public void onRegisterCapabilities(RegisterCapabilitiesEvent event) { - event.register(PlayerCapabilityStorage.class); - FutureLibMod.LOGGER.info("RegisterCapabilitiesEvent success for ManaManager"); - } - // Whenever a new object of some type is created the AttachCapabilitiesEvent will fire. In our case we want to know - // when a new player arrives so that we can attach our capability here + public static void onRegisterCapabilities(RegisterCapabilitiesEvent event) { + event.registerEntity( + PlayerCapProvider.PLAYER_MANA_CAP, + EntityType.PLAYER, + (entity, ctx) -> entity.getData(PlayerCapProvider.PLAYER_MANA.get())); - // @SubscribeEvent not sub, uses MinecraftForge.EVENT_BUS.addGenericListener instead - public static void onAttachCapabilitiesPlayer(AttachCapabilitiesEvent event) { - if (event.getObject() instanceof Player) { - if (!event.getObject().getCapability(PlayerCapProvider.PLAYERCAP).isPresent()) { - // The player does not already have this capability so we need to add the capability provider here - //TODO: Data keyword string from IMC? - event.addCapability(new ResourceLocation(FutureLibMod.MODID, "data"), new PlayerCapProvider()); - FutureLibMod.LOGGER.info("CapabilityRegistry success for data"); - } - } + FutureLibMod.LOGGER.info("RegisterCapabilitiesEvent success"); } } diff --git a/src/main/java/com/lothrazar/library/events/EventFlib.java b/src/main/java/com/lothrazar/library/events/EventFlib.java index 99b0ccb..2057f1a 100644 --- a/src/main/java/com/lothrazar/library/events/EventFlib.java +++ b/src/main/java/com/lothrazar/library/events/EventFlib.java @@ -1,6 +1,6 @@ package com.lothrazar.library.events; -import net.minecraftforge.common.MinecraftForge; +import net.neoforged.neoforge.common.NeoForge; public abstract class EventFlib { @@ -18,6 +18,6 @@ public EventFlib() { * * inside of the event @FMLCommonSetupEvent */ - MinecraftForge.EVENT_BUS.register(this); + NeoForge.EVENT_BUS.register(this); } } diff --git a/src/main/java/com/lothrazar/library/events/FlibBlockEvents.java b/src/main/java/com/lothrazar/library/events/FlibBlockEvents.java index 70ddf6c..c6249e0 100644 --- a/src/main/java/com/lothrazar/library/events/FlibBlockEvents.java +++ b/src/main/java/com/lothrazar/library/events/FlibBlockEvents.java @@ -2,8 +2,8 @@ import com.lothrazar.library.block.BlockFlib; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.event.entity.player.PlayerInteractEvent.RightClickBlock; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.neoforged.neoforge.event.entity.player.PlayerInteractEvent.RightClickBlock; +import net.neoforged.bus.api.SubscribeEvent; public class FlibBlockEvents extends EventFlib { diff --git a/src/main/java/com/lothrazar/library/fluid/FluidHolder.java b/src/main/java/com/lothrazar/library/fluid/FluidHolder.java index 1be713a..f2bc9f1 100644 --- a/src/main/java/com/lothrazar/library/fluid/FluidHolder.java +++ b/src/main/java/com/lothrazar/library/fluid/FluidHolder.java @@ -5,8 +5,8 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.material.PushReaction; -import net.minecraftforge.common.SoundActions; -import net.minecraftforge.fluids.FluidType; +import net.neoforged.neoforge.common.SoundActions; +import net.neoforged.neoforge.fluids.FluidType; public class FluidHolder { diff --git a/src/main/java/com/lothrazar/library/gui/ContainerFlib.java b/src/main/java/com/lothrazar/library/gui/ContainerFlib.java index 77ed96f..784d98a 100644 --- a/src/main/java/com/lothrazar/library/gui/ContainerFlib.java +++ b/src/main/java/com/lothrazar/library/gui/ContainerFlib.java @@ -10,8 +10,8 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.common.capabilities.ForgeCapabilities; -import net.minecraftforge.energy.IEnergyStorage; +import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.energy.IEnergyStorage; public abstract class ContainerFlib extends AbstractContainerMenu { @@ -30,7 +30,10 @@ protected void trackEnergy(BlockEntity tile) { @Override public int get() { - return tile.getCapability(ForgeCapabilities.ENERGY).map(IEnergyStorage::getEnergyStored).orElse(0); + IEnergyStorage storage = tile.getLevel() != null + ? tile.getLevel().getCapability(Capabilities.EnergyStorage.BLOCK, tile.getBlockPos(), tile.getBlockState(), tile, null) + : null; + return storage != null ? storage.getEnergyStored() : 0; } @Override diff --git a/src/main/java/com/lothrazar/library/gui/EnergyBar.java b/src/main/java/com/lothrazar/library/gui/EnergyBar.java index 779907b..75d4cc2 100644 --- a/src/main/java/com/lothrazar/library/gui/EnergyBar.java +++ b/src/main/java/com/lothrazar/library/gui/EnergyBar.java @@ -2,6 +2,8 @@ import java.util.ArrayList; import java.util.List; + +import com.lothrazar.library.FutureLibMod; import net.minecraft.client.gui.Font; import net.minecraft.client.gui.GuiGraphics; import net.minecraft.network.chat.Component; @@ -9,7 +11,7 @@ public class EnergyBar { - public static final ResourceLocation ENERGY_BAR = new ResourceLocation("flib", "textures/gui/energy_bar.png"); + public static final ResourceLocation ENERGY_BAR = ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "textures/gui/energy_bar.png"); private int x = 154; private int y = 8; public int capacity; diff --git a/src/main/java/com/lothrazar/library/gui/FluidBar.java b/src/main/java/com/lothrazar/library/gui/FluidBar.java index e121f82..98da02a 100644 --- a/src/main/java/com/lothrazar/library/gui/FluidBar.java +++ b/src/main/java/com/lothrazar/library/gui/FluidBar.java @@ -2,6 +2,8 @@ import java.util.ArrayList; import java.util.List; + +import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.render.FluidRenderMap; import com.lothrazar.library.render.FluidRenderMap.FluidFlow; import com.mojang.blaze3d.systems.RenderSystem; @@ -11,11 +13,11 @@ import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.material.Fluids; -import net.minecraftforge.fluids.FluidStack; +import net.neoforged.neoforge.fluids.FluidStack; public class FluidBar { - public static final ResourceLocation FLUID_WIDGET = new ResourceLocation("flib", "textures/gui/fluid.png"); + public static final ResourceLocation FLUID_WIDGET = ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "textures/gui/fluid.png"); public String emtpyTooltip = "0"; private Font font; private int x; @@ -112,7 +114,7 @@ public int getCapacity() { public void renderTooltip(GuiGraphics gg, int mouseX, int mouseY, FluidStack current) { String tt = emtpyTooltip; if (current != null && !current.isEmpty()) { - tt = current.getAmount() + "/" + getCapacity() + " " + current.getDisplayName().getString(); + tt = current.getAmount() + "/" + getCapacity() + " " + current.getHoverName().getString(); // getDisplayName() -> getHoverName() } List list = new ArrayList<>(); list.add(Component.translatable(tt)); diff --git a/src/main/java/com/lothrazar/library/item/BlockItemFlib.java b/src/main/java/com/lothrazar/library/item/BlockItemFlib.java index 77a8e72..bb06783 100644 --- a/src/main/java/com/lothrazar/library/item/BlockItemFlib.java +++ b/src/main/java/com/lothrazar/library/item/BlockItemFlib.java @@ -4,13 +4,14 @@ import com.lothrazar.library.item.ItemFlib.Settings; import net.minecraft.network.chat.Component; import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; public class BlockItemFlib extends BlockItem { @@ -27,7 +28,7 @@ public BlockItemFlib(Block b, Properties prop) { @Override @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Item.TooltipContext worldIn, List tooltip, TooltipFlag flagIn) { if (me.tooltip) { me.tooltipApply(this, tooltip); } diff --git a/src/main/java/com/lothrazar/library/item/ItemFlib.java b/src/main/java/com/lothrazar/library/item/ItemFlib.java index 3258cb2..d74109f 100644 --- a/src/main/java/com/lothrazar/library/item/ItemFlib.java +++ b/src/main/java/com/lothrazar/library/item/ItemFlib.java @@ -1,6 +1,8 @@ package com.lothrazar.library.item; import java.util.List; + +import net.minecraft.world.entity.LivingEntity; import org.joml.Quaternionf; import org.joml.Vector3f; import com.lothrazar.library.util.ChatUtil; @@ -16,8 +18,8 @@ import net.minecraft.world.item.crafting.RecipeType; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; public class ItemFlib extends Item { @@ -68,7 +70,7 @@ public int getBurnTime(ItemStack itemStack, RecipeType recipeType) { @Override @OnlyIn(Dist.CLIENT) - public void appendHoverText(ItemStack stack, Level worldIn, List tooltip, TooltipFlag flagIn) { + public void appendHoverText(ItemStack stack, Item.TooltipContext worldIn, List tooltip, TooltipFlag flagIn) { if (me.tooltip) { me.tooltipApply(this, tooltip); } @@ -112,7 +114,7 @@ protected ItemStack findAmmo(Player player, Item item) { return ItemStack.EMPTY; } - public float getChargedPercent(ItemStack stack, int chargeTimer) { - return BowItem.getPowerForTime(this.getUseDuration(stack) - chargeTimer); + public float getChargedPercent(ItemStack stack, int chargeTimer, LivingEntity entity) { + return BowItem.getPowerForTime(this.getUseDuration(stack, entity) - chargeTimer); } } diff --git a/src/main/java/com/lothrazar/library/mod/CommandModule.java b/src/main/java/com/lothrazar/library/mod/CommandModule.java index 1936981..ee1a07e 100644 --- a/src/main/java/com/lothrazar/library/mod/CommandModule.java +++ b/src/main/java/com/lothrazar/library/mod/CommandModule.java @@ -34,11 +34,9 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.GameType; -import net.minecraft.world.scores.Objective; -import net.minecraft.world.scores.Score; -import net.minecraft.world.scores.Scoreboard; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraft.world.scores.*; +import net.neoforged.neoforge.event.RegisterCommandsEvent; +import net.neoforged.bus.api.SubscribeEvent; public class CommandModule extends EventFlib { @@ -229,7 +227,7 @@ public void onRegisterCommandsEvent(RegisterCommandsEvent event) { .then(Commands.argument(ARG_MIN, IntegerArgumentType.integer()) .then(Commands.argument(ARG_MAX, IntegerArgumentType.integer()) .then(Commands.argument(ARG_OBJECTIVE, StringArgumentType.greedyString()) - .executes(x -> { + .executes(x -> { // TODO: fix ScoreHolder instead of x as string return CommandScoreboard.scoreboardRng(x, ScoreHolderArgument.getNamesWithDefaultWildcard(x, ARG_TARGETS), ObjectiveArgument.getObjective(x, ARG_OBJECTIVE), IntegerArgumentType.getInteger(x, ARG_MIN), @@ -272,25 +270,25 @@ public void onRegisterCommandsEvent(RegisterCommandsEvent event) { .then(Commands.argument(ARG_PLAYER, EntityArgument.players()) .then(Commands.argument(ARG_VALUE, IntegerArgumentType.integer(-10000, 10000)) .executes(x -> { - return AttributesUtil.add(ResourceArgument.getAttribute(x, ARG_ATTR).get(), EntityArgument.getPlayers(x, ARG_PLAYER), IntegerArgumentType.getInteger(x, ARG_VALUE)); + return AttributesUtil.add(ResourceArgument.getAttribute(x, ARG_ATTR), EntityArgument.getPlayers(x, ARG_PLAYER), IntegerArgumentType.getInteger(x, ARG_VALUE)); })))) .then(Commands.literal(FORK_RANDOM) .then(Commands.argument(ARG_PLAYER, EntityArgument.players()) .then(Commands.argument(ARG_MIN, IntegerArgumentType.integer(-10000, 10000)) .then(Commands.argument(ARG_MAX, IntegerArgumentType.integer(-10000, 10000)) .executes(x -> { - return AttributesUtil.addRandom(ResourceArgument.getAttribute(x, ARG_ATTR).get(), EntityArgument.getPlayers(x, ARG_PLAYER), IntegerArgumentType.getInteger(x, ARG_MIN), IntegerArgumentType.getInteger(x, ARG_MAX)); + return AttributesUtil.addRandom(ResourceArgument.getAttribute(x, ARG_ATTR), EntityArgument.getPlayers(x, ARG_PLAYER), IntegerArgumentType.getInteger(x, ARG_MIN), IntegerArgumentType.getInteger(x, ARG_MAX)); }))))) .then(Commands.literal(FORK_FACTOR) .then(Commands.argument(ARG_PLAYER, EntityArgument.players()) .then(Commands.argument(ARG_VALUE, DoubleArgumentType.doubleArg(0, 100)) .executes(x -> { - return AttributesUtil.multiply(ResourceArgument.getAttribute(x, ARG_ATTR).get(), EntityArgument.getPlayers(x, ARG_PLAYER), DoubleArgumentType.getDouble(x, ARG_VALUE)); + return AttributesUtil.multiply(ResourceArgument.getAttribute(x, ARG_ATTR), EntityArgument.getPlayers(x, ARG_PLAYER), DoubleArgumentType.getDouble(x, ARG_VALUE)); })))) .then(Commands.literal(FORK_RESET) .then(Commands.argument(ARG_PLAYER, EntityArgument.players()) .executes(x -> { - return AttributesUtil.reset(ResourceArgument.getAttribute(x, ARG_ATTR).get(), EntityArgument.getPlayers(x, ARG_PLAYER)); + return AttributesUtil.reset(ResourceArgument.getAttribute(x, ARG_ATTR), EntityArgument.getPlayers(x, ARG_PLAYER)); }))))) //new commands here ); @@ -369,43 +367,41 @@ public static int addRandom(CommandContext x, Collection x, Collection scoreHolderTargets, Objective objective) { + public static int scoreboardRngTest(CommandContext x, Collection scoreHolderTargets, Objective objective) { Scoreboard scoreboard = x.getSource().getServer().getScoreboard(); int i = 0; - for (String s : scoreHolderTargets) { - Score score = scoreboard.getOrCreatePlayerScore(s, objective); - // ModCyclic.LOGGER.error("[test cmd]" + score.getScore()); - i += score.getScore(); + for (ScoreHolder s : scoreHolderTargets) { + ScoreAccess score = scoreboard.getOrCreatePlayerScore(s, objective); + i += score.get(); } return i; } - public static int scoreboardAdd(CommandContext x, Collection scoreHolderTargets, Objective objective, int integer) { + public static int scoreboardAdd(CommandContext x, Collection scoreHolderTargets, Objective objective, int integer) { Scoreboard scoreboard = x.getSource().getServer().getScoreboard(); int i = 0; - for (String s : scoreHolderTargets) { - Score score = scoreboard.getOrCreatePlayerScore(s, objective); + for (ScoreHolder s : scoreHolderTargets) { + ScoreAccess score = scoreboard.getOrCreatePlayerScore(s, objective); score.add(integer); - // ModCyclic.LOGGER.info("objective add " + score.getScore()); - i += score.getScore(); + i += score.get(); } return i; } - public static int scoreboardRng(CommandContext x, Collection scoreHolderTargets, Objective objective, int min, int max) { + public static int scoreboardRng(CommandContext x, Collection scoreHolderTargets, Objective objective, int min, int max) { Scoreboard scoreboard = x.getSource().getServer().getScoreboard(); int i = 0; - for (String s : scoreHolderTargets) { - Score score = scoreboard.getOrCreatePlayerScore(s, objective); + for (ScoreHolder s : scoreHolderTargets) { // TODO: s used to be a string + ScoreAccess score = scoreboard.getOrCreatePlayerScore(s, objective); if (min < max) { - score.setScore(RAND.nextInt(min, max)); + score.set(RAND.nextInt(min, max)); } else { //either equal, or max is lower than min - score.setScore(min); + score.set(min); } // ModCyclic.LOGGER.info("objective rng " + score.getScore()); - i += score.getScore(); + i += score.get(); } return i; } @@ -461,10 +457,10 @@ public static int executePrintPlayerNbt(CommandContext ctx, public static int executePrintNbt(CommandContext ctx) throws CommandSyntaxException { ServerPlayer player = ctx.getSource().getPlayerOrException(); ItemStack held = player.getMainHandItem(); - if (held.hasTag()) { - ChatUtil.sendFeedback(ctx, held.getTag().toString()); - } - else { + net.minecraft.world.item.component.CustomData customData = held.get(net.minecraft.core.component.DataComponents.CUSTOM_DATA); + if (customData != null) { + ChatUtil.sendFeedback(ctx, customData.copyTag().toString()); + } else { ChatUtil.sendFeedback(ctx, "command.flib.nbtprint.null"); } return 0; diff --git a/src/main/java/com/lothrazar/library/mod/ConfigModule.java b/src/main/java/com/lothrazar/library/mod/ConfigModule.java index d282162..dcf5d66 100644 --- a/src/main/java/com/lothrazar/library/mod/ConfigModule.java +++ b/src/main/java/com/lothrazar/library/mod/ConfigModule.java @@ -1,24 +1,26 @@ package com.lothrazar.library.mod; import com.lothrazar.library.FutureLibMod; -import com.lothrazar.library.config.ConfigTemplate; -import net.minecraftforge.common.ForgeConfigSpec; -import net.minecraftforge.common.ForgeConfigSpec.BooleanValue; -import net.minecraftforge.common.ForgeConfigSpec.Builder; +import net.neoforged.fml.ModContainer; +import net.neoforged.fml.config.ModConfig; +import net.neoforged.neoforge.common.ModConfigSpec; +import net.neoforged.neoforge.common.ModConfigSpec.BooleanValue; +import net.neoforged.neoforge.common.ModConfigSpec.Builder; -public class ConfigModule extends ConfigTemplate { +public class ConfigModule { - private static ForgeConfigSpec CONFIG; + private static final ModConfigSpec CONFIG; public static BooleanValue ENABLE_COMMANDS; + static { - final Builder builder = builder(); + final Builder builder = new ModConfigSpec.Builder(); builder.comment("General settings").push(FutureLibMod.MODID); ENABLE_COMMANDS = builder.comment("If true, the /flib command will be registered").define("command.enabled", true); - builder.pop(); // one pop for every push + builder.pop(); CONFIG = builder.build(); } - public ConfigModule() { - CONFIG.setConfig(setup(FutureLibMod.MODID)); + public ConfigModule(ModContainer modContainer) { + modContainer.registerConfig(ModConfig.Type.COMMON, CONFIG); } } diff --git a/src/main/java/com/lothrazar/library/mod/FlibRegistrations.java b/src/main/java/com/lothrazar/library/mod/FlibRegistrations.java index 43a15dc..c47e0fd 100644 --- a/src/main/java/com/lothrazar/library/mod/FlibRegistrations.java +++ b/src/main/java/com/lothrazar/library/mod/FlibRegistrations.java @@ -1,20 +1,23 @@ package com.lothrazar.library.mod; +import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.recipe.conditions.EntityExistsCondition; -import net.minecraftforge.common.crafting.CraftingHelper; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegisterEvent; +import com.mojang.serialization.MapCodec; +import net.neoforged.bus.api.IEventBus; +import net.neoforged.neoforge.common.conditions.ICondition; +import net.neoforged.neoforge.registries.DeferredRegister; +import net.neoforged.neoforge.registries.NeoForgeRegistries; -@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD) public class FlibRegistrations { - public static final EntityExistsCondition.Serializer ENTITY_EXISTS = new EntityExistsCondition.Serializer(); + private static final DeferredRegister> CONDITIONS = + DeferredRegister.create(NeoForgeRegistries.Keys.CONDITION_CODECS, FutureLibMod.MODID); - @SubscribeEvent - public static void onRegistry(RegisterEvent event) { - event.register(ForgeRegistries.Keys.RECIPE_SERIALIZERS, - helper -> CraftingHelper.register(ENTITY_EXISTS)); + static { + CONDITIONS.register("entity_exists", () -> EntityExistsCondition.CODEC); + } + + public static void register(IEventBus modBus) { + CONDITIONS.register(modBus); } } diff --git a/src/main/java/com/lothrazar/library/mod/PacketRegistry.java b/src/main/java/com/lothrazar/library/mod/PacketRegistry.java index 63a79ed..ccc0eaf 100644 --- a/src/main/java/com/lothrazar/library/mod/PacketRegistry.java +++ b/src/main/java/com/lothrazar/library/mod/PacketRegistry.java @@ -1,23 +1,27 @@ package com.lothrazar.library.mod; -import com.lothrazar.library.FutureLibMod; +import com.lothrazar.library.packet.PacketItemToggle; import com.lothrazar.library.packet.PacketPlayerFalldamage; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.simple.SimpleChannel; +import com.lothrazar.library.packet.PacketRotateBlock; +import com.lothrazar.library.packet.PacketSyncEnergy; +import com.lothrazar.library.packet.PacketSyncFluid; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.neoforged.neoforge.network.registration.PayloadRegistrar; public class PacketRegistry { - private static final String PROTOCOL_VERSION = Integer.toString(1); - public static final SimpleChannel INSTANCE = NetworkRegistry.ChannelBuilder - .named(new ResourceLocation(FutureLibMod.MODID, "main_channel")) - .clientAcceptedVersions(PROTOCOL_VERSION::equals) - .serverAcceptedVersions(PROTOCOL_VERSION::equals) - .networkProtocolVersion(() -> PROTOCOL_VERSION) - .simpleChannel(); + public static void setup(FMLCommonSetupEvent event) { + // Registration now happens via RegisterPayloadHandlersEvent on the mod bus. + // This method is kept for API compatibility but does nothing. + } - public static void setup() { - int id = 0; - INSTANCE.registerMessage(id++, PacketPlayerFalldamage.class, PacketPlayerFalldamage::encode, PacketPlayerFalldamage::decode, PacketPlayerFalldamage::handle); + public static void onRegisterPayloads(RegisterPayloadHandlersEvent event) { + final PayloadRegistrar registrar = event.registrar("1"); + registrar.playToServer(PacketPlayerFalldamage.TYPE, PacketPlayerFalldamage.STREAM_CODEC, PacketPlayerFalldamage::handle); + registrar.playToServer(PacketItemToggle.TYPE, PacketItemToggle.STREAM_CODEC, PacketItemToggle::handle); + registrar.playToServer(PacketRotateBlock.TYPE, PacketRotateBlock.STREAM_CODEC, PacketRotateBlock::handle); + registrar.playToClient(PacketSyncEnergy.TYPE, PacketSyncEnergy.STREAM_CODEC, PacketSyncEnergy::handle); + registrar.playToClient(PacketSyncFluid.TYPE, PacketSyncFluid.STREAM_CODEC, PacketSyncFluid::handle); } } diff --git a/src/main/java/com/lothrazar/library/packet/PacketFlib.java b/src/main/java/com/lothrazar/library/packet/PacketFlib.java index 895fe4b..852490f 100644 --- a/src/main/java/com/lothrazar/library/packet/PacketFlib.java +++ b/src/main/java/com/lothrazar/library/packet/PacketFlib.java @@ -1,11 +1,10 @@ package com.lothrazar.library.packet; -import java.util.function.Supplier; -import net.minecraftforge.network.NetworkEvent.Context; - +/** + * Base class for FLib packets. Subclasses implement CustomPacketPayload. + * With the NeoForge 1.21+ payload system, packets are marked as handled automatically + * once the handler method returns — no explicit done() call is needed. + */ public class PacketFlib { - - public void done(Supplier ctx) { - ctx.get().setPacketHandled(true); - } + // intentionally empty } diff --git a/src/main/java/com/lothrazar/library/packet/PacketItemToggle.java b/src/main/java/com/lothrazar/library/packet/PacketItemToggle.java index c5cc076..37c28a6 100644 --- a/src/main/java/com/lothrazar/library/packet/PacketItemToggle.java +++ b/src/main/java/com/lothrazar/library/packet/PacketItemToggle.java @@ -1,52 +1,55 @@ package com.lothrazar.library.packet; -import java.util.function.Supplier; +import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.core.IHasClickToggle; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.inventory.Slot; import net.minecraft.world.item.ItemStack; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; -public class PacketItemToggle extends PacketFlib { +public class PacketItemToggle extends PacketFlib implements CustomPacketPayload { - private int slot; + public static final CustomPacketPayload.Type TYPE = + new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "item_toggle")); + + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + ByteBufCodecs.INT, PacketItemToggle::getSlot, + PacketItemToggle::new); + + private final int slot; public PacketItemToggle(int slot) { this.slot = slot; } - public static void handle(PacketItemToggle message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - ServerPlayer player = ctx.get().getSender(); - if (player.containerMenu == null) { - return; - } + public int getSlot() { + return slot; + } + + @Override + public CustomPacketPayload.Type type() { + return TYPE; + } + + public static void handle(PacketItemToggle msg, IPayloadContext context) { + context.enqueueWork(() -> { + ServerPlayer player = (ServerPlayer) context.player(); + if (player.containerMenu == null) return; int scount = player.containerMenu.slots.size(); - //this is an edge case but it DID happen: put charmin your hotbar and then open a creative inventory tab. avoid index OOB - if (message.slot >= scount) { - //will NOT work in creative mode. slots are messed up - return; - } - Slot slotObj = player.containerMenu.getSlot(message.slot); + if (msg.slot >= scount) return; + Slot slotObj = player.containerMenu.getSlot(msg.slot); if (slotObj != null && !slotObj.getItem().isEmpty()) { ItemStack maybeCharm = slotObj.getItem(); - if (maybeCharm.getItem() instanceof IHasClickToggle) { - //example: is a charm or something - IHasClickToggle c = (IHasClickToggle) maybeCharm.getItem(); + if (maybeCharm.getItem() instanceof IHasClickToggle c) { c.toggle(player, maybeCharm); } } }); - message.done(ctx); - } - - public static PacketItemToggle decode(FriendlyByteBuf buf) { - PacketItemToggle p = new PacketItemToggle(buf.readInt()); - return p; - } - - public static void encode(PacketItemToggle msg, FriendlyByteBuf buf) { - buf.writeInt(msg.slot); } } diff --git a/src/main/java/com/lothrazar/library/packet/PacketPlayerFalldamage.java b/src/main/java/com/lothrazar/library/packet/PacketPlayerFalldamage.java index 1ebdfd2..1e24193 100644 --- a/src/main/java/com/lothrazar/library/packet/PacketPlayerFalldamage.java +++ b/src/main/java/com/lothrazar/library/packet/PacketPlayerFalldamage.java @@ -1,36 +1,36 @@ package com.lothrazar.library.packet; -import java.util.function.Supplier; +import com.lothrazar.library.FutureLibMod; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; /** - * Used by: Fan block; Launch enchant; Air charm; Climbing Glove; Scaffolding Block + * Sent client→server to reset fall distance (used by climbing, fan blocks, etc.). */ -public class PacketPlayerFalldamage extends PacketFlib { +public class PacketPlayerFalldamage extends PacketFlib implements CustomPacketPayload { - public static final int TICKS_FALLDIST_SYNC = 22; //tick every so often + public static final int TICKS_FALLDIST_SYNC = 22; - public static void handle(PacketPlayerFalldamage message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - ServerPlayer player = ctx.get().getSender(); - /** - * if fall damage gets high, they take damage on landing - */ + public static final CustomPacketPayload.Type TYPE = + new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "fall_damage")); + + public static final StreamCodec STREAM_CODEC = + StreamCodec.unit(new PacketPlayerFalldamage()); + + @Override + public CustomPacketPayload.Type type() { + return TYPE; + } + + public static void handle(PacketPlayerFalldamage msg, IPayloadContext context) { + context.enqueueWork(() -> { + ServerPlayer player = (ServerPlayer) context.player(); player.fallDistance = 0.0F; - /** - * Used to keep track of how the player is floating while gamerules should prevent that. Surpassing 80 ticks means kick - */ player.connection.aboveGroundTickCount = 0; }); - message.done(ctx); } - - public static PacketPlayerFalldamage decode(FriendlyByteBuf buf) { - PacketPlayerFalldamage message = new PacketPlayerFalldamage(); - return message; - } - - public static void encode(PacketPlayerFalldamage msg, FriendlyByteBuf buf) {} } diff --git a/src/main/java/com/lothrazar/library/packet/PacketRotateBlock.java b/src/main/java/com/lothrazar/library/packet/PacketRotateBlock.java index 54d6f69..294baf2 100644 --- a/src/main/java/com/lothrazar/library/packet/PacketRotateBlock.java +++ b/src/main/java/com/lothrazar/library/packet/PacketRotateBlock.java @@ -1,79 +1,70 @@ -/******************************************************************************* - * The MIT License (MIT) - * - * Copyright (C) 2014-2018 Sam Bassett (aka Lothrazar) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ package com.lothrazar.library.packet; -import java.util.function.Supplier; +import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.util.BlockUtil; import com.lothrazar.library.util.ItemStackUtil; import com.lothrazar.library.util.SoundUtil; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; -public class PacketRotateBlock extends PacketFlib { +public class PacketRotateBlock extends PacketFlib implements CustomPacketPayload { - private BlockPos pos; - private Direction side; - private InteractionHand hand; + public static final CustomPacketPayload.Type TYPE = + new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "rotate_block")); - public PacketRotateBlock(BlockPos mouseover, Direction s, InteractionHand hand) { - pos = mouseover; - side = s; + private static final StreamCodec DIRECTION_CODEC = + StreamCodec.of((buf, dir) -> buf.writeEnum(dir), buf -> buf.readEnum(Direction.class)); + + private static final StreamCodec HAND_CODEC = + StreamCodec.of((buf, hand) -> buf.writeEnum(hand), buf -> buf.readEnum(InteractionHand.class)); + + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + BlockPos.STREAM_CODEC, PacketRotateBlock::getPos, + DIRECTION_CODEC, PacketRotateBlock::getSide, + HAND_CODEC, PacketRotateBlock::getHand, + PacketRotateBlock::new); + + private final BlockPos pos; + private final Direction side; + private final InteractionHand hand; + + public PacketRotateBlock(BlockPos pos, Direction side, InteractionHand hand) { + this.pos = pos; + this.side = side; this.hand = hand; } - public static PacketRotateBlock decode(FriendlyByteBuf buf) { - return new PacketRotateBlock(buf.readBlockPos(), - Direction.values()[buf.readInt()], - InteractionHand.values()[buf.readInt()]); - } + public BlockPos getPos() { return pos; } + public Direction getSide() { return side; } + public InteractionHand getHand() { return hand; } - public static void encode(PacketRotateBlock msg, FriendlyByteBuf buf) { - buf.writeBlockPos(msg.pos); - buf.writeInt(msg.side.ordinal()); - buf.writeInt(msg.hand.ordinal()); + @Override + public CustomPacketPayload.Type type() { + return TYPE; } - public static void handle(PacketRotateBlock message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - //rotate type - Level level = ctx.get().getSender().level(); - boolean succ = BlockUtil.rotateBlockValidState(level, message.pos, message.side); + public static void handle(PacketRotateBlock msg, IPayloadContext context) { + context.enqueueWork(() -> { + ServerPlayer player = (ServerPlayer) context.player(); + Level level = player.level(); + boolean succ = BlockUtil.rotateBlockValidState(level, msg.pos, msg.side); if (succ) { - ServerPlayer player = ctx.get().getSender(); - ItemStack itemStackHeld = player.getItemInHand(message.hand); + ItemStack itemStackHeld = player.getItemInHand(msg.hand); ItemStackUtil.damageItem(player, itemStackHeld); - if (level.getBlockState(message.pos).getSoundType() != null) { - SoundUtil.playSoundFromServer(player, level.getBlockState(message.pos).getSoundType().getPlaceSound(), 1F, 1F); + if (level.getBlockState(msg.pos).getSoundType() != null) { + SoundUtil.playSoundFromServer(player, level.getBlockState(msg.pos).getSoundType().getPlaceSound(), 1F, 1F); } } }); - message.done(ctx); } } diff --git a/src/main/java/com/lothrazar/library/packet/PacketSyncEnergy.java b/src/main/java/com/lothrazar/library/packet/PacketSyncEnergy.java index 8f64840..4e08098 100644 --- a/src/main/java/com/lothrazar/library/packet/PacketSyncEnergy.java +++ b/src/main/java/com/lothrazar/library/packet/PacketSyncEnergy.java @@ -1,71 +1,53 @@ -/******************************************************************************* - * The MIT License (MIT) - * - * Copyright (C) 2014-2018 Sam Bassett (aka Lothrazar) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ package com.lothrazar.library.packet; -import java.util.function.Supplier; +import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.core.IHasEnergy; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.network.handling.IPayloadContext; /** - * Forge docs suggest using a direct packet to keep capabilities, such as power, in sync with the client according to https://mcforge.readthedocs.io/en/latest/datastorage/capabilities/ + * Sent server→client to sync energy level on a block entity. */ -public class PacketSyncEnergy extends PacketFlib { +public class PacketSyncEnergy extends PacketFlib implements CustomPacketPayload { - private BlockPos pos; - private int energy; + public static final CustomPacketPayload.Type TYPE = + new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "sync_energy")); - public PacketSyncEnergy(BlockPos p, int fluid) { - pos = p; - this.energy = fluid; - } + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + BlockPos.STREAM_CODEC, PacketSyncEnergy::getPos, + ByteBufCodecs.INT, PacketSyncEnergy::getEnergy, + PacketSyncEnergy::new); - public static void handle(PacketSyncEnergy message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - doWork(message); - }); - message.done(ctx); - } + private final BlockPos pos; + private final int energy; - private static void doWork(PacketSyncEnergy message) { - BlockEntity te = Minecraft.getInstance().level.getBlockEntity(message.pos); - if (te instanceof IHasEnergy tile) { - tile.setEnergy(message.energy); - } + public PacketSyncEnergy(BlockPos pos, int energy) { + this.pos = pos; + this.energy = energy; } - public static PacketSyncEnergy decode(FriendlyByteBuf buf) { - PacketSyncEnergy msg = new PacketSyncEnergy(buf.readBlockPos(), - buf.readInt()); - return msg; + public BlockPos getPos() { return pos; } + public int getEnergy() { return energy; } + + @Override + public CustomPacketPayload.Type type() { + return TYPE; } - public static void encode(PacketSyncEnergy msg, FriendlyByteBuf buf) { - buf.writeBlockPos(msg.pos); - buf.writeInt(msg.energy); + public static void handle(PacketSyncEnergy msg, IPayloadContext context) { + context.enqueueWork(() -> { + BlockEntity te = Minecraft.getInstance().level.getBlockEntity(msg.pos); + if (te instanceof IHasEnergy tile) { + tile.setEnergy(msg.energy); + } + }); } } diff --git a/src/main/java/com/lothrazar/library/packet/PacketSyncFluid.java b/src/main/java/com/lothrazar/library/packet/PacketSyncFluid.java index 97e5238..02f9801 100644 --- a/src/main/java/com/lothrazar/library/packet/PacketSyncFluid.java +++ b/src/main/java/com/lothrazar/library/packet/PacketSyncFluid.java @@ -1,74 +1,54 @@ -/******************************************************************************* - * The MIT License (MIT) - * - * Copyright (C) 2014-2018 Sam Bassett (aka Lothrazar) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - ******************************************************************************/ package com.lothrazar.library.packet; -import java.util.function.Supplier; +import com.lothrazar.library.FutureLibMod; import com.lothrazar.library.core.IHasFluid; import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.StreamCodec; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; +import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.entity.BlockEntity; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.network.NetworkEvent; +import net.neoforged.neoforge.fluids.FluidStack; +import net.neoforged.neoforge.network.handling.IPayloadContext; -public class PacketSyncFluid extends PacketFlib { +/** + * Sent server→client to sync fluid content on a block entity. + */ +public class PacketSyncFluid extends PacketFlib implements CustomPacketPayload { - private BlockPos pos; - private FluidStack fluid; + public static final CustomPacketPayload.Type TYPE = + new CustomPacketPayload.Type<>(ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "sync_fluid")); - public PacketSyncFluid(BlockPos p, FluidStack fluid) { - pos = p; - this.fluid = fluid; - } + public static final StreamCodec STREAM_CODEC = + StreamCodec.composite( + BlockPos.STREAM_CODEC, PacketSyncFluid::getPos, + FluidStack.STREAM_CODEC, PacketSyncFluid::getFluid, + PacketSyncFluid::new); - public static void handle(PacketSyncFluid message, Supplier ctx) { - ctx.get().enqueueWork(() -> { - doWork(message); - }); - message.done(ctx); - } + private final BlockPos pos; + private final FluidStack fluid; - private static void doWork(PacketSyncFluid message) { - BlockEntity te = Minecraft.getInstance().level.getBlockEntity(message.pos); - if (te instanceof IHasFluid tile) { - tile.setFluid(message.fluid); - } + public PacketSyncFluid(BlockPos pos, FluidStack fluid) { + this.pos = pos; + this.fluid = fluid; } - public static PacketSyncFluid decode(FriendlyByteBuf buf) { - PacketSyncFluid msg = new PacketSyncFluid(buf.readBlockPos(), - FluidStack.loadFluidStackFromNBT(buf.readNbt())); - return msg; + public BlockPos getPos() { return pos; } + public FluidStack getFluid() { return fluid; } + + @Override + public CustomPacketPayload.Type type() { + return TYPE; } - public static void encode(PacketSyncFluid msg, FriendlyByteBuf buf) { - buf.writeBlockPos(msg.pos); - CompoundTag tags = new CompoundTag(); - if (msg.fluid != null) { - msg.fluid.writeToNBT(tags); - } - buf.writeNbt(tags); + public static void handle(PacketSyncFluid msg, IPayloadContext context) { + context.enqueueWork(() -> { + BlockEntity te = Minecraft.getInstance().level.getBlockEntity(msg.pos); + if (te instanceof IHasFluid tile) { + tile.setFluid(msg.fluid); + } + }); } } diff --git a/src/main/java/com/lothrazar/library/particle/AbstractSingleQuadParticle.java b/src/main/java/com/lothrazar/library/particle/AbstractSingleQuadParticle.java index 9dd7d2b..0567126 100644 --- a/src/main/java/com/lothrazar/library/particle/AbstractSingleQuadParticle.java +++ b/src/main/java/com/lothrazar/library/particle/AbstractSingleQuadParticle.java @@ -2,26 +2,21 @@ import com.mojang.blaze3d.platform.GlStateManager; import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; -import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexConsumer; -import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.particle.ParticleRenderType; import net.minecraft.client.particle.SingleQuadParticle; -import net.minecraft.client.renderer.GameRenderer; -import net.minecraft.client.renderer.texture.TextureManager; +import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.minecraft.world.phys.Vec3; +import com.mojang.blaze3d.vertex.VertexConsumer; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; /** * used by ParticleCasting - * - * @author lothr * + * @author lothr */ @OnlyIn(Dist.CLIENT) public abstract class AbstractSingleQuadParticle extends SingleQuadParticle { @@ -38,19 +33,14 @@ protected AbstractSingleQuadParticle(ClientLevel world, double x, double y, doub @Override public void render(VertexConsumer buffer, Camera entityIn, float partialTicks) { - TextureManager textureManager = Minecraft.getInstance().textureManager; - // Lighting.turnOff(); + // For CUSTOM render type, we set up the texture/blend state then delegate to super. + // The VertexConsumer writes into the buffer provided by the particle engine. + RenderSystem.setShaderTexture(0, getTexture()); RenderSystem.depthMask(false); - textureManager.bindForSetup(getTexture()); RenderSystem.enableBlend(); RenderSystem.blendFunc(GlStateManager.SourceFactor.SRC_ALPHA, GlStateManager.DestFactor.ONE_MINUS_SRC_ALPHA); - // RenderSystem.alphaFunc(516, 0.003921569F); - // Tesselator.getInstance().getBuilder().begin(7, DefaultVertexFormat.PARTICLE); - RenderSystem.setShader(GameRenderer::getParticleShader); - RenderSystem.setShaderTexture(0, getTexture()); - Tesselator.getInstance().getBuilder().begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE); // QUADS == tuess super.render(buffer, entityIn, partialTicks); - Tesselator.getInstance().end(); + RenderSystem.depthMask(true); } @Override diff --git a/src/main/java/com/lothrazar/library/particle/data/ParticleOptionsTwoInt.java b/src/main/java/com/lothrazar/library/particle/data/ParticleOptionsTwoInt.java index 85d8121..9809793 100644 --- a/src/main/java/com/lothrazar/library/particle/data/ParticleOptionsTwoInt.java +++ b/src/main/java/com/lothrazar/library/particle/data/ParticleOptionsTwoInt.java @@ -1,45 +1,36 @@ package com.lothrazar.library.particle.data; -import java.util.Locale; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.serialization.Codec; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleType; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.registries.ForgeRegistries; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.RegistryFriendlyByteBuf; +import net.minecraft.network.codec.ByteBufCodecs; +import net.minecraft.network.codec.StreamCodec; /** - * used by ParticleBlinkingAura + * ParticleOptions implementation carrying two ints (e.g. two RGB color values). + * Used by ParticleBlinkingAura and similar effects. * + *

In 1.21.1, ParticleOptions no longer has Deserializer, writeToNetwork, or + * writeToString. Instead, the ParticleType provides a MapCodec and a StreamCodec. + * Use the static factory methods here when registering your ParticleType:

+ * + *
+ * PARTICLES.register("my_particle", () -> new ParticleType<<>;ParticleOptionsTwoInt>;(false) {
+ *   public MapCodec; codec() {
+ *     return ParticleOptionsTwoInt.codec(this);
+ *   }
+ *  public StreamCodec; streamCodec() {
+ *     return ParticleOptionsTwoInt.streamCodec(this);
+ *   }
+ * });
+ * 
*/ public class ParticleOptionsTwoInt implements ParticleOptions { - @SuppressWarnings("deprecation") - public static final Deserializer DESERIALIZER = new Deserializer() { - - @Override - public ParticleOptionsTwoInt fromCommand(ParticleType particleType, StringReader reader) throws CommandSyntaxException { - if (reader.canRead()) { - reader.expect(' '); - } - int oneInt = 0xffffff, twoInt = 0xffffff; - if (reader.canRead()) { - oneInt = reader.readInt(); - } - if (reader.canRead()) { - reader.expect(' '); - } - if (reader.canRead()) { - twoInt = reader.readInt(); - } - return new ParticleOptionsTwoInt(particleType, oneInt, twoInt); - } - - @Override - public ParticleOptionsTwoInt fromNetwork(ParticleType particleType, FriendlyByteBuf buf) { - return new ParticleOptionsTwoInt(particleType, buf.readInt(), buf.readInt()); - } - }; private final ParticleType particleType; public int oneInt, twoInt; @@ -54,14 +45,33 @@ public ParticleType getType() { return this.particleType; } - @Override - public void writeToNetwork(FriendlyByteBuf buf) { - buf.writeInt(this.oneInt); - buf.writeInt(this.twoInt); + /** + * Returns a MapCodec for command/config serialization. + * Call this from your ParticleType's codec() override, passing {@code this}. + */ + public static MapCodec codec(ParticleType type) { + return RecordCodecBuilder.mapCodec(instance -> + instance.group( + Codec.INT.fieldOf("oneInt").forGetter(p -> p.oneInt), + Codec.INT.fieldOf("twoInt").forGetter(p -> p.twoInt) + ).apply(instance, (a, b) -> new ParticleOptionsTwoInt(type, a, b)) + ); + } + + /** + * Returns a StreamCodec for network serialization. + * Call this from your ParticleType's streamCodec() override, passing {@code this}. + */ + public static StreamCodec streamCodec(ParticleType type) { + return StreamCodec.composite( + ByteBufCodecs.INT, p -> p.oneInt, + ByteBufCodecs.INT, p -> p.twoInt, + (a, b) -> new ParticleOptionsTwoInt(type, a, b) + ); } @Override - public String writeToString() { - return String.format(Locale.ROOT, "%s %d %d", ForgeRegistries.PARTICLE_TYPES.getKey(getType()), this.oneInt, this.twoInt); + public String toString() { + return String.format("%s %d %d", BuiltInRegistries.PARTICLE_TYPE.getKey(getType()), oneInt, twoInt); } } diff --git a/src/main/java/com/lothrazar/library/portal/DimensionTransitionWrapper.java b/src/main/java/com/lothrazar/library/portal/DimensionTransitionWrapper.java new file mode 100644 index 0000000..3dbf6ac --- /dev/null +++ b/src/main/java/com/lothrazar/library/portal/DimensionTransitionWrapper.java @@ -0,0 +1,87 @@ +package com.lothrazar.library.portal; + +import com.lothrazar.library.core.BlockPosDim; +import com.lothrazar.library.util.LevelWorldUtil; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.level.portal.DimensionTransition; +import net.minecraft.world.phys.Vec3; + +/** + * Handles cross-dimension teleportation via the vanilla 1.21 DimensionTransition API. + * ITeleporter (Forge) no longer exists — entity.changeDimension(DimensionTransition) is the replacement. + * + * @see com/lothrazar/cyclic/world/ + */ +public class DimensionTransitionWrapper { + + protected ServerLevel world; + private BlockPosDim target; + + public DimensionTransitionWrapper(ServerLevel world, BlockPosDim target) { + this.world = world; + this.target = target; + } + + private BlockPos moveToSafeCoords(ServerLevel destWorld, BlockPos pos) { + int tries = 10; + while (tries > 0) { + tries--; + if (destWorld.getBlockState(pos).isSolid()) { + pos = pos.above(); + } + } + return pos; + } + + /** + * Builds the DimensionTransition for use with entity.changeDimension(). + * The PostDimensionTransition callback applies effects on the entity after arrival. + */ + public DimensionTransition buildTransition(Player player) { + ServerLevel targetLevel = getTargetLevel(); + BlockPos safePos = moveToSafeCoords(targetLevel, target.getPos()); + return new DimensionTransition( + targetLevel, + new Vec3(safePos.getX() + 0.5, safePos.getY() + 0.5, safePos.getZ() + 0.5), + Vec3.ZERO, + player.getYRot(), + player.getXRot(), + false, + entity -> { + // PostDimensionTransition: runs on the entity after it arrives in the new dimension + if (entity instanceof LivingEntity living) { + living.addEffect(new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 200, 200, false, false)); + living.addEffect(new MobEffectInstance(MobEffects.SLOW_FALLING, 20, 20, false, false)); + } + entity.fallDistance = 0; + } + ); + } + + /** + * Applies pre-teleport effects and plays the portal sound at the destination. + * Call this before changeDimension(). + */ + public void applyPreTeleportEffects(Player player) { + if (!player.isCreative() && !player.level().isClientSide) { + player.addEffect(new MobEffectInstance(MobEffects.DAMAGE_RESISTANCE, 200, 200, false, false)); + } + if (this.world != null) { + this.world.playSound(null, + target.getX() + 0.5D, target.getY() + 0.5D, target.getZ() + 0.5D, + SoundEvents.PORTAL_TRAVEL, SoundSource.MASTER, + 0.25F, this.world.random.nextFloat() * 0.4F + 0.8F); + } + } + + public ServerLevel getTargetLevel() { + return world == null ? null : world.getServer().getLevel(LevelWorldUtil.stringToDimension(target.getDimension())); + } +} diff --git a/src/main/java/com/lothrazar/library/recipe/BrewingRecipeFlib.java b/src/main/java/com/lothrazar/library/recipe/BrewingRecipeFlib.java index d838c6c..3b2589d 100644 --- a/src/main/java/com/lothrazar/library/recipe/BrewingRecipeFlib.java +++ b/src/main/java/com/lothrazar/library/recipe/BrewingRecipeFlib.java @@ -1,9 +1,10 @@ package com.lothrazar.library.recipe; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.alchemy.PotionUtils; +import net.minecraft.world.item.alchemy.PotionContents; import net.minecraft.world.item.crafting.Ingredient; -import net.minecraftforge.common.brewing.BrewingRecipe; +import net.neoforged.neoforge.common.brewing.BrewingRecipe; public class BrewingRecipeFlib extends BrewingRecipe { @@ -16,6 +17,9 @@ public BrewingRecipeFlib(ItemStack inputStack, Ingredient ingredient, ItemStack @Override public boolean isInput(ItemStack stack) { - return super.isInput(stack) && PotionUtils.getPotion(stack) == PotionUtils.getPotion(inputStack); + // PotionUtils.getPotion() removed in 1.21.1 — use DataComponents.POTION_CONTENTS + PotionContents p1 = stack.get(DataComponents.POTION_CONTENTS); + PotionContents p2 = inputStack.get(DataComponents.POTION_CONTENTS); + return super.isInput(stack) && p1 != null && p1.equals(p2); } } diff --git a/src/main/java/com/lothrazar/library/recipe/conditions/EntityExistsCondition.java b/src/main/java/com/lothrazar/library/recipe/conditions/EntityExistsCondition.java index e57567d..f82d330 100644 --- a/src/main/java/com/lothrazar/library/recipe/conditions/EntityExistsCondition.java +++ b/src/main/java/com/lothrazar/library/recipe/conditions/EntityExistsCondition.java @@ -1,63 +1,42 @@ package com.lothrazar.library.recipe.conditions; -import com.google.gson.JsonObject; -import com.lothrazar.library.FutureLibMod; +import com.mojang.serialization.MapCodec; +import com.mojang.serialization.codecs.RecordCodecBuilder; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.crafting.conditions.ICondition; -import net.minecraftforge.common.crafting.conditions.IConditionSerializer; -import net.minecraftforge.registries.ForgeRegistries; +import net.neoforged.neoforge.common.conditions.ICondition; /** - * Example: "conditions": [ {"type": "flib:entity_exists", "value": "veincreeper:coal_creeper" } ] + * Recipe condition that passes only if the given entity type is registered. + * Example JSON: + * "conditions": [{"type": "flib:entity_exists", "value": "veincreeper:coal_creeper"}] */ public class EntityExistsCondition implements ICondition { - private static final ResourceLocation ID = new ResourceLocation(FutureLibMod.MODID, "entity_exists"); - private ResourceLocation entityId; + public static final MapCodec CODEC = RecordCodecBuilder.mapCodec(instance -> + instance.group( + ResourceLocation.CODEC.fieldOf("value").forGetter(c -> c.entityId) + ).apply(instance, EntityExistsCondition::new)); - public EntityExistsCondition(ResourceLocation resourceLocation) { - this.entityId = resourceLocation; - } + private final ResourceLocation entityId; - @Override - public String toString() { - return "entity_exists(\"" + entityId + "\")"; + public EntityExistsCondition(ResourceLocation entityId) { + this.entityId = entityId; } + // used to be ICondition.Context @Override - public ResourceLocation getID() { - return ID; + public boolean test(IContext context) { + return entityId != null && BuiltInRegistries.ENTITY_TYPE.containsKey(entityId); } - // "conditions": [ - // { - // "type": "flib:entity_exists", - // "value": "veincreeper:copper_creeper" - // } - // ], @Override - public boolean test(IContext context) { - return this.entityId != null && ForgeRegistries.ENTITY_TYPES.containsKey(this.entityId); + public MapCodec codec() { + return CODEC; } - public static class Serializer implements IConditionSerializer { - - public static final Serializer INSTANCE = new Serializer(); - - @Override - public void write(JsonObject json, EntityExistsCondition value) { - json.addProperty("value", value.entityId.toString()); - } - - @Override - public EntityExistsCondition read(JsonObject json) { - String entityId = json.get("value").getAsString(); - return new EntityExistsCondition(new ResourceLocation(entityId)); - } - - @Override - public ResourceLocation getID() { - return ID; - } + @Override + public String toString() { + return "entity_exists(\"" + entityId + "\")"; } } diff --git a/src/main/java/com/lothrazar/library/recipe/ingredient/FluidTagIngredient.java b/src/main/java/com/lothrazar/library/recipe/ingredient/FluidTagIngredient.java index 5a893c3..d9ff65c 100644 --- a/src/main/java/com/lothrazar/library/recipe/ingredient/FluidTagIngredient.java +++ b/src/main/java/com/lothrazar/library/recipe/ingredient/FluidTagIngredient.java @@ -2,13 +2,16 @@ import java.util.ArrayList; import java.util.List; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.core.registries.Registries; import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.tags.FluidTags; import net.minecraft.tags.TagKey; import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.registries.ForgeRegistries; +import net.minecraft.world.level.material.Fluids; +import net.neoforged.neoforge.fluids.FluidStack; public class FluidTagIngredient { @@ -42,12 +45,10 @@ public List list() { if (!hasTag()) { return List.of(fluid.getFluid()); } - TagKey ft = FluidTags.create(new ResourceLocation(tag)); - if (ft != null) { - TagKey key = ForgeRegistries.FLUIDS.tags().createTagKey(new ResourceLocation(tag)); - return ForgeRegistries.FLUIDS.tags().getTag(key).stream().toList(); - } - return null; + TagKey key = TagKey.create(Registries.FLUID, ResourceLocation.parse(tag)); + return BuiltInRegistries.FLUID.getTag(key) + .map(set -> set.stream().map(Holder::value).collect(java.util.stream.Collectors.toList())) + .orElseGet(List::of); } /** @@ -65,11 +66,20 @@ public List getMatchingFluids() { } public static FluidTagIngredient readFromPacket(FriendlyByteBuf buffer) { - return new FluidTagIngredient(FluidStack.readFromPacket(buffer), buffer.readUtf(), buffer.readInt()); + ResourceLocation fluidId = buffer.readResourceLocation(); + int fluidAmount = buffer.readInt(); + String tagStr = buffer.readUtf(); + int cnt = buffer.readInt(); + Fluid fluid = BuiltInRegistries.FLUID.getOptional(fluidId).orElse(Fluids.EMPTY); + FluidStack stack = fluid == Fluids.EMPTY ? FluidStack.EMPTY : new FluidStack(fluid, fluidAmount); + return new FluidTagIngredient(stack, tagStr, cnt); } public void writeToPacket(FriendlyByteBuf buffer) { - fluid.writeToPacket(buffer); + ResourceKey key = BuiltInRegistries.FLUID.getResourceKey(fluid.getFluid()) + .orElseThrow(() -> new IllegalStateException("Unknown fluid: " + fluid.getFluid())); + buffer.writeResourceLocation(key.location()); + buffer.writeInt(fluid.getAmount()); buffer.writeUtf(tag); buffer.writeInt(amount); } diff --git a/src/main/java/com/lothrazar/library/recipe/ingredient/RandomizedOutputIngredient.java b/src/main/java/com/lothrazar/library/recipe/ingredient/RandomizedOutputIngredient.java index d3d2d36..fe8ebb0 100644 --- a/src/main/java/com/lothrazar/library/recipe/ingredient/RandomizedOutputIngredient.java +++ b/src/main/java/com/lothrazar/library/recipe/ingredient/RandomizedOutputIngredient.java @@ -1,6 +1,8 @@ package com.lothrazar.library.recipe.ingredient; import com.google.gson.JsonObject; +import com.lothrazar.library.FutureLibMod; +import com.mojang.serialization.JsonOps; import net.minecraft.util.GsonHelper; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.crafting.ShapedRecipe; @@ -23,7 +25,15 @@ public RandomizedOutputIngredient(int readInt, ItemStack readItem) { private void parseData(JsonObject json) { if (json.has(KEY_BONUS) && json.has(KEY_PERCENT)) { - bonus = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, KEY_BONUS)); + + //bonus = ShapedRecipe.itemStackFromJson(GsonHelper.getAsJsonObject(json, KEY_BONUS)); + // replaced with codec parse + bonus = ItemStack.CODEC.parse(JsonOps.INSTANCE, json) + .resultOrPartial(errorMessage -> { + FutureLibMod.LOGGER.error("Failed to parse ItemStack: {}", errorMessage); + }) + .orElse(ItemStack.EMPTY); + percent = json.get(KEY_PERCENT).getAsInt(); percent = Math.max(0, percent); if (percent > 100) { diff --git a/src/main/java/com/lothrazar/library/registry/GameRuleFactory.java b/src/main/java/com/lothrazar/library/registry/GameRuleFactory.java index 6bea537..08acc51 100644 --- a/src/main/java/com/lothrazar/library/registry/GameRuleFactory.java +++ b/src/main/java/com/lothrazar/library/registry/GameRuleFactory.java @@ -8,7 +8,7 @@ import net.minecraft.world.level.GameRules.Category; import net.minecraft.world.level.GameRules.Key; import net.minecraft.world.level.GameRules.Type; -import net.minecraftforge.fml.util.ObfuscationReflectionHelper; +import net.neoforged.fml.util.ObfuscationReflectionHelper; /** * accesstransformers.cfg: diff --git a/src/main/java/com/lothrazar/library/registry/RecipeCauldronFactory.java b/src/main/java/com/lothrazar/library/registry/RecipeCauldronFactory.java index 52a4cb1..1aa970f 100644 --- a/src/main/java/com/lothrazar/library/registry/RecipeCauldronFactory.java +++ b/src/main/java/com/lothrazar/library/registry/RecipeCauldronFactory.java @@ -4,10 +4,11 @@ import java.util.List; import net.minecraft.core.cauldron.CauldronInteraction; import net.minecraft.world.InteractionResult; +import net.minecraft.world.ItemInteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.ItemLike; import net.minecraft.world.level.block.LayeredCauldronBlock; -import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; public class RecipeCauldronFactory { @@ -59,11 +60,11 @@ public static void setup(FMLCommonSetupEvent event) { if (rec.lowerFillLevel) { LayeredCauldronBlock.lowerFillLevel(state, level, pos); } - return InteractionResult.sidedSuccess(level.isClientSide); + return ItemInteractionResult.sidedSuccess(level.isClientSide); } - return InteractionResult.PASS; + return ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION; }; - CauldronInteraction.WATER.put(rec.input.asItem(), interaction); + CauldronInteraction.WATER.map().put(rec.input.asItem(), interaction); } } } diff --git a/src/main/java/com/lothrazar/library/render/FluidRenderMap.java b/src/main/java/com/lothrazar/library/render/FluidRenderMap.java index d29da79..afc96b5 100644 --- a/src/main/java/com/lothrazar/library/render/FluidRenderMap.java +++ b/src/main/java/com/lothrazar/library/render/FluidRenderMap.java @@ -7,8 +7,8 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.inventory.InventoryMenu; import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; -import net.minecraftforge.fluids.FluidStack; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; /** * Source from MIT open source https://github.com/mekanism/Mekanism/tree/1.15x @@ -59,15 +59,15 @@ public int hashCode(FluidStack stack) { } int code = 1; code = 31 * code + stack.getFluid().hashCode(); - if (stack.hasTag()) { - code = 31 * code + stack.getTag().hashCode(); + if (!stack.getComponents().isEmpty()) { + code = 31 * code + stack.getComponents().hashCode(); } return code; } @Override public boolean equals(FluidStack a, FluidStack b) { - return a == null ? b == null : b != null && a.isFluidEqual(b); + return a == null ? b == null : b != null && FluidStack.isSameFluidSameComponents(a, b); } } } diff --git a/src/main/java/com/lothrazar/library/render/RenderBlockOverlay.java b/src/main/java/com/lothrazar/library/render/RenderBlockOverlay.java index 9966df3..ba9284f 100644 --- a/src/main/java/com/lothrazar/library/render/RenderBlockOverlay.java +++ b/src/main/java/com/lothrazar/library/render/RenderBlockOverlay.java @@ -17,8 +17,8 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.client.event.RenderHighlightEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.neoforged.neoforge.client.event.RenderHighlightEvent; +import net.neoforged.bus.api.SubscribeEvent; /** * Copyright (c) 2015 Vorquel (modified by Lothrazar 2016-2023) @@ -225,8 +225,8 @@ private void drawSide(VertexConsumer buffer, Matrix4f matrix, int c, int i, int } private void addVertex(VertexConsumer buffer, Matrix4f matrix, double u, double v, int i) { - buffer.vertex(matrix, (float) vs[i].x, (float) vs[i].y, (float) vs[i].z) - .color(1.0f, 1.0f, 1.0f, 0.375f) - .uv((float) u, (float) v).endVertex(); + buffer.addVertex(matrix, (float) vs[i].x, (float) vs[i].y, (float) vs[i].z) + .setColor(1.0f, 1.0f, 1.0f, 0.375f) + .setUv((float) u, (float) v); } } diff --git a/src/main/java/com/lothrazar/library/render/RenderEntityToBlockLaser.java b/src/main/java/com/lothrazar/library/render/RenderEntityToBlockLaser.java index 45d9c26..1f59a1f 100644 --- a/src/main/java/com/lothrazar/library/render/RenderEntityToBlockLaser.java +++ b/src/main/java/com/lothrazar/library/render/RenderEntityToBlockLaser.java @@ -11,14 +11,13 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.texture.OverlayTexture; import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.client.event.RenderLevelStageEvent; +import net.neoforged.neoforge.client.event.RenderLevelStageEvent; /** * Citation/source/author @@ -118,26 +117,26 @@ private static void drawBeam(ItemStack stack, double xOffset, double yOffset, do Vector4f vec4 = new Vector4f(startXOffset, thickness + startYOffset, startZOffset, 1.0F); vec4.mul(positionMatrix); if (hand == InteractionHand.MAIN_HAND) { - builder.vertex(vec4.x(), vec4.y(), vec4.z(), r, g, b, alpha, 0, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec3.x(), vec3.y(), vec3.z(), r, g, b, alpha, 0, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec2.x(), vec2.y(), vec2.z(), r, g, b, alpha, 1, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec1.x(), vec1.y(), vec1.z(), r, g, b, alpha, 1, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); + builder.addVertex(vec4.x(), vec4.y(), vec4.z()).setColor(r, g, b, alpha).setUv(0, (float) v1); + builder.addVertex(vec3.x(), vec3.y(), vec3.z()).setColor(r, g, b, alpha).setUv(0, (float) v2); + builder.addVertex(vec2.x(), vec2.y(), vec2.z()).setColor(r, g, b, alpha).setUv(1, (float) v2); + builder.addVertex(vec1.x(), vec1.y(), vec1.z()).setColor(r, g, b, alpha).setUv(1, (float) v1); //Rendering a 2nd time to allow you to see both sides in multiplayer, shouldn't be necessary with culling disabled but here we are.... - builder.vertex(vec1.x(), vec1.y(), vec1.z(), r, g, b, alpha, 1, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec2.x(), vec2.y(), vec2.z(), r, g, b, alpha, 1, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec3.x(), vec3.y(), vec3.z(), r, g, b, alpha, 0, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec4.x(), vec4.y(), vec4.z(), r, g, b, alpha, 0, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); + builder.addVertex(vec1.x(), vec1.y(), vec1.z()).setColor(r, g, b, alpha).setUv(1, (float) v1); + builder.addVertex(vec2.x(), vec2.y(), vec2.z()).setColor(r, g, b, alpha).setUv(1, (float) v2); + builder.addVertex(vec3.x(), vec3.y(), vec3.z()).setColor(r, g, b, alpha).setUv(0, (float) v2); + builder.addVertex(vec4.x(), vec4.y(), vec4.z()).setColor(r, g, b, alpha).setUv(0, (float) v1); } else { - builder.vertex(vec1.x(), vec1.y(), vec1.z(), r, g, b, alpha, 1, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec2.x(), vec2.y(), vec2.z(), r, g, b, alpha, 1, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec3.x(), vec3.y(), vec3.z(), r, g, b, alpha, 0, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec4.x(), vec4.y(), vec4.z(), r, g, b, alpha, 0, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); + builder.addVertex(vec1.x(), vec1.y(), vec1.z()).setColor(r, g, b, alpha).setUv(1, (float) v1); + builder.addVertex(vec2.x(), vec2.y(), vec2.z()).setColor(r, g, b, alpha).setUv(1, (float) v2); + builder.addVertex(vec3.x(), vec3.y(), vec3.z()).setColor(r, g, b, alpha).setUv(0, (float) v2); + builder.addVertex(vec4.x(), vec4.y(), vec4.z()).setColor(r, g, b, alpha).setUv(0, (float) v1); //Rendering a 2nd time to allow you to see both sides in multiplayer, shouldn't be necessary with culling disabled but here we are.... - builder.vertex(vec4.x(), vec4.y(), vec4.z(), r, g, b, alpha, 0, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec3.x(), vec3.y(), vec3.z(), r, g, b, alpha, 0, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec2.x(), vec2.y(), vec2.z(), r, g, b, alpha, 1, (float) v2, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); - builder.vertex(vec1.x(), vec1.y(), vec1.z(), r, g, b, alpha, 1, (float) v1, OverlayTexture.NO_OVERLAY, 15728880, vector3f.x(), vector3f.y(), vector3f.z()); + builder.addVertex(vec4.x(), vec4.y(), vec4.z()).setColor(r, g, b, alpha).setUv(0, (float) v1); + builder.addVertex(vec3.x(), vec3.y(), vec3.z()).setColor(r, g, b, alpha).setUv(0, (float) v2); + builder.addVertex(vec2.x(), vec2.y(), vec2.z()).setColor(r, g, b, alpha).setUv(1, (float) v2); + builder.addVertex(vec1.x(), vec1.y(), vec1.z()).setColor(r, g, b, alpha).setUv(1, (float) v1); } } } diff --git a/src/main/java/com/lothrazar/library/render/RenderResizableCuboid.java b/src/main/java/com/lothrazar/library/render/RenderResizableCuboid.java index 1a6efc6..dd8ccc2 100644 --- a/src/main/java/com/lothrazar/library/render/RenderResizableCuboid.java +++ b/src/main/java/com/lothrazar/library/render/RenderResizableCuboid.java @@ -129,6 +129,6 @@ private void renderPoint(Matrix4f matrix4f, VertexConsumer buffer, Direction fac Vector3f vertex = withValue(VEC_ZERO, u, xyz[uFinal]); vertex = withValue(vertex, v, xyz[vFinal]); vertex = withValue(vertex, face.getAxis(), other); - buffer.vertex(matrix4f, vertex.x(), vertex.y(), vertex.z()).color(red, green, blue, alpha).uv(uv[uFinal], uv[vFinal]).uv2(light).endVertex(); + buffer.addVertex(matrix4f, vertex.x(), vertex.y(), vertex.z()).setColor(red, green, blue, alpha).setUv(uv[uFinal], uv[vFinal]).setLight(light); } } diff --git a/src/main/java/com/lothrazar/library/render/type/FakeBlockRenderTypes.java b/src/main/java/com/lothrazar/library/render/type/FakeBlockRenderTypes.java index f9fb403..eaa52bb 100644 --- a/src/main/java/com/lothrazar/library/render/type/FakeBlockRenderTypes.java +++ b/src/main/java/com/lothrazar/library/render/type/FakeBlockRenderTypes.java @@ -2,8 +2,12 @@ import java.util.OptionalDouble; import com.lothrazar.library.FutureLibMod; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; @@ -22,11 +26,21 @@ public FakeBlockRenderTypes(String nameIn, VertexFormat formatIn, VertexFormat.M super(nameIn, formatIn, drawModeIn, bufferSizeIn, useDelegateIn, needsSortingIn, setupTaskIn, clearTaskIn); } - public final static ResourceLocation BEAM = new ResourceLocation(FutureLibMod.MODID, "textures/effect/beam.png"); + // ADDITIVE_TRANSPARENCY was removed from RenderStateShard in 1.21.1; define it locally + private static final TransparencyStateShard ADDITIVE_TRANSPARENCY_SHARD = new TransparencyStateShard( + "additive_transparency", + () -> { + RenderSystem.enableBlend(); + RenderSystem.blendFunc(GlStateManager.SourceFactor.ONE, GlStateManager.DestFactor.ONE); + }, + RenderSystem::disableBlend); + + public final static ResourceLocation BEAM = ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "textures/effect/beam.png"); public static final RenderType LASER_MAIN_BEAM = create(FutureLibMod.MODID + ":mininglasermainbeam", - DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, BUFFERSIZE, CRUMBLING, SORT, + DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, BUFFERSIZE, CRUMBLING, SORT, RenderType.CompositeState.builder() - .setTextureState(new TextureStateShard(BEAM, BLUR, MIPMAP)).setShaderState(ShaderStateShard.POSITION_COLOR_TEX_SHADER) + .setTextureState(new TextureStateShard(BEAM, BLUR, MIPMAP)) + .setShaderState(new RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexColorShader)) // was POSITION_COLOR_TEX_SHADER .setLayeringState(VIEW_OFFSET_Z_LAYERING) .setTransparencyState(TRANSLUCENT_TRANSPARENCY) .setDepthTestState(NO_DEPTH_TEST) @@ -36,16 +50,16 @@ public FakeBlockRenderTypes(String nameIn, VertexFormat formatIn, VertexFormat.M .createCompositeState(false)); /** * used by TESR that render blocks with textures Shape builder, ghostsoundmuffler, render light camo. - * + * */ public static final RenderType FAKE_BLOCK = create(FutureLibMod.MODID + ":fakeblock", DefaultVertexFormat.BLOCK, VertexFormat.Mode.QUADS, BUFFERSIZE, CRUMBLING, SORT, RenderType.CompositeState.builder() .setShaderState(RENDERTYPE_SOLID_SHADER) //1.17 was - BLOCK_SHADER - .setLayeringState(POLYGON_OFFSET_LAYERING) // VIEW_OFFSET_Z_LAYERING) // .setShadeModelState(SMOOTH_SHADE) + .setLayeringState(POLYGON_OFFSET_LAYERING) // VIEW_OFFSET_Z_LAYERING) .setLightmapState(NO_LIGHTMAP) .setTextureState(BLOCK_SHEET_MIPPED) - .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setTransparencyState(ADDITIVE_TRANSPARENCY_SHARD) .setDepthTestState(NO_DEPTH_TEST) .setCullState(CULL) .setWriteMaskState(COLOR_DEPTH_WRITE) @@ -59,7 +73,7 @@ public FakeBlockRenderTypes(String nameIn, VertexFormat formatIn, VertexFormat.M .setShaderState(RENDERTYPE_LINES_SHADER) .setLayeringState(VIEW_OFFSET_Z_LAYERING) .setOutputState(ITEM_ENTITY_TARGET) - .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setTransparencyState(ADDITIVE_TRANSPARENCY_SHARD) .setTextureState(NO_TEXTURE) .setDepthTestState(NO_DEPTH_TEST) .setCullState(CULL) @@ -68,8 +82,8 @@ public FakeBlockRenderTypes(String nameIn, VertexFormat formatIn, VertexFormat.M .createCompositeState(false)); /** * used by most blocks that select blocks such as cyclic:forester, cyclic:harvester, cyclic:miner in TESRs - * - * + * + * */ public static final RenderType SOLID_COLOUR = create(FutureLibMod.MODID + ":solidcolour", DefaultVertexFormat.POSITION_COLOR, VertexFormat.Mode.QUADS, BUFFERSIZE, CRUMBLING, SORT, @@ -77,7 +91,7 @@ public FakeBlockRenderTypes(String nameIn, VertexFormat formatIn, VertexFormat.M .setShaderState(RENDERTYPE_LINES_SHADER) .setLayeringState(VIEW_OFFSET_Z_LAYERING) .setOutputState(ITEM_ENTITY_TARGET) - .setTransparencyState(ADDITIVE_TRANSPARENCY) + .setTransparencyState(ADDITIVE_TRANSPARENCY_SHARD) .setTextureState(NO_TEXTURE) .setDepthTestState(NO_DEPTH_TEST) .setCullState(CULL) diff --git a/src/main/java/com/lothrazar/library/render/type/LaserRenderType.java b/src/main/java/com/lothrazar/library/render/type/LaserRenderType.java index 9226d1d..7d761bb 100644 --- a/src/main/java/com/lothrazar/library/render/type/LaserRenderType.java +++ b/src/main/java/com/lothrazar/library/render/type/LaserRenderType.java @@ -3,14 +3,19 @@ import com.lothrazar.library.FutureLibMod; import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; /** - * Citation/source/author - * - * - * https://github.com/Direwolf20-MC/MiningGadgets + * + * Old Forge 1.20 NeoForge 1.21 (GameRenderer Method or Constant) + * POSITION_COLOR_TEX_SHADER getPositionTexColorShader() + * POSITION_COLOR_SHADER getPositionColorShader() + * POSITION_TEX_SHADER getPositionTexShader() + * POSITION_SHADER getPositionShader() + * POSITION_COLOR_TEX POSITION_TEX_COLOR * */ public class LaserRenderType extends RenderType { @@ -19,13 +24,13 @@ public LaserRenderType(String nameIn, VertexFormat formatIn, VertexFormat.Mode d super(nameIn, formatIn, drawModeIn, bufferSizeIn, useDelegateIn, needsSortingIn, setupTaskIn, clearTaskIn); } - private final static ResourceLocation RL_LASER = new ResourceLocation(FutureLibMod.MODID, "textures/effect/laser.png"); - private final static ResourceLocation RL_BEAM = new ResourceLocation(FutureLibMod.MODID, "textures/effect/beam.png"); - private final static ResourceLocation RL_GLOW = new ResourceLocation(FutureLibMod.MODID, "textures/effect/glow.png"); + private final static ResourceLocation RL_LASER = ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "textures/effect/laser.png"); + private final static ResourceLocation RL_BEAM = ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "textures/effect/beam.png"); + private final static ResourceLocation RL_GLOW = ResourceLocation.fromNamespaceAndPath(FutureLibMod.MODID, "textures/effect/glow.png"); public static final RenderType LASER_MAIN_BEAM = create("MAIN_", - DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, false, false, + DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, 256, false, false, RenderType.CompositeState.builder().setTextureState(new TextureStateShard(RL_BEAM, false, false)) - .setShaderState(ShaderStateShard.POSITION_COLOR_TEX_SHADER) + .setShaderState(new RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexColorShader)) // was POSITION_COLOR_TEX_SHADER .setLayeringState(VIEW_OFFSET_Z_LAYERING) .setTransparencyState(TRANSLUCENT_TRANSPARENCY) .setDepthTestState(NO_DEPTH_TEST) @@ -34,9 +39,9 @@ public LaserRenderType(String nameIn, VertexFormat formatIn, VertexFormat.Mode d .setWriteMaskState(COLOR_WRITE) .createCompositeState(false)); public static final RenderType LASER_MAIN_ADDITIVE = create("MiningLaserAdditiveBeam", - DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, false, false, + DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, 256, false, false, RenderType.CompositeState.builder().setTextureState(new TextureStateShard(RL_GLOW, false, false)) - .setShaderState(ShaderStateShard.POSITION_COLOR_TEX_SHADER) + .setShaderState(new RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexColorShader)) // was POSITION_COLOR_TEX_SHADER .setLayeringState(VIEW_OFFSET_Z_LAYERING) .setTransparencyState(TRANSLUCENT_TRANSPARENCY) .setDepthTestState(NO_DEPTH_TEST) @@ -45,9 +50,9 @@ public LaserRenderType(String nameIn, VertexFormat formatIn, VertexFormat.Mode d .setWriteMaskState(COLOR_WRITE) .createCompositeState(false)); public static final RenderType LASER_MAIN_CORE = create("MiningLaserCoreBeam", - DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, false, false, + DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, 256, false, false, RenderType.CompositeState.builder().setTextureState(new TextureStateShard(RL_LASER, false, false)) - .setShaderState(ShaderStateShard.POSITION_COLOR_TEX_SHADER) + .setShaderState(new RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexColorShader))// was POSITION_COLOR_TEX_SHADER .setLayeringState(VIEW_OFFSET_Z_LAYERING) .setTransparencyState(TRANSLUCENT_TRANSPARENCY) .setDepthTestState(NO_DEPTH_TEST) diff --git a/src/main/java/com/lothrazar/library/render/type/OverlayRenderType.java b/src/main/java/com/lothrazar/library/render/type/OverlayRenderType.java index 5bcf8bc..c40b05b 100644 --- a/src/main/java/com/lothrazar/library/render/type/OverlayRenderType.java +++ b/src/main/java/com/lothrazar/library/render/type/OverlayRenderType.java @@ -2,6 +2,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat; import com.mojang.blaze3d.vertex.VertexFormat; +import net.minecraft.client.renderer.GameRenderer; import net.minecraft.client.renderer.RenderStateShard; import net.minecraft.client.renderer.RenderType; import net.minecraft.resources.ResourceLocation; @@ -34,10 +35,10 @@ public static RenderType overlayRenderer(String id, ResourceLocation resourceLoc RenderType.CompositeState state = RenderType.CompositeState.builder() .setTextureState(new RenderStateShard.TextureStateShard(resourceLocation, false, false)) .setCullState(RenderStateShard.NO_CULL) - .setShaderState(RenderStateShard.POSITION_COLOR_TEX_SHADER) + .setShaderState(new RenderStateShard.ShaderStateShard(GameRenderer::getPositionTexColorShader))// was POSITION_COLOR_TEX_SHADER .setTransparencyState(TRANSLUCENT_TRANSPARENCY) .setOutputState(RenderStateShard.TRANSLUCENT_TARGET) .createCompositeState(true); - return create(id, DefaultVertexFormat.POSITION_COLOR_TEX, VertexFormat.Mode.QUADS, 256, true, false, state); + return create(id, DefaultVertexFormat.POSITION_TEX_COLOR, VertexFormat.Mode.QUADS, 256, true, false, state); } } diff --git a/src/main/java/com/lothrazar/library/render/type/ParticleRenderTypes.java b/src/main/java/com/lothrazar/library/render/type/ParticleRenderTypes.java index 1a5211d..135c8e2 100644 --- a/src/main/java/com/lothrazar/library/render/type/ParticleRenderTypes.java +++ b/src/main/java/com/lothrazar/library/render/type/ParticleRenderTypes.java @@ -4,9 +4,9 @@ import com.mojang.blaze3d.platform.GlStateManager.SourceFactor; import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.vertex.BufferBuilder; -import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.MeshData; import com.mojang.blaze3d.vertex.Tesselator; -import com.mojang.blaze3d.vertex.VertexFormat; import net.minecraft.client.particle.ParticleRenderType; import net.minecraft.client.renderer.texture.TextureAtlas; import net.minecraft.client.renderer.texture.TextureManager; @@ -14,34 +14,46 @@ /** * https://github.com/Lothrazar/RootsClassic * + * In 1.21.1, the ParticleEngine calls Tesselator.begin(Mode, Format) BEFORE + * calling type.begin(buffer, textureManager), so begin() only sets up GL state. + * end() must call BufferUploader.drawWithShader(tessellator.end()) since + * Tesselator.end() now returns MeshData instead of uploading directly. + * + * see other Render Types in this library or build your own */ +@Deprecated public class ParticleRenderTypes { - public static final ParticleRenderType MAGIC_RENDER = new ParticleRenderType() { - - @SuppressWarnings("deprecation") - @Override - public void begin(BufferBuilder buffer, TextureManager textureManager) { - RenderSystem.enableBlend(); - RenderSystem.enableCull(); - RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); - RenderSystem.depthMask(false); - RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); - buffer.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.PARTICLE); - } - @Override - public void end(Tesselator tessellator) { - tessellator.end(); - RenderSystem.enableDepthTest(); - RenderSystem.depthMask(true); - RenderSystem.blendFunc(SourceFactor.SRC_ALPHA.value, DestFactor.ONE_MINUS_SRC_ALPHA.value); - RenderSystem.disableCull(); - } - @Override - public String toString() { - return "rootsclassic:magic"; - } - }; +// public static final ParticleRenderType MAGIC_RENDER = new ParticleRenderType() { +// +// @Override +// public void begin(BufferBuilder buffer, TextureManager textureManager) { +// RenderSystem.enableBlend(); +// RenderSystem.enableCull(); +// RenderSystem.setShaderTexture(0, TextureAtlas.LOCATION_PARTICLES); +// RenderSystem.depthMask(false); +// RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); +// // Note: do NOT call buffer.begin() here - the ParticleEngine already started +// // the buffer via Tesselator.begin(Mode, Format) before calling this method. +// } +// +// @Override +// public void end(Tesselator tessellator) { +// MeshData meshData = tessellator.end(); +// if (meshData != null) { +// BufferUploader.drawWithShader(meshData); +// } +// RenderSystem.enableDepthTest(); +// RenderSystem.depthMask(true); +// RenderSystem.blendFunc(SourceFactor.SRC_ALPHA, DestFactor.ONE_MINUS_SRC_ALPHA); +// RenderSystem.disableCull(); +// } +// +// @Override +// public String toString() { +// return "rootsclassic:magic"; +// } +// }; } diff --git a/src/main/java/com/lothrazar/library/util/AttributesUtil.java b/src/main/java/com/lothrazar/library/util/AttributesUtil.java index f1c4930..ea6072b 100644 --- a/src/main/java/com/lothrazar/library/util/AttributesUtil.java +++ b/src/main/java/com/lothrazar/library/util/AttributesUtil.java @@ -2,27 +2,29 @@ import java.util.Collection; import java.util.Random; -import java.util.UUID; -import com.lothrazar.library.FutureLibMod; +import net.minecraft.core.Holder; +import net.minecraft.resources.ResourceLocation; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeInstance; 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.minecraftforge.common.ForgeMod; + +import static com.lothrazar.library.FutureLibMod.MODID; public class AttributesUtil { static final Random RAND = new Random(); - public static final UUID DEFAULT_ID = UUID.fromString("06d30aa2-eff2-4a81-b92b-a1cb95f115c6"); - public static final UUID MULT_ID = UUID.fromString("c6d30aa2-eff2-4a81-b92b-a1cb95f115cd"); - public static final UUID ID_STEP_HEIGHT = UUID.fromString("66d30aa2-eaa2-4a81-b92b-a1cb95f115ca"); + // TODO: we should take id as input? instead of just hardcoding? + public static final ResourceLocation DEFAULT_ID = ResourceLocation.fromNamespaceAndPath(MODID, "default"); + public static final ResourceLocation MULT_ID = ResourceLocation.fromNamespaceAndPath(MODID, "multi"); + public static final ResourceLocation ID_STEP_HEIGHT = ResourceLocation.fromNamespaceAndPath(MODID, "step_height"); static final float VANILLA = 0.6F; // player.maxUpStep = 0.6F; // LivingEntity.class constructor defaults to this public static void disableStepHeight(Player player) { - AttributeInstance attr = player.getAttribute(ForgeMod.STEP_HEIGHT_ADDITION.get()); + AttributeInstance attr = player.getAttribute(Attributes.STEP_HEIGHT); attr.removeModifier(ID_STEP_HEIGHT); } @@ -36,46 +38,45 @@ public static void enableStepHeight(Player player) { newVal = 1.0F + (1F / 16F) - VANILLA; //PATH BLOCKS etc are 1/16th downif MY feature turns this on, then do it } // player.maxUpStep = newVal; // Deprecated - AttributeInstance attr = player.getAttribute(ForgeMod.STEP_HEIGHT_ADDITION.get()); + AttributeInstance attr = player.getAttribute(Attributes.STEP_HEIGHT); AttributeModifier oldModifier = attr.getModifier(AttributesUtil.ID_STEP_HEIGHT); - double old = oldModifier == null ? 0 : oldModifier.getAmount(); + double old = oldModifier == null ? 0 : oldModifier.amount(); if (newVal != old) { AttributesUtil.setStepHeightInternal(player, newVal); } } - private static void setStepHeightInternal(Player player, double newVal) { // player.maxUpStep = 0.6F; // LivingEntity.class constructor defaults to this - AttributeInstance attr = player.getAttribute(ForgeMod.STEP_HEIGHT_ADDITION.get()); + AttributeInstance attr = player.getAttribute(Attributes.STEP_HEIGHT); attr.removeModifier(ID_STEP_HEIGHT); if (newVal != 0) { - AttributeModifier healthModifier = new AttributeModifier(ID_STEP_HEIGHT, FutureLibMod.MODID, newVal, AttributeModifier.Operation.ADDITION); + AttributeModifier healthModifier = new AttributeModifier(ID_STEP_HEIGHT, newVal, AttributeModifier.Operation.ADD_VALUE); attr.addPermanentModifier(healthModifier); } } - public static int add(Attribute attribute, Collection players, int integer) { + public static int add(Holder attribute, Collection players, int integer) { for (ServerPlayer playerIn : players) { updateAttrModifierBy(attribute, DEFAULT_ID, playerIn, integer); } return 0; } - public static int addRandom(Attribute attribute, Collection players, int min, int max) { + public static int addRandom(Holder attribute, Collection players, int min, int max) { for (ServerPlayer playerIn : players) { updateAttrModifierBy(attribute, DEFAULT_ID, playerIn, RAND.nextInt(min, max)); } return 0; } - public static int multiply(Attribute attribute, Collection players, double integer) { + public static int multiply(Holder attribute, Collection players, double integer) { for (ServerPlayer playerIn : players) { multiplyAttrModifierBy(attribute, playerIn, integer); } return 0; } - public static int reset(Attribute attribute, Collection players) { + public static int reset(Holder attribute, Collection players) { for (ServerPlayer playerIn : players) { AttributeInstance attr = playerIn.getAttribute(attribute); attr.removeModifier(DEFAULT_ID); @@ -84,29 +85,30 @@ public static int reset(Attribute attribute, Collection players) { return 0; } - //ench - public static void removePlayerReach(UUID id, Player player) { - AttributeInstance attr = player.getAttribute(ForgeMod.BLOCK_REACH.get()); + // this is block reach not entity reach + public static void removePlayerReach(ResourceLocation id, Player player) { + + AttributeInstance attr = player.getAttribute(Attributes.BLOCK_INTERACTION_RANGE); attr.removeModifier(id); } - // ench - public static void setPlayerReach(UUID id, Player player, int reachBoost) { + // this is block reach not entity reach + public static void setPlayerReach(ResourceLocation id, Player player, int reachBoost) { removePlayerReach(id, player); - AttributeInstance attr = player.getAttribute(ForgeMod.BLOCK_REACH.get()); + AttributeInstance attr = player.getAttribute(Attributes.BLOCK_INTERACTION_RANGE); //vanilla is 5, so +11 it becomes 16 - AttributeModifier enchantment = new AttributeModifier(id, "ReachFLIB", reachBoost, AttributeModifier.Operation.ADDITION); + AttributeModifier enchantment = new AttributeModifier(id, reachBoost, AttributeModifier.Operation.ADD_VALUE); attr.addPermanentModifier(enchantment); } - public static void updateAttrModifierBy(Attribute attr, UUID id, Player playerIn, int value) { + public static void updateAttrModifierBy(Holder attr, ResourceLocation id, Player playerIn, int value) { AttributeInstance healthAttribute = playerIn.getAttribute(attr); AttributeModifier oldHealthModifier = healthAttribute.getModifier(id); //what is our value - double old = oldHealthModifier == null ? 0 : oldHealthModifier.getAmount(); + double old = oldHealthModifier == null ? 0 : oldHealthModifier.amount(); double newVal = value + old; healthAttribute.removeModifier(id); - AttributeModifier healthModifier = new AttributeModifier(id, "Bonus", newVal, AttributeModifier.Operation.ADDITION); + AttributeModifier healthModifier = new AttributeModifier(id, newVal, AttributeModifier.Operation.ADD_VALUE); healthAttribute.addPermanentModifier(healthModifier); if (attr == Attributes.MAX_HEALTH && playerIn.getHealth() > healthAttribute.getValue()) { @@ -114,11 +116,11 @@ public static void updateAttrModifierBy(Attribute attr, UUID id, Player playerIn } } - public static void multiplyAttrModifierBy(Attribute attr, Player playerIn, double value) { + public static void multiplyAttrModifierBy(Holder attr, Player playerIn, double value) { AttributeInstance healthAttribute = playerIn.getAttribute(attr); //what is our value healthAttribute.removeModifier(MULT_ID); - AttributeModifier healthModifier = new AttributeModifier(MULT_ID, "Bonus from Cyclic", value, AttributeModifier.Operation.MULTIPLY_BASE); + AttributeModifier healthModifier = new AttributeModifier(MULT_ID, value, AttributeModifier.Operation.ADD_MULTIPLIED_BASE); healthAttribute.addPermanentModifier(healthModifier); if (attr == Attributes.MAX_HEALTH && playerIn.getHealth() > healthAttribute.getValue()) { @@ -138,7 +140,7 @@ private static void setHearts(int finalHearts, ServerPlayer playerIn) { AttributeInstance healthAttribute = playerIn.getAttribute(Attributes.MAX_HEALTH); healthAttribute.removeModifier(DEFAULT_ID); //just remove and replace the modifier - AttributeModifier healthModifier = new AttributeModifier(DEFAULT_ID, "HP Bonus from Cyclic", (modifiedHearts * 2), AttributeModifier.Operation.ADDITION); + AttributeModifier healthModifier = new AttributeModifier(DEFAULT_ID, (modifiedHearts * 2), AttributeModifier.Operation.ADD_VALUE); healthAttribute.addPermanentModifier(healthModifier); if (playerIn.getHealth() > healthAttribute.getValue()) { playerIn.setHealth((float) healthAttribute.getValue()); diff --git a/src/main/java/com/lothrazar/library/util/AutoSprintUtil.java b/src/main/java/com/lothrazar/library/util/AutoSprintUtil.java index 81d3f32..c81a1f8 100644 --- a/src/main/java/com/lothrazar/library/util/AutoSprintUtil.java +++ b/src/main/java/com/lothrazar/library/util/AutoSprintUtil.java @@ -9,8 +9,8 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; @OnlyIn(Dist.CLIENT) public class AutoSprintUtil { diff --git a/src/main/java/com/lothrazar/library/util/BlockUtil.java b/src/main/java/com/lothrazar/library/util/BlockUtil.java index e13b4f6..5b183ae 100644 --- a/src/main/java/com/lothrazar/library/util/BlockUtil.java +++ b/src/main/java/com/lothrazar/library/util/BlockUtil.java @@ -23,7 +23,7 @@ public class BlockUtil { @SuppressWarnings("deprecation") public static Block.Properties wrap(Block.Properties propIn, Block blockIn) { return propIn - .sound(blockIn.getSoundType(blockIn.defaultBlockState())) + .sound(blockIn.soundType) .strength(blockIn.defaultBlockState().destroySpeed); } diff --git a/src/main/java/com/lothrazar/library/util/BlockstatesUtil.java b/src/main/java/com/lothrazar/library/util/BlockstatesUtil.java index 58f8423..3066538 100644 --- a/src/main/java/com/lothrazar/library/util/BlockstatesUtil.java +++ b/src/main/java/com/lothrazar/library/util/BlockstatesUtil.java @@ -9,12 +9,12 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; -import net.minecraftforge.common.Tags; +import net.neoforged.neoforge.common.Tags; public class BlockstatesUtil { public static boolean isGlass(BlockState blockIn) { - return blockIn.is(Tags.Blocks.GLASS) || blockIn.is(Tags.Blocks.GLASS_PANES); + return blockIn.is(Tags.Blocks.GLASS_BLOCKS) || blockIn.is(Tags.Blocks.GLASS_PANES); } public static Direction getFacingFromEntity(BlockPos clickedBlock, LivingEntity entity) { diff --git a/src/main/java/com/lothrazar/library/util/EnchantUtil.java b/src/main/java/com/lothrazar/library/util/EnchantUtil.java index 4a9f155..d7def2c 100644 --- a/src/main/java/com/lothrazar/library/util/EnchantUtil.java +++ b/src/main/java/com/lothrazar/library/util/EnchantUtil.java @@ -1,16 +1,15 @@ package com.lothrazar.library.util; import java.util.ArrayList; -import java.util.Collection; import java.util.List; -import net.minecraft.nbt.ListTag; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.effect.MobEffect; import net.minecraft.world.effect.MobEffectCategory; -import net.minecraft.world.item.EnchantedBookItem; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; -import net.minecraftforge.registries.ForgeRegistries; +import net.minecraft.world.item.enchantment.ItemEnchantments; public class EnchantUtil { @@ -31,9 +30,8 @@ public static List getAllEffects() { } public static List getEffects(MobEffectCategory effectType) { - Collection effects = ForgeRegistries.MOB_EFFECTS.getValues(); List effectsList = new ArrayList<>(); - for (MobEffect effect : effects) { + for (MobEffect effect : BuiltInRegistries.MOB_EFFECT) { if (effectType == null || effect.getCategory() == effectType) { effectsList.add(effect); } @@ -45,8 +43,8 @@ public static boolean doBookEnchantmentsMatch(ItemStack stack1, ItemStack stack2 Item item1 = stack1.getItem(); Item item2 = stack2.getItem(); if (item1 == Items.ENCHANTED_BOOK && item2 == Items.ENCHANTED_BOOK) { - ListTag ench1 = EnchantedBookItem.getEnchantments(stack1); - ListTag ench2 = EnchantedBookItem.getEnchantments(stack2); + ItemEnchantments ench1 = stack1.get(DataComponents.STORED_ENCHANTMENTS); + ItemEnchantments ench2 = stack2.get(DataComponents.STORED_ENCHANTMENTS); if (ench1 == null || ench2 == null) { return false; } diff --git a/src/main/java/com/lothrazar/library/util/EntityUtil.java b/src/main/java/com/lothrazar/library/util/EntityUtil.java index bfb988d..4e88f91 100644 --- a/src/main/java/com/lothrazar/library/util/EntityUtil.java +++ b/src/main/java/com/lothrazar/library/util/EntityUtil.java @@ -27,9 +27,9 @@ import java.util.List; import com.lothrazar.library.core.BlockPosDim; import com.lothrazar.library.core.Vector3; -import com.lothrazar.library.dim.DimensionTransit; -import com.lothrazar.library.mod.PacketRegistry; +import com.lothrazar.library.portal.DimensionTransitionWrapper; import com.lothrazar.library.packet.PacketPlayerFalldamage; +import net.neoforged.neoforge.network.PacketDistributor; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; @@ -51,7 +51,7 @@ import net.minecraft.world.level.Level; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.common.util.FakePlayer; +import net.neoforged.neoforge.common.util.FakePlayer; public class EntityUtil { @@ -350,7 +350,7 @@ public static void centerEntityHoriz(Entity entity, BlockPos pos) { public static List getVillagers(Level world, BlockPos p, int r) { BlockPos start = p.offset(-r, -r, -r); BlockPos end = p.offset(r, r, r); - return world.getEntitiesOfClass(Villager.class, new AABB(start, end)); + return world.getEntitiesOfClass(Villager.class, AABB.encapsulatingFullBlocks(start, end)); } public static LivingEntity getClosestEntity(Level world, Player player, List list) { @@ -449,11 +449,11 @@ public static void setCooldownItem(Player player, Item item, int cooldown) { } public static Attribute getAttributeJump(Horse ahorse) { - return Attributes.JUMP_STRENGTH; //was reflection lol + return Attributes.JUMP_STRENGTH.value(); } public static void eatingHorse(Horse ahorse) { - ahorse.eating(); // requires accesstransformer.cfg + ahorse.eating(); // requires accesstransformer.cfg } public static void tryMakeEntityClimb(Level worldIn, LivingEntity entity, double climbSpeed) { @@ -465,7 +465,7 @@ else if (entity.zza > 0.0F && entity.getDeltaMovement().y < climbSpeed) { entity.fallDistance = 0.0F; } //setting fall distance on clientside wont work if (worldIn.isClientSide && entity.tickCount % TICKS_FALLDIST_SYNC == 0) { - PacketRegistry.INSTANCE.sendToServer(new PacketPlayerFalldamage()); + PacketDistributor.sendToServer(new PacketPlayerFalldamage()); } } @@ -473,13 +473,13 @@ public static void dimensionTeleport(ServerPlayer player, ServerLevel world, Blo if (player instanceof FakePlayer) { return; } - if (!player.canChangeDimensions()) { + if (!player.canChangeDimensions(player.getCommandSenderWorld(), world)) { return; } if (!world.isClientSide) { - DimensionTransit transit = new DimensionTransit(world, loc); - transit.teleport(player); - player.changeDimension(transit.getTargetLevel(), transit); + DimensionTransitionWrapper transit = new DimensionTransitionWrapper(world, loc); + transit.applyPreTeleportEffects(player); + player.changeDimension(transit.buildTransition(player)); } } } diff --git a/src/main/java/com/lothrazar/library/util/FakePlayerUtil.java b/src/main/java/com/lothrazar/library/util/FakePlayerUtil.java index edb7b5a..244a622 100644 --- a/src/main/java/com/lothrazar/library/util/FakePlayerUtil.java +++ b/src/main/java/com/lothrazar/library/util/FakePlayerUtil.java @@ -39,11 +39,10 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; import net.minecraft.world.phys.BlockHitResult; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.common.util.FakePlayerFactory; -import net.minecraftforge.common.util.LazyOptional; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.items.ItemStackHandler; +import net.neoforged.neoforge.common.util.FakePlayer; +import net.neoforged.neoforge.common.util.FakePlayerFactory; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.ItemStackHandler; public class FakePlayerUtil { @@ -62,31 +61,27 @@ public static WeakReference initFakePlayer(ServerLevel ws, String bl return null; // trying to get around https://github.com/PrinceOfAmber/Cyclic/issues/113 } fakePlayer.get().setOnGround(true); - // fakePlayer.get().onGround = true; - fakePlayer.get().connection = new ServerGamePacketListenerImpl(ws.getServer(), new Connection(PacketFlow.SERVERBOUND), fakePlayer.get()) { - - @Override - public void send(Packet packetIn) {} - }; + // in neoforge 1.21.1 the connection should already be faked +// fakePlayer.get().connection = new ServerGamePacketListenerImpl(ws.getServer(), new Connection(PacketFlow.SERVERBOUND), fakePlayer.get()) { +// +// @Override +// public void send(Packet packetIn) {} +// }; fakePlayer.get().setSilent(true); return fakePlayer; } - public static void tryEquipItem(LazyOptional i, WeakReference fp, int slot, InteractionHand hand) { - if (fp == null) { + public static void tryEquipItem(IItemHandler inv, WeakReference fp, int slot, InteractionHand hand) { + if (fp == null || inv == null) { return; } - i.ifPresent(inv -> { - ItemStack maybeTool = inv.getStackInSlot(0); - if (!maybeTool.isEmpty()) { - if (maybeTool.getCount() <= 0) { - maybeTool = ItemStack.EMPTY; - } - } - if (!maybeTool.equals(fp.get().getItemInHand(hand))) { - fp.get().setItemInHand(hand, maybeTool); - } - }); + ItemStack maybeTool = inv.getStackInSlot(0); + if (!maybeTool.isEmpty() && maybeTool.getCount() <= 0) { + maybeTool = ItemStack.EMPTY; + } + if (!maybeTool.equals(fp.get().getItemInHand(hand))) { + fp.get().setItemInHand(hand, maybeTool); + } } public static InteractionResult interactUseOnBlock(WeakReference fakePlayer, diff --git a/src/main/java/com/lothrazar/library/util/ItemStackUtil.java b/src/main/java/com/lothrazar/library/util/ItemStackUtil.java index 3b35f26..e6381b1 100644 --- a/src/main/java/com/lothrazar/library/util/ItemStackUtil.java +++ b/src/main/java/com/lothrazar/library/util/ItemStackUtil.java @@ -1,24 +1,25 @@ package com.lothrazar.library.util; import java.util.List; +import net.minecraft.ChatFormatting; import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.RandomSource; import net.minecraft.world.Containers; import net.minecraft.world.InteractionHand; +import net.minecraft.world.entity.EquipmentSlot; 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.item.enchantment.EnchantmentHelper; +import net.minecraft.world.item.component.ItemLore; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.minecraftforge.items.IItemHandler; -import net.minecraftforge.registries.ForgeRegistries; +import net.neoforged.neoforge.items.IItemHandler; public class ItemStackUtil { @@ -38,24 +39,18 @@ public class ItemStackUtil { * @param color */ public static void addLoreToStack(ItemStack crafting, String lore, String color) { - CompoundTag displayTag = new CompoundTag(); - ListTag tagList = new ListTag(); if (color == null) { color = "gold"; } - String escaped = "{\"text\":\"" + lore + "\",\"color\":\"" + color + "\"}"; - tagList.add(StringTag.valueOf(escaped)); - displayTag.put(NBT_LORE, tagList); - crafting.getTag().put(NBT_DISPLAY, displayTag); + ChatFormatting fmt = ChatFormatting.getByName(color); + Component loreText = fmt != null + ? Component.literal(lore).withStyle(fmt) + : Component.literal(lore); + crafting.set(DataComponents.LORE, new ItemLore(List.of(loreText))); } - public static void applyRandomEnch(RandomSource random, ItemStack crafting) { - crafting = EnchantmentHelper.enchantItem(random, crafting, 1, false); - } - - public static void applyRandomEnch(RandomSource random, ItemStack crafting, int level, boolean allowTreasure) { - applyRandomEnch(random, crafting); - } + // NOTE: EnchantmentHelper.enchantItem signature changed in 1.21 - now requires HolderLookup.Provider. + // Call EnchantmentHelper.enchantItem(random, stack, level, registries, Optional.empty()) directly from your code. // private void merge(Map oldEnch, ItemStack crafting) { // Map newEnch = EnchantmentHelper.getEnchantments(crafting); // //anything in new thats also in old, merge it over @@ -91,7 +86,7 @@ public static int countEmptySlots(IItemHandler handler) { } public static ItemStack findItem(String id) { - Item head = ForgeRegistries.ITEMS.getValue(ResourceLocation.tryParse(id)); + Item head = BuiltInRegistries.ITEM.getOptional(ResourceLocation.tryParse(id)).orElse(null); if (head != null) { return new ItemStack(head); } @@ -128,9 +123,11 @@ public static void damageItem(LivingEntity player, ItemStack stack, InteractionH stack.setDamageValue(stack.getDamageValue() + 1); } else { - stack.hurtAndBreak(1, player, (p) -> { - p.broadcastBreakEvent(InteractionHand.MAIN_HAND); - }); + final Item item = stack.getItem(); + stack.hurtAndBreak(1, player, EquipmentSlot.MAINHAND); +// (p) -> { +// p.broadcastBreakEvent(EquipmentSlot.MAINHAND); +// }); } if (stack.getDamageValue() >= stack.getMaxDamage()) { stack.shrink(1); @@ -158,8 +155,7 @@ public static void drop(Level world, BlockPos pos, ItemStack drop) { public static boolean matches(ItemStack current, ItemStack in) { //first one fails if size is off - return ItemStack.matches(current, in) - && ItemStack.isSameItemSameTags(current, in); + return ItemStack.isSameItemSameComponents(current, in); } public static void shrink(Player player, ItemStack stac) { @@ -194,7 +190,7 @@ public static void dropItemStackMotionless(Level world, BlockPos pos, ItemStack */ public static void deleteTag(ItemStack itemstack) { int dmg = itemstack.getDamageValue(); - itemstack.setTag(null); + itemstack.remove(DataComponents.CUSTOM_DATA); itemstack.setDamageValue(dmg); } @@ -210,4 +206,12 @@ public static void randomlyRepair(RandomSource rnd, ItemStack stack, int factor) stack.setDamageValue(stack.getDamageValue() - 1); } } + + /** + * true if item is edible. replaces old item.isEdible(). based on FoodProperties + * @return + */ + public static boolean isEdible(ItemStack s) { + return (s.getItem().getFoodProperties(s,null) != null); + } } diff --git a/src/main/java/com/lothrazar/library/util/LevelWorldUtil.java b/src/main/java/com/lothrazar/library/util/LevelWorldUtil.java index a290fe1..f3ca298 100644 --- a/src/main/java/com/lothrazar/library/util/LevelWorldUtil.java +++ b/src/main/java/com/lothrazar/library/util/LevelWorldUtil.java @@ -42,7 +42,7 @@ public static boolean removeFlowingLiquid(Level world, BlockPos pos, boolean nuk if (blockHere.getBlock() instanceof BucketPickup) { BucketPickup block = (BucketPickup) blockHere.getBlock(); // - ItemStack res = block.pickupBlock(world, pos, blockHere); + ItemStack res = block.pickupBlock(null, world, pos, blockHere); if (!res.isEmpty()) { // flowing block return world.setBlock(pos, Blocks.AIR.defaultBlockState(), 18); @@ -61,7 +61,7 @@ else if (nukeOption) { public static String dimensionToString(Level world) { //example: returns "minecraft:overworld" resource location return world.dimension().location().toString(); - //RegistryKey.create(Registry.WORLD_KEY, new ResourceLocation("twilightforest", "twilightforest")); + //RegistryKey.create(Registry.WORLD_KEY, ResourceLocation.fromNamespaceAndPath("twilightforest", "twilightforest")); } public static ResourceKey stringToDimension(String key) { diff --git a/src/main/java/com/lothrazar/library/util/PacketUtil.java b/src/main/java/com/lothrazar/library/util/PacketUtil.java index 7a6c299..e1bb9c6 100644 --- a/src/main/java/com/lothrazar/library/util/PacketUtil.java +++ b/src/main/java/com/lothrazar/library/util/PacketUtil.java @@ -1,22 +1,29 @@ package com.lothrazar.library.util; import com.lothrazar.library.packet.PacketFlib; +import net.minecraft.network.protocol.common.custom.CustomPacketPayload; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.simple.SimpleChannel; +import net.neoforged.neoforge.network.PacketDistributor; public class PacketUtil { - public static void sendToAllClients(SimpleChannel instance, Level world, PacketFlib packet) { - if (world.isClientSide) { + public static void sendToAllClients(Level world, PacketFlib packet) { + if (world.isClientSide || !(packet instanceof CustomPacketPayload payload)) { return; } for (Player player : world.players()) { if (player instanceof ServerPlayer sp) { - instance.sendTo(packet, sp.connection.connection, NetworkDirection.PLAY_TO_CLIENT); + PacketDistributor.sendToPlayer(sp, payload); } } } + + /** + * Send a packet to a specific player. + */ + public static void sendToPlayer(ServerPlayer player, CustomPacketPayload packet) { + PacketDistributor.sendToPlayer(player, packet); + } } diff --git a/src/main/java/com/lothrazar/library/util/ParticleUtil.java b/src/main/java/com/lothrazar/library/util/ParticleUtil.java index 8651a66..edaafb6 100644 --- a/src/main/java/com/lothrazar/library/util/ParticleUtil.java +++ b/src/main/java/com/lothrazar/library/util/ParticleUtil.java @@ -12,8 +12,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; public class ParticleUtil { diff --git a/src/main/java/com/lothrazar/library/util/PlayerUtil.java b/src/main/java/com/lothrazar/library/util/PlayerUtil.java index 42ff22c..d55d277 100644 --- a/src/main/java/com/lothrazar/library/util/PlayerUtil.java +++ b/src/main/java/com/lothrazar/library/util/PlayerUtil.java @@ -1,9 +1,8 @@ package com.lothrazar.library.util; import java.util.Optional; -import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.level.portal.DimensionTransition; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; @@ -120,12 +119,21 @@ public static Item getItemArmorSlot(Player player, EquipmentSlot slot) { return item; } + /** + * Teleport player to a specific location in a different dimension + * + * Also see EndPortalBlock.java getPortalDestination + * and PlayerList.java respawn + * + * + * @param player + * @return optional vec3 respawn position + */ public static Optional getPlayerHome(ServerPlayer player) { - BlockPos respawnPos = player.getRespawnPosition(); - Optional optional = Optional.empty(); - if (respawnPos != null) { - optional = Player.findRespawnPositionAndUseSpawnBlock((ServerLevel) player.level(), respawnPos, 0.0F, true, true); + if (player.getRespawnPosition() == null) { // TODO: is this redundant? player method has its own null check + return Optional.empty(); } - return optional; + DimensionTransition dt = player.findRespawnPositionAndUseSpawnBlock(false, DimensionTransition.DO_NOTHING); + return Optional.of(dt.pos()); } } diff --git a/src/main/java/com/lothrazar/library/util/RecipeUtil.java b/src/main/java/com/lothrazar/library/util/RecipeUtil.java index d7ad7d2..5309365 100644 --- a/src/main/java/com/lothrazar/library/util/RecipeUtil.java +++ b/src/main/java/com/lothrazar/library/util/RecipeUtil.java @@ -3,15 +3,16 @@ import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.lothrazar.library.recipe.ingredient.FluidTagIngredient; +import com.mojang.serialization.JsonOps; import net.minecraft.core.NonNullList; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.FluidTags; import net.minecraft.tags.TagKey; import net.minecraft.util.GsonHelper; import net.minecraft.world.item.crafting.Ingredient; import net.minecraft.world.level.material.Fluid; -import net.minecraftforge.fluids.FluidStack; -import net.minecraftforge.registries.ForgeRegistries; +import net.neoforged.neoforge.fluids.FluidStack; public class RecipeUtil { @@ -25,7 +26,7 @@ public static boolean matchFluid(FluidStack tileFluid, FluidTagIngredient ing) { //either recipe has no fluid or didnt match, try for tag if (ing.hasTag()) { //see /data//tags/fluids/ - TagKey ft = FluidTags.create(new ResourceLocation(ing.getTag())); + TagKey ft = FluidTags.create(ResourceLocation.parse(ing.getTag())); if (FluidHelpersUtil.matches(tileFluid.getFluid(), ft)) { return true; } @@ -42,8 +43,8 @@ public static FluidTagIngredient parseFluid(JsonObject json, String key) { FluidStack fluidstack = FluidStack.EMPTY; if (mix.has("fluid")) { String fluidId = mix.get("fluid").getAsString(); // JSONUtils.getString(mix, "fluid"); - ResourceLocation resourceLocation = new ResourceLocation(fluidId); - Fluid fluid = ForgeRegistries.FLUIDS.getValue(resourceLocation); + ResourceLocation resourceLocation = ResourceLocation.parse(fluidId); + Fluid fluid = BuiltInRegistries.FLUID.getOptional(resourceLocation).orElse(null); fluidstack = (fluid == null) ? FluidStack.EMPTY : new FluidStack(fluid, count); } String ftag = mix.has("tag") ? mix.get("tag").getAsString() : ""; @@ -54,7 +55,7 @@ public static NonNullList getIngredientsArray(JsonObject obj) { JsonArray array = GsonHelper.getAsJsonArray(obj, "ingredients"); NonNullList nonnulllist = NonNullList.create(); for (int i = 0; i < array.size(); ++i) { - Ingredient ingredient = Ingredient.fromJson(array.get(i)); + Ingredient ingredient = Ingredient.CODEC.parse(JsonOps.INSTANCE, array.get(i)).result().orElse(Ingredient.EMPTY); if (!ingredient.isEmpty()) { nonnulllist.add(ingredient); } @@ -67,8 +68,8 @@ public static FluidStack getFluid(JsonObject fluidJson) { // String fluidTag = fluidJson.get("fluidTag").getAsString(); } String fluidId = GsonHelper.getAsString(fluidJson, "fluid"); - ResourceLocation resourceLocation = new ResourceLocation(fluidId); - Fluid fluid = ForgeRegistries.FLUIDS.getValue(resourceLocation); + ResourceLocation resourceLocation = ResourceLocation.parse(fluidId); + Fluid fluid = BuiltInRegistries.FLUID.getOptional(resourceLocation).orElse(null); int count = fluidJson.get("count").getAsInt(); if (count < 1) { count = 1; diff --git a/src/main/java/com/lothrazar/library/util/RenderBlockUtils.java b/src/main/java/com/lothrazar/library/util/RenderBlockUtils.java index 4f5054d..6e6762e 100644 --- a/src/main/java/com/lothrazar/library/util/RenderBlockUtils.java +++ b/src/main/java/com/lothrazar/library/util/RenderBlockUtils.java @@ -15,7 +15,7 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.color.block.BlockColors; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.client.renderer.GameRenderer; + import net.minecraft.client.renderer.LightTexture; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.block.BlockRenderDispatcher; @@ -32,9 +32,9 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.client.event.RenderLevelStageEvent; -import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions; -import net.minecraftforge.fluids.FluidStack; +import net.neoforged.neoforge.client.event.RenderLevelStageEvent; +import net.neoforged.neoforge.client.extensions.common.IClientFluidTypeExtensions; +import net.neoforged.neoforge.fluids.FluidStack; /** * legacy ref https://www.minecraftforge.net/forum/topic/79556-1151-rendering-block-manually-clientside/?tab=comments#comment-379808 @@ -49,35 +49,35 @@ public static void renderCube(Matrix4f matrix, VertexConsumer builder, BlockPos float red = color.getRed() / 255f, green = color.getGreen() / 255f, blue = color.getBlue() / 255f; float startX = 0, startY = 0, startZ = -1, endX = 1, endY = 1, endZ = 0; //down - builder.vertex(matrix, startX, startY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, startY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, startY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, startY, endZ).color(red, green, blue, alpha).endVertex(); + builder.addVertex(matrix,startX, startY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, startY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, startY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, startY, endZ).setColor(red, green, blue, alpha); //up - builder.vertex(matrix, startX, endY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, endY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, endY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, endY, startZ).color(red, green, blue, alpha).endVertex(); + builder.addVertex(matrix,startX, endY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, endY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, endY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, endY, startZ).setColor(red, green, blue, alpha); //east - builder.vertex(matrix, startX, startY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, endY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, endY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, startY, startZ).color(red, green, blue, alpha).endVertex(); + builder.addVertex(matrix,startX, startY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, endY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, endY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, startY, startZ).setColor(red, green, blue, alpha); //west - builder.vertex(matrix, startX, startY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, startY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, endY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, endY, endZ).color(red, green, blue, alpha).endVertex(); + builder.addVertex(matrix,startX, startY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, startY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, endY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, endY, endZ).setColor(red, green, blue, alpha); //south - builder.vertex(matrix, endX, startY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, endY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, endY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, endX, startY, endZ).color(red, green, blue, alpha).endVertex(); + builder.addVertex(matrix,endX, startY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, endY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, endY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,endX, startY, endZ).setColor(red, green, blue, alpha); //north - builder.vertex(matrix, startX, startY, startZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, startY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, endY, endZ).color(red, green, blue, alpha).endVertex(); - builder.vertex(matrix, startX, endY, startZ).color(red, green, blue, alpha).endVertex(); + builder.addVertex(matrix,startX, startY, startZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, startY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, endY, endZ).setColor(red, green, blue, alpha); + builder.addVertex(matrix,startX, endY, startZ).setColor(red, green, blue, alpha); } /** @@ -190,7 +190,7 @@ public static void renderAsBlock(Level level, final BlockPos centerPos, final Li */ public static void renderAsBlock(Level world, final BlockPos centerPos, final List shape, PoseStack matrix, BlockState renderBlockState, float alpha, float scale) { - RenderSystem.setShader(GameRenderer::getPositionTexShader); + // GameRenderer::getPositionTexShader removed in 1.21.1; shader is managed by the RenderType RenderSystem.setShaderTexture(0, InventoryMenu.BLOCK_ATLAS); Minecraft mc = Minecraft.getInstance(); @@ -339,30 +339,30 @@ public static void createBox(MultiBufferSource.BufferSource bufferSource, Vec3 c VertexConsumer vertexConsumer = bufferSource.getBuffer(FakeBlockRenderTypes.TOMB_LINES); poseStack.translate(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z); Matrix4f pose = poseStack.last().pose(); - vertexConsumer.vertex(pose, x, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); + vertexConsumer.addVertex(pose, x, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); bufferSource.endBatch(FakeBlockRenderTypes.TOMB_LINES); RenderSystem.enableDepthTest(); } diff --git a/src/main/java/com/lothrazar/library/util/RenderUtil.java b/src/main/java/com/lothrazar/library/util/RenderUtil.java index b0e4876..e0c77c2 100644 --- a/src/main/java/com/lothrazar/library/util/RenderUtil.java +++ b/src/main/java/com/lothrazar/library/util/RenderUtil.java @@ -11,8 +11,8 @@ import net.minecraft.client.renderer.RenderType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.api.distmarker.OnlyIn; public class RenderUtil { @@ -50,30 +50,30 @@ public static void createBox(MultiBufferSource.BufferSource bufferSource, PoseSt VertexConsumer vertexConsumer = bufferSource.getBuffer(renderType); poseStack.translate(-cameraPosition.x, -cameraPosition.y, -cameraPosition.z); Matrix4f pose = poseStack.last().pose(); - vertexConsumer.vertex(pose, x, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y + offset, z).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x + offset, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); - vertexConsumer.vertex(pose, x, y + offset, z + offset).color(color[0], color[1], color[2], 1.0F).endVertex(); + vertexConsumer.addVertex(pose, x, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y + offset, z).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x + offset, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y, z + offset).setColor(color[0], color[1], color[2], 1.0F); + vertexConsumer.addVertex(pose, x, y + offset, z + offset).setColor(color[0], color[1], color[2], 1.0F); bufferSource.endBatch(renderType); RenderSystem.enableDepthTest(); } diff --git a/src/main/java/com/lothrazar/library/util/SoundUtil.java b/src/main/java/com/lothrazar/library/util/SoundUtil.java index 4ee600d..a03c2cd 100644 --- a/src/main/java/com/lothrazar/library/util/SoundUtil.java +++ b/src/main/java/com/lothrazar/library/util/SoundUtil.java @@ -11,7 +11,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.level.Level; -import net.minecraftforge.registries.ForgeRegistries; +import net.minecraft.core.registries.BuiltInRegistries; public class SoundUtil { @@ -70,7 +70,7 @@ public static void playSoundFromServer(ServerLevel world, BlockPos pos, SoundEve } public static void playSoundFromServerById(ServerLevel world, BlockPos pos, String sid) { - SoundEvent sound = ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation(sid)); + SoundEvent sound = BuiltInRegistries.SOUND_EVENT.getOptional(ResourceLocation.parse(sid)).orElse(null); if (sound != null) { for (ServerPlayer sp : world.players()) { playSoundFromServer(sp, pos, sound, 1F, 1F); @@ -80,7 +80,7 @@ public static void playSoundFromServerById(ServerLevel world, BlockPos pos, Stri public static void playSoundById(Player player, String sid) { //do the thing - SoundEvent sound = ForgeRegistries.SOUND_EVENTS.getValue(new ResourceLocation(sid)); + SoundEvent sound = BuiltInRegistries.SOUND_EVENT.getOptional(ResourceLocation.parse(sid)).orElse(null); if (sound != null && player.level().isClientSide) { SoundUtil.playSound(player, sound); } diff --git a/src/main/java/com/lothrazar/library/util/StringParseUtil.java b/src/main/java/com/lothrazar/library/util/StringParseUtil.java index 1385785..d3fed92 100644 --- a/src/main/java/com/lothrazar/library/util/StringParseUtil.java +++ b/src/main/java/com/lothrazar/library/util/StringParseUtil.java @@ -26,7 +26,7 @@ import java.util.List; import com.lothrazar.library.FutureLibMod; import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; public class StringParseUtil { @@ -37,7 +37,7 @@ public static boolean isInList(final List list, ResourceLocati public static String getFluidRatioName(IFluidHandler handler) { String ratio = handler.getFluidInTank(0).getAmount() + "/" + handler.getTankCapacity(0); if (!handler.getFluidInTank(0).isEmpty()) { - ratio += " " + handler.getFluidInTank(0).getDisplayName().getString(); + ratio += " " + handler.getFluidInTank(0).getHoverName().getString(); } return ratio; } diff --git a/src/main/java/com/lothrazar/library/util/TagDataUtil.java b/src/main/java/com/lothrazar/library/util/TagDataUtil.java index 3273703..209f65c 100644 --- a/src/main/java/com/lothrazar/library/util/TagDataUtil.java +++ b/src/main/java/com/lothrazar/library/util/TagDataUtil.java @@ -1,10 +1,12 @@ package com.lothrazar.library.util; import net.minecraft.core.BlockPos; +import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.CustomData; public class TagDataUtil { @@ -22,7 +24,7 @@ public static ItemStack buildNamedPlayerSkull(String displayNameString) { public static ItemStack buildSkullFromTag(CompoundTag player) { ItemStack skull = new ItemStack(Items.PLAYER_HEAD); - skull.setTag(player); + skull.set(DataComponents.CUSTOM_DATA, CustomData.of(player)); return skull; } @@ -42,10 +44,17 @@ public static void putBlockPos(CompoundTag tag, BlockPos pos) { } public static BlockPos getItemStackBlockPos(ItemStack item) { - if (item.isEmpty() || item.getTag() == null || !item.getTag().contains("xpos")) { + if (item.isEmpty()) { + return null; + } + CustomData data = item.get(DataComponents.CUSTOM_DATA); + if (data == null) { + return null; + } + CompoundTag tag = data.copyTag(); + if (!tag.contains("xpos")) { return null; } - CompoundTag tag = item.getOrCreateTag(); return getBlockPos(tag); } @@ -57,10 +66,12 @@ public static void setItemStackNBTVal(ItemStack item, String prop, int value) { if (item.isEmpty()) { return; } - item.getOrCreateTag().putInt(prop, value); + CompoundTag tag = item.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); + tag.putInt(prop, value); + item.set(DataComponents.CUSTOM_DATA, CustomData.of(tag)); } public static CompoundTag getItemStackNBT(ItemStack held) { - return held.getOrCreateTag(); + return held.getOrDefault(DataComponents.CUSTOM_DATA, CustomData.EMPTY).copyTag(); } } diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index e9374bf..a5693c2 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -35,7 +35,6 @@ public net.minecraft.world.entity.LivingEntity f_20922_ # ticksSinceLastSwing public net.minecraft.world.entity.player.Player f_36110_ # sleepCounter public net.minecraft.world.entity.LivingEntity m_21329_()V # updatingUsingItem -public net.minecraft.world.entity.animal.horse.AbstractHorse m_30610_()V # eating public net.minecraft.client.renderer.BlockEntityWithoutLevelRenderer f_108823_ # shieldModel @@ -48,5 +47,14 @@ public net.minecraft.world.entity.decoration.ArmorStand func_175413_k(Z)V # setS public net.minecraft.world.level.GameRules$BooleanValue m_46250_(Z)Lnet/minecraft/world/level/GameRules$Type; # create boolean gamerule public net.minecraft.server.network.ServerGamePacketListenerImpl f_9737_ # aboveGroundTickCount -public net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase f_60599_ # destroySpeed + +# neoforge does not use SRG name, just mojang names. TODO: fix or remove all above this line +public net.minecraft.server.network.ServerGamePacketListenerImpl aboveGroundTickCount + +public net.minecraft.world.entity.animal.horse.AbstractHorse eating()V # m_30610_ + +# net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase destroySpeed +public net.minecraft.world.level.block.state.BlockBehaviour$BlockStateBase destroySpeed # f_60599_ + +public net.minecraft.world.level.block.state.BlockBehaviour soundType diff --git a/src/main/resources/META-INF/mods.toml b/src/main/templates/META-INF/neoforge.mods.toml similarity index 52% rename from src/main/resources/META-INF/mods.toml rename to src/main/templates/META-INF/neoforge.mods.toml index 76c2e40..3cf5067 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/templates/META-INF/neoforge.mods.toml @@ -1,33 +1,34 @@ -# This is an example mods.toml file. It contains the data relating to the loading mods. +# 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 -license="MIT" -# A version range to match for said mod loader - for regular FML @Mod it will be the forge version -loaderVersion="[26,)" #mandatory (26 is current forge version) +license="${mod_license}" + +# 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 + # A URL to refer people to when problems occur with this mod -issueTrackerURL="https://github.com/Lothrazar/FLib/issues" #optional +issueTrackerURL="https://github.com/Lothrazar/${mod_id}/issues" #optional # A list of mods - how many allowed here is determined by the individual mod loader [[mods]] #mandatory # The modid of the mod -modId="flib" #mandatory +modId="${mod_id}" #mandatory # The version number of the mod - there's a few well known ${} variables useable here or just hardcode it version="${mod_version}" #mandatory # A display name for the mod - -displayName="flib" #mandatory + +displayName="${mod_name}" #mandatory # A URL to query for updates for this mod. See the JSON update specification -#updateJSONURL="https://raw.githubusercontent.com/Lothrazar/FLib/trunk/${mc_version}/update.json" #optional +# updateJSONURL="https://raw.githubusercontent.com/Lothrazar/${mod_id}/trunk/${minecraft_version}/update.json" #optional # A URL for the "homepage" for this mod, displayed in the mod UI # replace with your website -displayURL="https://www.curseforge.com/minecraft/mc-mods/flib" +displayURL="https://www.curseforge.com/minecraft/mc-mods/${curse_slug}" # A file name (in the root of the mod JAR) containing a logo for display logoFile="logoFile.png" #optional -# A text field displayed in the mod UI -credits="Lothrazar" #optional + # A text field displayed in the mod UI authors="${mod_authors}" #optional # The description text for the mod (multi line!) (#mandatory) @@ -35,19 +36,33 @@ authors="${mod_authors}" #optional 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" + +#[features.${mod_id}] +#openGLVersion="[3.2,)" + +# 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" + # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. -[[dependencies.flib]] - modId="forge" #mandatory +[[dependencies.${mod_id}]] #optional + # the modid of the dependency + modId="neoforge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified - mandatory=true - versionRange="[47.1,)" #mandatory, hardcoded + type="required" # was mandatory=true + # The version range of the dependency + versionRange="[${neo_version},)" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory ordering="NONE" # Side this dependency is applied on - BOTH, CLIENT or SERVER side="BOTH" -# Here's another dependency -[[dependencies.flib]] +[[dependencies.${mod_id}]] modId="minecraft" - mandatory=true - versionRange="[${mc_version},)" + type="required" # was mandatory=true + versionRange="[${minecraft_version},)" ordering="NONE" - side="BOTH" \ No newline at end of file + side="BOTH" diff --git a/update.json b/update.json index f024715..dd555f5 100644 --- a/update.json +++ b/update.json @@ -29,5 +29,8 @@ ,"0.0.13":"Updated to latest neoforge. Four PlayerUtil functions added; fix crash error with dependency CustomGameRules" ,"0.0.14":"Fix compatibility with old-forge v47.1.47+ (STEP_HEIGHT crash). " ,"0.0.15":"Add worldlycontainer interface sided support for io itemstack handler (interface used by mojang hoppers)" + }, + "1.21.1": { + "1.0.0": "Ported" } } \ No newline at end of file