diff --git a/build.gradle b/build.gradle index 3202ee3..2bd2892 100644 --- a/build.gradle +++ b/build.gradle @@ -1,24 +1,25 @@ +//file:noinspection GroovyAssignabilityCheck plugins { + id 'java' + id 'idea' id 'java-library' id 'maven-publish' - id 'net.neoforged.moddev' version '2.0.116' - id 'idea' + id 'com.github.johnrengelman.shadow' version '8.1.1' + id 'net.neoforged.moddev.legacyforge' version '2.0.103' +} + +java { + toolchain.languageVersion = JavaLanguageVersion.of(17) } tasks.named('wrapper', Wrapper).configure { - // Define wrapper values here so as to not have to always do so when updating gradlew.properties. - // Switching this to Wrapper.DistributionType.ALL will download the full gradle sources that comes with - // documentation attached on cursor hover of gradle classes and methods. However, this comes with increased - // file size for Gradle. If you do switch this to ALL, run the Gradle wrapper task twice afterwards. - // (Verify by checking gradle/wrapper/gradle-wrapper.properties to see if distributionUrl now points to `-all`) distributionType = Wrapper.DistributionType.BIN } -version = mod_version +version = "${minecraft_version}-${mod_version}" group = mod_group_id repositories { - // Add here additional repositories if required by some of the dependencies below. mavenLocal() maven { url = "https://libraries.minecraft.net/" } maven { url = "https://neoforged.forgecdn.net/releases" } @@ -37,31 +38,24 @@ base { archivesName = mod_id } -// Mojang ships Java 21 to end users in 1.21.10, so mods should target Java 21. -java.toolchain.languageVersion = JavaLanguageVersion.of(21) +// Mojang ships Java 17 to end users in 1.20.1, so mods should target Java 17. +java.toolchain.languageVersion = JavaLanguageVersion.of(17) -neoForge { - // Specify the version of NeoForge to use. - version = project.neo_version +legacyForge { + // Specify the version of MinecraftForge to use. + version = project.minecraft_version + '-' + project.forge_version parchment { mappingsVersion = project.parchment_mappings_version minecraftVersion = project.parchment_minecraft_version } - // This line is optional. Access Transformers are automatically detected - accessTransformers = project.files('src/main/templates/META-INF/accesstransformer.cfg') - // Default run configurations. - // These can be tweaked, removed, or duplicated as needed. runs { client { client() - - // Comma-separated list of namespaces to load gametests from. Empty = all namespaces. - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } - clientAuth{ devLogin = true client() @@ -70,47 +64,27 @@ neoForge { server { server() - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + programArgument '--nogui' + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } - // This run config launches GameTestServer and runs all registered gametests, then exits. - // By default, the server will crash when no gametests are provided. - // The gametest system is also enabled by default for other run configs under the /test command. gameTestServer { type = "gameTestServer" - systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id + systemProperty 'forge.enabledGameTestNamespaces', project.mod_id } data { - clientData() - - // example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it - // gameDirectory = project.file('run-data') - - // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + data() programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath() } - // applies to all the run configs above configureEach { - // Recommended logging data for a userdev environment - // The markers can be added/remove as needed separated by commas. - // "SCAN": For mods scan. - // "REGISTRIES": For firing of registry events. - // "REGISTRYDUMP": For getting the contents of all registries. systemProperty 'forge.logging.markers', 'REGISTRIES' - - // Recommended logging level for the console - // You can set various levels here. - // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels logLevel = org.slf4j.event.Level.DEBUG } } mods { - // define mod <-> source bindings - // these are used to tell the game which sources are for which mod - // multi mod projects should define one per mod "${mod_id}" { sourceSet(sourceSets.main) } @@ -120,86 +94,267 @@ neoForge { // Include resources generated by data generators. sourceSets.main.resources { srcDir 'src/generated/resources' } -// 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 } +obfuscation { + createRemappingConfiguration(configurations.localRuntime) +} dependencies { - // Example optional mod dependency with JEI - // The JEI API is declared for compile time use, while the full JEI artifact is used at runtime - // compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}" - // compileOnly "mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}" - // We add the full version to localRuntime, not runtimeOnly, so that we do not publish a dependency on it - // localRuntime "mezz.jei:jei-${mc_version}-neoforge:${jei_version}" + // 依赖项可以在这里添加 - // Example mod dependency using a mod jar from ./libs with a flat dir repository - // This maps to ./libs/coolmod-${mc_version}-${coolmod_version}.jar - // The group id is ignored when searching -- in this case, it is "blank" - // implementation "blank:coolmod-${mc_version}:${coolmod_version}" - - // Example mod dependency using a file as dependency - // implementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar") - - // Example project dependency using a sister or child project: - // implementation project(":myproject") - - // For more info: - // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html - // http://www.gradle.org/docs/current/userguide/dependency_management.html } // This block of code expands all declared replace properties in the specified resource targets. -// A missing property will result in an error. Properties are expanded using ${} Groovy notation. var generateModMetadata = tasks.register("generateModMetadata", ProcessResources) { var replaceProperties = [ - minecraft_version : minecraft_version, - minecraft_version_range: minecraft_version_range, - neo_version : neo_version, - mod_id : mod_id, - mod_name : mod_name, - mod_license : mod_license, - mod_version : mod_version, - mod_authors : mod_authors, - mod_credits : mod_credits, - mod_description : mod_description + minecraft_version : minecraft_version, + minecraft_version_range : minecraft_version_range, + forge_version : forge_version, + forge_version_range : forge_version_range, + loader_version_range : loader_version_range, + mod_id : mod_id, + mod_name : mod_name, + mod_license : mod_license, + mod_version : mod_version, + mod_authors : mod_authors, + mod_description : mod_description, + mod_credits : mod_credits ] + duplicatesStrategy = DuplicatesStrategy.EXCLUDE inputs.properties replaceProperties expand replaceProperties from "src/main/templates" into "build/generated/sources/modMetadata" } -// Include the output of "generateModMetadata" as an input directory for the build -// this works with both building through Gradle and the IDE. -sourceSets.main.resources.srcDir generateModMetadata -// To avoid having to run "generateModMetadata" manually, make it run on every project reload -neoForge.ideSyncTask generateModMetadata -// Example configuration to allow publishing using the maven-publish plugin +sourceSets.main.resources.srcDir generateModMetadata +legacyForge.ideSyncTask generateModMetadata + +// ==================== Javadoc 配置 ==================== +javadoc { + options { + encoding = 'UTF-8' + charSet = 'UTF-8' + author = true + version = true + windowTitle = "Lib39 ${project.mod_version} API" + docTitle = "Lib39 ${project.mod_version} API" + memberLevel = JavadocMemberLevel.PROTECTED + links = [ + 'https://docs.oracle.com/javase/8/docs/api/' + ] + addBooleanOption('Xdoclint:none', true) + addBooleanOption('html5', true) + } + + source = sourceSets.main.allJava + classpath = configurations.compileClasspath + exclude '**/test/**' + exclude '**/internal/**' +} + +tasks.register('javadocJar', Jar) { + archiveClassifier.set('javadoc') + from tasks.javadoc + dependsOn tasks.javadoc +} + +// ===================== 主包完整 Jar(class + java) ===================== +tasks.register('deobfJar', Jar) { + archiveFileName = "${mod_id}-${minecraft_version}-${mod_version}.jar" + from(sourceSets.main.output) + + // === 避免重复打包资源(即使混入其他 jar 时也不会重复) === + duplicatesStrategy = DuplicatesStrategy.EXCLUDE + + manifest { + attributes( + 'Specification-Title': mod_id, + 'Specification-Vendor': mod_authors, + 'Implementation-Title': project.name, + 'Implementation-Version': archiveVersion, + 'Implementation-Vendor': mod_authors, + 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ) + } + + dependsOn classes +} + + + + +// ==================== 发布配置 ==================== publishing { publications { - register('mavenJava', MavenPublication) { - from components.java + mavenJava(MavenPublication) { + artifactId = mod_id + artifact deobfJar + artifact javadocJar + + pom { + name = 'Lib39' + description = 'Lib39 is a general-purpose dependency library for Minecraft mods.' + url = 'https://github.com/3944Realms/lib39' + + properties = [ + 'minecraft.version': project.minecraft_version, + 'mod.version': project.mod_version, + 'forge.version': project.forge_version, + 'java.version': '17' + ] + + licenses { + license { + name = 'MIT' + url = 'https://raw.githubusercontent.com/3944Realms/lib39/refs/heads/main/LICENSE' + distribution = 'repo' + } + } + + developers { + developer { + id = 'R3944Realms' + name = "${mod_authors}" + email = 'f256198830@hotmail.com' + } + } + + scm { + connection = 'scm:git:https://github.com/3944Realms/lib39.git' + developerConnection = 'scm:git:ssh://git@github.com:3944Realms/lib39.git' + url = 'https://github.com/3944Realms/lib39' + tag = 'main' + } + + issueManagement { + system = 'GitHub' + url = 'https://github.com/3944Realms/lib39/issues' + } + } } } + repositories { + // 本地仓库 maven { - url "file://${project.projectDir}/repo" + name = 'local' + url = layout.buildDirectory.dir("repo") + } + + // Nexus 远程仓库 + maven { + name = 'LTDNexus' + url = 'https://nexus.bot.leisuretimedock.top/repository/maven-releases/' + credentials { + username = System.getenv('LTDNexusUsername') ?: '' + password = System.getenv('LTDNexusPassword') ?: '' + } } } } +// ==================== 任务配置 ==================== tasks.withType(JavaCompile).configureEach { - options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation + options.encoding = 'UTF-8' + options.compilerArgs += ['-Xlint:unchecked', '-Xlint:deprecation'] } -// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior. +// 配置 Javadoc JAR - 使用标准 javadoc 任务输出 +tasks.named('javadocJar') { + from javadoc.destinationDir +} +// ==================== 验证任务 ==================== +tasks.register('verifyNexusCredentials') { + doLast { + def username = System.getenv('LTDNexusUsername') + def password = System.getenv('LTDNexusPassword') + + // 安全地显示用户名和密码(只显示最后两位) + def displayUsername = username ? "***${username.length() > 2 ? username.substring(username.length() - 2) : '**'}" : 'NOT SET' + def displayPassword = password ? "***${password.length() > 2 ? password.substring(password.length() - 2) : '**'}" : 'NOT SET' + + println "Nexus Username: ${displayUsername}" + println "Nexus Password: ${displayPassword}" + + if (!username || !password) { + throw new GradleException('LTDNexusUsername or LTDNexusPassword environment variables are not set') + } + } +} + +tasks.register('checkPublicationContents') { + doLast { + def publication = publishing.publications.mavenJava + println "=== Publication Details ===" + println "Group: ${publication.groupId}" + println "Artifact: ${publication.artifactId}" + println "Version: ${publication.version}" + println "Artifacts:" + publication.artifacts.each { artifact -> + def file = artifact.file + def exists = file.exists() + println " - ${file.name} (${artifact.classifier ?: 'main'}) - Exists: ${exists}" + + if (!exists) { + throw new GradleException("Publication artifact missing: ${file.absolutePath}") + } + } + } +} + +// ==================== 任务依赖 ==================== +tasks.named('publishMavenJavaPublicationToLTDNexusRepository') { + dependsOn verifyNexusCredentials + dependsOn checkPublicationContents +} + +tasks.withType(PublishToMavenRepository) { + dependsOn assemble + dependsOn javadocJar +} + +// ==================== 便捷任务 ==================== +tasks.register('publishToNexus') { + group = 'publishing' + description = 'Publishes all publications to LTD Nexus' + dependsOn 'publishMavenJavaPublicationToLTDNexusRepository' +} + +tasks.register('publishLocal') { + group = 'publishing' + description = 'Publishes all publications to the local Maven repository' + dependsOn 'publishToMavenLocal' +} + +tasks.register('cleanRepo', Delete) { + delete layout.buildDirectory.dir("repo") +} + +tasks.named('clean') { + dependsOn cleanRepo +} + +// ==================== IDEA 配置 ==================== idea { module { downloadSources = true downloadJavadoc = true } } + +// 禁用模块元数据生成 +tasks.withType(GenerateModuleMetadata) { + enabled = false +} + +afterEvaluate { + tasks.named('deobfJar') { + doLast { + def jar = file(layout.buildDirectory.dir("repo") + "${mod_id}-${minecraft_version}-${mod_version}.jar") + if (jar.exists()) ant.delete(jar) + } + } +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index 43c58b4..f707d4d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,18 +7,22 @@ org.gradle.configuration-cache=false #read more on this at https://github.com/neoforged/ModDevGradle?tab=readme-ov-file#better-minecraft-parameter-names--javadoc-parchment # you can also find the latest versions at: https://parchmentmc.org/docs/getting-started -parchment_minecraft_version=1.21.10 -parchment_mappings_version=2025.10.12 +parchment_minecraft_version=1.20.1 +parchment_mappings_version=2023.09.03 # Environment Properties # You can find the latest versions here: https://files.minecraftforge.net/net/minecraftforge/forge/index_1.20.1.html # The Minecraft version must agree with the Forge version to get a valid artifact -minecraft_version=1.21.10 +minecraft_version=1.20.1 # The Minecraft version range can use any release version of Minecraft as bounds. # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # as they do not follow standard versioning conventions. -minecraft_version_range=[1.21.10] - -neo_version=21.10.42-beta +minecraft_version_range=[1.20.1, 1.21) +# The Forge version must agree with the Minecraft version to get a valid artifact +forge_version=47.1.3 +# The Forge version range can use any version of Forge as bounds +forge_version_range=[47.1.3,) +# The loader version range can only use the major version of FML as bounds +loader_version_range=[47,) ## Mod Properties # The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63} diff --git a/settings.gradle b/settings.gradle index 153968c..bcbdfe2 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,11 +1,12 @@ +//file:noinspection GroovyAssignabilityCheck pluginManagement { repositories { + mavenLocal() gradlePluginPortal() maven { url = 'https://maven.neoforged.net/releases' } - maven { url = 'https://maven.parchmentmc.org' } + maven { url = 'https://maven.parchmentmc.org' } // Add this line } } - plugins { id 'org.gradle.toolchains.foojay-resolver-convention' version '1.0.0' -} +} \ No newline at end of file diff --git a/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 b/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 new file mode 100644 index 0000000..6acc8d5 --- /dev/null +++ b/src/generated/resources/.cache/1de3d2ee724999f84a11b20b51c37030049be277 @@ -0,0 +1,2 @@ +// 1.20.1 2025-10-25T19:14:21.1829335 Languages: zh_tw +4cb94c651f6aa74538a2ab25cb183cffd75be688 assets/lib39/lang/zh_tw.json diff --git a/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac b/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac new file mode 100644 index 0000000..d291622 --- /dev/null +++ b/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac @@ -0,0 +1,2 @@ +// 1.20.1 2025-10-25T19:14:21.1764262 Languages: zh_cn +a1db601a0fca923c5434b8b0843773a3115d0b59 assets/lib39/lang/zh_cn.json diff --git a/src/generated/resources/.cache/2dbf84d84cf6f7b7a95fea9038e192dbf226e5f5 b/src/generated/resources/.cache/2dbf84d84cf6f7b7a95fea9038e192dbf226e5f5 new file mode 100644 index 0000000..c17c4ef --- /dev/null +++ b/src/generated/resources/.cache/2dbf84d84cf6f7b7a95fea9038e192dbf226e5f5 @@ -0,0 +1,3 @@ +// 1.20.1 2025-10-25T18:42:29.3405259 Item Models: lib39 +14f581c8f8e7f0de004c57a180f371e60e7b12ae assets/lib39/models/item/fabric.json +447b36747d0aa8748dcd86715f4cce2cff19aca7 assets/lib39/models/item/neoforge.json diff --git a/src/generated/resources/.cache/82018c5420b46ddbb7071e62df09fdecd98133e6 b/src/generated/resources/.cache/82018c5420b46ddbb7071e62df09fdecd98133e6 new file mode 100644 index 0000000..b518cbb --- /dev/null +++ b/src/generated/resources/.cache/82018c5420b46ddbb7071e62df09fdecd98133e6 @@ -0,0 +1,2 @@ +// 1.20.1 2025-10-25T19:14:21.1804258 Languages: lzh +098df025475d3f4d9d2abefa91a7d38c44644ba4 assets/lib39/lang/lzh.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 new file mode 100644 index 0000000..99da09b --- /dev/null +++ b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 @@ -0,0 +1,2 @@ +// 1.20.1 2025-10-25T19:14:21.1784269 Languages: en_us +c6b6aadca0a922823a8c949ebde93f8f999737f9 assets/lib39/lang/en_us.json diff --git a/src/main/java/top/r3944realms/lib39/Lib39.java b/src/main/java/top/r3944realms/lib39/Lib39.java index 2bd4fb8..e294953 100644 --- a/src/main/java/top/r3944realms/lib39/Lib39.java +++ b/src/main/java/top/r3944realms/lib39/Lib39.java @@ -1,12 +1,11 @@ package top.r3944realms.lib39; - -import net.neoforged.bus.api.IEventBus; -import net.neoforged.fml.ModList; -import net.neoforged.fml.common.Mod; -import net.neoforged.fml.loading.FMLEnvironment; +import net.minecraftforge.fml.ModList; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.loading.FMLEnvironment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import top.r3944realms.lib39.core.network.NetworkHandler; import top.r3944realms.lib39.example.Lib39Example; /** @@ -26,18 +25,19 @@ public class Lib39 { /** * Instantiates a new Lib 39. */ - public Lib39(IEventBus event) { - initialize(event); + public Lib39() { + initialize(); } /** * Initialize. */ - public static void initialize(IEventBus event) { + public static void initialize() { LOGGER.info("[Lib39] Initializing Lib39"); + NetworkHandler.register(); if (shouldRegisterExamples()) { LOGGER.info("[Lib39] Registering Examples"); - registerExamples(event); + registerExamples(); } LOGGER.info("[Lib39] Initialized Lib39"); @@ -66,17 +66,17 @@ public class Lib39 { * @return the boolean */ static boolean shouldRegisterExamples() { - return !FMLEnvironment.isProduction(); + return !FMLEnvironment.production; } /** * Register examples. */ - static void registerExamples(IEventBus event) { + static void registerExamples() { LOGGER.info("[Lib39] Starting example demonstrations"); try { // 创建示例实例并演示功能 - Lib39Example example = new Lib39Example(event); + Lib39Example example = new Lib39Example(); example.demonstrateFeature(); LOGGER.info("[Lib39] Example demonstrations completed successfully"); diff --git a/src/main/java/top/r3944realms/lib39/api/event/RegisterCompatEvent.java b/src/main/java/top/r3944realms/lib39/api/event/RegisterCompatEvent.java index 9cc1463..f34b815 100644 --- a/src/main/java/top/r3944realms/lib39/api/event/RegisterCompatEvent.java +++ b/src/main/java/top/r3944realms/lib39/api/event/RegisterCompatEvent.java @@ -1,8 +1,8 @@ package top.r3944realms.lib39.api.event; import net.minecraft.resources.ResourceLocation; -import net.neoforged.bus.api.Event; -import net.neoforged.fml.event.IModBusEvent; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; import top.r3944realms.lib39.core.compat.CompatManager; import top.r3944realms.lib39.core.compat.ICompat; diff --git a/src/main/java/top/r3944realms/lib39/api/event/SyncManagerRegisterEvent.java b/src/main/java/top/r3944realms/lib39/api/event/SyncManagerRegisterEvent.java index ebdf342..ebb61a4 100644 --- a/src/main/java/top/r3944realms/lib39/api/event/SyncManagerRegisterEvent.java +++ b/src/main/java/top/r3944realms/lib39/api/event/SyncManagerRegisterEvent.java @@ -2,7 +2,8 @@ package top.r3944realms.lib39.api.event; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; -import net.neoforged.bus.api.Event; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.eventbus.api.Event; import top.r3944realms.lib39.core.sync.ISyncData; import top.r3944realms.lib39.core.sync.ISyncManager; import top.r3944realms.lib39.core.sync.SyncData2Manager; @@ -38,6 +39,22 @@ public class SyncManagerRegisterEvent extends Event { return syncs2Manager; } + /** + * 类型安全的同步管理器注册 + * + * @param the type parameter + * @param the type parameter + * @param id the id + * @param syncManager the sync manager + * @param capability the capability + */ + public > void registerSyncManager( + ResourceLocation id, + ISyncManager syncManager, + Capability capability + ) { + syncs2Manager.registerManager(id, syncManager, entity -> entity.getCapability(capability).resolve()); + } /** * 类型安全的同步管理器注册 @@ -86,6 +103,16 @@ public class SyncManagerRegisterEvent extends Event { syncs2Manager.disallowEntityClass(id, entityClasses); } + /** + * 绑定能力(用于分离注册的情况) + * + * @param the type parameter + * @param id 必须先注册安全同步管理器,再绑定Cap,否则会抛出{@link IllegalStateException 未找到对应安全同步管理器} + * @param capability the capability + */ + public > void bindCapability(ResourceLocation id, Capability capability) { + syncs2Manager.bindDataGetter(id, entity -> entity.getCapability(capability).resolve()); + } /** * 解绑数据提供者 @@ -96,6 +123,27 @@ public class SyncManagerRegisterEvent extends Event { syncs2Manager.unbindDataProvider(id); } + /** + * 完整的类型安全注册 + * + * @param the type parameter + * @param the type parameter + * @param id the id + * @param syncManager the sync manager + * @param capability the capability + * @param allowedEntityClasses the allowed entity classes + */ + public > void registerComplete( + ResourceLocation id, + ISyncManager syncManager, + Capability capability, + Class... allowedEntityClasses + ) { + registerSyncManager(id, syncManager, capability); + if (allowedEntityClasses.length > 0) { + addAllowEntityClass(id, allowedEntityClasses); + } + } /** * 完整的类型安全注册 diff --git a/src/main/java/top/r3944realms/lib39/core/compat/CompatManager.java b/src/main/java/top/r3944realms/lib39/core/compat/CompatManager.java index 88def3e..6bede5d 100644 --- a/src/main/java/top/r3944realms/lib39/core/compat/CompatManager.java +++ b/src/main/java/top/r3944realms/lib39/core/compat/CompatManager.java @@ -1,8 +1,9 @@ package top.r3944realms.lib39.core.compat; import net.minecraft.resources.ResourceLocation; -import net.neoforged.api.distmarker.Dist; -import net.neoforged.bus.api.IEventBus; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.common.Mod; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import top.r3944realms.lib39.Lib39; @@ -57,7 +58,7 @@ public class CompatManager { * @param compat the compat */ public void registerCompat(String namespace, String path, ICompat compat) { - registerCompat(ResourceLocation.fromNamespaceAndPath(namespace, path), compat); + registerCompat(new ResourceLocation(namespace, path), compat); } /** @@ -66,8 +67,8 @@ public class CompatManager { * @param dists the dists * @param bus the bus */ - public void addListenerForAll(@Nullable Dist dists, boolean isModbus) { - listenerConfigs.add(new ListenerConfig(null, dists, isModbus)); + public void addListenerForAll(@Nullable Dist dists, Mod.EventBusSubscriber.Bus bus) { + listenerConfigs.add(new ListenerConfig(null, dists, bus)); } /** @@ -77,8 +78,8 @@ public class CompatManager { * @param dists the dists * @param bus the bus */ - public void addListenerForCompat(ResourceLocation compatId, @Nullable Dist dists, boolean isModbus) { - listenerConfigs.add(new ListenerConfig(compatId, dists, isModbus)); + public void addListenerForCompat(ResourceLocation compatId, @Nullable Dist dists, Mod.EventBusSubscriber.Bus bus) { + listenerConfigs.add(new ListenerConfig(compatId, dists, bus)); } /** @@ -88,8 +89,8 @@ public class CompatManager { * @param bus the bus * @param consumer the consumer */ - public void addListenerForLoaded(@Nullable Dist dists, boolean isModbus, Consumer consumer) { - listenerConfigs.add(new ListenerConfig(null, dists, isModbus) { + public void addListenerForLoaded(@Nullable Dist dists, Mod.EventBusSubscriber.Bus bus, Consumer consumer) { + listenerConfigs.add(new ListenerConfig(null, dists, bus) { @Override boolean shouldApply(@NotNull ICompat compat) { return super.shouldApply(compat); @@ -166,14 +167,14 @@ public class CompatManager { if (config.dists != null) { switch (config.dists) { case CLIENT -> { - if (!config.isModBus) { + if (config.bus == Mod.EventBusSubscriber.Bus.FORGE) { compat.addClientGameListener(gameEventBus); } else { compat.addClientModListener(modEventBus); } } case DEDICATED_SERVER -> { - if (!config.isModBus) { + if (config.bus == Mod.EventBusSubscriber.Bus.FORGE) { compat.addServerGameListener(gameEventBus); } else { compat.addServerModListener(modEventBus); @@ -182,7 +183,7 @@ public class CompatManager { } } else { // 通用监听器 - if (!config.isModBus) { + if (config.bus == Mod.EventBusSubscriber.Bus.FORGE) { compat.addCommonGameListener(gameEventBus); } else { compat.addCommonModListener(modEventBus); @@ -203,9 +204,9 @@ public class CompatManager { private @NotNull String getListenerTypeName(@NotNull ListenerConfig config) { if (config.dists != null) { return config.dists.name().toLowerCase() + " " + - (!config.isModBus ? "game" : "mod"); + (config.bus == Mod.EventBusSubscriber.Bus.FORGE ? "game" : "mod"); } else { - return "common " + (!config.isModBus ? "game" : "mod"); + return "common " + (config.bus == Mod.EventBusSubscriber.Bus.FORGE ? "game" : "mod"); } } @@ -216,8 +217,8 @@ public class CompatManager { * @param compatId the compat id * @param bus the bus */ - public void addListenerForCompat(ResourceLocation compatId, boolean isModbus) { - addListenerForCompat(compatId, null, isModbus); + public void addListenerForCompat(ResourceLocation compatId, Mod.EventBusSubscriber.Bus bus) { + addListenerForCompat(compatId, null, bus); } private static class ListenerConfig { @@ -232,7 +233,7 @@ public class CompatManager { /** * The Bus. */ - final boolean isModBus; + final Mod.EventBusSubscriber.Bus bus; /** * Instantiates a new Listener config. @@ -241,10 +242,10 @@ public class CompatManager { * @param dists the dists * @param bus the bus */ - ListenerConfig(ResourceLocation compatId, Dist dists, boolean isModbus) { + ListenerConfig(ResourceLocation compatId, Dist dists, Mod.EventBusSubscriber.Bus bus) { this.compatId = compatId; this.dists = dists; - this.isModBus = isModbus; + this.bus = bus; } /** diff --git a/src/main/java/top/r3944realms/lib39/core/compat/ICompat.java b/src/main/java/top/r3944realms/lib39/core/compat/ICompat.java index d53479a..467bfa6 100644 --- a/src/main/java/top/r3944realms/lib39/core/compat/ICompat.java +++ b/src/main/java/top/r3944realms/lib39/core/compat/ICompat.java @@ -1,7 +1,7 @@ package top.r3944realms.lib39.core.compat; import net.minecraft.resources.ResourceLocation; -import net.neoforged.bus.api.IEventBus; +import net.minecraftforge.eventbus.api.IEventBus; import java.util.concurrent.Callable; diff --git a/src/main/java/top/r3944realms/lib39/core/event/CommonEventHandler.java b/src/main/java/top/r3944realms/lib39/core/event/CommonEventHandler.java index eaa5662..a4951fa 100644 --- a/src/main/java/top/r3944realms/lib39/core/event/CommonEventHandler.java +++ b/src/main/java/top/r3944realms/lib39/core/event/CommonEventHandler.java @@ -7,24 +7,21 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Block; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.ModLoadingContext; -import net.neoforged.fml.common.EventBusSubscriber; -import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; -import net.neoforged.neoforge.common.NeoForge; -import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent; -import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent; -import net.neoforged.neoforge.event.entity.EntityLeaveLevelEvent; -import net.neoforged.neoforge.event.level.LevelEvent; -import net.neoforged.neoforge.event.tick.ServerTickEvent; -import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; -import net.neoforged.neoforge.registries.DeferredHolder; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.event.BuildCreativeModeTabContentsEvent; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.event.entity.EntityJoinLevelEvent; +import net.minecraftforge.event.entity.EntityLeaveLevelEvent; +import net.minecraftforge.event.level.LevelEvent; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.RegistryObject; import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.api.event.RegisterCompatEvent; import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent; import top.r3944realms.lib39.core.compat.CompatManager; -import top.r3944realms.lib39.core.network.NetworkHandler; import top.r3944realms.lib39.core.sync.ISyncData; import top.r3944realms.lib39.core.sync.SyncData2Manager; @@ -41,7 +38,7 @@ public class CommonEventHandler { * The type Game. */ @SuppressWarnings("unused") - @EventBusSubscriber(modid = Lib39.MOD_ID) + @net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Lib39.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE) public static class Game extends CommonEventHandler { private static ServerLevel sl; @@ -82,7 +79,7 @@ public class CommonEventHandler { synchronized (Game.class) { if (!isSync2MInitialized) { syncData2Manager = new SyncData2Manager(); - NeoForge.EVENT_BUS.post(new SyncManagerRegisterEvent(syncData2Manager)); + MinecraftForge.EVENT_BUS.post(new SyncManagerRegisterEvent(syncData2Manager)); isSync2MInitialized = true; sl = serverLevel; Lib39.LOGGER.info("SyncData2Manager initialized on world load"); @@ -110,11 +107,13 @@ public class CommonEventHandler { * @param event the event */ @SubscribeEvent - public static void onServerTick(ServerTickEvent.Post event) { - if (syncData2Manager == null) return; - if (event.getServer().getTickCount() % 10 == 0) - syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty))); - syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate))); + public static void onServerTick(TickEvent.ServerTickEvent event) { + if (event.phase == TickEvent.Phase.END) { + if (syncData2Manager == null) return; + if (event.getServer().getTickCount() % 10 == 0) + syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::markDirty))); + syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate))); + } } /** @@ -125,7 +124,7 @@ public class CommonEventHandler { @SubscribeEvent public static void onEntityJoinWorld(EntityJoinLevelEvent event) { Entity entity = event.getEntity(); - if (entity.level().isClientSide()) return; + if (entity.level().isClientSide) return; for (ResourceLocation id : syncData2Manager.getRegisteredKeys()) { if (syncData2Manager.isEntityClassAllowed(id, entity.getClass())) { @@ -142,7 +141,7 @@ public class CommonEventHandler { @SubscribeEvent public static void onEntityLeaveWorld(EntityLeaveLevelEvent event) { Entity entity = event.getEntity(); - if (entity.level().isClientSide()) return; + if (entity.level().isClientSide) return; for (ResourceLocation id : syncData2Manager.getRegisteredKeys()) { if (syncData2Manager.isEntityClassAllowed(id, entity.getClass())) { @@ -156,10 +155,10 @@ public class CommonEventHandler { * The type Mod. */ @SuppressWarnings("unused") - @EventBusSubscriber(modid = Lib39.MOD_ID) + @net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Lib39.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD) public static class Mod extends CommonEventHandler { - private static final Map, ResourceKey[]> itemAddMap = new ConcurrentHashMap<>(); - private static final Map, List>> tabToItemsMap = new ConcurrentHashMap<>(); + private static final Map, ResourceKey[]> itemAddMap = new ConcurrentHashMap<>(); + private static final Map, List>> tabToItemsMap = new ConcurrentHashMap<>(); /** * Gets compat manager. @@ -183,16 +182,12 @@ public class CommonEventHandler { @SubscribeEvent public static void onFMLCommonSetup (FMLCommonSetupEvent event) { event.enqueueWork(() -> { - IEventBus modBus = ModLoadingContext.get().getActiveContainer().getEventBus(); - IEventBus gameBus = NeoForge.EVENT_BUS; + IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + IEventBus gameBus = MinecraftForge.EVENT_BUS; compatManager = new CompatManager(modBus, gameBus); - gameBus.post(new RegisterCompatEvent(compatManager)); + MinecraftForge.EVENT_BUS.post(new RegisterCompatEvent(compatManager)); }); } - @SubscribeEvent - public static void onPacketRegister (RegisterPayloadHandlersEvent event) { - NetworkHandler.registerPackets(event); - } /** * Add item to tabs. @@ -201,7 +196,7 @@ public class CommonEventHandler { * @param tabs the tabs */ @SafeVarargs - public static void addItemToTabs(DeferredHolder item, ResourceKey... tabs) { + public static void addItemToTabs(RegistryObject item, ResourceKey... tabs) { itemAddMap.put(item, tabs); // 更新反向映射 @@ -217,9 +212,9 @@ public class CommonEventHandler { */ @SubscribeEvent public static void onBuildCreativeTabContents(BuildCreativeModeTabContentsEvent event) { - List> itemsForTab = tabToItemsMap.get(event.getTabKey()); + List> itemsForTab = tabToItemsMap.get(event.getTabKey()); if (itemsForTab != null) { - itemsForTab.forEach(i -> event.accept(i.get().asItem().getDefaultInstance(), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS)); + itemsForTab.forEach(event::accept); } } @@ -228,7 +223,7 @@ public class CommonEventHandler { * * @return the item add map */ - public static Map, ResourceKey[]> getItemAddMap() { + public static Map, ResourceKey[]> getItemAddMap() { return itemAddMap; } } diff --git a/src/main/java/top/r3944realms/lib39/core/network/NetworkHandler.java b/src/main/java/top/r3944realms/lib39/core/network/NetworkHandler.java index e73e194..78e13ad 100644 --- a/src/main/java/top/r3944realms/lib39/core/network/NetworkHandler.java +++ b/src/main/java/top/r3944realms/lib39/core/network/NetworkHandler.java @@ -1,17 +1,73 @@ package top.r3944realms.lib39.core.network; - -import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; -import net.neoforged.neoforge.network.registration.PayloadRegistrar; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkDirection; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.PacketDistributor; +import net.minecraftforge.network.simple.SimpleChannel; import org.jetbrains.annotations.NotNull; import top.r3944realms.lib39.Lib39; +import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPack; /** * The type Network handler. */ @SuppressWarnings("unused") public class NetworkHandler { - public static void registerPackets(@NotNull RegisterPayloadHandlersEvent event) { - PayloadRegistrar registrar = event.registrar(Lib39.MOD_ID + "-" + Lib39.ModInfo.VERSION); + private static int cid = 0; + /** + * The constant INSTANCE. + */ + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation(Lib39.MOD_ID, "main"), + () -> Lib39.ModInfo.VERSION, + Lib39.ModInfo.VERSION::equals, + Lib39.ModInfo.VERSION::equals + ); + + /** + * Register. + */ + public static void register() { + INSTANCE.messageBuilder(SyncNBTCapDataEntityS2CPack.class, cid++, NetworkDirection.PLAY_TO_CLIENT) + .encoder(SyncNBTCapDataEntityS2CPack::encode) + .decoder(SyncNBTCapDataEntityS2CPack::decode) + .consumerNetworkThread(SyncNBTCapDataEntityS2CPack::handle) + .add(); + } + + /** + * Send to player. + * + * @param the type parameter + * @param message the message + * @param player the player + */ + public static void sendToPlayer(MSG message, ServerPlayer player){ + INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message); + } + + /** + * Send to player. + * + * @param the type parameter + * @param the type parameter + * @param message the message + * @param entity the entity + * @param packetDistributor the packet distributor + */ + public static void sendToPlayer(MSG message, T entity, @NotNull PacketDistributor packetDistributor){ + INSTANCE.send(packetDistributor.with(() -> entity), message); + } + + /** + * Send to player. + * + * @param the type parameter + * @param message the message + */ + public static void sendToAllPlayer(MSG message){ + INSTANCE.send(PacketDistributor.ALL.noArg(), message); } } diff --git a/src/main/java/top/r3944realms/lib39/core/network/toClient/SyncNBTCapDataEntityS2CPack.java b/src/main/java/top/r3944realms/lib39/core/network/toClient/SyncNBTCapDataEntityS2CPack.java new file mode 100644 index 0000000..d841474 --- /dev/null +++ b/src/main/java/top/r3944realms/lib39/core/network/toClient/SyncNBTCapDataEntityS2CPack.java @@ -0,0 +1,94 @@ +package top.r3944realms.lib39.core.network.toClient; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.network.NetworkEvent; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import top.r3944realms.lib39.Lib39; +import top.r3944realms.lib39.core.event.CommonEventHandler; +import top.r3944realms.lib39.core.sync.ISyncData; +import top.r3944realms.lib39.core.sync.NBTEntitySyncData; +import top.r3944realms.lib39.core.sync.SyncData2Manager; + +import java.util.Optional; +import java.util.function.Supplier; + +/** + * The type Sync nbt data s 2 c pack. + */ +@SuppressWarnings("unused") +public record SyncNBTCapDataEntityS2CPack(int entityId, ResourceLocation id, CompoundTag data) { + + /** + * Instantiates a new Sync nbt data s 2 c pack. + * + * @param entityId the entity id + * @param id the id + * @param data the data + */ + public SyncNBTCapDataEntityS2CPack(int entityId, ResourceLocation id, @NotNull NBTEntitySyncData data) { + this(entityId, data.id(), data.serializeNBT()); + } + + /** + * Encode. + * + * @param msg the msg + * @param buffer the buffer + */ + public static void encode(@NotNull SyncNBTCapDataEntityS2CPack msg, @NotNull FriendlyByteBuf buffer) { + buffer.writeInt(msg.entityId); + buffer.writeResourceLocation(msg.id); + buffer.writeNbt(msg.data); + } + + /** + * Decode sync nbt data s 2 c pack. + * + * @param buffer the buffer + * @return the sync nbt data s 2 c pack + */ + @Contract("_ -> new") + public static @NotNull SyncNBTCapDataEntityS2CPack decode(@NotNull FriendlyByteBuf buffer) { + return new SyncNBTCapDataEntityS2CPack(buffer.readInt(), buffer.readResourceLocation(), buffer.readNbt()); + } + + /** + * Handle. + * + * @param msg the msg + * @param ctx the ctx + */ + public static void handle(SyncNBTCapDataEntityS2CPack msg, @NotNull Supplier ctx) { + NetworkEvent.Context context = ctx.get(); + context.enqueueWork(() -> { + ClientLevel level = Minecraft.getInstance().level; + if (level != null) { + Entity entity = level.getEntity(msg.entityId); + if (entity != null) { + Optional>> capability = + CommonEventHandler.Game + .getSyncData2Manager() + .getDataProvider(msg.id); + capability.flatMap(dataProvider -> dataProvider.getData(entity)) + .ifPresent(cap -> { + if (cap instanceof NBTEntitySyncData nbtCap) { + CompoundTag current = nbtCap.serializeNBT(); + if (!current.equals(msg.data)) { + nbtCap.deserializeNBT(msg.data); + } + } else Lib39.LOGGER.debug("Unhandled sync data: {}", msg.data); + } + ); + } + } + }); + context.setPacketHandled(true); + } + +} diff --git a/src/main/java/top/r3944realms/lib39/core/sync/NBTEntitySyncData.java b/src/main/java/top/r3944realms/lib39/core/sync/NBTEntitySyncData.java new file mode 100644 index 0000000..73f3470 --- /dev/null +++ b/src/main/java/top/r3944realms/lib39/core/sync/NBTEntitySyncData.java @@ -0,0 +1,59 @@ +package top.r3944realms.lib39.core.sync; + +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.common.util.INBTSerializable; +import org.jetbrains.annotations.NotNull; +import top.r3944realms.lib39.core.network.NetworkHandler; +import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPack; + +/** + * The type Nbt sync data. + */ +public abstract class NBTEntitySyncData implements IEntity, ISyncData, INBTSerializable { + /** + * The Dirty. + */ + protected boolean dirty; + /** + * The Id. + */ + protected final ResourceLocation id; + + /** + * Instantiates a new Nbt sync data. + * + * @param id the id + */ + protected NBTEntitySyncData(ResourceLocation id) { + this.id = id; + } + + @Override + public ResourceLocation id() { + return id; + } + + @Override + public boolean isDirty() { + return dirty; + } + + @Override + public void setDirty(boolean dirty) { + this.dirty = dirty; + } + + @Override + public void copyFrom(@NotNull NBTEntitySyncData src) { + this.dirty = src.isDirty(); + } + + @Override + public void checkIfDirtyThenUpdate() { + if (isDirty()) { + NetworkHandler.sendToAllPlayer(new SyncNBTCapDataEntityS2CPack(entityId(), id(), serializeNBT())); + } + dirty = false; + } +} diff --git a/src/main/java/top/r3944realms/lib39/core/sync/SyncData2CapManager.java b/src/main/java/top/r3944realms/lib39/core/sync/SyncData2CapManager.java new file mode 100644 index 0000000..71919d6 --- /dev/null +++ b/src/main/java/top/r3944realms/lib39/core/sync/SyncData2CapManager.java @@ -0,0 +1,390 @@ +package top.r3944realms.lib39.core.sync; + +import com.google.common.collect.Maps; +import com.google.common.collect.Sets; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.common.capabilities.Capability; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.*; +import java.util.function.BiConsumer; + +/** + * The type Sync data 2 manager. + */ +@SuppressWarnings("unused") +public class SyncData2CapManager { + private final Map> typedEntries = Maps.newConcurrentMap(); + + private static class TypedSyncEntry> { + /** + * The Manager. + */ + final ISyncManager manager; + /** + * The Capability. + */ + @Nullable + Capability capability; + /** + * The Allowed classes. + */ + final Set> allowedClasses; + + /** + * Instantiates a new Typed sync entry. + * + * @param manager the manager + * @param capability the capability + */ + TypedSyncEntry(ISyncManager manager, @Nullable Capability capability) { + this.manager = manager; + this.capability = capability; + this.allowedClasses = Sets.newConcurrentHashSet(); + } + } + + /** + * Register manager. + * + * @param the type parameter + * @param the type parameter + * @param key the key + * @param manager the manager + * @param capability the capability + */ + public > void registerManager( + ResourceLocation key, + ISyncManager manager, + Capability capability + ) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + Objects.requireNonNull(manager, "Sync manager cannot be null"); + Objects.requireNonNull(capability, "Capability cannot be null"); + + typedEntries.put(key, new TypedSyncEntry<>(manager, capability)); + } + + /** + * 向后兼容的注册方法(只注册管理器,不注册能力) + * + * @param key the key + * @param manager the manager + */ + @SuppressWarnings("unchecked") + public void registerManager(ResourceLocation key, ISyncManager> manager) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + Objects.requireNonNull(manager, "Sync manager cannot be null"); + + // 创建一个虚拟的 TypedSyncEntry,但 capability 为 null + // 注意:这种方法会限制类型安全的功能 + typedEntries.put(key, new TypedSyncEntry<>( + (ISyncManager>) manager, + null + )); + } + + /** + * Gets manager. + * + * @param the type parameter + * @param the type parameter + * @param key the key + * @return the manager + */ + @SuppressWarnings("unchecked") + public > Optional> getManager(ResourceLocation key) { + TypedSyncEntry entry = typedEntries.get(key); + return entry != null ? Optional.of((ISyncManager) entry.manager) : Optional.empty(); + } + + /** + * Gets capability. + * + * @param the type parameter + * @param key the key + * @return the capability + */ + @SuppressWarnings("unchecked") + public > Optional> getCapability(ResourceLocation key) { + TypedSyncEntry entry = typedEntries.get(key); + if (entry != null && entry.capability != null) { + return Optional.of((Capability) entry.capability); + } + return Optional.empty(); + } + + /** + * Allow entity class. + * + * @param key the key + * @param classes the classes + */ + public final void allowEntityClass(ResourceLocation key, Class... classes) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + Objects.requireNonNull(classes, "Classes array cannot be null"); + + if (classes.length == 0) { + return; + } + + TypedSyncEntry entry = typedEntries.get(key); + if (entry != null) { + entry.allowedClasses.addAll(Arrays.asList(classes)); + } + } + + /** + * 移除允许的实体类 + * + * @param key the key + * @param classes the classes + */ + public final void disallowEntityClass(ResourceLocation key, Class... classes) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + Objects.requireNonNull(classes, "Classes array cannot be null"); + + TypedSyncEntry entry = typedEntries.get(key); + if (entry != null && classes.length > 0) { + Arrays.asList(classes).forEach(entry.allowedClasses::remove); + + } + } + + /** + * 绑定能力(用于分离注册的情况) + * + * @param the type parameter + * @param key the key + * @param capability the capability + */ + public > void bindCapability(ResourceLocation key, Capability capability) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + Objects.requireNonNull(capability, "Capability cannot be null"); + + TypedSyncEntry entry = typedEntries.get(key); + if (entry != null) { + // 更新现有条目的能力 + updateCapabilityInEntry(key, entry, capability); + } else throw new IllegalArgumentException("No manager found for " + key); + } + + /** + * 解绑能力 + * + * @param key the key + */ + public void unbindCapability(ResourceLocation key) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + + TypedSyncEntry entry = typedEntries.get(key); + if (entry != null) { + // 将能力设置为null,但保留管理器和其他配置 + updateCapabilityInEntry(key, entry, null); + } + } + + /** + * 清除允许的实体类 + * + * @param key the key + */ + public void clearAllowedEntityClasses(ResourceLocation key) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + + TypedSyncEntry entry = typedEntries.get(key); + if (entry != null) { + entry.allowedClasses.clear(); + } + } + + /** + * Is entity class allowed boolean. + * + * @param key the key + * @param entityClass the entity class + * @return the boolean + */ + public boolean isEntityClassAllowed(ResourceLocation key, Class entityClass) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + Objects.requireNonNull(entityClass, "Entity class cannot be null"); + + TypedSyncEntry entry = typedEntries.get(key); + boolean isAllowed = false; + if (entry != null) { + for (Class allowedClass : entry.allowedClasses) { + if (entityClass.isAssignableFrom(allowedClass)) { + isAllowed = true; + break; + } + } + } + return entry != null && isAllowed ; + } + + /** + * Track entity for manager. + * + * @param entity the entity + * @param managerId the manager id + */ +// 类型安全的事件处理 + @SuppressWarnings("unchecked") + public void trackEntityForManager(Entity entity, ResourceLocation managerId) { + TypedSyncEntry entry = (TypedSyncEntry) typedEntries.get(managerId); + if (entry != null) { + trackEntityWithTypedEntry(entity, entry); + } + } + + private > void trackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry entry) { + if (entry.capability != null) { + entity.getCapability(entry.capability) + .ifPresent(cap -> entry.manager.track(entity.getUUID(), cap)); + } + } + + /** + * Untrack entity for manager. + * + * @param entity the entity + * @param managerId the manager id + */ +// 类型安全的事件处理 - 取消跟踪实体 + @SuppressWarnings("unchecked") + public void untrackEntityForManager(Entity entity, ResourceLocation managerId) { + TypedSyncEntry entry = (TypedSyncEntry) typedEntries.get(managerId); + if (entry != null) { + untrackEntityWithTypedEntry(entity, entry); + } + } + + private > void untrackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry entry) { + if (entry.capability != null) { + entity.getCapability(entry.capability) + .ifPresent(cap -> entry.manager.untrack(entity.getUUID(), cap)); + } + } + + /** + * 从所有管理器中移除实体跟踪 + * + * @param entity the entity + */ + public void untrackEntityFromAllManagers(Entity entity) { + for (ResourceLocation id : getRegisteredKeys()) { + if (isEntityClassAllowed(id, entity.getClass())) { + untrackEntityForManager(entity, id); + } + } + } + + /** + * 批量从管理器中移除实体跟踪 + * + * @param entities the entities + * @param managerId the manager id + */ + public void untrackEntitiesForManager(@NotNull Iterable entities, ResourceLocation managerId) { + for (Entity entity : entities) { + untrackEntityForManager(entity, managerId); + } + } + + /** + * 从所有管理器中批量移除实体跟踪 + * + * @param entities the entities + */ + public void untrackEntitiesFromAllManagers(@NotNull Iterable entities) { + for (Entity entity : entities) { + untrackEntityFromAllManagers(entity); + } + } + + /** + * 强制清理管理器中的所有跟踪数据 + * + * @param managerId the manager id + */ + public void clearAllTrackedData(ResourceLocation managerId) { + TypedSyncEntry entry = typedEntries.get(managerId); + if (entry != null) { + clearTrackedDataForEntry(entry); + } + } + + private > void clearTrackedDataForEntry(@NotNull TypedSyncEntry entry) { + // 获取当前跟踪的集合并清空 + Set syncSet = entry.manager.getSyncSet(); + if (syncSet != null) { + syncSet.clear(); + } + } + + /** + * 清理所有管理器的跟踪数据 + */ + public void clearAllTrackedData() { + for (ResourceLocation id : getRegisteredKeys()) { + clearAllTrackedData(id); + } + } + + // 辅助方法:更新条目的能力 + @SuppressWarnings("unchecked") + private > void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry entry, Capability newCapability) { + TypedSyncEntry typedEntry = (TypedSyncEntry) entry; + //重构了 TypedSyncEntry 使 capability 可变 + typedEntry.capability = newCapability; + typedEntries.computeIfPresent(id, (resourceLocation, typedSyncEntry) -> typedEntry); + } + + + /** + * Gets registered keys. + * + * @return the registered keys + */ + public Set getRegisteredKeys() { + return Collections.unmodifiableSet(typedEntries.keySet()); + } + + /** + * For each. + * + * @param consumer the consumer + */ + public void forEach(BiConsumer> consumer) { + Objects.requireNonNull(consumer, "Consumer cannot be null"); + typedEntries.forEach((key, entry) -> consumer.accept(key, entry.manager)); + } + + /** + * Gets manager count. + * + * @return the manager count + */ + public int getManagerCount() { + return typedEntries.size(); + } + + /** + * Clear all. + */ + public void clearAll() { + typedEntries.clear(); + } + + /** + * 移除管理器(包括所有相关配置) + * + * @param key the key + */ + public void removeManager(ResourceLocation key) { + Objects.requireNonNull(key, "ResourceLocation key cannot be null"); + typedEntries.remove(key); + } +} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/datagen/provider/SimpleLanguageProvider.java b/src/main/java/top/r3944realms/lib39/datagen/provider/SimpleLanguageProvider.java index 6d3e204..58da14b 100644 --- a/src/main/java/top/r3944realms/lib39/datagen/provider/SimpleLanguageProvider.java +++ b/src/main/java/top/r3944realms/lib39/datagen/provider/SimpleLanguageProvider.java @@ -1,7 +1,7 @@ package top.r3944realms.lib39.datagen.provider; import net.minecraft.data.PackOutput; -import net.neoforged.neoforge.common.data.LanguageProvider; +import net.minecraftforge.common.data.LanguageProvider; import org.jetbrains.annotations.NotNull; import top.r3944realms.lib39.datagen.value.ILangKeyValue; import top.r3944realms.lib39.datagen.value.ILangKeyValueCollection; diff --git a/src/main/java/top/r3944realms/lib39/datagen/value/IResourceKeyValue.java b/src/main/java/top/r3944realms/lib39/datagen/value/IResourceKeyValue.java deleted file mode 100644 index bc0449a..0000000 --- a/src/main/java/top/r3944realms/lib39/datagen/value/IResourceKeyValue.java +++ /dev/null @@ -1,8 +0,0 @@ -package top.r3944realms.lib39.datagen.value; - -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.item.Item; - -public interface IResourceKeyValue { - ResourceKey getResourceKey(); -} diff --git a/src/main/java/top/r3944realms/lib39/datagen/value/McLocale.java b/src/main/java/top/r3944realms/lib39/datagen/value/McLocale.java index 2d70a12..91cd9b6 100644 --- a/src/main/java/top/r3944realms/lib39/datagen/value/McLocale.java +++ b/src/main/java/top/r3944realms/lib39/datagen/value/McLocale.java @@ -21,7 +21,7 @@ public enum McLocale implements ILocaleEntry { /** * The Lzh. */ - LZH("lzh", Locale.of("lzh", "ZH")), + LZH("lzh", new Locale("lzh", "ZH")), /** * Ja jp mc locale. */ @@ -33,7 +33,7 @@ public enum McLocale implements ILocaleEntry { /** * The Ru ru. */ - RU_RU("ru_ru", Locale.of("ru", "RU")), + RU_RU("ru_ru", new Locale("ru", "RU")), /** * Fr fr mc locale. */ @@ -45,7 +45,7 @@ public enum McLocale implements ILocaleEntry { /** * The Es es. */ - ES_ES("es_es", Locale.of("es", "ES")); + ES_ES("es_es", new Locale("es", "ES")); private final String mcCode; private final Locale javaLocale; diff --git a/src/main/java/top/r3944realms/lib39/example/Lib39Example.java b/src/main/java/top/r3944realms/lib39/example/Lib39Example.java index 2434fee..78c6902 100644 --- a/src/main/java/top/r3944realms/lib39/example/Lib39Example.java +++ b/src/main/java/top/r3944realms/lib39/example/Lib39Example.java @@ -1,9 +1,10 @@ package top.r3944realms.lib39.example; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.common.NeoForge; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; import top.r3944realms.lib39.example.core.event.ExCommonEventHandler; -import top.r3944realms.lib39.example.core.register.ExLib39Attachments; +import top.r3944realms.lib39.example.core.network.ExNetworkHandler; import top.r3944realms.lib39.example.core.register.ExLib39Items; /** @@ -15,19 +16,22 @@ public class Lib39Example { /** * Instantiates a new Lib 39 example. */ - public Lib39Example(IEventBus modEventBus) { + public Lib39Example() { if (!registered) { - init(modEventBus); - registerToEventBus(modEventBus); + init(); + registerToEventBus(); registered = true; } } - private void init(IEventBus modEventBus) { + private void init() { + IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); ExLib39Items.register(modEventBus); - ExLib39Attachments.register(modEventBus); + ExNetworkHandler.register(); } - private void registerToEventBus(IEventBus modBus) { + private void registerToEventBus() { + IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); + IEventBus gameBus = MinecraftForge.EVENT_BUS; // DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> { // modBus.register(ExClientEventHandler.Mod.class); // gameBus.register(ExClientEventHandler.Game.class); @@ -39,7 +43,7 @@ public class Lib39Example { // return null; // }); modBus.register(ExCommonEventHandler.Mod.class); - NeoForge.EVENT_BUS.register(ExCommonEventHandler.Game.class); + gameBus.register(ExCommonEventHandler.Game.class); } diff --git a/src/main/java/top/r3944realms/lib39/example/content/capability/AbstractedTestSyncData.java b/src/main/java/top/r3944realms/lib39/example/content/capability/AbstractedTestSyncData.java index 04df6b6..2dc49ad 100644 --- a/src/main/java/top/r3944realms/lib39/example/content/capability/AbstractedTestSyncData.java +++ b/src/main/java/top/r3944realms/lib39/example/content/capability/AbstractedTestSyncData.java @@ -1,25 +1,20 @@ package top.r3944realms.lib39.example.content.capability; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; -import net.neoforged.neoforge.common.util.ValueIOSerializable; -import top.r3944realms.lib39.core.sync.IEntity; +import top.r3944realms.lib39.core.sync.NBTEntitySyncData; /** * The type Abstracted test sync data. */ @SuppressWarnings("unused") -public abstract class AbstractedTestSyncData implements ValueIOSerializable, IEntity { - +public abstract class AbstractedTestSyncData extends NBTEntitySyncData { /** * Instantiates a new Nbt sync data. * * @param id the id */ protected AbstractedTestSyncData(ResourceLocation id) { - + super(id); } /** @@ -131,17 +126,10 @@ public abstract class AbstractedTestSyncData implements ValueIOSerializable, IEn * 测试数据对象 */ public static class TestData { - public static StreamCodec CODEC = StreamCodec.composite( - ByteBufCodecs.STRING_UTF8, TestData::getName, - ByteBufCodecs.INT, TestData::getValue, - ByteBufCodecs.BOOL, TestData::isFlag, - TestData::new - ); private String name; private int value; private boolean flag; - /** * Instantiates a new Test data. */ diff --git a/src/main/java/top/r3944realms/lib39/example/content/capability/ExCapabilityHandler.java b/src/main/java/top/r3944realms/lib39/example/content/capability/ExCapabilityHandler.java index 31e89fd..dbdffe4 100644 --- a/src/main/java/top/r3944realms/lib39/example/content/capability/ExCapabilityHandler.java +++ b/src/main/java/top/r3944realms/lib39/example/content/capability/ExCapabilityHandler.java @@ -1,15 +1,12 @@ package top.r3944realms.lib39.example.content.capability; -import net.minecraft.resources.ResourceLocation; - -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.vehicle.Boat; -import net.minecraft.world.entity.vehicle.Minecart; -import net.neoforged.neoforge.capabilities.EntityCapability; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; -import top.r3944realms.lib39.Lib39; -import top.r3944realms.lib39.example.core.register.ExLib39Attachments; -import top.r3944realms.lib39.util.capability.EntityCapabilityHelper; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import org.jetbrains.annotations.NotNull; /** * The type Ex capability handler. @@ -18,29 +15,26 @@ public class ExCapabilityHandler { /** * The constant TEST_CAP. */ - public static final EntityCapability TEST_CAP = EntityCapability.createVoid( - ResourceLocation.fromNamespaceAndPath(Lib39.MOD_ID, "test_data"), - AbstractedTestSyncData.class - ); + public static final Capability TEST_CAP = CapabilityManager.get(new CapabilityToken<>() {}); - public static void registerCapabilities(RegisterCapabilitiesEvent event) { - EntityCapabilityHelper.registerForEntityClass( - event, - TEST_CAP, - (entity, context) -> entity.getData(ExLib39Attachments.TEST_DATA_ATTACHMENT), - LivingEntity.class - ); - EntityCapabilityHelper.registerForEntityClass( - event, - TEST_CAP, - (entity, context) -> entity.getData(ExLib39Attachments.TEST_DATA_ATTACHMENT), - Boat.class - ); - EntityCapabilityHelper.registerForEntityClass( - event, - TEST_CAP, - (entity, context) -> entity.getData(ExLib39Attachments.TEST_DATA_ATTACHMENT), - Minecart.class - ); + /** + * Register capability. + * + * @param event the event + */ + public static void registerCapability(@NotNull RegisterCapabilitiesEvent event) { + event.register(AbstractedTestSyncData.class); + } + + /** + * Attach capability. + * + * @param event the event + */ + public static void attachCapability(@NotNull AttachCapabilitiesEvent event) { + Object object = event.getObject(); + if(object instanceof Entity entity ) { + event.addCapability(TestSyncCapProvider.TEST_SYNC_REL, new TestSyncCapProvider(entity)); + } } } diff --git a/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncCapProvider.java b/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncCapProvider.java new file mode 100644 index 0000000..f500642 --- /dev/null +++ b/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncCapProvider.java @@ -0,0 +1,49 @@ +package top.r3944realms.lib39.example.content.capability; + +import net.minecraft.core.Direction; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.entity.Entity; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.ICapabilitySerializable; +import net.minecraftforge.common.util.LazyOptional; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import top.r3944realms.lib39.Lib39; + +/** + * The type Test sync cap provider. + */ +public class TestSyncCapProvider implements ICapabilitySerializable { + + /** + * The constant TEST_SYNC_REL. + */ + public static final ResourceLocation TEST_SYNC_REL = new ResourceLocation(Lib39.MOD_ID, "test_sync_data"); + private final AbstractedTestSyncData instance; + private final LazyOptional optional; + + /** + * Instantiates a new Test sync cap provider. + * + * @param entity the entity + */ + public TestSyncCapProvider(Entity entity) { + this.instance = new TestSyncData(entity); + this.optional = LazyOptional.of(() -> instance); + } + @Override + public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { + return ExCapabilityHandler.TEST_CAP.orEmpty(cap, optional); + } + + @Override + public CompoundTag serializeNBT() { + return instance.serializeNBT(); + } + + @Override + public void deserializeNBT(CompoundTag nbt) { + instance.deserializeNBT(nbt); + } +} diff --git a/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncData.java b/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncData.java index 2424cb1..bbba0d9 100644 --- a/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncData.java +++ b/src/main/java/top/r3944realms/lib39/example/content/capability/TestSyncData.java @@ -1,21 +1,14 @@ package top.r3944realms.lib39.example.content.capability; +import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.network.codec.ByteBufCodecs; -import net.minecraft.network.codec.StreamCodec; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.entity.Entity; -import net.minecraft.world.level.storage.ValueInput; -import net.minecraft.world.level.storage.ValueOutput; -import net.neoforged.neoforge.attachment.IAttachmentHolder; import org.jetbrains.annotations.NotNull; import top.r3944realms.lib39.Lib39; -import top.r3944realms.lib39.example.core.register.ExLib39Attachments; -import top.r3944realms.lib39.example.core.register.ExLib39ItemResourceKeys; -import top.r3944realms.lib39.util.storage.valueio.ValueInputReader; -import top.r3944realms.lib39.util.storage.valueio.ValueOutputWriter; +import top.r3944realms.lib39.util.nbt.NBTReader; +import top.r3944realms.lib39.util.nbt.NBTWriter; -import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -23,59 +16,25 @@ import java.util.concurrent.atomic.AtomicReference; /** * 测试同步数据实现 */ +@SuppressWarnings("unused") public class TestSyncData extends AbstractedTestSyncData { - private static final Random RANDOM = new Random(); + /** + * The constant ID. + */ + public static final ResourceLocation ID = new ResourceLocation(Lib39.MOD_ID, "test_sync_data"); - public static final ResourceLocation ID = ResourceLocation.fromNamespaceAndPath(Lib39.MOD_ID, "test_sync_data"); + // NBT 键常量 + private static final String NBT_KEY_STRING = "test_string"; + private static final String NBT_KEY_INT = "test_int"; + private static final String NBT_KEY_BOOLEAN = "test_boolean"; + private static final String NBT_KEY_DOUBLE = "test_double"; + private static final String NBT_KEY_COUNTER = "counter"; + private static final String NBT_KEY_SYNC_TIME = "last_sync_time"; + private static final String NBT_KEY_CUSTOM_DATA = "custom_data"; + private static final String NBT_KEY_CUSTOM_NAME = "name"; + private static final String NBT_KEY_CUSTOM_VALUE = "value"; + private static final String NBT_KEY_CUSTOM_FLAG = "flag"; - // 网络同步编解码器 - public static final StreamCodec CODEC = StreamCodec.composite( - ByteBufCodecs.STRING_UTF8, TestSyncData::getTestString, - ByteBufCodecs.INT, TestSyncData::getTestInt, - ByteBufCodecs.BOOL, TestSyncData::isTestBoolean, - ByteBufCodecs.DOUBLE, TestSyncData::getTestDouble, - TestData.CODEC, TestSyncData::getCustomData, - ByteBufCodecs.INT, TestSyncData::getCounter, - ByteBufCodecs.LONG, TestSyncData::getLastSyncTime, - (testString, testInt, testBoolean, testDouble, customData, counter, lastSyncTime) -> { - TestSyncData data = new TestSyncData(); - data.testString = testString; - data.testInt = testInt; - data.testBoolean = testBoolean; - data.testDouble = testDouble; - data.customData = customData; - data.counter = counter; - data.lastSyncTime = lastSyncTime; - return data; - } - ); - /** 重置为默认值 */ - public void resetToDefaults() { - this.testString = "default_string"; - this.testInt = 0; - this.testDouble = 0.0; - this.testBoolean = false; - this.counter = 0; - this.lastSyncTime = System.currentTimeMillis(); - this.customData = new TestData("init", 0, false); - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); - } - - /** 随机生成一组数据 */ - public void generateRandomData() { - this.testString = "rand_" + RANDOM.nextInt(10000); - this.testInt = RANDOM.nextInt(1000); - this.testDouble = RANDOM.nextDouble() * 100.0; - this.testBoolean = RANDOM.nextBoolean(); - this.counter = RANDOM.nextInt(20); - this.lastSyncTime = System.currentTimeMillis(); - this.customData = new TestData( - "custom_" + RANDOM.nextInt(1000), - RANDOM.nextInt(500), - RANDOM.nextBoolean() - ); - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); - } // 数据字段 private String testString = "default_value"; private int testInt = 42; @@ -86,134 +45,332 @@ public class TestSyncData extends AbstractedTestSyncData { private TestData customData = new TestData("default", 100, false); private Entity self; - // --- 构造函数区域 --- - - /** 默认构造函数(反序列化/同步使用) */ - public TestSyncData() { - super(ID); - } - - /** 用于实体附加 */ + /** + * 构造函数 + * + * @param entity 关联的实体 + */ public TestSyncData(Entity entity) { super(ID); this.self = entity; } - /** 用于 AttachmentType.serializable(holder -> ...) */ - public TestSyncData(IAttachmentHolder holder) { - this(holder instanceof Entity e ? e : null); - if (self == null) throw new IllegalArgumentException("TestSyncData must be attached to Entity"); + /** + * 构造函数(用于测试) + * + * @param entityId 实体ID + * @param self the self + */ + public TestSyncData(int entityId, Entity self) { + super(ID); + this.self = self; } - // --- 数据逻辑部分 --- - - public String getTestString() { return testString; } - public void setTestString(String s) { - this.testString = s; - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + /** + * 构造函数(用于数据包反序列化) + * + * @param buf 字节缓冲区 + */ + public TestSyncData(FriendlyByteBuf buf) { + super(ID); + this.self = null; // 实体在从数据包重建时可能为null,需要在接收端设置 + fromBytes(buf); } - public int getTestInt() { return testInt; } - public void setTestInt(int i) { - this.testInt = i; - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + /** + * 将数据写入字节缓冲区(用于网络传输) + * + * @param buf 字节缓冲区 + */ + public void toBytes(FriendlyByteBuf buf) { + // 写入基本类型字段 + buf.writeUtf(testString != null ? testString : ""); + buf.writeInt(testInt); + buf.writeBoolean(testBoolean); + buf.writeDouble(testDouble); + buf.writeInt(counter); + buf.writeLong(lastSyncTime); + + // 写入自定义数据 + if (customData != null) { + buf.writeUtf(customData.getName() != null ? customData.getName() : ""); + buf.writeInt(customData.getValue()); + buf.writeBoolean(customData.isFlag()); + } else { + buf.writeUtf(""); + buf.writeInt(0); + buf.writeBoolean(false); + } + + // 写入实体ID(如果实体存在) + if (self != null) { + buf.writeInt(self.getId()); + } else { + buf.writeInt(-1); + } + + // 写入脏数据状态 + buf.writeBoolean(isDirty()); } - public boolean isTestBoolean() { return testBoolean; } - public void setTestBoolean(boolean b) { this.testBoolean = b; - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + /** + * 从字节缓冲区读取数据(用于网络传输) + * + * @param buf 字节缓冲区 + */ + public void fromBytes(@NotNull FriendlyByteBuf buf) { + // 读取基本类型字段 + this.testString = buf.readUtf(32767); // Minecraft字符串最大长度 + this.testInt = buf.readInt(); + this.testBoolean = buf.readBoolean(); + this.testDouble = buf.readDouble(); + this.counter = buf.readInt(); + this.lastSyncTime = buf.readLong(); + + // 读取自定义数据 + String customName = buf.readUtf(); + int customValue = buf.readInt(); + boolean customFlag = buf.readBoolean(); + this.customData = new TestData(customName, customValue, customFlag); + + // 读取实体ID(在接收端可能需要额外处理) + int entityId = buf.readInt(); + + // 读取脏数据状态 + boolean wasDirty = buf.readBoolean(); + if (wasDirty) { + markDirty(); + } } - public double getTestDouble() { return testDouble; } - public void setTestDouble(double d) { - this.testDouble = d; - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + /** + * 静态方法:从字节缓冲区创建 TestSyncData 实例 + * + * @param buf 字节缓冲区 + * @return 新的 TestSyncData 实例 + */ + public static TestSyncData staticFromBytes(FriendlyByteBuf buf) { + return new TestSyncData(buf); } - public int getCounter() { return counter; } + @Override + public String getTestString() { + return testString; + } + + @Override + public void setTestString(String value) { + if (!java.util.Objects.equals(this.testString, value)) { + this.testString = value; + markDirty(); + } + } + + @Override + public int getTestInt() { + return testInt; + } + + @Override + public void setTestInt(int value) { + if (this.testInt != value) { + this.testInt = value; + markDirty(); + } + } + + @Override + public boolean isTestBoolean() { + return testBoolean; + } + + @Override + public void setTestBoolean(boolean value) { + if (this.testBoolean != value) { + this.testBoolean = value; + markDirty(); + } + } + + @Override + public double getTestDouble() { + return testDouble; + } + + @Override + public void setTestDouble(double value) { + if (this.testDouble != value) { + this.testDouble = value; + markDirty(); + } + } + + @Override + public int getCounter() { + return counter; + } + + @Override public void incrementCounter() { this.counter++; - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + markDirty(); } - public long getLastSyncTime() { return lastSyncTime; } + @Override + public long getLastSyncTime() { + return lastSyncTime; + } + + @Override public void updateSyncTime() { this.lastSyncTime = System.currentTimeMillis(); - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + markDirty(); } - public TestData getCustomData() { return customData; } + @Override + public TestData getCustomData() { + return customData; + } + + @Override public void setCustomData(TestData data) { - this.customData = data; - self.syncData(ExLib39Attachments.TEST_DATA_ATTACHMENT); + if (data == null) { + throw new IllegalArgumentException("Custom data cannot be null"); + } + if (!java.util.Objects.equals(this.customData, data)) { + this.customData = data; + markDirty(); + } } + @Override public boolean validateData() { - return testString != null && !testString.isEmpty() - && customData != null && customData.getName() != null - && counter >= 0 && testInt >= 0; - } - - // --- 实体管理 --- - - public int entityId() { return self != null ? self.getId() : -1; } - - public void setSelf(Entity entity) { - this.self = entity; - } - public TestSyncData createSyncCopy(Entity entity) { - TestSyncData copy = new TestSyncData(entity); - copy.testString = testString; - copy.testInt = testInt; - copy.testBoolean = testBoolean; - copy.testDouble = testDouble; - copy.counter = counter; - copy.lastSyncTime = lastSyncTime; - copy.customData = new TestData(customData.getName(), customData.getValue(), customData.isFlag()); - return copy; + return testString != null && + !testString.isEmpty() && + customData != null && + customData.getName() != null && + !customData.getName().isEmpty() && + counter >= 0 && + testInt >= 0; } @Override - public void serialize(@NotNull ValueOutput out) { - ValueOutputWriter.of(out) - .string("test_string", testString) - .intValue("test_int", testInt) - .booleanValue("test_boolean", testBoolean) - .doubleValue("test_double", testDouble) - .intValue("counter", counter) - .longValue("last_sync_time", lastSyncTime) - .nested("custom_data", n -> - n.string("name", customData.getName()) - .intValue("value", customData.getValue()) - .booleanValue("flag", customData.isFlag())); + public CompoundTag serializeNBT() { + return NBTWriter.builder() + .string(NBT_KEY_STRING, testString) + .intValue(NBT_KEY_INT, testInt) + .booleanValue(NBT_KEY_BOOLEAN, testBoolean) + .doubleValue(NBT_KEY_DOUBLE, testDouble) + .intValue(NBT_KEY_COUNTER, counter) + .longValue(NBT_KEY_SYNC_TIME, lastSyncTime) + .compound( + NBT_KEY_CUSTOM_DATA, + NBTWriter.builder() + .string(NBT_KEY_CUSTOM_NAME, customData.getName()) + .intValue(NBT_KEY_CUSTOM_VALUE, customData.getValue()) + .booleanValue(NBT_KEY_CUSTOM_FLAG, customData.isFlag()) + .build() + ).build(); } @Override - public void deserialize(@NotNull ValueInput in) { - ValueInputReader.of(in) - .string("test_string", s -> testString = s) - .intValue("test_int", i -> testInt = i) - .booleanValue("test_boolean", b -> testBoolean = b) - .doubleValue("test_double", d -> testDouble = d) - .intValue("counter", c -> counter = c) - .longValue("last_sync_time", t -> lastSyncTime = t) - .nested("custom_data", n -> { - AtomicReference name = new AtomicReference<>("default"); - AtomicInteger value = new AtomicInteger(100); + public void deserializeNBT(CompoundTag nbt) { + NBTReader.of(nbt) + .intValue(NBT_KEY_INT, integer -> testInt = integer) + .string(NBT_KEY_STRING, string -> testString = string) + .booleanValue(NBT_KEY_BOOLEAN, bool -> testBoolean = bool) + .intValue(NBT_KEY_COUNTER, integer -> counter = integer) + .doubleValue(NBT_KEY_DOUBLE, dou -> testDouble = dou) + .longValue(NBT_KEY_SYNC_TIME, sync -> lastSyncTime = sync) + .compound(NBT_KEY_CUSTOM_DATA, customDataTag -> { + AtomicReference name = new AtomicReference<>(""); + AtomicInteger value = new AtomicInteger(-1); AtomicBoolean flag = new AtomicBoolean(false); - n.string("name", name::set) - .intValue("value", value::set) - .booleanValue("flag", flag::set); - customData = new TestData(name.get(), value.get(), flag.get()); + NBTReader.of(customDataTag) + .string(NBT_KEY_CUSTOM_NAME, name::set) + .intValue(NBT_KEY_CUSTOM_VALUE, value::set) + .booleanValue(NBT_KEY_CUSTOM_FLAG, flag::set); + this.customData = new TestData(name.get(), value.get(), flag.get()); }); } + @Override + public int entityId() { + return self != null ? self.getId() : -1; + } + + /** + * 设置关联的实体 + * + * @param entity 关联的实体 + */ + public void setEntity(Entity entity) { + this.self = entity; + } + + + /** + * 获取所有数据的字符串表示(用于调试) + */ @Override public String toString() { return String.format( - "TestSyncData[%s,id=%d]{str=%s,int=%d,bool=%s,double=%.2f,counter=%d,time=%d,custom=%s}", - self == null ? "null" : self.getClass().getSimpleName(), - entityId(), testString, testInt, testBoolean, testDouble, counter, lastSyncTime, customData + "TestSyncData{id=%d, string='%s', int=%d, boolean=%s, double=%.2f, counter=%d, lastSync=%d, custom=%s}", + self.getId(), testString, testInt, testBoolean, testDouble, counter, lastSyncTime, customData ); } -} + + /** + * 重置为默认值 + */ + public void resetToDefaults() { + testString = "default_value"; + testInt = 42; + testBoolean = true; + testDouble = 3.14159; + counter = 0; + lastSyncTime = 0L; + customData = new TestData("default", 100, false); + markDirty(); + } + + /** + * 生成随机测试数据 + */ + public void generateRandomData() { + testString = "random_" + System.currentTimeMillis(); + testInt = (int) (Math.random() * 1000); + testBoolean = Math.random() > 0.5; + testDouble = Math.random() * 100.0; + counter++; + lastSyncTime = System.currentTimeMillis(); + customData = new TestData( + "custom_" + counter, + (int) (Math.random() * 500), + Math.random() > 0.5 + ); + markDirty(); + } + + /** + * 创建一个不依赖实体的副本(用于网络传输) + * + * @return 不包含实体引用的副本 test sync data + */ + public TestSyncData createNetworkCopy() { + TestSyncData copy = new TestSyncData((Entity) null); + copy.testString = this.testString; + copy.testInt = this.testInt; + copy.testBoolean = this.testBoolean; + copy.testDouble = this.testDouble; + copy.counter = this.counter; + copy.lastSyncTime = this.lastSyncTime; + copy.customData = new TestData( + this.customData.getName(), + this.customData.getValue(), + this.customData.isFlag() + ); + return copy; + } + +} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/content/item/FabricItem.java b/src/main/java/top/r3944realms/lib39/example/content/item/FabricItem.java index 011eecd..f3ba19a 100644 --- a/src/main/java/top/r3944realms/lib39/example/content/item/FabricItem.java +++ b/src/main/java/top/r3944realms/lib39/example/content/item/FabricItem.java @@ -1,10 +1,9 @@ package top.r3944realms.lib39.example.content.item; -import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; @@ -12,22 +11,20 @@ import net.minecraft.world.entity.projectile.ProjectileUtil; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.level.Level; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.Vec3; -import net.neoforged.neoforge.client.network.ClientPacketDistributor; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.example.content.capability.AbstractedTestSyncData; import top.r3944realms.lib39.example.content.capability.ExCapabilityHandler; import top.r3944realms.lib39.example.content.capability.TestSyncData; -import top.r3944realms.lib39.example.core.network.ClientDataPayload; -import top.r3944realms.lib39.util.chat.MessageDisplayClientHelper; +import top.r3944realms.lib39.example.core.network.ClientDataPacket; +import top.r3944realms.lib39.example.core.network.ExNetworkHandler; +import java.util.List; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; /** * 用于执行数据查询并检查同步状态的物品 @@ -46,7 +43,8 @@ public class FabricItem extends Item { } @Override - public @NotNull InteractionResult use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) { + public @NotNull InteractionResultHolder use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) { + ItemStack itemStack = player.getItemInHand(hand); if (level.isClientSide()) { // 客户端逻辑 @@ -63,17 +61,17 @@ public class FabricItem extends Item { if (player.isShiftKeyDown()) { // 服务器端已经通过数据包处理双端检查,这里只发送开始消息 - ((ServerPlayer) player).sendSystemMessage(Component.literal("§b开始双端同步检查,请等待客户端数据...")); + player.sendSystemMessage(Component.literal("§b开始双端同步检查,请等待客户端数据...")); } else { // 服务器单端查询 handleServerSingleEndQuery(serverPlayer); } // 添加冷却时间 - player.getCooldowns().addCooldown(this.getDefaultInstance(), 20); // 1秒冷却 + player.getCooldowns().addCooldown(this, 20); // 1秒冷却 } - return InteractionResult.SUCCESS; + return InteractionResultHolder.sidedSuccess(itemStack, level.isClientSide()); } /** @@ -91,15 +89,15 @@ public class FabricItem extends Item { sendClientDataToServer(clientData, livingTarget.getId()); // 客户端提示 - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§b已发送客户端数据到服务器,等待对比结果..."), false); + player.sendSystemMessage(Component.literal("§b已发送客户端数据到服务器,等待对比结果...")); } else { - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§c无法获取客户端本地数据"), false); + player.sendSystemMessage(Component.literal("§c无法获取客户端本地数据")); } } else { if (targetEntity == null && player.isShiftKeyDown()) { handlePlayerSelfData(player); } else { - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§c请对准一个生物进行同步检查!"), false); + player.sendSystemMessage(Component.literal("§c请对准一个生物进行同步检查!")); } } } @@ -116,9 +114,9 @@ public class FabricItem extends Item { sendClientDataToServer(clientData, player.getId()); // 客户端提示 - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§b已发送玩家自身客户端数据到服务器,等待对比结果..."), false); + player.sendSystemMessage(Component.literal("§b已发送玩家自身客户端数据到服务器,等待对比结果...")); } else { - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§c无法获取玩家自身客户端数据"), false); + player.sendSystemMessage(Component.literal("§c无法获取玩家自身客户端数据")); } } /** @@ -131,12 +129,12 @@ public class FabricItem extends Item { TestSyncData clientData = getLocalClientData(livingTarget); if (clientData != null) { - displayClientSideResults(livingTarget, clientData); + displayClientSideResults(player, livingTarget, clientData); } else { - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§c无法查询客户端本地数据"), false); + player.sendSystemMessage(Component.literal("§c无法查询客户端本地数据")); } } else { - Minecraft.getInstance().getChatListener().handleSystemMessage(Component.literal("§c请对准一个生物使用!"), false); + player.sendSystemMessage(Component.literal("§c请对准一个生物使用!")); } } @@ -163,7 +161,7 @@ public class FabricItem extends Item { */ private TestSyncData getLocalClientData(LivingEntity target) { try { - AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP); + AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElse(null); if (abstractData instanceof TestSyncData) { return (TestSyncData) abstractData; } @@ -178,7 +176,7 @@ public class FabricItem extends Item { */ private void sendClientDataToServer(TestSyncData clientData, int targetEntityId) { // 使用网络系统发送数据包 - ClientPacketDistributor.sendToServer(new ClientDataPayload(clientData, targetEntityId)); + ExNetworkHandler.INSTANCE.sendToServer(new ClientDataPacket(clientData, targetEntityId)); } /** @@ -211,7 +209,7 @@ public class FabricItem extends Item { */ private static @Nullable TestSyncData getServerSideData(LivingEntity target) { try { - AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP); + AbstractedTestSyncData abstractData = target.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElse(null); if (abstractData instanceof TestSyncData) { return (TestSyncData) abstractData; } @@ -231,7 +229,9 @@ public class FabricItem extends Item { Thread.sleep(3000); // 在服务器线程中执行结果处理 - player.server.execute(() -> displayServerSingleEndResults(player, target)); + player.server.execute(() -> { + displayServerSingleEndResults(player, target); + }); } catch (InterruptedException e) { Thread.currentThread().interrupt(); @@ -268,23 +268,24 @@ public class FabricItem extends Item { /** * 显示客户端查询结果 */ - private void displayClientSideResults(LivingEntity target, TestSyncData clientData) { - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§6=== 客户端数据查询结果 ===")); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7目标生物: §e" + target.getName().getString())); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7数据来源: §9客户端本地")); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("")); + private void displayClientSideResults(Player player, LivingEntity target, TestSyncData clientData) { + player.sendSystemMessage(Component.literal("§6=== 客户端数据查询结果 ===")); + player.sendSystemMessage(Component.literal("§7目标生物: §e" + target.getName().getString())); + player.sendSystemMessage(Component.literal("§7数据来源: §9客户端本地")); + player.sendSystemMessage(Component.literal("")); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§a基础数据:")); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7字符串: §f" + clientData.getTestString())); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7整数值: §f" + clientData.getTestInt())); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7布尔值: §f" + clientData.isTestBoolean())); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7双精度值: §f" + String.format("%.2f", clientData.getTestDouble()))); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7计数器: §f" + clientData.getCounter())); + player.sendSystemMessage(Component.literal("§a基础数据:")); + player.sendSystemMessage(Component.literal("§7字符串: §f" + clientData.getTestString())); + player.sendSystemMessage(Component.literal("§7整数值: §f" + clientData.getTestInt())); + player.sendSystemMessage(Component.literal("§7布尔值: §f" + clientData.isTestBoolean())); + player.sendSystemMessage(Component.literal("§7双精度值: §f" + String.format("%.2f", clientData.getTestDouble()))); + player.sendSystemMessage(Component.literal("§7计数器: §f" + clientData.getCounter())); // 显示客户端特定信息 - MessageDisplayClientHelper.sendSystemMessage(Component.literal("")); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§e客户端状态:")); - MessageDisplayClientHelper.sendSystemMessage(Component.literal("§7数据验证: " + (clientData.validateData() ? "§a通过" : "§c失败"))); + player.sendSystemMessage(Component.literal("")); + player.sendSystemMessage(Component.literal("§e客户端状态:")); + player.sendSystemMessage(Component.literal("§7数据验证: " + (clientData.validateData() ? "§a通过" : "§c失败"))); + player.sendSystemMessage(Component.literal("§7同步状态: " + (clientData.isDirty() ? "§6待同步" : "§a已同步"))); } /** @@ -341,6 +342,9 @@ public class FabricItem extends Item { player.sendSystemMessage(Component.literal( String.format("§7数据验证: %s", isValid ? "§a通过" : "§c失败") )); + player.sendSystemMessage(Component.literal( + String.format("§7数据状态: %s", testData.isDirty() ? "§6未同步" : "§a已同步") + )); } /** @@ -356,7 +360,7 @@ public class FabricItem extends Item { // 显示双端数据来源 player.sendSystemMessage(Component.literal("§a数据来源:")); player.sendSystemMessage(Component.literal("§7- §c服务器端§7: 实体ID " + serverData.entityId())); - player.sendSystemMessage(Component.literal("§7- §9客户端§7: 实体ID " + serverData.entityId())); + player.sendSystemMessage(Component.literal("§7- §9客户端§7: 实体ID " + clientData.entityId())); player.sendSystemMessage(Component.literal("")); // 比较各个字段 @@ -406,6 +410,12 @@ public class FabricItem extends Item { // 显示数据状态差异 player.sendSystemMessage(Component.literal("")); player.sendSystemMessage(Component.literal("§a数据状态差异:")); + player.sendSystemMessage(Component.literal( + String.format("§7服务器脏数据状态: %s", serverData.isDirty() ? "§6脏" : "§a干净") + )); + player.sendSystemMessage(Component.literal( + String.format("§7客户端脏数据状态: %s", clientData.isDirty() ? "§6脏" : "§a干净") + )); player.sendSystemMessage(Component.literal( String.format("§7服务器验证状态: %s", serverData.validateData() ? "§a通过" : "§c失败") )); @@ -542,37 +552,38 @@ public class FabricItem extends Item { */ private AbstractedTestSyncData getTestSyncData(Entity entity) { try { - return entity.getCapability(ExCapabilityHandler.TEST_CAP); + return entity.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElse(null); } catch (Exception e) { Lib39.LOGGER.debug("[FabricItem] 获取生物 {} 的 TestSyncData 失败: {}", entity.getName().getString(), e.getMessage()); return null; } } - @SuppressWarnings("deprecation") - public void appendHoverText( - @NotNull ItemStack stack, Item.@NotNull TooltipContext context, @NotNull TooltipDisplay tooltipDisplay, @NotNull Consumer tooltipAdder, @NotNull TooltipFlag flag - ) { - tooltipAdder.accept(Component.literal("§7右键点击在 3 秒后执行")); - tooltipAdder.accept(Component.literal("§7§e准星瞄准生物§7的数据查询")); - tooltipAdder.accept(Component.literal("§7§oShift + 右键§7进行§e客户端-服务器双端同步检查§7")); - tooltipAdder.accept(Component.literal("")); - tooltipAdder.accept(Component.literal("§6查询延迟: §e3秒")); - tooltipAdder.accept(Component.literal("§6瞄准距离: §e20格")); - tooltipAdder.accept(Component.literal("§6冷却时间: §e1秒")); - tooltipAdder.accept(Component.literal("")); - tooltipAdder.accept(Component.literal("§a单端查询内容:")); - tooltipAdder.accept(Component.literal("§7- 基础数据字段")); - tooltipAdder.accept(Component.literal("§7- 自定义数据结构")); - tooltipAdder.accept(Component.literal("§7- 数据验证状态")); - tooltipAdder.accept(Component.literal("§7- 同步状态信息")); - tooltipAdder.accept(Component.literal("")); - tooltipAdder.accept(Component.literal("§e双端同步检查:")); - tooltipAdder.accept(Component.literal("§7- 客户端和服务器同时查询")); - tooltipAdder.accept(Component.literal("§7- 字段级同步状态对比")); - tooltipAdder.accept(Component.literal("§7- 总体同步率计算")); - tooltipAdder.accept(Component.literal("§7- 双端数据状态差异")); - tooltipAdder.accept(Component.literal("§7- 同步建议")); - } + @Override + public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, + @NotNull List tooltip, @NotNull TooltipFlag flag) { + super.appendHoverText(stack, level, tooltip, flag); + + tooltip.add(Component.literal("§7右键点击在 3 秒后执行")); + tooltip.add(Component.literal("§7§e准星瞄准生物§7的数据查询")); + tooltip.add(Component.literal("§7§oShift + 右键§7进行§e客户端-服务器双端同步检查§7")); + tooltip.add(Component.literal("")); + tooltip.add(Component.literal("§6查询延迟: §e3秒")); + tooltip.add(Component.literal("§6瞄准距离: §e20格")); + tooltip.add(Component.literal("§6冷却时间: §e1秒")); + tooltip.add(Component.literal("")); + tooltip.add(Component.literal("§a单端查询内容:")); + tooltip.add(Component.literal("§7- 基础数据字段")); + tooltip.add(Component.literal("§7- 自定义数据结构")); + tooltip.add(Component.literal("§7- 数据验证状态")); + tooltip.add(Component.literal("§7- 同步状态信息")); + tooltip.add(Component.literal("")); + tooltip.add(Component.literal("§e双端同步检查:")); + tooltip.add(Component.literal("§7- 客户端和服务器同时查询")); + tooltip.add(Component.literal("§7- 字段级同步状态对比")); + tooltip.add(Component.literal("§7- 总体同步率计算")); + tooltip.add(Component.literal("§7- 双端数据状态差异")); + tooltip.add(Component.literal("§7- 同步建议")); + } } \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/content/item/NeoForgeItem.java b/src/main/java/top/r3944realms/lib39/example/content/item/NeoForgeItem.java index 78de2e2..4d669f8 100644 --- a/src/main/java/top/r3944realms/lib39/example/content/item/NeoForgeItem.java +++ b/src/main/java/top/r3944realms/lib39/example/content/item/NeoForgeItem.java @@ -3,7 +3,7 @@ package top.r3944realms.lib39.example.content.item; import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; @@ -11,19 +11,18 @@ import net.minecraft.world.entity.projectile.ProjectileUtil; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.component.TooltipDisplay; import net.minecraft.world.level.Level; import net.minecraft.world.phys.EntityHitResult; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.example.content.capability.AbstractedTestSyncData; import top.r3944realms.lib39.example.content.capability.ExCapabilityHandler; import top.r3944realms.lib39.example.content.capability.TestSyncData; -import top.r3944realms.lib39.util.chat.MessageDisplayClientHelper; +import java.util.List; import java.util.Random; -import java.util.function.Consumer; /** * 用于对准星生物触发 TestSyncData 随机变换的物品 @@ -43,7 +42,9 @@ public class NeoForgeItem extends Item { } @Override - public @NotNull InteractionResult use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) { + public @NotNull InteractionResultHolder use(@NotNull Level level, @NotNull Player player, @NotNull InteractionHand hand) { + ItemStack itemStack = player.getItemInHand(hand); + if (!level.isClientSide()) { ServerPlayer serverPlayer = (ServerPlayer) player; @@ -56,10 +57,10 @@ public class NeoForgeItem extends Item { } // 添加冷却时间 - player.getCooldowns().addCooldown(this.getDefaultInstance(), 20); // 1秒冷却 + player.getCooldowns().addCooldown(this, 20); // 1秒冷却 } - return InteractionResult.SUCCESS_SERVER; + return InteractionResultHolder.sidedSuccess(itemStack, level.isClientSide()); } /** @@ -206,8 +207,8 @@ public class NeoForgeItem extends Item { } // 显示数据预览(仅对玩家自己操作时显示) - if (entity instanceof Player player) { - displayDataPreview(player, testData); + if (entity instanceof Player) { + displayDataPreview((Player) entity, testData); } return true; @@ -223,18 +224,16 @@ public class NeoForgeItem extends Item { * 显示数据预览给玩家 */ private void displayDataPreview(Player player, TestSyncData testData) { - if(player instanceof ServerPlayer serverPlayer) { - serverPlayer.sendSystemMessage(Component.literal("§6数据预览:")); - serverPlayer.sendSystemMessage(Component.literal( - String.format("§7字符串: §f%s", testData.getTestString()) - )); - serverPlayer.sendSystemMessage(Component.literal( - String.format("§7计数器: §f%d", testData.getCounter()) - )); - serverPlayer.sendSystemMessage(Component.literal( - String.format("§7验证状态: %s", testData.validateData() ? "§a通过" : "§c失败") - )); - } + player.sendSystemMessage(Component.literal("§6数据预览:")); + player.sendSystemMessage(Component.literal( + String.format("§7字符串: §f%s", testData.getTestString()) + )); + player.sendSystemMessage(Component.literal( + String.format("§7计数器: §f%d", testData.getCounter()) + )); + player.sendSystemMessage(Component.literal( + String.format("§7验证状态: %s", testData.validateData() ? "§a通过" : "§c失败") + )); } /** @@ -250,7 +249,7 @@ public class NeoForgeItem extends Item { private AbstractedTestSyncData getOrCreateTestSyncData(Entity entity) { try { - return entity.getCapability(ExCapabilityHandler.TEST_CAP); + return entity.getCapability(ExCapabilityHandler.TEST_CAP).resolve().orElseThrow(); } catch (Exception e) { Lib39.LOGGER.error("[NeoForgeItem] 获取 {} 的 TestSyncData 失败: {}", getEntityName((LivingEntity) entity), e.getMessage()); @@ -258,28 +257,28 @@ public class NeoForgeItem extends Item { } } - @SuppressWarnings("deprecation") - public void appendHoverText( - @NotNull ItemStack stack, Item.@NotNull TooltipContext context, @NotNull TooltipDisplay tooltipDisplay, @NotNull Consumer tooltipAdder, @NotNull TooltipFlag flag - ) { + @Override + public void appendHoverText(@NotNull ItemStack stack, @Nullable Level level, + @NotNull List tooltip, @NotNull TooltipFlag flag) { + super.appendHoverText(stack, level, tooltip, flag); - tooltipAdder.accept(Component.literal("§7右键点击触发§e准星瞄准生物§7的")); - tooltipAdder.accept(Component.literal("§7测试数据随机变换")); - tooltipAdder.accept(Component.literal("§7§oShift + 右键§7操作§e自身§7数据")); - tooltipAdder.accept(Component.literal("")); - tooltipAdder.accept(Component.literal("§6冷却时间: §e1秒")); - tooltipAdder.accept(Component.literal("§6瞄准距离: §e20格")); - tooltipAdder.accept(Component.literal("")); - tooltipAdder.accept(Component.literal("§a变换类型:")); - tooltipAdder.accept(Component.literal("§7- 完全随机数据")); - tooltipAdder.accept(Component.literal("§7- 字符串+计数器")); - tooltipAdder.accept(Component.literal("§7- 数值数据")); - tooltipAdder.accept(Component.literal("§7- 自定义数据")); - tooltipAdder.accept(Component.literal("§7- 重置默认值")); - tooltipAdder.accept(Component.literal("§7- 玩家专属数据")); - tooltipAdder.accept(Component.literal("")); - tooltipAdder.accept(Component.literal("§e自身操作特性:")); - tooltipAdder.accept(Component.literal("§7- 显示数据预览")); - tooltipAdder.accept(Component.literal("§7- 玩家专属数据变换")); + tooltip.add(Component.literal("§7右键点击触发§e准星瞄准生物§7的")); + tooltip.add(Component.literal("§7测试数据随机变换")); + tooltip.add(Component.literal("§7§oShift + 右键§7操作§e自身§7数据")); + tooltip.add(Component.literal("")); + tooltip.add(Component.literal("§6冷却时间: §e1秒")); + tooltip.add(Component.literal("§6瞄准距离: §e20格")); + tooltip.add(Component.literal("")); + tooltip.add(Component.literal("§a变换类型:")); + tooltip.add(Component.literal("§7- 完全随机数据")); + tooltip.add(Component.literal("§7- 字符串+计数器")); + tooltip.add(Component.literal("§7- 数值数据")); + tooltip.add(Component.literal("§7- 自定义数据")); + tooltip.add(Component.literal("§7- 重置默认值")); + tooltip.add(Component.literal("§7- 玩家专属数据")); + tooltip.add(Component.literal("")); + tooltip.add(Component.literal("§e自身操作特性:")); + tooltip.add(Component.literal("§7- 显示数据预览")); + tooltip.add(Component.literal("§7- 玩家专属数据变换")); } } \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/core/event/ExCommonEventHandler.java b/src/main/java/top/r3944realms/lib39/example/core/event/ExCommonEventHandler.java index ba316de..d3c6a11 100644 --- a/src/main/java/top/r3944realms/lib39/example/core/event/ExCommonEventHandler.java +++ b/src/main/java/top/r3944realms/lib39/example/core/event/ExCommonEventHandler.java @@ -1,20 +1,20 @@ package top.r3944realms.lib39.example.core.event; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.vehicle.Boat; -import net.minecraft.world.entity.vehicle.Minecart; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; -import net.neoforged.neoforge.data.event.GatherDataEvent; -import net.neoforged.neoforge.event.entity.EntityJoinLevelEvent; -import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; +import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; +import net.minecraftforge.data.event.GatherDataEvent; +import net.minecraftforge.event.AttachCapabilitiesEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; +import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent; +import top.r3944realms.lib39.core.sync.CachedSyncManager; +import top.r3944realms.lib39.example.content.capability.AbstractedTestSyncData; import top.r3944realms.lib39.example.content.capability.ExCapabilityHandler; import top.r3944realms.lib39.example.content.capability.TestSyncData; -import top.r3944realms.lib39.example.core.network.ExNetworkHandler; -import top.r3944realms.lib39.example.core.register.ExLib39Attachments; -import top.r3944realms.lib39.example.datagen.ExLib39DataGenEvent; +import top.r3944realms.lib39.example.datagen.EXLib39DataGenEvent; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * The type Common handler. @@ -26,18 +26,40 @@ public class ExCommonEventHandler { @SuppressWarnings("unused") public static class Game extends ExCommonEventHandler { + /** + * Attach capability. + * + * @param event the event + */ @SubscribeEvent - public static void onEntityJoinLevel(EntityJoinLevelEvent event) { - Entity entity = event.getEntity(); - if (entity instanceof LivingEntity || entity instanceof Boat || entity instanceof Minecart) { - TestSyncData data = entity.getData(ExLib39Attachments.TEST_DATA_ATTACHMENT); - if (data.entityId() == -1) { - data.setSelf(entity); - } - } + public static void attachCapability(AttachCapabilitiesEvent event) { + ExCapabilityHandler.attachCapability(event); } + + /** + * On register sync. + * + * @param event the event + */ + @SubscribeEvent + public static void onRegisterSync (SyncManagerRegisterEvent event) { + event.registerSyncManager( + TestSyncData.ID, + new CachedSyncManager() { + private final Map syncDataMap = new ConcurrentHashMap<>(); + @Override + public Map getSyncMap() { + return syncDataMap; + } + }, + ExCapabilityHandler.TEST_CAP + + ); + } + } + /** * The type Mod. */ @@ -62,7 +84,7 @@ public class ExCommonEventHandler { */ @SubscribeEvent public static void registerCapability(RegisterCapabilitiesEvent event) { - ExCapabilityHandler.registerCapabilities(event); + ExCapabilityHandler.registerCapability(event); } /** @@ -71,12 +93,8 @@ public class ExCommonEventHandler { * @param event the event */ @SubscribeEvent - public static void gatherData(GatherDataEvent.Client event) { - ExLib39DataGenEvent.gatherData(event); - } - @SubscribeEvent - public static void registerPayloadPacket (RegisterPayloadHandlersEvent event) { - ExNetworkHandler.registerPackets(event); + public static void gatherData(GatherDataEvent event) { + EXLib39DataGenEvent.gatherData(event); } } } diff --git a/src/main/java/top/r3944realms/lib39/example/core/network/ClientDataPacket.java b/src/main/java/top/r3944realms/lib39/example/core/network/ClientDataPacket.java new file mode 100644 index 0000000..81e5a46 --- /dev/null +++ b/src/main/java/top/r3944realms/lib39/example/core/network/ClientDataPacket.java @@ -0,0 +1,69 @@ +package top.r3944realms.lib39.example.core.network; + +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraftforge.network.NetworkEvent; +import top.r3944realms.lib39.example.content.capability.TestSyncData; +import top.r3944realms.lib39.example.content.item.FabricItem; + +import java.util.function.Supplier; + +/** + * The type Client data packet. + */ +public class ClientDataPacket { + private final TestSyncData clientData; + private final int targetEntityId; + + /** + * Instantiates a new Client data packet. + * + * @param clientData the client data + * @param targetEntityId the target entity id + */ + public ClientDataPacket(TestSyncData clientData, int targetEntityId) { + this.clientData = clientData; + this.targetEntityId = targetEntityId; + } + + /** + * Instantiates a new Client data packet. + * + * @param buf the buf + */ + public ClientDataPacket(FriendlyByteBuf buf) { + this.clientData = TestSyncData.staticFromBytes(buf); + this.targetEntityId = buf.readInt(); + } + + /** + * To bytes. + * + * @param buf the buf + */ + public void toBytes(FriendlyByteBuf buf) { + clientData.toBytes(buf); + buf.writeInt(targetEntityId); + } + + /** + * Handle. + * + * @param supplier the supplier + */ + public void handle(Supplier supplier) { + NetworkEvent.Context context = supplier.get(); + context.enqueueWork(() -> { + ServerPlayer player = context.getSender(); + if (player != null) { + // 处理客户端发送的数据 + handleClientData(player, clientData, targetEntityId); + } + }); + context.setPacketHandled(true); + } + + private void handleClientData(ServerPlayer player, TestSyncData clientData, int targetEntityId) { + FabricItem.handleClientDataFromPacket(player, clientData, targetEntityId); + } +} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/core/network/ClientDataPayload.java b/src/main/java/top/r3944realms/lib39/example/core/network/ClientDataPayload.java deleted file mode 100644 index 36bbc33..0000000 --- a/src/main/java/top/r3944realms/lib39/example/core/network/ClientDataPayload.java +++ /dev/null @@ -1,43 +0,0 @@ -package top.r3944realms.lib39.example.core.network; - -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.neoforged.neoforge.network.handling.IPayloadContext; -import org.jetbrains.annotations.NotNull; -import top.r3944realms.lib39.Lib39; -import top.r3944realms.lib39.example.content.capability.TestSyncData; -import top.r3944realms.lib39.example.content.item.FabricItem; - -/** - * The type Client data packet. - */ -public record ClientDataPayload(TestSyncData clientData, int targetEntityId) implements CustomPacketPayload { - public static final Type TYPE = new Type<>(ResourceLocation.fromNamespaceAndPath(Lib39.MOD_ID, "client_data")); - public static final StreamCodec STREAM_CODEC = - StreamCodec.composite( - TestSyncData.CODEC, ClientDataPayload::clientData, - ByteBufCodecs.INT, ClientDataPayload::targetEntityId, - ClientDataPayload::new - ); - public void handle(IPayloadContext context) { - context.enqueueWork(() -> { - ServerPlayer player = (ServerPlayer) context.player(); - // 处理客户端发送的数据 - handleClientData(player, clientData, targetEntityId); - }); - } - - private void handleClientData(ServerPlayer player, TestSyncData clientData, int targetEntityId) { - FabricItem.handleClientDataFromPacket(player, clientData, targetEntityId); - } - - @Override - public @NotNull Type type() { - return TYPE; - } -} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/core/network/ExNetworkHandler.java b/src/main/java/top/r3944realms/lib39/example/core/network/ExNetworkHandler.java index 661102e..d85fdab 100644 --- a/src/main/java/top/r3944realms/lib39/example/core/network/ExNetworkHandler.java +++ b/src/main/java/top/r3944realms/lib39/example/core/network/ExNetworkHandler.java @@ -1,21 +1,37 @@ package top.r3944realms.lib39.example.core.network; - -import net.neoforged.neoforge.network.event.RegisterPayloadHandlersEvent; -import net.neoforged.neoforge.network.registration.PayloadRegistrar; -import org.jetbrains.annotations.NotNull; +import net.minecraft.resources.ResourceLocation; +import net.minecraftforge.network.NetworkRegistry; +import net.minecraftforge.network.simple.SimpleChannel; import top.r3944realms.lib39.Lib39; /** * The type Ex network handler. */ public class ExNetworkHandler { - public static void registerPackets(@NotNull RegisterPayloadHandlersEvent event) { - PayloadRegistrar registrar = event.registrar(Lib39.MOD_ID + "-ex-" + Lib39.ModInfo.VERSION); - registrar.playToServer( - ClientDataPayload.TYPE, - ClientDataPayload.STREAM_CODEC, - ClientDataPayload::handle + /** + * The constant INSTANCE. + */ + public static final SimpleChannel INSTANCE; + private static int ID = 0; + + static { + INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation(Lib39.MOD_ID, "test"), + () -> "1.0", + s -> true, + s -> true ); } + + /** + * Register. + */ + public static void register() { + // 注册数据包 + INSTANCE.registerMessage(ID++, ClientDataPacket.class, + ClientDataPacket::toBytes, + ClientDataPacket::new, + ClientDataPacket::handle); + } } \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Attachments.java b/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Attachments.java deleted file mode 100644 index 9bee2d8..0000000 --- a/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Attachments.java +++ /dev/null @@ -1,36 +0,0 @@ -package top.r3944realms.lib39.example.core.register; - -import net.minecraft.world.entity.Entity; -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.attachment.AttachmentType; -import net.neoforged.neoforge.registries.DeferredRegister; -import net.neoforged.neoforge.registries.NeoForgeRegistries; -import top.r3944realms.lib39.Lib39; -import top.r3944realms.lib39.example.content.capability.TestSyncData; - -import java.util.function.Supplier; - -public class ExLib39Attachments { - private static final DeferredRegister> ATTACHMENTS = - DeferredRegister.create(NeoForgeRegistries.ATTACHMENT_TYPES, Lib39.MOD_ID); - - public static final Supplier> TEST_DATA_ATTACHMENT = - ATTACHMENTS.register( - "test_data", - () -> AttachmentType - .serializable(holder -> new TestSyncData(holder)) - .copyOnDeath() - .copyHandler((attachment, holder, provider) -> { - if (!(holder instanceof Entity newEntity)) { - throw new IllegalArgumentException("TestSyncData can only be copied to entities"); - } - return attachment.createSyncCopy(newEntity); - }) - .sync(TestSyncData.CODEC) - .build() - ); - - public static void register(IEventBus iModBus) { - ATTACHMENTS.register(iModBus); - } -} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39ItemResourceKeys.java b/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39ItemResourceKeys.java deleted file mode 100644 index 945edee..0000000 --- a/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39ItemResourceKeys.java +++ /dev/null @@ -1,30 +0,0 @@ -package top.r3944realms.lib39.example.core.register; - -import net.minecraft.core.registries.Registries; -import net.minecraft.resources.ResourceKey; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import net.neoforged.neoforge.registries.DeferredHolder; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import top.r3944realms.lib39.Lib39; -import top.r3944realms.lib39.datagen.value.IResourceKeyValue; - -public enum ExLib39ItemResourceKeys implements IResourceKeyValue { - FABRIC("fabric"), - NEOFORGE("neoforge"), - ; - private final ResourceKey resourceKey; - ExLib39ItemResourceKeys(String name) { - resourceKey = ResourceKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(Lib39.MOD_ID, name)); - } - ExLib39ItemResourceKeys(@NotNull DeferredHolder item) { - resourceKey = ResourceKey.create(Registries.ITEM, item.getId()); - } - @Contract(pure = true) - @Override - public @Nullable ResourceKey getResourceKey() { - return resourceKey; - } -} diff --git a/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Items.java b/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Items.java index f16b4d5..de21c86 100644 --- a/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Items.java +++ b/src/main/java/top/r3944realms/lib39/example/core/register/ExLib39Items.java @@ -1,18 +1,14 @@ package top.r3944realms.lib39.example.core.register; - -import net.minecraft.core.registries.Registries; import net.minecraft.world.item.Item; - -import net.neoforged.bus.api.IEventBus; -import net.neoforged.neoforge.registries.DeferredHolder; -import net.neoforged.neoforge.registries.DeferredRegister; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; +import net.minecraftforge.registries.RegistryObject; import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.example.content.item.FabricItem; import top.r3944realms.lib39.example.content.item.NeoForgeItem; -import java.util.Objects; - /** * The type Ex lib 39 items. */ @@ -20,29 +16,27 @@ public class ExLib39Items { /** * The constant ITEMS. */ - public static final DeferredRegister ITEMS = DeferredRegister.create(Registries.ITEM, Lib39.MOD_ID); + public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, Lib39.MOD_ID); /** * The constant SUPER_LEAD_ROPE. */ - public static final DeferredHolder FABRIC = ITEMS.register( + public static final RegistryObject FABRIC = ITEMS.register( "fabric", () -> new FabricItem( new Item.Properties() .stacksTo(1) .fireResistant() - .setId(Objects.requireNonNull(ExLib39ItemResourceKeys.FABRIC.getResourceKey())) ) ); /** * The constant ETERNAL_POTATO. */ - public static final DeferredHolder NEOFORGE = + public static final RegistryObject NEOFORGE = ITEMS.register("neoforge", () -> new NeoForgeItem( new Item.Properties() .stacksTo(1) .fireResistant() - .setId(Objects.requireNonNull(ExLib39ItemResourceKeys.NEOFORGE.getResourceKey())) )); /** diff --git a/src/main/java/top/r3944realms/lib39/example/datagen/ExLib39DataGenEvent.java b/src/main/java/top/r3944realms/lib39/example/datagen/EXLib39DataGenEvent.java similarity index 56% rename from src/main/java/top/r3944realms/lib39/example/datagen/ExLib39DataGenEvent.java rename to src/main/java/top/r3944realms/lib39/example/datagen/EXLib39DataGenEvent.java index 21deb70..a1b4ca3 100644 --- a/src/main/java/top/r3944realms/lib39/example/datagen/ExLib39DataGenEvent.java +++ b/src/main/java/top/r3944realms/lib39/example/datagen/EXLib39DataGenEvent.java @@ -1,48 +1,48 @@ package top.r3944realms.lib39.example.datagen; import net.minecraft.data.DataProvider; -import net.neoforged.neoforge.data.event.GatherDataEvent; +import net.minecraftforge.data.event.GatherDataEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import top.r3944realms.lib39.Lib39; import top.r3944realms.lib39.datagen.provider.SimpleLanguageProvider; import top.r3944realms.lib39.datagen.value.McLocale; import top.r3944realms.lib39.example.datagen.data.ExLib39LangKeys; -import top.r3944realms.lib39.example.datagen.provider.ExModelDataProvider; +import top.r3944realms.lib39.example.datagen.provider.ExItemModelProvider; /** * The type Ex lib 39 data gen event. */ -public class ExLib39DataGenEvent { +public class EXLib39DataGenEvent { /** * The Logger. */ - static Logger logger = LoggerFactory.getLogger(ExLib39DataGenEvent.class); + static Logger logger = LoggerFactory.getLogger(EXLib39DataGenEvent.class); /** * Gather data. * * @param event the event */ - public static void gatherData(GatherDataEvent.Client event) { + public static void gatherData(GatherDataEvent event) { logger.info("GatherDataEvent thread: {}", Thread.currentThread().getName()); - LanguageGenerate(event, McLocale.EN_US); - LanguageGenerate(event, McLocale.ZH_CN); - LanguageGenerate(event, McLocale.ZH_TW); - LanguageGenerate(event, McLocale.LZH); + LanguageGenerator(event, McLocale.EN_US); + LanguageGenerator(event, McLocale.ZH_CN); + LanguageGenerator(event, McLocale.ZH_TW); + LanguageGenerator(event, McLocale.LZH); ModelDataGenerate(event); } - private static void LanguageGenerate(GatherDataEvent event, McLocale language) { + private static void LanguageGenerator(GatherDataEvent event, McLocale language) { event.getGenerator().addProvider( - true, + event.includeClient(), (DataProvider.Factory) pOutput -> new SimpleLanguageProvider(pOutput, Lib39.MOD_ID ,language ,ExLib39LangKeys.INSTANCE) ); } private static void ModelDataGenerate(GatherDataEvent event) { event.getGenerator().addProvider( - true, - (DataProvider.Factory) pOutput -> new ExModelDataProvider(pOutput, Lib39.MOD_ID) + event.includeClient(), + (DataProvider.Factory) pOutput -> new ExItemModelProvider(pOutput, event.getExistingFileHelper()) ); } } diff --git a/src/main/java/top/r3944realms/lib39/example/datagen/generator/ExBlockModelGenerator.java b/src/main/java/top/r3944realms/lib39/example/datagen/generator/ExBlockModelGenerator.java deleted file mode 100644 index 47025a9..0000000 --- a/src/main/java/top/r3944realms/lib39/example/datagen/generator/ExBlockModelGenerator.java +++ /dev/null @@ -1,21 +0,0 @@ -package top.r3944realms.lib39.example.datagen.generator; - -import net.minecraft.client.data.models.BlockModelGenerators; -import net.minecraft.client.data.models.ItemModelOutput; -import net.minecraft.client.data.models.blockstates.BlockModelDefinitionGenerator; -import net.minecraft.client.data.models.model.ModelInstance; -import net.minecraft.resources.ResourceLocation; - -import java.util.function.BiConsumer; -import java.util.function.Consumer; - -public class ExBlockModelGenerator extends BlockModelGenerators { - public ExBlockModelGenerator(Consumer blockStateOutput, ItemModelOutput itemModelOutput, BiConsumer modelOutput) { - super(blockStateOutput, itemModelOutput, modelOutput); - } - - @Override - public void run() { - - } -} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/example/datagen/generator/ExItemModelGenerators.java b/src/main/java/top/r3944realms/lib39/example/datagen/generator/ExItemModelGenerators.java deleted file mode 100644 index 265bbc8..0000000 --- a/src/main/java/top/r3944realms/lib39/example/datagen/generator/ExItemModelGenerators.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Super Lead rope mod - * Copyright (C) 2025 R3944Realms - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package top.r3944realms.lib39.example.datagen.generator; - -import net.minecraft.client.data.models.ItemModelGenerators; -import net.minecraft.client.data.models.ItemModelOutput; -import net.minecraft.client.data.models.model.ModelInstance; -import net.minecraft.client.data.models.model.ModelTemplates; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.Item; -import top.r3944realms.lib39.datagen.value.LangKeyValue; -import top.r3944realms.lib39.datagen.value.ModPartEnum; -import top.r3944realms.lib39.example.datagen.data.ExLib39LangKeys; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.BiConsumer; - -/** - * The type Slp item model provider. - */ -public class ExItemModelGenerators extends ItemModelGenerators { - private static List objectList; - - /** - * Instantiates a new Slp item model provider. - * - * @param output the output - * @param existingFileHelper the existing file helper - */ - public ExItemModelGenerators(ItemModelOutput itemModelOutput, BiConsumer modelOutput) { - super(itemModelOutput, modelOutput); - objectList = new ArrayList<>(); - init(); - } - - private void init() { - for(LangKeyValue obj : ExLib39LangKeys.INSTANCE.getValues()) { - if(!(obj.isDefault() && obj.getMPE().equals(ModPartEnum.ITEM))) continue; - objectList.add(obj.getItem()); - } - } - @Override - public void run() { - DefaultModItemModelRegister(); - } - - /** - * @implNote
 先有纹理才会成功构建 - */ - private void DefaultModItemModelRegister() { - objectList.forEach(i -> generateFlatItem(i, ModelTemplates.FLAT_ITEM)); - } - -} diff --git a/src/main/java/top/r3944realms/lib39/example/datagen/provider/ExItemModelProvider.java b/src/main/java/top/r3944realms/lib39/example/datagen/provider/ExItemModelProvider.java new file mode 100644 index 0000000..459ad8d --- /dev/null +++ b/src/main/java/top/r3944realms/lib39/example/datagen/provider/ExItemModelProvider.java @@ -0,0 +1,115 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.lib39.example.datagen.provider; + +import net.minecraft.data.PackOutput; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraftforge.client.model.generators.ItemModelProvider; +import net.minecraftforge.common.data.ExistingFileHelper; +import net.minecraftforge.registries.ForgeRegistries; +import top.r3944realms.lib39.Lib39; +import top.r3944realms.lib39.datagen.value.LangKeyValue; +import top.r3944realms.lib39.datagen.value.ModPartEnum; +import top.r3944realms.lib39.example.datagen.data.ExLib39LangKeys; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + +/** + * The type Slp item model provider. + */ +public class ExItemModelProvider extends ItemModelProvider { + private static List objectList; + /** + * The constant GENERATED. + */ + public static final String GENERATED = "item/generated"; + /** + * The constant HANDHELD. + */ + public static final String HANDHELD = "item/handheld"; + + /** + * Instantiates a new Slp item model provider. + * + * @param output the output + * @param existingFileHelper the existing file helper + */ + public ExItemModelProvider(PackOutput output, ExistingFileHelper existingFileHelper) { + super(output, Lib39.MOD_ID, existingFileHelper); + objectList = new ArrayList<>(); + init(); + } + + @Override + protected void registerModels() { + DefaultModItemModelRegister(); + } + private void init() { + for(LangKeyValue obj : ExLib39LangKeys.INSTANCE.getValues()) { + if(!(obj.isDefault() && obj.getMPE().equals(ModPartEnum.ITEM))) continue; + objectList.add(obj.getItem()); + } + } + /** + * @implNote
 先有纹理才会成功构建 + */ + private void DefaultModItemModelRegister() { + objectList.forEach(this::basicItem); + } + + /** + * Item generate model. + * + * @param item the item + * @param location the location + */ + public void itemGenerateModel(Item item, ResourceLocation location){ + withExistingParent(itemName(item), GENERATED).texture("layer0", location); + } + + /** + * Item hand held model. + * + * @param item the item + * @param location the location + */ + public void itemHandHeldModel(Item item, ResourceLocation location){ + withExistingParent(itemName(item), HANDHELD).texture("layer0", location); + } + + /** + * Item name string. + * + * @param item the item + * @return the string + */ + public String itemName(Item item){ + return Objects.requireNonNull(ForgeRegistries.ITEMS.getKey(item)).getPath(); + } + + /** + * Resource item resource location. + * + * @param path the path + * @return the resource location + */ + public ResourceLocation resourceItem(String path){ + return modLoc("item/" + path); + } +} diff --git a/src/main/java/top/r3944realms/lib39/example/datagen/provider/ExModelDataProvider.java b/src/main/java/top/r3944realms/lib39/example/datagen/provider/ExModelDataProvider.java deleted file mode 100644 index 1fcd21b..0000000 --- a/src/main/java/top/r3944realms/lib39/example/datagen/provider/ExModelDataProvider.java +++ /dev/null @@ -1,179 +0,0 @@ -package top.r3944realms.lib39.example.datagen.provider; - -import com.google.common.collect.Maps; -import com.google.gson.JsonElement; -import net.minecraft.client.data.models.ItemModelOutput; -import net.minecraft.client.data.models.ModelProvider; -import net.minecraft.client.data.models.blockstates.BlockModelDefinitionGenerator; -import net.minecraft.client.data.models.model.ItemModelUtils; -import net.minecraft.client.data.models.model.ModelInstance; -import net.minecraft.client.data.models.model.ModelLocationUtils; -import net.minecraft.client.renderer.block.model.BlockModelDefinition; -import net.minecraft.client.renderer.item.ClientItem; -import net.minecraft.client.renderer.item.ItemModel; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.data.CachedOutput; -import net.minecraft.data.DataProvider; -import net.minecraft.data.PackOutput; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.item.BlockItem; -import net.minecraft.world.item.Item; -import net.minecraft.world.level.block.Block; -import org.jetbrains.annotations.NotNull; -import top.r3944realms.lib39.example.datagen.generator.ExBlockModelGenerator; -import top.r3944realms.lib39.example.datagen.generator.ExItemModelGenerators; - -import java.nio.file.Path; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.CompletableFuture; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Supplier; -import java.util.stream.Stream; - -public class ExModelDataProvider extends ModelProvider { - private final PackOutput.PathProvider blockStatePathProvider; - private final PackOutput.PathProvider itemInfoPathProvider; - private final PackOutput.PathProvider modelPathProvider; - public ExModelDataProvider(PackOutput packOutput, String modId) { - super(packOutput, modId); - this.blockStatePathProvider = packOutput.createPathProvider(PackOutput.Target.RESOURCE_PACK, "blockstates"); - this.itemInfoPathProvider = packOutput.createPathProvider(PackOutput.Target.RESOURCE_PACK, "items"); - this.modelPathProvider = packOutput.createPathProvider(PackOutput.Target.RESOURCE_PACK, "models"); - } - - @Override - public @NotNull CompletableFuture run(@NotNull CachedOutput cachedOutput) { - - ItemInfoCollector itemModelOutput = new ItemInfoCollector(this::getKnownItems); - BlockStateGeneratorCollector blockModelOutput = new BlockStateGeneratorCollector(this::getKnownBlocks); - SimpleModelCollector modelOutput = new SimpleModelCollector(); - itemModelOutput.finalizeAndValidate(); - this.registerModels(new ExBlockModelGenerator(blockModelOutput, itemModelOutput, modelOutput), new ExItemModelGenerators(itemModelOutput, modelOutput)); - return CompletableFuture.allOf(blockModelOutput.save(cachedOutput, this.blockStatePathProvider), modelOutput.save(cachedOutput, this.modelPathProvider), itemModelOutput.save(cachedOutput, this.itemInfoPathProvider)); - } - - static class ItemInfoCollector implements ItemModelOutput { - private final Map itemInfos; - private final Map copies; - private final Supplier>> knownItems; - - public ItemInfoCollector(Supplier>> knownItems) { - this.itemInfos = new HashMap<>(); - this.copies = new HashMap<>(); - this.knownItems = knownItems; - } - - - public void accept(@NotNull Item item, ItemModel.@NotNull Unbaked model) { - this.register(item, new ClientItem(model, ClientItem.Properties.DEFAULT)); - } - - public void register(@NotNull Item item, @NotNull ClientItem clientItem) { - ClientItem clientitem = this.itemInfos.put(item, clientItem); - if (clientitem != null) { - throw new IllegalStateException("Duplicate item model definition for " + item); - } - } - - public void copy(@NotNull Item item, @NotNull Item copyItem) { - this.copies.put(copyItem, item); - } - - public void finalizeAndValidate() { - (this.knownItems.get()).map(Holder::value).forEach((item) -> { - if (!this.copies.containsKey(item) && item instanceof BlockItem blockitem) { - if (!this.itemInfos.containsKey(blockitem)) { - ResourceLocation resourcelocation = ModelLocationUtils.getModelLocation(blockitem.getBlock()); - this.accept(blockitem, ItemModelUtils.plainModel(resourcelocation)); - } - } - - }); - this.copies.forEach((item, item1) -> { - ClientItem clientitem = this.itemInfos.get(item1); - if (clientitem == null) { - String item1Name = String.valueOf(item1); - throw new IllegalStateException("Missing donor: " + item1Name + " -> " + item); - } else { - this.register(item, clientitem); - } - }); - List list = (this.knownItems.get()).filter((holder) -> !this.itemInfos.containsKey(holder.value())).map((holder) -> holder.unwrapKey().orElseThrow().location()).toList(); - - if (!list.isEmpty()) { - LOGGER.warn("Missing item model definitions for: {}", list); - } - } - - public CompletableFuture save(CachedOutput cachedOutput, PackOutput.PathProvider pathProvider) { - return DataProvider.saveAll(cachedOutput, ClientItem.CODEC, (item) -> pathProvider.json(item.builtInRegistryHolder().key().location()), this.itemInfos); - } - } - - static class SimpleModelCollector implements BiConsumer { - private final Map models = new HashMap<>(); - - SimpleModelCollector() { - } - - public void accept(ResourceLocation resourceLocation, ModelInstance modelInstance) { - Supplier supplier = this.models.put(resourceLocation, modelInstance); - if (supplier != null) { - throw new IllegalStateException("Duplicate model definition for " + resourceLocation); - } - } - - public CompletableFuture save(CachedOutput cachedOutput, PackOutput.PathProvider pathProvider) { - Objects.requireNonNull(pathProvider); - return saveAll(cachedOutput, pathProvider::json, this.models); - } - - static CompletableFuture saveAll(CachedOutput cachedOutput, Function tPathFunction, Map> tMap) { - return DataProvider.saveAll(cachedOutput, Supplier::get, tPathFunction, tMap); - } - } - - static class BlockStateGeneratorCollector implements Consumer { - private final Map generators = new HashMap<>(); - private final Supplier>> knownBlocks; - - public BlockStateGeneratorCollector(Supplier>> knownBlocks) { - this.knownBlocks = knownBlocks; - } - - @Deprecated // Neo: Provided for vanilla/multi-loader compatibility. Use constructor with Supplier parameter. - public BlockStateGeneratorCollector() { - this(BuiltInRegistries.BLOCK::listElements); - } - - public void accept(BlockModelDefinitionGenerator p_405192_) { - Block block = p_405192_.block(); - BlockModelDefinitionGenerator blockmodeldefinitiongenerator = this.generators.put(block, p_405192_); - if (blockmodeldefinitiongenerator != null) { - throw new IllegalStateException("Duplicate blockstate definition for " + block); - } - } - - public void validate() { - Stream> stream = knownBlocks.get(); - List list = stream.filter(p_386843_ -> !this.generators.containsKey(p_386843_.value())) - .map(p_386823_ -> p_386823_.unwrapKey().orElseThrow().location()) - .toList(); - if (!list.isEmpty()) { - throw new IllegalStateException("Missing blockstate definitions for: " + list); - } - } - - public CompletableFuture save(CachedOutput output, PackOutput.PathProvider pathProvider) { - Map map = Maps.transformValues(this.generators, BlockModelDefinitionGenerator::create); - Function function = p_387598_ -> pathProvider.json(p_387598_.builtInRegistryHolder().key().location()); - return DataProvider.saveAll(output, BlockModelDefinition.CODEC, function, map); - } - } -} diff --git a/src/main/java/top/r3944realms/lib39/util/block/BlockRegistryBuilder.java b/src/main/java/top/r3944realms/lib39/util/block/BlockRegistryBuilder.java index 8993f0b..2415ad1 100644 --- a/src/main/java/top/r3944realms/lib39/util/block/BlockRegistryBuilder.java +++ b/src/main/java/top/r3944realms/lib39/util/block/BlockRegistryBuilder.java @@ -4,9 +4,8 @@ import net.minecraft.resources.ResourceKey; import net.minecraft.world.item.CreativeModeTab; import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.level.block.Block; -import net.neoforged.neoforge.registries.DeferredBlock; -import net.neoforged.neoforge.registries.DeferredHolder; -import net.neoforged.neoforge.registries.DeferredRegister; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.RegistryObject; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import top.r3944realms.lib39.core.event.CommonEventHandler; @@ -19,7 +18,7 @@ import java.util.function.Supplier; @SuppressWarnings({"UnusedReturnValue", "unused"}) public class BlockRegistryBuilder { private String registryName; - private DeferredHolder blockObject; + private RegistryObject blockObject; /** * 创建新的构建器实例 @@ -58,7 +57,7 @@ public class BlockRegistryBuilder { * 内部方法:注册对应的方块物品 */ @SafeVarargs - private void registerBlockItem(DeferredHolder blockObject, ResourceKey... creativeTabs) { + private void registerBlockItem(RegistryObject blockObject, ResourceKey... creativeTabs) { CommonEventHandler.Mod.addItemToTabs(blockObject, creativeTabs); } @@ -93,7 +92,7 @@ public class BlockRegistryBuilder { * * @return the registry object */ - public DeferredHolder build() { + public RegistryObject build() { return this.blockObject; } diff --git a/src/main/java/top/r3944realms/lib39/util/capability/EntityCapabilityHelper.java b/src/main/java/top/r3944realms/lib39/util/capability/EntityCapabilityHelper.java deleted file mode 100644 index 63d2cff..0000000 --- a/src/main/java/top/r3944realms/lib39/util/capability/EntityCapabilityHelper.java +++ /dev/null @@ -1,199 +0,0 @@ -package top.r3944realms.lib39.util.capability; - -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.*; -import net.minecraft.world.entity.animal.Animal; -import net.minecraft.world.entity.monster.Monster; -import net.neoforged.neoforge.capabilities.EntityCapability; -import net.neoforged.neoforge.capabilities.ICapabilityProvider; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.Collection; -import java.util.function.Predicate; - -/** - * 实体 Capability 注册工具类 - * 简化批量注册实体能力的过程 - */ -@SuppressWarnings("unused") -public class EntityCapabilityHelper { - - /** - * 为多个实体类型注册相同的 Capability Provider - */ - public static void registerForEntityTypes( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider, - EntityType... entityTypes) { - - if (entityTypes.length == 0) { - throw new IllegalArgumentException("必须提供至少一个实体类型"); - } - - for (EntityType entityType : entityTypes) { - event.registerEntity(capability, entityType, provider); - } - } - - /** - * 为继承自某个基类的所有实体注册 Capability - */ - public static void registerForEntityClass( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider, - Class baseClass) { - - BuiltInRegistries.ENTITY_TYPE.stream() - .filter(entityType -> entityType.getBaseClass().isAssignableFrom(baseClass)) - .forEach(entityType -> event.registerEntity(capability, entityType, provider)); - } - - /** - * 为特定命名空间的所有实体注册 Capability - */ - public static void registerForModEntities( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider, - String namespace) { - - BuiltInRegistries.ENTITY_TYPE.stream() - .filter(entityType -> { - ResourceLocation key = BuiltInRegistries.ENTITY_TYPE.getKey(entityType); - return namespace.equals(key.getNamespace()); - }) - .forEach(entityType -> event.registerEntity(capability, entityType, provider)); - } - - /** - * 为特定生物类别的所有实体注册 Capability - */ - public static void registerForMobCategory( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider, - MobCategory category) { - - BuiltInRegistries.ENTITY_TYPE.stream() - .filter(entityType -> entityType.getCategory() == category) - .forEach(entityType -> event.registerEntity(capability, entityType, provider)); - } - - /** - * 基于条件筛选注册实体 Capability - */ - public static void registerEntitiesByCondition( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider, - Predicate> condition) { - - BuiltInRegistries.ENTITY_TYPE.stream() - .filter(condition) - .forEach(entityType -> event.registerEntity(capability, entityType, provider)); - } - - /** - * 为所有生物实体注册 Capability(包括玩家) - */ - public static void registerForAllLivingEntities( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider) { - - registerForEntityClass(event, capability, provider, LivingEntity.class); - } - - /** - * 为所有怪物实体注册 Capability - */ - public static void registerForAllMonsters( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider) { - - registerForEntityClass(event, capability, provider, Monster.class); - } - - /** - * 为所有动物实体注册 Capability - */ - public static void registerForAllAnimals( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider) { - - registerForEntityClass(event, capability, provider, Animal.class); - } - - /** - * 为所有玩家注册 Capability - */ - public static void registerForPlayers( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider) { - - registerForEntityTypes(event, capability, provider, EntityType.PLAYER); - } - - /** - * 为所有BOSS实体注册 Capability - */ - public static void registerForBossEntities( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider) { - - registerEntitiesByCondition(event, capability, provider, entityType -> - entityType == EntityType.ENDER_DRAGON || - entityType == EntityType.WITHER || - entityType == EntityType.WARDEN - ); - } - - /** - * 排除特定实体类型进行注册 - */ - public static void registerWithExclusions( - RegisterCapabilitiesEvent event, - EntityCapability capability, - ICapabilityProvider provider, - Collection> includedEntities, - EntityType... excludedTypes) { - - Collection> excludedSet = Arrays.asList(excludedTypes); - - includedEntities.stream() - .filter(entityType -> !excludedSet.contains(entityType)) - .forEach(entityType -> event.registerEntity(capability, entityType, provider)); - } - - /** - * 检查某个实体类型是否已经注册了指定的 Capability - */ - public static boolean isEntityCapabilityRegistered( - RegisterCapabilitiesEvent event, - EntityCapability capability, - EntityType entityType) { - - return event.isEntityRegistered(capability, entityType); - } - - /** - * 获取已注册指定 Capability 的实体类型数量 - */ - public static long getRegisteredEntityCount( - RegisterCapabilitiesEvent event, - EntityCapability capability) { - - return BuiltInRegistries.ENTITY_TYPE.stream() - .filter(entityType -> event.isEntityRegistered(capability, entityType)) - .count(); - } -} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/lib39/util/chat/MessageDisplayClientHelper.java b/src/main/java/top/r3944realms/lib39/util/chat/MessageDisplayClientHelper.java deleted file mode 100644 index a63f0b4..0000000 --- a/src/main/java/top/r3944realms/lib39/util/chat/MessageDisplayClientHelper.java +++ /dev/null @@ -1,13 +0,0 @@ -package top.r3944realms.lib39.util.chat; - -import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; - -public class MessageDisplayClientHelper { - public static void sendSystemMessage(Component component) { - sendSystemMessage(component, false); - } - public static void sendSystemMessage(Component component, boolean isOverlay) { - Minecraft.getInstance().execute(() -> Minecraft.getInstance().getChatListener().handleSystemMessage(component, isOverlay)); - } -} diff --git a/src/main/java/top/r3944realms/lib39/util/storage/nbt/NBTReader.java b/src/main/java/top/r3944realms/lib39/util/nbt/NBTReader.java similarity index 67% rename from src/main/java/top/r3944realms/lib39/util/storage/nbt/NBTReader.java rename to src/main/java/top/r3944realms/lib39/util/nbt/NBTReader.java index 184b45b..86a4a08 100644 --- a/src/main/java/top/r3944realms/lib39/util/storage/nbt/NBTReader.java +++ b/src/main/java/top/r3944realms/lib39/util/nbt/NBTReader.java @@ -1,4 +1,19 @@ -package top.r3944realms.lib39.util.storage.nbt; +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.lib39.util.nbt; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -6,6 +21,7 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.UUID; import java.util.function.Consumer; /** @@ -39,8 +55,8 @@ public class NBTReader { */ // 基本读取方法 - 直接赋值给成员变量 public NBTReader string(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getString(key).isPresent()) { - setter.accept(nbt.getString(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getString(key)); } return this; } @@ -54,7 +70,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader string(String key, @NotNull Consumer setter, String defaultValue) { - setter.accept(nbt.contains(key) && nbt.getString(key).isPresent() ? nbt.getString(key).get() : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getString(key) : defaultValue); return this; } @@ -66,8 +82,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader byteValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getByte(key).isPresent()) { - setter.accept(nbt.getByte(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getByte(key)); } return this; } @@ -81,7 +97,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader byteValue(String key, @NotNull Consumer setter, byte defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getByteOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getByte(key) : defaultValue); return this; } @@ -93,8 +109,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader shortValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getShort(key).isPresent()) { - setter.accept(nbt.getShort(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getShort(key)); } return this; } @@ -108,7 +124,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader shortValue(String key, @NotNull Consumer setter, short defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getShortOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getShort(key) : defaultValue); return this; } @@ -120,8 +136,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader intValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getInt(key).isPresent()) { - setter.accept(nbt.getInt(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getInt(key)); } return this; } @@ -135,7 +151,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader intValue(String key, @NotNull Consumer setter, int defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getIntOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getInt(key) : defaultValue); return this; } @@ -147,8 +163,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader longValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getLong(key).isPresent()) { - setter.accept(nbt.getLong(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getLong(key)); } return this; } @@ -162,7 +178,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader longValue(String key, @NotNull Consumer setter, long defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getLongOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getLong(key) : defaultValue); return this; } @@ -174,8 +190,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader floatValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getFloat(key).isPresent()) { - setter.accept(nbt.getFloat(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getFloat(key)); } return this; } @@ -189,9 +205,10 @@ public class NBTReader { * @return the nbt reader */ public NBTReader floatValue(String key, @NotNull Consumer setter, float defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getFloatOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getFloat(key) : defaultValue); return this; } + /** * Double value nbt reader. * @@ -200,8 +217,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader doubleValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getDouble(key).isPresent()) { - setter.accept(nbt.getDouble(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getDouble(key)); } return this; } @@ -215,7 +232,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader doubleValue(String key, @NotNull Consumer setter, double defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getDoubleOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getDouble(key) : defaultValue); return this; } @@ -227,8 +244,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader booleanValue(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getBoolean(key).isPresent()) { - setter.accept(nbt.getBoolean(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getBoolean(key)); } return this; } @@ -242,7 +259,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader booleanValue(String key, @NotNull Consumer setter, boolean defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getBooleanOr(key, defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getBoolean(key) : defaultValue); return this; } @@ -253,26 +270,14 @@ public class NBTReader { * @param setter the setter * @return the nbt reader */ +// 数组类型 public NBTReader byteArray(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getByteArray(key).isPresent()) { - setter.accept(nbt.getByteArray(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getByteArray(key)); } return this; } - /** - * Byte array nbt reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the nbt reader - */ - public NBTReader byteArray(String key, @NotNull Consumer setter, byte[] defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getByteArray(key).orElse(defaultValue) : defaultValue); - return this; - } - /** * Int array nbt reader. * @@ -281,25 +286,12 @@ public class NBTReader { * @return the nbt reader */ public NBTReader intArray(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getIntArray(key).isPresent()) { - setter.accept(nbt.getIntArray(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getIntArray(key)); } return this; } - /** - * Int array nbt reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the nbt reader - */ - public NBTReader intArray(String key, @NotNull Consumer setter, int[] defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getIntArray(key).orElse(defaultValue) : defaultValue); - return this; - } - /** * Long array nbt reader. * @@ -308,22 +300,37 @@ public class NBTReader { * @return the nbt reader */ public NBTReader longArray(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getLongArray(key).isPresent()) { - setter.accept(nbt.getLongArray(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getLongArray(key)); } return this; } /** - * Long array nbt reader. + * Uuid nbt reader. + * + * @param key the key + * @param setter the setter + * @return the nbt reader + */ +// UUID + public NBTReader uuid(String key, Consumer setter) { + if (nbt.hasUUID(key)) { + setter.accept(nbt.getUUID(key)); + } + return this; + } + + /** + * Uuid nbt reader. * * @param key the key * @param setter the setter * @param defaultValue the default value * @return the nbt reader */ - public NBTReader longArray(String key, @NotNull Consumer setter, long[] defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getLongArray(key).orElse(defaultValue) : defaultValue); + public NBTReader uuid(String key, @NotNull Consumer setter, UUID defaultValue) { + setter.accept(nbt.hasUUID(key) ? nbt.getUUID(key) : defaultValue); return this; } @@ -334,10 +341,10 @@ public class NBTReader { * @param setter the setter * @return the nbt reader */ - @SuppressWarnings("UnusedReturnValue") +// CompoundTag public NBTReader compound(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getCompound(key).isPresent()) { - setter.accept(nbt.getCompound(key).get()); + if (nbt.contains(key)) { + setter.accept(nbt.getCompound(key)); } return this; } @@ -351,7 +358,7 @@ public class NBTReader { * @return the nbt reader */ public NBTReader compound(String key, @NotNull Consumer setter, CompoundTag defaultValue) { - setter.accept(nbt.contains(key) ? nbt.getCompound(key).orElse(defaultValue) : defaultValue); + setter.accept(nbt.contains(key) ? nbt.getCompound(key) : defaultValue); return this; } @@ -359,33 +366,14 @@ public class NBTReader { * List nbt reader. * * @param key the key + * @param type the type * @param setter the setter * @return the nbt reader */ - public NBTReader list(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getList(key).isPresent()) { - ListTag list = nbt.getList(key).get(); - if (!list.isEmpty()) { - setter.accept(list); - } - } - return this; - } - - /** - * List nbt reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the nbt reader - */ - public NBTReader list(String key, @NotNull Consumer setter, ListTag defaultValue) { +// ListTag + public NBTReader list(String key, int type, Consumer setter) { if (nbt.contains(key)) { - ListTag list = nbt.getListOrEmpty(key); - setter.accept(list.isEmpty() ? defaultValue : list); - } else { - setter.accept(defaultValue); + setter.accept(nbt.getList(key, type)); } return this; } @@ -397,14 +385,15 @@ public class NBTReader { * @param setter the setter * @return the nbt reader */ +// Vec3支持 public NBTReader vec3(String key, Consumer setter) { - if (nbt.contains(key) && nbt.getCompound(key).isPresent()) { - CompoundTag vecTag = nbt.getCompound(key).get(); + if (nbt.contains(key)) { + CompoundTag vecTag = nbt.getCompound(key); if (vecTag.contains("X") && vecTag.contains("Y") && vecTag.contains("Z")) { setter.accept(new Vec3( - vecTag.getDouble("X").orElse(0.0), - vecTag.getDouble("Y").orElse(0.0), - vecTag.getDouble("Z").orElse(0.0) + vecTag.getDouble("X"), + vecTag.getDouble("Y"), + vecTag.getDouble("Z") )); } } @@ -420,13 +409,13 @@ public class NBTReader { * @return the nbt reader */ public NBTReader vec3(String key, Consumer setter, Vec3 defaultValue) { - if (nbt.contains(key) && nbt.getCompound(key).isPresent()) { - CompoundTag vecTag = nbt.getCompound(key).get(); + if (nbt.contains(key)) { + CompoundTag vecTag = nbt.getCompound(key); if (vecTag.contains("X") && vecTag.contains("Y") && vecTag.contains("Z")) { setter.accept(new Vec3( - vecTag.getDouble("X").orElse(0.0), - vecTag.getDouble("Y").orElse(0.0), - vecTag.getDouble("Z").orElse(0.0) + vecTag.getDouble("X"), + vecTag.getDouble("Y"), + vecTag.getDouble("Z") )); return this; } @@ -444,13 +433,14 @@ public class NBTReader { * @param setter the setter * @return the nbt reader */ +// 枚举支持 public > NBTReader enumValue(String key, Class enumClass, Consumer setter) { - if (nbt.contains(key) && nbt.getString(key).isPresent()) { - String value = nbt.getString(key).get(); + if (nbt.contains(key)) { + String value = nbt.getString(key); try { setter.accept(Enum.valueOf(enumClass, value.toUpperCase())); } catch (IllegalArgumentException ignored) { - + // 保持setter的当前值 } } return this; @@ -467,8 +457,8 @@ public class NBTReader { * @return the nbt reader */ public > NBTReader enumValue(String key, Class enumClass, Consumer setter, T defaultValue) { - if (nbt.contains(key) && nbt.getString(key).isPresent()) { - String value = nbt.getString(key).get(); + if (nbt.contains(key)) { + String value = nbt.getString(key); try { setter.accept(Enum.valueOf(enumClass, value.toUpperCase())); return this; @@ -486,9 +476,10 @@ public class NBTReader { * @param consumer the consumer * @return the nbt reader */ +// 嵌套读取支持 public NBTReader nested(String key, Consumer consumer) { - if (nbt.contains(key) && nbt.getCompound(key).isPresent()) { - consumer.accept(new NBTReader(nbt.getCompound(key).get())); + if (nbt.contains(key)) { + consumer.accept(new NBTReader(nbt.getCompound(key))); } return this; } @@ -502,8 +493,8 @@ public class NBTReader { * @return the nbt reader */ public NBTReader nested(String key, Consumer consumer, Runnable orElse) { - if (nbt.contains(key) && nbt.getCompound(key).isPresent()) { - consumer.accept(new NBTReader(nbt.getCompound(key).get())); + if (nbt.contains(key)) { + consumer.accept(new NBTReader(nbt.getCompound(key))); } else { orElse.run(); } @@ -517,6 +508,7 @@ public class NBTReader { * @param action the action * @return the nbt reader */ +// 条件读取 public NBTReader ifPresent(String key, Runnable action) { if (nbt.contains(key)) { action.run(); @@ -543,6 +535,7 @@ public class NBTReader { * * @return the raw */ +// 获取原始NBT @NotNull public CompoundTag getRaw() { return nbt; @@ -554,13 +547,14 @@ public class NBTReader { * @param nbt the nbt * @return the vec 3 */ +// 便捷的静态方法(保持原有功能) @NotNull public static Vec3 readVec3(@NotNull CompoundTag nbt) { if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) { return new Vec3( - nbt.getDouble("X").orElse(0.0), - nbt.getDouble("Y").orElse(0.0), - nbt.getDouble("Z").orElse(0.0) + nbt.getDouble("X"), + nbt.getDouble("Y"), + nbt.getDouble("Z") ); } else { throw new IllegalArgumentException("NBT is missing X, Y, or Z value for Vec3"); @@ -577,11 +571,11 @@ public class NBTReader { public static Vec3 readVec3Safe(@NotNull CompoundTag nbt) { if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) { return new Vec3( - nbt.getDouble("X").orElse(0.0), - nbt.getDouble("Y").orElse(0.0), - nbt.getDouble("Z").orElse(0.0) + nbt.getDouble("X"), + nbt.getDouble("Y"), + nbt.getDouble("Z") ); } return null; } -} \ No newline at end of file +} diff --git a/src/main/java/top/r3944realms/lib39/util/storage/nbt/NBTWriter.java b/src/main/java/top/r3944realms/lib39/util/nbt/NBTWriter.java similarity index 96% rename from src/main/java/top/r3944realms/lib39/util/storage/nbt/NBTWriter.java rename to src/main/java/top/r3944realms/lib39/util/nbt/NBTWriter.java index 737af11..7235330 100644 --- a/src/main/java/top/r3944realms/lib39/util/storage/nbt/NBTWriter.java +++ b/src/main/java/top/r3944realms/lib39/util/nbt/NBTWriter.java @@ -1,4 +1,4 @@ -package top.r3944realms.lib39.util.storage.nbt; +package top.r3944realms.lib39.util.nbt; import net.minecraft.nbt.*; import net.minecraft.world.phys.Vec3; @@ -6,6 +6,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.UUID; import java.util.function.Consumer; /** @@ -393,6 +394,38 @@ public class NBTWriter { return this; } + /** + * Uuid nbt writer. + * + * @param key the key + * @param value the value + * @return the nbt writer + */ +// UUID支持 + public NBTWriter uuid(String key, UUID value) { + if (value != null) { + root.putUUID(key, value); + } + return this; + } + + /** + * Uuid nbt writer. + * + * @param key the key + * @param value the value + * @param defaultValue the default value + * @return the nbt writer + */ + public NBTWriter uuid(String key, UUID value, UUID defaultValue) { + if (value != null) { + root.putUUID(key, value); + } else if (defaultValue != null) { + root.putUUID(key, defaultValue); + } + return this; + } + /** * Compound nbt writer. * @@ -1028,7 +1061,7 @@ public class NBTWriter { * @return the all keys */ public java.util.Set getAllKeys() { - return root.tags.keySet(); + return root.getAllKeys(); } /** diff --git a/src/main/java/top/r3944realms/lib39/util/riding/RidingApplier.java b/src/main/java/top/r3944realms/lib39/util/riding/RidingApplier.java index d9502e7..9611659 100644 --- a/src/main/java/top/r3944realms/lib39/util/riding/RidingApplier.java +++ b/src/main/java/top/r3944realms/lib39/util/riding/RidingApplier.java @@ -75,7 +75,7 @@ public class RidingApplier { if (RidingValidator.wouldCreateCycle(entity, vehicle)) { throw new RidingCycleException(entityId, vehicleId); } - boolean success = entity.startRiding(vehicle, true, true); + boolean success = entity.startRiding(vehicle, true); if (!success) { Lib39.LOGGER.error("Failed to mount entity {} to vehicle {}", entityId, vehicleId); } diff --git a/src/main/java/top/r3944realms/lib39/util/storage/valueio/ValueInputReader.java b/src/main/java/top/r3944realms/lib39/util/storage/valueio/ValueInputReader.java deleted file mode 100644 index 606d32c..0000000 --- a/src/main/java/top/r3944realms/lib39/util/storage/valueio/ValueInputReader.java +++ /dev/null @@ -1,526 +0,0 @@ -package top.r3944realms.lib39.util.storage.valueio; - - -import com.mojang.serialization.Codec; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; -import java.util.function.Consumer; - -/** - * ValueInput Helper类 - * 提供链式操作和类型安全的ValueInput数据读取 - */ -@SuppressWarnings("unused") -public class ValueInputReader { - private final net.minecraft.world.level.storage.ValueInput valueInput; - - private ValueInputReader(net.minecraft.world.level.storage.ValueInput valueInput) { - this.valueInput = valueInput; - } - - /** - * 从ValueInput创建读取器 - * - * @param valueInput the value input - * @return the value input reader - */ - @NotNull - public static ValueInputReader of(@NotNull net.minecraft.world.level.storage.ValueInput valueInput) { - return new ValueInputReader(valueInput); - } - - /** - * String value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - // 基本读取方法 - 直接赋值给成员变量 - public ValueInputReader string(String key, Consumer setter) { - valueInput.getString(key).ifPresent(setter); - return this; - } - - /** - * String value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader string(String key, @NotNull Consumer setter, String defaultValue) { - setter.accept(valueInput.getStringOr(key, defaultValue)); - return this; - } - - /** - * Boolean value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader booleanValue(String key, Consumer setter) { - valueInput.read(key, Codec.BOOL).ifPresent(setter); - return this; - } - - /** - * Boolean value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader booleanValue(String key, @NotNull Consumer setter, boolean defaultValue) { - setter.accept(valueInput.getBooleanOr(key, defaultValue)); - return this; - } - - /** - * Byte value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader byteValue(String key, Consumer setter) { - valueInput.read(key, Codec.BYTE).ifPresent(setter); - return this; - } - - /** - * Byte value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader byteValue(String key, @NotNull Consumer setter, byte defaultValue) { - setter.accept(valueInput.getByteOr(key, defaultValue)); - return this; - } - - /** - * Short value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader shortValue(String key, Consumer setter) { - valueInput.read(key, Codec.SHORT).ifPresent(setter); - return this; - } - - /** - * Short value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader shortValue(String key, @NotNull Consumer setter, short defaultValue) { - setter.accept((short) valueInput.getShortOr(key, defaultValue)); - return this; - } - - /** - * Int value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader intValue(String key, Consumer setter) { - valueInput.getInt(key).ifPresent(setter); - return this; - } - - /** - * Int value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader intValue(String key, @NotNull Consumer setter, int defaultValue) { - setter.accept(valueInput.getIntOr(key, defaultValue)); - return this; - } - - /** - * Long value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader longValue(String key, Consumer setter) { - valueInput.getLong(key).ifPresent(setter); - return this; - } - - /** - * Long value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader longValue(String key, @NotNull Consumer setter, long defaultValue) { - setter.accept(valueInput.getLongOr(key, defaultValue)); - return this; - } - - /** - * Float value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader floatValue(String key, Consumer setter) { - valueInput.read(key, Codec.FLOAT).ifPresent(setter); - return this; - } - - /** - * Float value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader floatValue(String key, @NotNull Consumer setter, float defaultValue) { - setter.accept(valueInput.getFloatOr(key, defaultValue)); - return this; - } - - /** - * Double value value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader doubleValue(String key, Consumer setter) { - valueInput.read(key, Codec.DOUBLE).ifPresent(setter); - return this; - } - - /** - * Double value value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader doubleValue(String key, @NotNull Consumer setter, double defaultValue) { - setter.accept(valueInput.getDoubleOr(key, defaultValue)); - return this; - } - - /** - * Int array value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader intArray(String key, Consumer setter) { - valueInput.getIntArray(key).ifPresent(setter); - return this; - } - - /** - * Int array value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader intArray(String key, @NotNull Consumer setter, int[] defaultValue) { - setter.accept(valueInput.getIntArray(key).orElse(defaultValue)); - return this; - } - - /** - * Codec value value input reader. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader codecValue(String key, Codec codec, Consumer setter) { - valueInput.read(key, codec).ifPresent(setter); - return this; - } - - /** - * Codec value value input reader. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader codecValue(String key, Codec codec, @NotNull Consumer setter, T defaultValue) { - setter.accept(valueInput.read(key, codec).orElse(defaultValue)); - return this; - } - - /** - * Vec 3 value input reader. - * - * @param key the key - * @param setter the setter - * @return the value input reader - */ - public ValueInputReader vec3(String key, Consumer setter) { - valueInput.child(key).ifPresent(child -> { - try { - Vec3 vec = readVec3(child); - setter.accept(vec); - } catch (IllegalArgumentException ignored) { - // 忽略解析错误 - } - }); - return this; - } - - /** - * Vec 3 value input reader. - * - * @param key the key - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader vec3(String key, Consumer setter, Vec3 defaultValue) { - Optional child = valueInput.child(key); - if (child.isPresent()) { - try { - Vec3 vec = readVec3(child.get()); - setter.accept(vec); - return this; - } catch (IllegalArgumentException ignored) { - // 忽略解析错误,使用默认值 - } - } - setter.accept(defaultValue); - return this; - } - - /** - * Enum value value input reader. - * - * @param the type parameter - * @param key the key - * @param enumClass the enum class - * @param setter the setter - * @return the value input reader - */ - public > ValueInputReader enumValue(String key, Class enumClass, Consumer setter) { - valueInput.getString(key).ifPresent(value -> { - try { - setter.accept(Enum.valueOf(enumClass, value.toUpperCase())); - } catch (IllegalArgumentException ignored) { - // 忽略枚举解析错误 - } - }); - return this; - } - - /** - * Enum value value input reader. - * - * @param the type parameter - * @param key the key - * @param enumClass the enum class - * @param setter the setter - * @param defaultValue the default value - * @return the value input reader - */ - public > ValueInputReader enumValue(String key, Class enumClass, Consumer setter, T defaultValue) { - Optional value = valueInput.getString(key); - if (value.isPresent()) { - try { - setter.accept(Enum.valueOf(enumClass, value.get().toUpperCase())); - return this; - } catch (IllegalArgumentException ignored) { - // 忽略枚举解析错误 - } - } - setter.accept(defaultValue); - return this; - } - - /** - * Nested value input reader. - * - * @param key the key - * @param consumer the consumer - * @return the value input reader - */ - public ValueInputReader nested(String key, Consumer consumer) { - valueInput.child(key).ifPresent(child -> consumer.accept(new ValueInputReader(child))); - return this; - } - - /** - * Nested value input reader. - * - * @param key the key - * @param consumer the consumer - * @param orElse the or else - * @return the value input reader - */ - public ValueInputReader nested(String key, Consumer consumer, Runnable orElse) { - Optional child = valueInput.child(key); - if (child.isPresent()) { - consumer.accept(new ValueInputReader(child.get())); - } else { - orElse.run(); - } - return this; - } - - /** - * List value input reader. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param consumer the consumer - * @return the value input reader - */ - public ValueInputReader list(String key, Codec codec, Consumer> consumer) { - valueInput.list(key, codec).ifPresent(list -> { - if (!list.isEmpty()) { - consumer.accept(list.stream()); - } - }); - return this; - } - - /** - * List value input reader. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param consumer the consumer - * @param defaultValue the default value - * @return the value input reader - */ - public ValueInputReader list(String key, Codec codec, @NotNull Consumer> consumer, java.util.stream.Stream defaultValue) { - Optional> list = valueInput.list(key, codec); - if (list.isPresent() && !list.get().isEmpty()) { - consumer.accept(list.get().stream()); - } else { - consumer.accept(defaultValue); - } - return this; - } - - /** - * Children list value input reader. - * - * @param key the key - * @param consumer the consumer - * @return the value input reader - */ - public ValueInputReader childrenList(String key, Consumer> consumer) { - valueInput.childrenList(key).ifPresent(list -> { - if (!list.isEmpty()) { - consumer.accept(list.stream().map(ValueInputReader::new)); - } - }); - return this; - } - - /** - * If present value input reader. - * - * @param key the key - * @param action the action - * @return the value input reader - */ - public ValueInputReader ifPresent(String key, Runnable action) { - if (valueInput.child(key).isPresent()) { - action.run(); - } - return this; - } - - /** - * If absent value input reader. - * - * @param key the key - * @param action the action - * @return the value input reader - */ - public ValueInputReader ifAbsent(String key, Runnable action) { - if (valueInput.child(key).isEmpty()) { - action.run(); - } - return this; - } - - /** - * Gets raw. - * - * @return the raw - */ - @NotNull - public net.minecraft.world.level.storage.ValueInput getRaw() { - return valueInput; - } - - /** - * Read vec 3 vec 3. - * - * @param valueInput the value input - * @return the vec 3 - */ - @NotNull - public static Vec3 readVec3(@NotNull net.minecraft.world.level.storage.ValueInput valueInput) { - double x = valueInput.getDoubleOr("X", 0.0); - double y = valueInput.getDoubleOr("Y", 0.0); - double z = valueInput.getDoubleOr("Z", 0.0); - return new Vec3(x, y, z); - } - - /** - * Read vec 3 safe vec 3. - * - * @param valueInput the value input - * @return the vec 3 - */ - @Nullable - public static Vec3 readVec3Safe(@NotNull net.minecraft.world.level.storage.ValueInput valueInput) { - try { - return readVec3(valueInput); - } catch (Exception e) { - return null; - } - } -} diff --git a/src/main/java/top/r3944realms/lib39/util/storage/valueio/ValueOutputWriter.java b/src/main/java/top/r3944realms/lib39/util/storage/valueio/ValueOutputWriter.java deleted file mode 100644 index c48af72..0000000 --- a/src/main/java/top/r3944realms/lib39/util/storage/valueio/ValueOutputWriter.java +++ /dev/null @@ -1,634 +0,0 @@ -package top.r3944realms.lib39.util.storage.valueio; - -import com.mojang.serialization.Codec; -import net.minecraft.util.ProblemReporter; -import net.minecraft.world.level.storage.TagValueOutput; -import net.minecraft.world.level.storage.ValueOutput; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.Contract; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; -import java.util.function.Consumer; -import java.util.function.Supplier; - -/** - * ValueOutput Helper类 - * 提供链式操作和类型安全的ValueOutput数据写入 - */ -@SuppressWarnings({"unused", "OptionalUsedAsFieldOrParameterType", "UnusedReturnValue"}) -public class ValueOutputWriter { - private final net.minecraft.world.level.storage.ValueOutput valueOutput; - private ValueOutputWriter() { - this.valueOutput = TagValueOutput.createWithoutContext(ProblemReporter.DISCARDING); - } - private ValueOutputWriter(net.minecraft.world.level.storage.ValueOutput valueOutput) { - this.valueOutput = valueOutput; - } - /** - * 创建一个新的NBT构建器 - * - * @return the nbt writer - */ - @Contract(value = " -> new", pure = true) - public static @NotNull ValueOutputWriter builder() { - return new ValueOutputWriter(); - } - - /** - * 从ValueOutput创建写入器 - * - * @param valueOutput the value output - * @return the value output writer - */ - @NotNull - public static ValueOutputWriter of(@NotNull net.minecraft.world.level.storage.ValueOutput valueOutput) { - return new ValueOutputWriter(valueOutput); - } - - /** - * String value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - // 基本写入方法 - public ValueOutputWriter string(String key, String value) { - if (value != null) { - valueOutput.putString(key, value); - } - return this; - } - - /** - * String value output writer. - * - * @param key the key - * @param value the value - * @param defaultValue the default value - * @return the value output writer - */ - public ValueOutputWriter string(String key, @Nullable String value, String defaultValue) { - valueOutput.putString(key, value != null ? value : defaultValue); - return this; - } - - /** - * String value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter string(String key, Optional value) { - value.ifPresent(v -> valueOutput.putString(key, v)); - return this; - } - - /** - * Boolean value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter booleanValue(String key, boolean value) { - valueOutput.putBoolean(key, value); - return this; - } - - /** - * Boolean value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter booleanValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putBoolean(key, v)); - return this; - } - - /** - * Byte value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter byteValue(String key, byte value) { - valueOutput.putByte(key, value); - return this; - } - - /** - * Byte value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter byteValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putByte(key, v)); - return this; - } - - /** - * Short value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter shortValue(String key, short value) { - valueOutput.putShort(key, value); - return this; - } - - /** - * Short value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter shortValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putShort(key, v)); - return this; - } - - /** - * Int value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter intValue(String key, int value) { - valueOutput.putInt(key, value); - return this; - } - - /** - * Int value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter intValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putInt(key, v)); - return this; - } - - /** - * Long value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter longValue(String key, long value) { - valueOutput.putLong(key, value); - return this; - } - - /** - * Long value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter longValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putLong(key, v)); - return this; - } - - /** - * Float value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter floatValue(String key, float value) { - valueOutput.putFloat(key, value); - return this; - } - - /** - * Float value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter floatValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putFloat(key, v)); - return this; - } - - /** - * Double value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter doubleValue(String key, double value) { - valueOutput.putDouble(key, value); - return this; - } - - /** - * Double value value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter doubleValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putDouble(key, v)); - return this; - } - - /** - * Int array value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter intArray(String key, int[] value) { - if (value != null && value.length > 0) { - valueOutput.putIntArray(key, value); - } - return this; - } - - /** - * Int array value output writer. - * - * @param key the key - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter intArray(String key, Optional value) { - value.ifPresent(v -> { - if (v.length > 0) { - valueOutput.putIntArray(key, v); - } - }); - return this; - } - - /** - * Codec value value output writer. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter codecValue(String key, Codec codec, T value) { - if (value != null) { - valueOutput.store(key, codec, value); - } - return this; - } - - /** - * Codec value value output writer. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter codecValue(String key, Codec codec, Optional value) { - value.ifPresent(v -> valueOutput.store(key, codec, v)); - return this; - } - - /** - * Codec nullable value value output writer. - * - * @param the type parameter - * @param key the key - * @param codec the codec - * @param value the value - * @return the value output writer - */ - public ValueOutputWriter codecNullable(String key, Codec codec, @Nullable T value) { - valueOutput.storeNullable(key, codec, value); - return this; - } - - /** - * Vec 3 value output writer. - * - * @param key the key - * @param vec the vec - * @return the value output writer - */ - public ValueOutputWriter vec3(String key, Vec3 vec) { - if (vec != null) { - ValueOutput child = valueOutput.child(key); - writeVec3(child, vec); - } - return this; - } - - /** - * Vec 3 value output writer. - * - * @param key the key - * @param vec the vec - * @return the value output writer - */ - public ValueOutputWriter vec3(String key, Optional vec) { - vec.ifPresent(v -> vec3(key, v)); - return this; - } - - /** - * Enum value value output writer. - * - * @param the type parameter - * @param key the key - * @param value the value - * @return the value output writer - */ - public > ValueOutputWriter enumValue(String key, T value) { - if (value != null) { - valueOutput.putString(key, value.name().toLowerCase()); - } - return this; - } - - /** - * Enum value value output writer. - * - * @param the type parameter - * @param key the key - * @param value the value - * @return the value output writer - */ - public > ValueOutputWriter enumValue(String key, Optional value) { - value.ifPresent(v -> valueOutput.putString(key, v.name().toLowerCase())); - return this; - } - - /** - * Nested value output writer. - * - * @param key the key - * @param consumer the consumer - * @return the value output writer - */ - public ValueOutputWriter nested(String key, Consumer consumer) { - ValueOutput child = valueOutput.child(key); - consumer.accept(new ValueOutputWriter(child)); - return this; - } - - /** - * Nested if present value output writer. - * - * @param key the key - * @param supplier the supplier - * @param consumer the consumer - * @return the value output writer - */ - public ValueOutputWriter nestedIfPresent(String key, Supplier supplier, Consumer consumer) { - if (supplier.get()) { - ValueOutput child = valueOutput.child(key); - consumer.accept(new ValueOutputWriter(child)); - } - return this; - } - - /** - * List value output writer. - * - * @param the type parameter - * @param key the key - * @param elementCodec the element codec - * @param elements the elements - * @param consumer the consumer - * @return the value output writer - */ - public ValueOutputWriter list(String key, Codec elementCodec, Iterable elements, Consumer> consumer) { - ValueOutput.TypedOutputList list = valueOutput.list(key, elementCodec); - if (!list.isEmpty()) { - TypedListWriter writer = new TypedListWriter<>(list); - consumer.accept(writer); - } - return this; - } - - /** - * List value output writer. - * - * @param the type parameter - * @param key the key - * @param elementCodec the element codec - * @param elements the elements - * @return the value output writer - */ - public ValueOutputWriter list(String key, Codec elementCodec, Iterable elements) { - ValueOutput.TypedOutputList list = valueOutput.list(key, elementCodec); - for (T element : elements) { - if (element != null) { - list.add(element); - } - } - return this; - } - - /** - * Children list value output writer. - * - * @param key the key - * @param consumer the consumer - * @return the value output writer - */ - public ValueOutputWriter childrenList(String key, Consumer consumer) { - ValueOutput.ValueOutputList list = valueOutput.childrenList(key); - if (!list.isEmpty()) { - ChildrenListWriter writer = new ChildrenListWriter(list); - consumer.accept(writer); - } - return this; - } - - /** - * If present value output writer. - * - * @param condition the condition - * @param action the action - * @return the value output writer - */ - public ValueOutputWriter ifPresent(boolean condition, Consumer action) { - if (condition) { - action.accept(this); - } - return this; - } - - /** - * If present value output writer. - * - * @param condition the condition - * @param action the action - * @return the value output writer - */ - public ValueOutputWriter ifPresent(Supplier condition, Consumer action) { - if (condition.get()) { - action.accept(this); - } - return this; - } - - /** - * Discard value output writer. - * - * @param key the key - * @return the value output writer - */ - public ValueOutputWriter discard(String key) { - valueOutput.discard(key); - return this; - } - - /** - * Gets raw. - * - * @return the raw - */ - @NotNull - public net.minecraft.world.level.storage.ValueOutput getRaw() { - return valueOutput; - } - - /** - * Write vec 3. - * - * @param valueOutput the value output - * @param vec the vec - */ - public static void writeVec3(@NotNull net.minecraft.world.level.storage.ValueOutput valueOutput, @NotNull Vec3 vec) { - valueOutput.putDouble("X", vec.x); - valueOutput.putDouble("Y", vec.y); - valueOutput.putDouble("Z", vec.z); - } - - /** - * Write vec 3 safe. - * - * @param valueOutput the value output - * @param vec the vec - */ - public static void writeVec3Safe(@NotNull net.minecraft.world.level.storage.ValueOutput valueOutput, @Nullable Vec3 vec) { - if (vec != null) { - writeVec3(valueOutput, vec); - } - } - - /** - * The type Typed list writer. - * - * @param the type parameter - */ - public static class TypedListWriter { - private final ValueOutput.TypedOutputList list; - - private TypedListWriter(ValueOutput.TypedOutputList list) { - this.list = list; - } - - /** - * Add typed list writer. - * - * @param element the element - * @return the typed list writer - */ - public TypedListWriter add(T element) { - if (element != null) { - list.add(element); - } - return this; - } - - /** - * Add all typed list writer. - * - * @param elements the elements - * @return the typed list writer - */ - public TypedListWriter addAll(Iterable elements) { - for (T element : elements) { - if (element != null) { - list.add(element); - } - } - return this; - } - - /** - * Is empty boolean. - * - * @return the boolean - */ - public boolean isEmpty() { - return list.isEmpty(); - } - } - - /** - * The type Children list writer. - */ - public static class ChildrenListWriter { - private final ValueOutput.ValueOutputList list; - - private ChildrenListWriter(ValueOutput.ValueOutputList list) { - this.list = list; - } - - /** - * Add child value output writer. - * - * @param consumer the consumer - * @return the children list writer - */ - public ChildrenListWriter addChild(Consumer consumer) { - ValueOutput child = list.addChild(); - consumer.accept(new ValueOutputWriter(child)); - return this; - } - - /** - * Discard last children list writer. - * - * @return the children list writer - */ - public ChildrenListWriter discardLast() { - list.discardLast(); - return this; - } - - /** - * Is empty boolean. - * - * @return the boolean - */ - public boolean isEmpty() { - return list.isEmpty(); - } - } -} diff --git a/src/main/templates/META-INF/accesstransformer.cfg b/src/main/templates/META-INF/accesstransformer.cfg deleted file mode 100644 index d83d96a..0000000 --- a/src/main/templates/META-INF/accesstransformer.cfg +++ /dev/null @@ -1,3 +0,0 @@ -# private -> public -public net.minecraft.server.level.ServerPlayer server -public net.minecraft.nbt.CompoundTag tags \ No newline at end of file diff --git a/src/main/templates/META-INF/neoforge.mods.toml b/src/main/templates/META-INF/mods.toml similarity index 82% rename from src/main/templates/META-INF/neoforge.mods.toml rename to src/main/templates/META-INF/mods.toml index a06dfcd..07e87be 100644 --- a/src/main/templates/META-INF/neoforge.mods.toml +++ b/src/main/templates/META-INF/mods.toml @@ -1,3 +1,14 @@ +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory + +# A version range to match for said mod loader - for regular FML @Mod it will be the Forge version +loaderVersion="${loader_version_range}" #mandatory This is typically bumped every Minecraft version by Forge. See download page for lists of versions. + # The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. # Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. license="${mod_license}" @@ -46,18 +57,14 @@ authors="${mod_authors}" #optional # The description text for the mod (multi line!) (#mandatory) description='''${mod_description}''' - -[[accessTransformers]] -file="META-INF/accesstransformer.cfg" - # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. [[dependencies.${mod_id}]] #optional # the modid of the dependency - modId="neoforge" #mandatory + modId="forge" #mandatory # Does this dependency have to exist - if not, ordering below must be specified - type="required" + mandatory=true #mandatory # The version range of the dependency - versionRange="[${neo_version},)" #mandatory + versionRange="${forge_version_range}" #mandatory # An ordering relationship for the dependency - BEFORE or AFTER required if the dependency is not mandatory # BEFORE - This mod is loaded BEFORE the dependency # AFTER - This mod is loaded AFTER the dependency @@ -68,7 +75,7 @@ file="META-INF/accesstransformer.cfg" # Here's another dependency [[dependencies.${mod_id}]] modId="minecraft" - type="required" + mandatory=true # This version range declares a minimum of the current minecraft version up to but not including the next major version versionRange="${minecraft_version_range}" ordering="NONE" diff --git a/src/main/templates/pack.mcmeta b/src/main/templates/pack.mcmeta new file mode 100644 index 0000000..ae03c9b --- /dev/null +++ b/src/main/templates/pack.mcmeta @@ -0,0 +1,6 @@ +{ + "pack": { + "description": "${mod_name} resources", + "pack_format": 15 + } +}