将SyncDataManager修改为更通用的同步管理
This commit is contained in:
parent
4f7a030843
commit
cf1b6dba5b
307
build.gradle
307
build.gradle
|
|
@ -8,12 +8,11 @@ plugins {
|
||||||
id 'net.neoforged.moddev.legacyforge' version '2.0.103'
|
id 'net.neoforged.moddev.legacyforge' version '2.0.103'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain.languageVersion = JavaLanguageVersion.of(17)
|
||||||
|
}
|
||||||
|
|
||||||
tasks.named('wrapper', Wrapper).configure {
|
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
|
distributionType = Wrapper.DistributionType.BIN
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -25,6 +24,11 @@ repositories {
|
||||||
maven { url = "https://libraries.minecraft.net/" }
|
maven { url = "https://libraries.minecraft.net/" }
|
||||||
maven { url = "https://neoforged.forgecdn.net/releases" }
|
maven { url = "https://neoforged.forgecdn.net/releases" }
|
||||||
maven { url = "https://neoforged.forgecdn.net/mojang-meta" }
|
maven { url = "https://neoforged.forgecdn.net/mojang-meta" }
|
||||||
|
maven { url = "https://maven.neoforged.net/releases" }
|
||||||
|
maven {
|
||||||
|
name = "LTD Maven"
|
||||||
|
url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/"
|
||||||
|
}
|
||||||
flatDir {
|
flatDir {
|
||||||
dir "libs"
|
dir "libs"
|
||||||
}
|
}
|
||||||
|
|
@ -46,16 +50,10 @@ legacyForge {
|
||||||
minecraftVersion = project.parchment_minecraft_version
|
minecraftVersion = project.parchment_minecraft_version
|
||||||
}
|
}
|
||||||
|
|
||||||
// This line is optional. Access Transformers are automatically detected
|
|
||||||
// accessTransformers = project.files('src/main/resources/META-INF/accesstransformer.cfg')
|
|
||||||
|
|
||||||
// Default run configurations.
|
// Default run configurations.
|
||||||
// These can be tweaked, removed, or duplicated as needed.
|
|
||||||
runs {
|
runs {
|
||||||
client {
|
client {
|
||||||
client()
|
client()
|
||||||
|
|
||||||
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
|
|
||||||
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
|
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
|
||||||
}
|
}
|
||||||
clientAuth{
|
clientAuth{
|
||||||
|
|
@ -70,9 +68,6 @@ legacyForge {
|
||||||
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
|
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 {
|
gameTestServer {
|
||||||
type = "gameTestServer"
|
type = "gameTestServer"
|
||||||
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
|
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
|
||||||
|
|
@ -80,35 +75,16 @@ legacyForge {
|
||||||
|
|
||||||
data {
|
data {
|
||||||
data()
|
data()
|
||||||
|
|
||||||
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
|
|
||||||
// gameDirectory = project.file('run-data')
|
|
||||||
|
|
||||||
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
|
|
||||||
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
|
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 {
|
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'
|
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
|
logLevel = org.slf4j.event.Level.DEBUG
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mods {
|
mods {
|
||||||
// define mod <-> source bindings
|
|
||||||
// these are used to tell the game which sources are for which mod
|
|
||||||
// mostly optional in a single mod project
|
|
||||||
// but multi mod projects should define one per mod
|
|
||||||
"${mod_id}" {
|
"${mod_id}" {
|
||||||
sourceSet(sourceSets.main)
|
sourceSet(sourceSets.main)
|
||||||
}
|
}
|
||||||
|
|
@ -118,10 +94,6 @@ legacyForge {
|
||||||
// Include resources generated by data generators.
|
// Include resources generated by data generators.
|
||||||
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
sourceSets.main.resources { srcDir 'src/generated/resources' }
|
||||||
|
|
||||||
// Sets up a dependency configuration called 'localRuntime' and a deobfuscating one called 'modLocalRuntime'
|
|
||||||
// These configurations 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 {
|
configurations {
|
||||||
runtimeClasspath.extendsFrom localRuntime
|
runtimeClasspath.extendsFrom localRuntime
|
||||||
}
|
}
|
||||||
|
|
@ -130,52 +102,11 @@ obfuscation {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// If you wish to declare dependencies against mods, make sure to use the 'mod*' configurations so that they're remapped.
|
// 依赖项可以在这里添加
|
||||||
// See https://github.com/neoforged/ModDevGradle/blob/main/LEGACY.md#remapping-mod-dependencies for more information.
|
|
||||||
|
|
||||||
// Example optional mod dependency with JEI
|
|
||||||
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
|
|
||||||
// modCompileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
|
|
||||||
// modCompileOnly "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
|
|
||||||
// modLocalRuntime "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"
|
|
||||||
// modImplementation "blank:coolmod-${mc_version}:${coolmod_version}"
|
|
||||||
|
|
||||||
// Example mod dependency using a file as dependency
|
|
||||||
// modImplementation files("libs/coolmod-${mc_version}-${coolmod_version}.jar")
|
|
||||||
|
|
||||||
// Example project dependency using a sister or child project:
|
|
||||||
// modImplementation 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uncomment the lines below if you wish to configure mixin. The mixin file should be named modid.mixins.json.
|
|
||||||
/*
|
|
||||||
mixin {
|
|
||||||
add sourceSets.main, "${mod_id}.refmap.json"
|
|
||||||
config "${mod_id}.mixins.json"
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest.attributes([
|
|
||||||
"MixinConfigs": "${mod_id}.mixins.json"
|
|
||||||
])
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
// This block of code expands all declared replace properties in the specified resource targets.
|
// 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 generateModMetadata = tasks.register("generateModMetadata", ProcessResources) {
|
||||||
var replaceProperties = [
|
var replaceProperties = [
|
||||||
minecraft_version : minecraft_version,
|
minecraft_version : minecraft_version,
|
||||||
|
|
@ -191,39 +122,239 @@ var generateModMetadata = tasks.register("generateModMetadata", ProcessResources
|
||||||
mod_description : mod_description,
|
mod_description : mod_description,
|
||||||
mod_credits : mod_credits
|
mod_credits : mod_credits
|
||||||
]
|
]
|
||||||
|
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||||
inputs.properties replaceProperties
|
inputs.properties replaceProperties
|
||||||
expand replaceProperties
|
expand replaceProperties
|
||||||
from "src/main/templates"
|
from "src/main/templates"
|
||||||
into "build/generated/sources/modMetadata"
|
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
|
sourceSets.main.resources.srcDir generateModMetadata
|
||||||
// To avoid having to run "generateModMetadata" manually, make it run on every project reload
|
|
||||||
legacyForge.ideSyncTask generateModMetadata
|
legacyForge.ideSyncTask generateModMetadata
|
||||||
|
|
||||||
// Example configuration to allow publishing using the maven-publish plugin
|
// ==================== 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 {
|
publishing {
|
||||||
publications {
|
publications {
|
||||||
register('mavenJava', MavenPublication) {
|
mavenJava(MavenPublication) {
|
||||||
from components.java
|
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 {
|
repositories {
|
||||||
|
// 本地仓库
|
||||||
maven {
|
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 {
|
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 {
|
idea {
|
||||||
module {
|
module {
|
||||||
downloadSources = true
|
downloadSources = true
|
||||||
downloadJavadoc = 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -33,7 +33,7 @@ mod_name=3944Realms 's Lib Mod
|
||||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||||
mod_license=MIT
|
mod_license=MIT
|
||||||
# The mod version. See https://semver.org/
|
# The mod version. See https://semver.org/
|
||||||
mod_version=0.0.14
|
mod_version=0.0.16
|
||||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||||
# This should match the base package used for the mod sources.
|
# This should match the base package used for the mod sources.
|
||||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,44 @@ import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import top.r3944realms.lib39.core.network.NetworkHandler;
|
import top.r3944realms.lib39.core.network.NetworkHandler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Lib 39.
|
||||||
|
*/
|
||||||
@Mod(Lib39.MOD_ID)
|
@Mod(Lib39.MOD_ID)
|
||||||
public class Lib39 {
|
public class Lib39 {
|
||||||
|
/**
|
||||||
|
* The constant MOD_ID.
|
||||||
|
*/
|
||||||
public static final String MOD_ID = "lib39";
|
public static final String MOD_ID = "lib39";
|
||||||
|
/**
|
||||||
|
* The constant LOGGER.
|
||||||
|
*/
|
||||||
public static final Logger LOGGER = LoggerFactory.getLogger(Lib39.class);
|
public static final Logger LOGGER = LoggerFactory.getLogger(Lib39.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Lib 39.
|
||||||
|
*/
|
||||||
public Lib39() {
|
public Lib39() {
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize.
|
||||||
|
*/
|
||||||
public static void initialize() {
|
public static void initialize() {
|
||||||
LOGGER.info("[Lib39] Initializing Lib39");
|
LOGGER.info("[Lib39] Initializing Lib39");
|
||||||
NetworkHandler.register();
|
NetworkHandler.register();
|
||||||
LOGGER.info("[Lib39] Initialized Lib39");
|
LOGGER.info("[Lib39] Initialized Lib39");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Mod info.
|
||||||
|
*/
|
||||||
public static class ModInfo {
|
public static class ModInfo {
|
||||||
|
/**
|
||||||
|
* The constant VERSION.
|
||||||
|
*/
|
||||||
public static final String VERSION;
|
public static final String VERSION;
|
||||||
static {
|
static {
|
||||||
// 从 ModList 获取当前 ModContainer 的元数据
|
// 从 ModList 获取当前 ModContainer 的元数据
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
package top.r3944realms.lib39.api.event;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Register compat event.
|
||||||
|
*/
|
||||||
|
public class RegisterCompatEvent extends Event implements IModBusEvent {
|
||||||
|
/**
|
||||||
|
* The Compat manager.
|
||||||
|
*/
|
||||||
|
protected final CompatManager compatManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Register compat event.
|
||||||
|
*
|
||||||
|
* @param compatManager the compat manager
|
||||||
|
*/
|
||||||
|
public RegisterCompatEvent(CompatManager compatManager) {
|
||||||
|
this.compatManager = compatManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets compat manager.
|
||||||
|
*
|
||||||
|
* @return the compat manager
|
||||||
|
*/
|
||||||
|
public CompatManager getCompatManager() {
|
||||||
|
return compatManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register compat.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @param compat the compat
|
||||||
|
*/
|
||||||
|
// 注册兼容模块
|
||||||
|
public void registerCompat(ResourceLocation id, ICompat compat) {
|
||||||
|
compatManager.registerCompat(id, compat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register compat.
|
||||||
|
*
|
||||||
|
* @param namespace the namespace
|
||||||
|
* @param path the path
|
||||||
|
* @param compat the compat
|
||||||
|
*/
|
||||||
|
// 注册兼容模块(简化版本)
|
||||||
|
public void registerCompat(String namespace, String path, ICompat compat) {
|
||||||
|
compatManager.registerCompat(namespace, path, compat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister compat.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
// 取消注册兼容模块
|
||||||
|
public void unregisterCompat(ResourceLocation id) {
|
||||||
|
compatManager.unregisterCompat(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,43 +1,93 @@
|
||||||
package top.r3944realms.lib39.api.event;
|
package top.r3944realms.lib39.api.event;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
import net.minecraftforge.common.capabilities.Capability;
|
||||||
import net.minecraftforge.eventbus.api.Event;
|
import net.minecraftforge.eventbus.api.Event;
|
||||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||||
import top.r3944realms.lib39.core.sync.ISyncManager;
|
import top.r3944realms.lib39.core.sync.ISyncManager;
|
||||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Sync manager register event.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class SyncManagerRegisterEvent extends Event {
|
public class SyncManagerRegisterEvent extends Event {
|
||||||
|
/**
|
||||||
|
* The Syncs 2 manager.
|
||||||
|
*/
|
||||||
protected final SyncData2Manager syncs2Manager;
|
protected final SyncData2Manager syncs2Manager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Sync manager register event.
|
||||||
|
*
|
||||||
|
* @param syncsManager the syncs manager
|
||||||
|
*/
|
||||||
public SyncManagerRegisterEvent(SyncData2Manager syncsManager) {
|
public SyncManagerRegisterEvent(SyncData2Manager syncsManager) {
|
||||||
this.syncs2Manager = syncsManager;
|
this.syncs2Manager = syncsManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets syncs manager.
|
||||||
|
*
|
||||||
|
* @return the syncs manager
|
||||||
|
*/
|
||||||
public SyncData2Manager getSyncsManager() {
|
public SyncData2Manager getSyncsManager() {
|
||||||
return syncs2Manager;
|
return syncs2Manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 类型安全的同步管理器注册
|
* 类型安全的同步管理器注册
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param id the id
|
||||||
|
* @param syncManager the sync manager
|
||||||
|
* @param capability the capability
|
||||||
*/
|
*/
|
||||||
public <K, T extends ISyncData<?>> void registerSyncManager(
|
public <K, T extends ISyncData<?>> void registerSyncManager(
|
||||||
ResourceLocation id,
|
ResourceLocation id,
|
||||||
ISyncManager<K, T> syncManager,
|
ISyncManager<K, T> syncManager,
|
||||||
Capability<T> capability
|
Capability<T> capability
|
||||||
) {
|
) {
|
||||||
syncs2Manager.registerManager(id, syncManager, capability);
|
syncs2Manager.registerManager(id, syncManager, entity -> entity.getCapability(capability).resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类型安全的同步管理器注册
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param id the id
|
||||||
|
* @param syncManager the sync manager
|
||||||
|
* @param dataProvider the dataProvider
|
||||||
|
*/
|
||||||
|
public <K, T extends ISyncData<?>> void registerSyncManager(
|
||||||
|
ResourceLocation id,
|
||||||
|
ISyncManager<K, T> syncManager,
|
||||||
|
Function<Entity, Optional<T>> dataProvider
|
||||||
|
) {
|
||||||
|
syncs2Manager.registerManager(id, syncManager, dataProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister sync manager.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
public void unregisterSyncManager(ResourceLocation id) {
|
public void unregisterSyncManager(ResourceLocation id) {
|
||||||
syncs2Manager.removeManager(id);
|
syncs2Manager.removeManager(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 允许实体类
|
* 允许实体类
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @param entityClasses the entity classes
|
||||||
*/
|
*/
|
||||||
public final void addAllowEntityClass(ResourceLocation id, Class<?>... entityClasses) {
|
public final void addAllowEntityClass(ResourceLocation id, Class<?>... entityClasses) {
|
||||||
syncs2Manager.allowEntityClass(id, entityClasses);
|
syncs2Manager.allowEntityClass(id, entityClasses);
|
||||||
|
|
@ -45,6 +95,9 @@ public class SyncManagerRegisterEvent extends Event {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除允许的实体类
|
* 移除允许的实体类
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @param entityClasses the entity classes
|
||||||
*/
|
*/
|
||||||
public final void removeAllowEntityClass(ResourceLocation id, Class<?>... entityClasses) {
|
public final void removeAllowEntityClass(ResourceLocation id, Class<?>... entityClasses) {
|
||||||
syncs2Manager.disallowEntityClass(id, entityClasses);
|
syncs2Manager.disallowEntityClass(id, entityClasses);
|
||||||
|
|
@ -52,21 +105,33 @@ public class SyncManagerRegisterEvent extends Event {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定能力(用于分离注册的情况)
|
* 绑定能力(用于分离注册的情况)
|
||||||
* @param id 必须先注册安全同步管理器,再绑定Cap,否则会抛出{@link IllegalStateException 未找到对应安全同步管理器}
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param id 必须先注册安全同步管理器,再绑定Cap,否则会抛出{@link IllegalStateException 未找到对应安全同步管理器}
|
||||||
|
* @param capability the capability
|
||||||
*/
|
*/
|
||||||
public <T extends ISyncData<?>> void bindCapability(ResourceLocation id, Capability<T> capability) {
|
public <T extends ISyncData<?>> void bindCapability(ResourceLocation id, Capability<T> capability) {
|
||||||
syncs2Manager.bindCapability(id, capability);
|
syncs2Manager.bindDataGetter(id, entity -> entity.getCapability(capability).resolve());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解绑能力
|
* 解绑数据提供者
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
*/
|
*/
|
||||||
public void unbindCapability(ResourceLocation id) {
|
public void unbindDataProvider(ResourceLocation id) {
|
||||||
syncs2Manager.unbindCapability(id);
|
syncs2Manager.unbindDataProvider(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 完整的类型安全注册
|
* 完整的类型安全注册
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param id the id
|
||||||
|
* @param syncManager the sync manager
|
||||||
|
* @param capability the capability
|
||||||
|
* @param allowedEntityClasses the allowed entity classes
|
||||||
*/
|
*/
|
||||||
public <K, T extends ISyncData<?>> void registerComplete(
|
public <K, T extends ISyncData<?>> void registerComplete(
|
||||||
ResourceLocation id,
|
ResourceLocation id,
|
||||||
|
|
@ -79,4 +144,26 @@ public class SyncManagerRegisterEvent extends Event {
|
||||||
addAllowEntityClass(id, allowedEntityClasses);
|
addAllowEntityClass(id, allowedEntityClasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 完整的类型安全注册
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param id the id
|
||||||
|
* @param syncManager the sync manager
|
||||||
|
* @param dataProvider the capability
|
||||||
|
* @param allowedEntityClasses the allowed entity classes
|
||||||
|
*/
|
||||||
|
public <K, T extends ISyncData<?>> void registerComplete(
|
||||||
|
ResourceLocation id,
|
||||||
|
ISyncManager<K, T> syncManager,
|
||||||
|
Function<Entity, Optional<T>> dataProvider,
|
||||||
|
Class<?>... allowedEntityClasses
|
||||||
|
) {
|
||||||
|
registerSyncManager(id, syncManager, dataProvider);
|
||||||
|
if (allowedEntityClasses.length > 0) {
|
||||||
|
addAllowEntityClass(id, allowedEntityClasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,332 @@
|
||||||
|
package top.r3944realms.lib39.core.compat;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
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;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Compat manager.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class CompatManager {
|
||||||
|
private final Map<ResourceLocation, ICompat> compats = new HashMap<>();
|
||||||
|
private final IEventBus modEventBus, gameEventBus;
|
||||||
|
|
||||||
|
// 存储事件监听器配置
|
||||||
|
private final List<ListenerConfig> listenerConfigs = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Compat manager.
|
||||||
|
*
|
||||||
|
* @param modEventBus the mod event bus
|
||||||
|
* @param gameEventBus the game event bus
|
||||||
|
*/
|
||||||
|
public CompatManager(IEventBus modEventBus, IEventBus gameEventBus) {
|
||||||
|
this.modEventBus = modEventBus;
|
||||||
|
this.gameEventBus = gameEventBus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register compat.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @param compat the compat
|
||||||
|
*/
|
||||||
|
public void registerCompat(ResourceLocation id, ICompat compat) {
|
||||||
|
if (compats.containsKey(id)) {
|
||||||
|
Lib39.LOGGER.warn("Compat with id {} is already registered!", id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
compats.put(id, compat);
|
||||||
|
Lib39.LOGGER.debug("Registered compat: {}", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register compat.
|
||||||
|
*
|
||||||
|
* @param namespace the namespace
|
||||||
|
* @param path the path
|
||||||
|
* @param compat the compat
|
||||||
|
*/
|
||||||
|
public void registerCompat(String namespace, String path, ICompat compat) {
|
||||||
|
registerCompat(new ResourceLocation(namespace, path), compat);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为所有兼容模块配置事件监听器
|
||||||
|
*
|
||||||
|
* @param dists the dists
|
||||||
|
* @param bus the bus
|
||||||
|
*/
|
||||||
|
public void addListenerForAll(@Nullable Dist dists, Mod.EventBusSubscriber.Bus bus) {
|
||||||
|
listenerConfigs.add(new ListenerConfig(null, dists, bus));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为特定兼容模块配置事件监听器
|
||||||
|
*
|
||||||
|
* @param compatId the compat id
|
||||||
|
* @param dists the dists
|
||||||
|
* @param bus the bus
|
||||||
|
*/
|
||||||
|
public void addListenerForCompat(ResourceLocation compatId, @Nullable Dist dists, Mod.EventBusSubscriber.Bus bus) {
|
||||||
|
listenerConfigs.add(new ListenerConfig(compatId, dists, bus));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 为已加载的兼容模块配置事件监听器
|
||||||
|
*
|
||||||
|
* @param dists the dists
|
||||||
|
* @param bus the bus
|
||||||
|
* @param consumer the consumer
|
||||||
|
*/
|
||||||
|
public void addListenerForLoaded(@Nullable Dist dists, Mod.EventBusSubscriber.Bus bus, Consumer<IEventBus> consumer) {
|
||||||
|
listenerConfigs.add(new ListenerConfig(null, dists, bus) {
|
||||||
|
@Override
|
||||||
|
boolean shouldApply(@NotNull ICompat compat) {
|
||||||
|
return super.shouldApply(compat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== 初始化和管理 =====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 初始化所有兼容模块并应用事件监听器
|
||||||
|
*/
|
||||||
|
public void initializeAll() {
|
||||||
|
Lib39.LOGGER.info("Initializing {} compatibility modules", compats.size());
|
||||||
|
|
||||||
|
// 1. 先初始化所有兼容模块
|
||||||
|
for (Map.Entry<ResourceLocation, ICompat> entry : compats.entrySet()) {
|
||||||
|
try {
|
||||||
|
entry.getValue().initialize();
|
||||||
|
Lib39.LOGGER.info("Initialized compat: {}", entry.getKey());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Lib39.LOGGER.error("Failed to initialize compat: {}", entry.getKey(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 然后应用所有事件监听器
|
||||||
|
applyAllEventListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用所有配置的事件监听器到对应的 ICompat 实例
|
||||||
|
*/
|
||||||
|
private void applyAllEventListeners() {
|
||||||
|
Lib39.LOGGER.info("Applying {} event listener configurations", listenerConfigs.size());
|
||||||
|
|
||||||
|
for (ListenerConfig config : listenerConfigs) {
|
||||||
|
if (config.compatId == null) {
|
||||||
|
// 应用到所有兼容模块
|
||||||
|
applyListenerToAllCompats(config);
|
||||||
|
} else {
|
||||||
|
// 应用到特定兼容模块
|
||||||
|
applyListenerToCompat(config.compatId, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将监听器应用到所有兼容模块
|
||||||
|
*/
|
||||||
|
private void applyListenerToAllCompats(ListenerConfig config) {
|
||||||
|
for (ICompat compat : compats.values()) {
|
||||||
|
if (config.shouldApply(compat)) {
|
||||||
|
applyListenerToCompat(compat, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将监听器应用到特定兼容模块
|
||||||
|
*/
|
||||||
|
private void applyListenerToCompat(ResourceLocation compatId, ListenerConfig config) {
|
||||||
|
ICompat compat = compats.get(compatId);
|
||||||
|
if (compat != null && config.shouldApply(compat)) {
|
||||||
|
applyListenerToCompat(compat, config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将监听器应用到具体的 ICompat 实例
|
||||||
|
*/
|
||||||
|
private void applyListenerToCompat(ICompat compat, ListenerConfig config) {
|
||||||
|
try {
|
||||||
|
// 根据配置调用对应的 ICompat 方法
|
||||||
|
if (config.dists != null) {
|
||||||
|
switch (config.dists) {
|
||||||
|
case CLIENT -> {
|
||||||
|
if (config.bus == Mod.EventBusSubscriber.Bus.FORGE) {
|
||||||
|
compat.addClientGameListener(gameEventBus);
|
||||||
|
} else {
|
||||||
|
compat.addClientModListener(modEventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case DEDICATED_SERVER -> {
|
||||||
|
if (config.bus == Mod.EventBusSubscriber.Bus.FORGE) {
|
||||||
|
compat.addServerGameListener(gameEventBus);
|
||||||
|
} else {
|
||||||
|
compat.addServerModListener(modEventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 通用监听器
|
||||||
|
if (config.bus == Mod.EventBusSubscriber.Bus.FORGE) {
|
||||||
|
compat.addCommonGameListener(gameEventBus);
|
||||||
|
} else {
|
||||||
|
compat.addCommonModListener(modEventBus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lib39.LOGGER.debug("Applied {} listener to compat: {}",
|
||||||
|
getListenerTypeName(config), compat.id());
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Lib39.LOGGER.error("Failed to apply listener to compat: {}", compat.id(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取监听器类型名称(用于日志)
|
||||||
|
*/
|
||||||
|
private @NotNull String getListenerTypeName(@NotNull ListenerConfig config) {
|
||||||
|
if (config.dists != null) {
|
||||||
|
return config.dists.name().toLowerCase() + " " +
|
||||||
|
(config.bus == Mod.EventBusSubscriber.Bus.FORGE ? "game" : "mod");
|
||||||
|
} else {
|
||||||
|
return "common " + (config.bus == Mod.EventBusSubscriber.Bus.FORGE ? "game" : "mod");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== 便捷方法 =====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add listener for all.
|
||||||
|
*
|
||||||
|
* @param bus the bus
|
||||||
|
*/
|
||||||
|
public void addListenerForAll(Mod.EventBusSubscriber.Bus bus) {
|
||||||
|
addListenerForAll(null, bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add listener for compat.
|
||||||
|
*
|
||||||
|
* @param compatId the compat id
|
||||||
|
* @param bus the bus
|
||||||
|
*/
|
||||||
|
public void addListenerForCompat(ResourceLocation compatId, Mod.EventBusSubscriber.Bus bus) {
|
||||||
|
addListenerForCompat(compatId, null, bus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class ListenerConfig {
|
||||||
|
/**
|
||||||
|
* The Compat id.
|
||||||
|
*/
|
||||||
|
final ResourceLocation compatId;
|
||||||
|
/**
|
||||||
|
* The Dists.
|
||||||
|
*/
|
||||||
|
final Dist dists;
|
||||||
|
/**
|
||||||
|
* The Bus.
|
||||||
|
*/
|
||||||
|
final Mod.EventBusSubscriber.Bus bus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Listener config.
|
||||||
|
*
|
||||||
|
* @param compatId the compat id
|
||||||
|
* @param dists the dists
|
||||||
|
* @param bus the bus
|
||||||
|
*/
|
||||||
|
ListenerConfig(ResourceLocation compatId, Dist dists, Mod.EventBusSubscriber.Bus bus) {
|
||||||
|
this.compatId = compatId;
|
||||||
|
this.dists = dists;
|
||||||
|
this.bus = bus;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should apply boolean.
|
||||||
|
*
|
||||||
|
* @param compat the compat
|
||||||
|
* @return the boolean
|
||||||
|
*/
|
||||||
|
boolean shouldApply(@NotNull ICompat compat) {
|
||||||
|
return compat.isModLoaded();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================== 其他方法 =====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On load complete.
|
||||||
|
*/
|
||||||
|
public void onLoadComplete() {
|
||||||
|
Lib39.LOGGER.info("Calling onLoadComplete for {} compatibility modules", compats.size());
|
||||||
|
for (Map.Entry<ResourceLocation, ICompat> entry : compats.entrySet()) {
|
||||||
|
try {
|
||||||
|
entry.getValue().onLoadComplete();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Lib39.LOGGER.error("Error in onLoadComplete for compat: {}", entry.getKey(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets compat.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return the compat
|
||||||
|
*/
|
||||||
|
public Optional<ICompat> getCompat(ResourceLocation id) {
|
||||||
|
return Optional.ofNullable(compats.get(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Has compat boolean.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
* @return the boolean
|
||||||
|
*/
|
||||||
|
public boolean hasCompat(ResourceLocation id) {
|
||||||
|
return compats.containsKey(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister compat.
|
||||||
|
*
|
||||||
|
* @param id the id
|
||||||
|
*/
|
||||||
|
public void unregisterCompat(ResourceLocation id) {
|
||||||
|
ICompat removed = compats.remove(id);
|
||||||
|
if (removed != null) {
|
||||||
|
Lib39.LOGGER.debug("Unregistered compat: {}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets loaded compats.
|
||||||
|
*
|
||||||
|
* @return the loaded compats
|
||||||
|
*/
|
||||||
|
public List<ICompat> getLoadedCompats() {
|
||||||
|
return compats.values().stream()
|
||||||
|
.filter(ICompat::isModLoaded)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
132
src/main/java/top/r3944realms/lib39/core/compat/ICompat.java
Normal file
132
src/main/java/top/r3944realms/lib39/core/compat/ICompat.java
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
package top.r3944realms.lib39.core.compat;
|
||||||
|
|
||||||
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
|
|
||||||
|
import java.util.concurrent.Callable;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface Compat.
|
||||||
|
*/
|
||||||
|
public interface ICompat {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Id resource location.
|
||||||
|
*
|
||||||
|
* @return the resource location
|
||||||
|
*/
|
||||||
|
ResourceLocation id();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize.
|
||||||
|
*/
|
||||||
|
void initialize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On load complete.
|
||||||
|
*/
|
||||||
|
default void onLoadComplete() {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is mod loaded boolean.
|
||||||
|
*
|
||||||
|
* @return the boolean
|
||||||
|
*/
|
||||||
|
default boolean isModLoaded() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call if present t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param callable the callable
|
||||||
|
* @return the t
|
||||||
|
* @throws Exception the exception
|
||||||
|
*/
|
||||||
|
default <T> T callIfPresent(Callable<T> callable) throws Exception {
|
||||||
|
if (isModLoaded()) return callable.call();
|
||||||
|
else return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call if pesent t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param callable the callable
|
||||||
|
* @param elseCall the else call
|
||||||
|
* @return the t
|
||||||
|
* @throws Exception the exception
|
||||||
|
*/
|
||||||
|
default <T> T callIfPresent(Callable<T> callable, Callable<T> elseCall) throws Exception {
|
||||||
|
if (isModLoaded()) return callable.call();
|
||||||
|
else return elseCall.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run if present boolean.
|
||||||
|
*
|
||||||
|
* @param runnable the runnable
|
||||||
|
* @return the boolean
|
||||||
|
* @throws Exception the exception
|
||||||
|
*/
|
||||||
|
default boolean runIfPresent(Runnable runnable) throws Exception {
|
||||||
|
if (isModLoaded()) runnable.run(); else return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add common game listener.
|
||||||
|
*
|
||||||
|
* @param gameBus the game bus
|
||||||
|
*/
|
||||||
|
default void addCommonGameListener(IEventBus gameBus) {
|
||||||
|
// 实现通用游戏事件监听器添加逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add common mod listener.
|
||||||
|
*
|
||||||
|
* @param modBus the mod bus
|
||||||
|
*/
|
||||||
|
default void addCommonModListener(IEventBus modBus) {
|
||||||
|
// 实现通用模组事件监听器添加逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add client game listener.
|
||||||
|
*
|
||||||
|
* @param gameBus the game bus
|
||||||
|
*/
|
||||||
|
default void addClientGameListener(IEventBus gameBus) {
|
||||||
|
// 实现客户端游戏事件监听器添加逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add client mod listener.
|
||||||
|
*
|
||||||
|
* @param modBus the mod bus
|
||||||
|
*/
|
||||||
|
default void addClientModListener(IEventBus modBus) {
|
||||||
|
// 实现客户端模组事件监听器添加逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add server game listener.
|
||||||
|
*
|
||||||
|
* @param gameBus the game bus
|
||||||
|
*/
|
||||||
|
default void addServerGameListener(IEventBus gameBus) {
|
||||||
|
// 实现服务端游戏事件监听器添加逻辑
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add server mod listener.
|
||||||
|
*
|
||||||
|
* @param modBus the mod bus
|
||||||
|
*/
|
||||||
|
default void addServerModListener(IEventBus modBus) {
|
||||||
|
// 实现服务端模组事件监听器添加逻辑
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package top.r3944realms.lib39.core.event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Client handler.
|
||||||
|
*/
|
||||||
|
public class ClientEventHandler {
|
||||||
|
}
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
package top.r3944realms.lib39.core.event;
|
|
||||||
|
|
||||||
public class ClientHandler {
|
|
||||||
}
|
|
||||||
|
|
@ -13,11 +13,16 @@ import net.minecraftforge.event.TickEvent;
|
||||||
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
|
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
|
||||||
import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
|
import net.minecraftforge.event.entity.EntityLeaveLevelEvent;
|
||||||
import net.minecraftforge.event.level.LevelEvent;
|
import net.minecraftforge.event.level.LevelEvent;
|
||||||
|
import net.minecraftforge.eventbus.api.IEventBus;
|
||||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
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 net.minecraftforge.registries.RegistryObject;
|
||||||
import top.r3944realms.lib39.Lib39;
|
import top.r3944realms.lib39.Lib39;
|
||||||
|
import top.r3944realms.lib39.api.event.RegisterCompatEvent;
|
||||||
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
|
import top.r3944realms.lib39.api.event.SyncManagerRegisterEvent;
|
||||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
import top.r3944realms.lib39.core.sync.ISyncData;
|
||||||
|
import top.r3944realms.lib39.core.compat.CompatManager;
|
||||||
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
import top.r3944realms.lib39.core.sync.SyncData2Manager;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
@ -25,44 +30,82 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
public class CommonHandler {
|
/**
|
||||||
|
* The type Common handler.
|
||||||
|
*/
|
||||||
|
public class CommonEventHandler {
|
||||||
|
/**
|
||||||
|
* The type Game.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Lib39.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE)
|
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Lib39.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.FORGE)
|
||||||
public static class Game extends CommonHandler {
|
public static class Game extends CommonEventHandler {
|
||||||
private static ServerLevel sl;
|
private static ServerLevel sl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets server level.
|
||||||
|
*
|
||||||
|
* @return the server level
|
||||||
|
*/
|
||||||
public static ServerLevel getServerLevel() {
|
public static ServerLevel getServerLevel() {
|
||||||
return sl;
|
return sl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Sync data 2 manager.
|
||||||
|
*/
|
||||||
static volatile SyncData2Manager syncData2Manager;
|
static volatile SyncData2Manager syncData2Manager;
|
||||||
private static boolean isInitialized = false;
|
private static boolean isSync2MInitialized = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets sync data 2 manager.
|
||||||
|
*
|
||||||
|
* @return the sync data 2 manager
|
||||||
|
*/
|
||||||
public static SyncData2Manager getSyncData2Manager() {
|
public static SyncData2Manager getSyncData2Manager() {
|
||||||
return syncData2Manager;
|
return syncData2Manager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On world load.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onWorldLoad(LevelEvent.Load event) {
|
public static void onWorldLoad(LevelEvent.Load event) {
|
||||||
if (event.getLevel().isClientSide() || !(event.getLevel() instanceof ServerLevel serverLevel)) return;
|
if (event.getLevel().isClientSide() || !(event.getLevel() instanceof ServerLevel serverLevel)) return;
|
||||||
// 只处理主世界(避免多次初始化)
|
// 只处理主世界(避免多次初始化)
|
||||||
if (!serverLevel.dimension().equals(Level.OVERWORLD)) return;
|
if (!serverLevel.dimension().equals(Level.OVERWORLD)) return;
|
||||||
synchronized (Game.class) {
|
synchronized (Game.class) {
|
||||||
if (!isInitialized) {
|
if (!isSync2MInitialized) {
|
||||||
syncData2Manager = new SyncData2Manager();
|
syncData2Manager = new SyncData2Manager();
|
||||||
MinecraftForge.EVENT_BUS.post(new SyncManagerRegisterEvent(syncData2Manager));
|
MinecraftForge.EVENT_BUS.post(new SyncManagerRegisterEvent(syncData2Manager));
|
||||||
isInitialized = true;
|
isSync2MInitialized = true;
|
||||||
sl = serverLevel;
|
sl = serverLevel;
|
||||||
Lib39.LOGGER.info("SyncData2Manager initialized on world load");
|
Lib39.LOGGER.info("SyncData2Manager initialized on world load");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On world unload.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onWorldUnload(LevelEvent.Unload event) {
|
public static void onWorldUnload(LevelEvent.Unload event) {
|
||||||
if (event.getLevel().isClientSide() || !(event.getLevel() instanceof ServerLevel serverLevel)) return;
|
if (event.getLevel().isClientSide() || !(event.getLevel() instanceof ServerLevel serverLevel)) return;
|
||||||
if (!serverLevel.dimension().equals(Level.OVERWORLD)) return;
|
if (!serverLevel.dimension().equals(Level.OVERWORLD)) return;
|
||||||
|
|
||||||
sl = null;
|
sl = null;
|
||||||
isInitialized = false;
|
isSync2MInitialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On server tick.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onServerTick(TickEvent.ServerTickEvent event) {
|
public static void onServerTick(TickEvent.ServerTickEvent event) {
|
||||||
if (event.phase == TickEvent.Phase.END) {
|
if (event.phase == TickEvent.Phase.END) {
|
||||||
|
|
@ -72,6 +115,12 @@ public class CommonHandler {
|
||||||
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
|
syncData2Manager.forEach(((resourceLocation, iSyncManager) -> iSyncManager.foreach(ISyncData::checkIfDirtyThenUpdate)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On entity join world.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onEntityJoinWorld(EntityJoinLevelEvent event) {
|
public static void onEntityJoinWorld(EntityJoinLevelEvent event) {
|
||||||
Entity entity = event.getEntity();
|
Entity entity = event.getEntity();
|
||||||
|
|
@ -83,6 +132,12 @@ public class CommonHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On entity leave world.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onEntityLeaveWorld(EntityLeaveLevelEvent event) {
|
public static void onEntityLeaveWorld(EntityLeaveLevelEvent event) {
|
||||||
Entity entity = event.getEntity();
|
Entity entity = event.getEntity();
|
||||||
|
|
@ -95,12 +150,51 @@ public class CommonHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Mod.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Lib39.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD)
|
@net.minecraftforge.fml.common.Mod.EventBusSubscriber(modid = Lib39.MOD_ID, bus = net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus.MOD)
|
||||||
public static class Mod extends CommonHandler {
|
public static class Mod extends CommonEventHandler {
|
||||||
private static final Map<RegistryObject<Block>, ResourceKey<CreativeModeTab>[]> itemAddMap = new ConcurrentHashMap<>();
|
private static final Map<RegistryObject<Block>, ResourceKey<CreativeModeTab>[]> itemAddMap = new ConcurrentHashMap<>();
|
||||||
private static final Map<ResourceKey<CreativeModeTab>, List<RegistryObject<Block>>> tabToItemsMap = new ConcurrentHashMap<>();
|
private static final Map<ResourceKey<CreativeModeTab>, List<RegistryObject<Block>>> tabToItemsMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets compat manager.
|
||||||
|
*
|
||||||
|
* @return the compat manager
|
||||||
|
*/
|
||||||
|
public static CompatManager getCompatManager() {
|
||||||
|
return compatManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Compat manager.
|
||||||
|
*/
|
||||||
|
static volatile CompatManager compatManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On fml common setup.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
|
@SubscribeEvent
|
||||||
|
public static void onFMLCommonSetup (FMLCommonSetupEvent event) {
|
||||||
|
event.enqueueWork(() -> {
|
||||||
|
IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||||
|
IEventBus gameBus = MinecraftForge.EVENT_BUS;
|
||||||
|
compatManager = new CompatManager(modBus, gameBus);
|
||||||
|
MinecraftForge.EVENT_BUS.post(new RegisterCompatEvent(compatManager));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add item to tabs.
|
||||||
|
*
|
||||||
|
* @param item the item
|
||||||
|
* @param tabs the tabs
|
||||||
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
public static void addItemToTabs(RegistryObject<Block> item, ResourceKey<CreativeModeTab>... tabs) {
|
public static void addItemToTabs(RegistryObject<Block> item, ResourceKey<CreativeModeTab>... tabs) {
|
||||||
itemAddMap.put(item, tabs);
|
itemAddMap.put(item, tabs);
|
||||||
|
|
@ -111,6 +205,11 @@ public class CommonHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* On build creative tab contents.
|
||||||
|
*
|
||||||
|
* @param event the event
|
||||||
|
*/
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public static void onBuildCreativeTabContents(BuildCreativeModeTabContentsEvent event) {
|
public static void onBuildCreativeTabContents(BuildCreativeModeTabContentsEvent event) {
|
||||||
List<RegistryObject<Block>> itemsForTab = tabToItemsMap.get(event.getTabKey());
|
List<RegistryObject<Block>> itemsForTab = tabToItemsMap.get(event.getTabKey());
|
||||||
|
|
@ -119,6 +218,11 @@ public class CommonHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets item add map.
|
||||||
|
*
|
||||||
|
* @return the item add map
|
||||||
|
*/
|
||||||
public static Map<RegistryObject<Block>, ResourceKey<CreativeModeTab>[]> getItemAddMap() {
|
public static Map<RegistryObject<Block>, ResourceKey<CreativeModeTab>[]> getItemAddMap() {
|
||||||
return itemAddMap;
|
return itemAddMap;
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
package top.r3944realms.lib39.core.event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Server handler.
|
||||||
|
*/
|
||||||
|
public class ServerEventHandler {
|
||||||
|
}
|
||||||
|
|
@ -1,4 +0,0 @@
|
||||||
package top.r3944realms.lib39.core.event;
|
|
||||||
|
|
||||||
public class ServerHandler {
|
|
||||||
}
|
|
||||||
|
|
@ -8,28 +8,66 @@ import net.minecraftforge.network.PacketDistributor;
|
||||||
import net.minecraftforge.network.simple.SimpleChannel;
|
import net.minecraftforge.network.simple.SimpleChannel;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import top.r3944realms.lib39.Lib39;
|
import top.r3944realms.lib39.Lib39;
|
||||||
import top.r3944realms.lib39.core.network.toClient.SyncNBTDataS2CPack;
|
import top.r3944realms.lib39.core.network.toClient.SyncNBTCapDataEntityS2CPack;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Network handler.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class NetworkHandler {
|
public class NetworkHandler {
|
||||||
private static int cid = 0;
|
private static int cid = 0;
|
||||||
|
/**
|
||||||
|
* The constant INSTANCE.
|
||||||
|
*/
|
||||||
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
|
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
|
||||||
new ResourceLocation(Lib39.MOD_ID, "main"),
|
new ResourceLocation(Lib39.MOD_ID, "main"),
|
||||||
() -> Lib39.ModInfo.VERSION,
|
() -> Lib39.ModInfo.VERSION,
|
||||||
Lib39.ModInfo.VERSION::equals,
|
Lib39.ModInfo.VERSION::equals,
|
||||||
Lib39.ModInfo.VERSION::equals
|
Lib39.ModInfo.VERSION::equals
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register.
|
||||||
|
*/
|
||||||
public static void register() {
|
public static void register() {
|
||||||
INSTANCE.messageBuilder(SyncNBTDataS2CPack.class, cid++, NetworkDirection.PLAY_TO_CLIENT)
|
INSTANCE.messageBuilder(SyncNBTCapDataEntityS2CPack.class, cid++, NetworkDirection.PLAY_TO_CLIENT)
|
||||||
.encoder(SyncNBTDataS2CPack::encode)
|
.encoder(SyncNBTCapDataEntityS2CPack::encode)
|
||||||
.decoder(SyncNBTDataS2CPack::decode)
|
.decoder(SyncNBTCapDataEntityS2CPack::decode)
|
||||||
.consumerNetworkThread(SyncNBTDataS2CPack::handle)
|
.consumerNetworkThread(SyncNBTCapDataEntityS2CPack::handle)
|
||||||
.add();
|
.add();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send to player.
|
||||||
|
*
|
||||||
|
* @param <MSG> the type parameter
|
||||||
|
* @param message the message
|
||||||
|
* @param player the player
|
||||||
|
*/
|
||||||
public static <MSG> void sendToPlayer(MSG message, ServerPlayer player){
|
public static <MSG> void sendToPlayer(MSG message, ServerPlayer player){
|
||||||
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
|
INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send to player.
|
||||||
|
*
|
||||||
|
* @param <MSG> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param message the message
|
||||||
|
* @param entity the entity
|
||||||
|
* @param packetDistributor the packet distributor
|
||||||
|
*/
|
||||||
public static <MSG, T> void sendToPlayer(MSG message, T entity, @NotNull PacketDistributor<T> packetDistributor){
|
public static <MSG, T> void sendToPlayer(MSG message, T entity, @NotNull PacketDistributor<T> packetDistributor){
|
||||||
INSTANCE.send(packetDistributor.with(() -> entity), message);
|
INSTANCE.send(packetDistributor.with(() -> entity), message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send to player.
|
||||||
|
*
|
||||||
|
* @param <MSG> the type parameter
|
||||||
|
* @param message the message
|
||||||
|
*/
|
||||||
|
public static <MSG> void sendToAllPlayer(MSG message){
|
||||||
|
INSTANCE.send(PacketDistributor.ALL.noArg(), message);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,95 @@
|
||||||
|
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.common.capabilities.Capability;
|
||||||
|
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<NetworkEvent.Context> 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<SyncData2Manager.DataProvider<Entity, ISyncData<?>>> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,60 +0,0 @@
|
||||||
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.common.capabilities.Capability;
|
|
||||||
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.CommonHandler;
|
|
||||||
import top.r3944realms.lib39.core.sync.ISyncData;
|
|
||||||
import top.r3944realms.lib39.core.sync.NBTSyncData;
|
|
||||||
|
|
||||||
import java.util.Optional;
|
|
||||||
import java.util.function.Supplier;
|
|
||||||
|
|
||||||
public record SyncNBTDataS2CPack(int entityId, ResourceLocation id, CompoundTag data) {
|
|
||||||
|
|
||||||
public SyncNBTDataS2CPack(int entityId, ResourceLocation id, @NotNull NBTSyncData data) {
|
|
||||||
this(entityId, data.id(), data.serializeNBT());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void encode(@NotNull SyncNBTDataS2CPack msg, @NotNull FriendlyByteBuf buffer) {
|
|
||||||
buffer.writeInt(msg.entityId);
|
|
||||||
buffer.writeResourceLocation(msg.id);
|
|
||||||
buffer.writeNbt(msg.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Contract("_ -> new")
|
|
||||||
public static @NotNull SyncNBTDataS2CPack decode(@NotNull FriendlyByteBuf buffer) {
|
|
||||||
return new SyncNBTDataS2CPack(buffer.readInt(), buffer.readResourceLocation(), buffer.readNbt());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void handle(SyncNBTDataS2CPack msg, @NotNull Supplier<NetworkEvent.Context> 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<ISyncData<?>>> capability = CommonHandler.Game.getSyncData2Manager().getCapability(msg.id);
|
|
||||||
capability.ifPresent(dataCapability -> entity.getCapability(dataCapability).ifPresent(cap -> {
|
|
||||||
if (cap instanceof NBTSyncData 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -8,6 +8,9 @@ import top.r3944realms.lib39.datagen.value.McLocale;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Locale registry.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class LocaleRegistry {
|
public class LocaleRegistry {
|
||||||
private static final Map<String, ILocaleEntry> REGISTRY = new LinkedHashMap<>();
|
private static final Map<String, ILocaleEntry> REGISTRY = new LinkedHashMap<>();
|
||||||
|
|
@ -19,23 +22,43 @@ public class LocaleRegistry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 注册(覆盖已有时直接返回旧值) */
|
/**
|
||||||
|
* 注册(覆盖已有时直接返回旧值) @param entry the entry
|
||||||
|
*
|
||||||
|
* @param entry the entry
|
||||||
|
* @return the locale entry
|
||||||
|
*/
|
||||||
@SuppressWarnings("UnusedReturnValue")
|
@SuppressWarnings("UnusedReturnValue")
|
||||||
public static ILocaleEntry register(ILocaleEntry entry) {
|
public static ILocaleEntry register(ILocaleEntry entry) {
|
||||||
return REGISTRY.putIfAbsent(entry.mcCode().toLowerCase(), entry);
|
return REGISTRY.putIfAbsent(entry.mcCode().toLowerCase(), entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 通过 Minecraft 代码查找 */
|
/**
|
||||||
|
* 通过 Minecraft 代码查找 @param code the code
|
||||||
|
*
|
||||||
|
* @param code the code
|
||||||
|
* @return the locale entry
|
||||||
|
*/
|
||||||
public static ILocaleEntry fromMcCode(@NotNull String code) {
|
public static ILocaleEntry fromMcCode(@NotNull String code) {
|
||||||
return REGISTRY.get(code.toLowerCase());
|
return REGISTRY.get(code.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 列出所有 */
|
/**
|
||||||
|
* 列出所有 @return the collection
|
||||||
|
*
|
||||||
|
* @return the collection
|
||||||
|
*/
|
||||||
public static @NotNull @UnmodifiableView Collection<ILocaleEntry> allValues() {
|
public static @NotNull @UnmodifiableView Collection<ILocaleEntry> allValues() {
|
||||||
return Collections.unmodifiableCollection(REGISTRY.values());
|
return Collections.unmodifiableCollection(REGISTRY.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 动态注册一个扩展 Locale */
|
/**
|
||||||
|
* 动态注册一个扩展 Locale @param mcCode the mc code
|
||||||
|
*
|
||||||
|
* @param mcCode the mc code
|
||||||
|
* @param locale the locale
|
||||||
|
* @return the locale entry
|
||||||
|
*/
|
||||||
public static ILocaleEntry registerDynamic(@NotNull String mcCode, Locale locale) {
|
public static ILocaleEntry registerDynamic(@NotNull String mcCode, Locale locale) {
|
||||||
return REGISTRY.computeIfAbsent(mcCode.toLowerCase(),
|
return REGISTRY.computeIfAbsent(mcCode.toLowerCase(),
|
||||||
k -> new ExtendedLocale(mcCode.toLowerCase(), locale));
|
k -> new ExtendedLocale(mcCode.toLowerCase(), locale));
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,12 @@ package top.r3944realms.lib39.core.sync;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Cached sync manager.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public abstract class CachedSyncManager<K, T extends ISyncData<?>> implements ISyncManager<K, T> {
|
public abstract class CachedSyncManager<K, T extends ISyncData<?>> implements ISyncManager<K, T> {
|
||||||
|
|
||||||
|
|
|
||||||
13
src/main/java/top/r3944realms/lib39/core/sync/IEntity.java
Normal file
13
src/main/java/top/r3944realms/lib39/core/sync/IEntity.java
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
package top.r3944realms.lib39.core.sync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface Entity.
|
||||||
|
*/
|
||||||
|
public interface IEntity {
|
||||||
|
/**
|
||||||
|
* Entity id int.
|
||||||
|
*
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
|
int entityId();
|
||||||
|
}
|
||||||
|
|
@ -2,13 +2,49 @@ package top.r3944realms.lib39.core.sync;
|
||||||
|
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface Sync data.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
*/
|
||||||
public interface ISyncData<T> {
|
public interface ISyncData<T> {
|
||||||
|
/**
|
||||||
|
* Id resource location.
|
||||||
|
*
|
||||||
|
* @return the resource location
|
||||||
|
*/
|
||||||
ResourceLocation id();
|
ResourceLocation id();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is dirty boolean.
|
||||||
|
*
|
||||||
|
* @return the boolean
|
||||||
|
*/
|
||||||
boolean isDirty();
|
boolean isDirty();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets dirty.
|
||||||
|
*
|
||||||
|
* @param dirty the dirty
|
||||||
|
*/
|
||||||
void setDirty(boolean dirty);
|
void setDirty(boolean dirty);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make dirty.
|
||||||
|
*/
|
||||||
default void makeDirty() {
|
default void makeDirty() {
|
||||||
setDirty(true);
|
setDirty(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy from.
|
||||||
|
*
|
||||||
|
* @param src the src
|
||||||
|
*/
|
||||||
void copyFrom(T src);
|
void copyFrom(T src);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if dirty then update.
|
||||||
|
*/
|
||||||
void checkIfDirtyThenUpdate();
|
void checkIfDirtyThenUpdate();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,26 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface Sync manager.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public interface ISyncManager<K, T extends ISyncData<?>> {
|
public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取同步映射
|
* 获取同步映射
|
||||||
|
*
|
||||||
|
* @return the sync map
|
||||||
*/
|
*/
|
||||||
Map<K, T> getSyncMap();
|
Map<K, T> getSyncMap();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取同步集合
|
* 获取同步集合
|
||||||
|
*
|
||||||
|
* @return the sync set
|
||||||
*/
|
*/
|
||||||
default Set<T> getSyncSet() {
|
default Set<T> getSyncSet() {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -22,6 +32,9 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 跟踪实例
|
* 跟踪实例
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param instance the instance
|
||||||
*/
|
*/
|
||||||
default void track(K key, T instance) {
|
default void track(K key, T instance) {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -33,6 +46,9 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消跟踪
|
* 取消跟踪
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param instance the instance
|
||||||
*/
|
*/
|
||||||
default void untrack(K key, T instance) {
|
default void untrack(K key, T instance) {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -45,6 +61,8 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 遍历操作
|
* 遍历操作
|
||||||
|
*
|
||||||
|
* @param consumer the consumer
|
||||||
*/
|
*/
|
||||||
default void foreach(Consumer<T> consumer) {
|
default void foreach(Consumer<T> consumer) {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -56,6 +74,8 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量操作
|
* 批量操作
|
||||||
|
*
|
||||||
|
* @param instances the instances
|
||||||
*/
|
*/
|
||||||
default void trackAll(Map<K, T> instances) {
|
default void trackAll(Map<K, T> instances) {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -67,6 +87,8 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取大小
|
* 获取大小
|
||||||
|
*
|
||||||
|
* @return the int
|
||||||
*/
|
*/
|
||||||
default int size() {
|
default int size() {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -75,6 +97,9 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否包含key
|
* 检查是否包含key
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
default boolean containsKey(K key) {
|
default boolean containsKey(K key) {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
@ -83,6 +108,9 @@ public interface ISyncManager<K, T extends ISyncData<?>> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否包含value
|
* 检查是否包含value
|
||||||
|
*
|
||||||
|
* @param value the value
|
||||||
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
default boolean containsValue(T value) {
|
default boolean containsValue(T value) {
|
||||||
Map<K, T> syncMap = getSyncMap();
|
Map<K, T> syncMap = getSyncMap();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
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<NBTEntitySyncData>, INBTSerializable<CompoundTag> {
|
||||||
|
/**
|
||||||
|
* 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()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
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;
|
|
||||||
|
|
||||||
public abstract class NBTSyncData implements ISyncData<NBTSyncData>, INBTSerializable<CompoundTag> {
|
|
||||||
protected boolean dirty;
|
|
||||||
protected final ResourceLocation id;
|
|
||||||
|
|
||||||
protected NBTSyncData(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 NBTSyncData src) {
|
|
||||||
this.dirty = src.isDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -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<ResourceLocation, TypedSyncEntry<?, ?>> typedEntries = Maps.newConcurrentMap();
|
||||||
|
|
||||||
|
private static class TypedSyncEntry<K, T extends ISyncData<?>> {
|
||||||
|
/**
|
||||||
|
* The Manager.
|
||||||
|
*/
|
||||||
|
final ISyncManager<K, T> manager;
|
||||||
|
/**
|
||||||
|
* The Capability.
|
||||||
|
*/
|
||||||
|
@Nullable
|
||||||
|
Capability<T> capability;
|
||||||
|
/**
|
||||||
|
* The Allowed classes.
|
||||||
|
*/
|
||||||
|
final Set<Class<?>> allowedClasses;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Typed sync entry.
|
||||||
|
*
|
||||||
|
* @param manager the manager
|
||||||
|
* @param capability the capability
|
||||||
|
*/
|
||||||
|
TypedSyncEntry(ISyncManager<K, T> manager, @Nullable Capability<T> capability) {
|
||||||
|
this.manager = manager;
|
||||||
|
this.capability = capability;
|
||||||
|
this.allowedClasses = Sets.newConcurrentHashSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register manager.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param manager the manager
|
||||||
|
* @param capability the capability
|
||||||
|
*/
|
||||||
|
public <K, T extends ISyncData<?>> void registerManager(
|
||||||
|
ResourceLocation key,
|
||||||
|
ISyncManager<K, T> manager,
|
||||||
|
Capability<T> 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<?, ? extends ISyncData<?>> 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<?, ISyncData<?>>) manager,
|
||||||
|
null
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets manager.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @return the manager
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <K, T extends ISyncData<?>> Optional<ISyncManager<K, T>> getManager(ResourceLocation key) {
|
||||||
|
TypedSyncEntry<?,?> entry = typedEntries.get(key);
|
||||||
|
return entry != null ? Optional.of((ISyncManager<K,T>) entry.manager) : Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets capability.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @return the capability
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends ISyncData<?>> Optional<Capability<T>> getCapability(ResourceLocation key) {
|
||||||
|
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
||||||
|
if (entry != null && entry.capability != null) {
|
||||||
|
return Optional.of((Capability<T>) 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 <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param capability the capability
|
||||||
|
*/
|
||||||
|
public <T extends ISyncData<?>> void bindCapability(ResourceLocation key, Capability<T> 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<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) typedEntries.get(managerId);
|
||||||
|
if (entry != null) {
|
||||||
|
trackEntityWithTypedEntry(entity, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends ISyncData<?>> void trackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry<UUID, T> 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<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) typedEntries.get(managerId);
|
||||||
|
if (entry != null) {
|
||||||
|
untrackEntityWithTypedEntry(entity, entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private <T extends ISyncData<?>> void untrackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry<UUID, T> 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<Entity> entities, ResourceLocation managerId) {
|
||||||
|
for (Entity entity : entities) {
|
||||||
|
untrackEntityForManager(entity, managerId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从所有管理器中批量移除实体跟踪
|
||||||
|
*
|
||||||
|
* @param entities the entities
|
||||||
|
*/
|
||||||
|
public void untrackEntitiesFromAllManagers(@NotNull Iterable<Entity> 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 <K, T extends ISyncData<?>> void clearTrackedDataForEntry(@NotNull TypedSyncEntry<K, T> entry) {
|
||||||
|
// 获取当前跟踪的集合并清空
|
||||||
|
Set<T> syncSet = entry.manager.getSyncSet();
|
||||||
|
if (syncSet != null) {
|
||||||
|
syncSet.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 清理所有管理器的跟踪数据
|
||||||
|
*/
|
||||||
|
public void clearAllTrackedData() {
|
||||||
|
for (ResourceLocation id : getRegisteredKeys()) {
|
||||||
|
clearAllTrackedData(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 辅助方法:更新条目的能力
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <K, T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?,?> entry, Capability<T> newCapability) {
|
||||||
|
TypedSyncEntry<K, T> typedEntry = (TypedSyncEntry<K, T>) entry;
|
||||||
|
//重构了 TypedSyncEntry 使 capability 可变
|
||||||
|
typedEntry.capability = newCapability;
|
||||||
|
typedEntries.computeIfPresent(id, (resourceLocation, typedSyncEntry) -> typedEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets registered keys.
|
||||||
|
*
|
||||||
|
* @return the registered keys
|
||||||
|
*/
|
||||||
|
public Set<ResourceLocation> getRegisteredKeys() {
|
||||||
|
return Collections.unmodifiableSet(typedEntries.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each.
|
||||||
|
*
|
||||||
|
* @param consumer the consumer
|
||||||
|
*/
|
||||||
|
public void forEach(BiConsumer<ResourceLocation, ISyncManager<?,?>> 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,73 +4,178 @@ import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.entity.Entity;
|
import net.minecraft.world.entity.Entity;
|
||||||
import net.minecraftforge.common.capabilities.Capability;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.BiConsumer;
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
/**
|
||||||
|
* The type Sync data 2 manager.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings({"unused", "DuplicatedCode"})
|
||||||
public class SyncData2Manager {
|
public class SyncData2Manager {
|
||||||
private final Map<ResourceLocation, TypedSyncEntry<?, ?>> typedEntries = Maps.newConcurrentMap();
|
private final Map<ResourceLocation, TypedSyncEntry<?, ?>> typedEntries = Maps.newConcurrentMap();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据提供者接口 - 用于通过键获取数据
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
*/
|
||||||
|
@FunctionalInterface
|
||||||
|
public interface DataProvider<K, T> {
|
||||||
|
/**
|
||||||
|
* 通过键获取数据的 Optional
|
||||||
|
*
|
||||||
|
* @param key 键
|
||||||
|
* @return 数据的 Optional
|
||||||
|
*/
|
||||||
|
Optional<T> getData(K key);
|
||||||
|
}
|
||||||
|
|
||||||
private static class TypedSyncEntry<K, T extends ISyncData<?>> {
|
private static class TypedSyncEntry<K, T extends ISyncData<?>> {
|
||||||
|
/**
|
||||||
|
* The Manager.
|
||||||
|
*/
|
||||||
final ISyncManager<K, T> manager;
|
final ISyncManager<K, T> manager;
|
||||||
|
/**
|
||||||
|
* The Data provider.
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
Capability<T> capability;
|
final DataProvider<Entity, T> dataProvider;
|
||||||
|
/**
|
||||||
|
* The Allowed classes.
|
||||||
|
*/
|
||||||
final Set<Class<?>> allowedClasses;
|
final Set<Class<?>> allowedClasses;
|
||||||
|
|
||||||
TypedSyncEntry(ISyncManager<K, T> manager, @Nullable Capability<T> capability) {
|
/**
|
||||||
|
* Instantiates a new Typed sync entry.
|
||||||
|
*
|
||||||
|
* @param manager the manager
|
||||||
|
* @param dataProvider the data provider
|
||||||
|
*/
|
||||||
|
TypedSyncEntry(ISyncManager<K, T> manager, @Nullable DataProvider<Entity, T> dataProvider) {
|
||||||
this.manager = manager;
|
this.manager = manager;
|
||||||
this.capability = capability;
|
this.dataProvider = dataProvider;
|
||||||
this.allowedClasses = Sets.newConcurrentHashSet();
|
this.allowedClasses = Sets.newConcurrentHashSet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public <K, T extends ISyncData<?>> void registerManager(
|
/**
|
||||||
|
* Register manager with data provider.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param manager the manager
|
||||||
|
* @param dataProvider the data provider
|
||||||
|
*/
|
||||||
|
public <K, T extends ISyncData<?>> void registerManagerWithProvider(
|
||||||
ResourceLocation key,
|
ResourceLocation key,
|
||||||
ISyncManager<K, T> manager,
|
ISyncManager<K, T> manager,
|
||||||
Capability<T> capability
|
DataProvider<Entity, T> dataProvider
|
||||||
) {
|
) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||||
Objects.requireNonNull(capability, "Capability cannot be null");
|
Objects.requireNonNull(dataProvider, "Data provider cannot be null");
|
||||||
|
|
||||||
typedEntries.put(key, new TypedSyncEntry<>(manager, capability));
|
typedEntries.put(key, new TypedSyncEntry<>(manager, dataProvider));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向后兼容的注册方法(只注册管理器,不注册能力)
|
* Register manager with function getter.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param manager the manager
|
||||||
|
* @param getter the data getter function
|
||||||
|
*/
|
||||||
|
public <K, T extends ISyncData<?>> void registerManager(
|
||||||
|
ResourceLocation key,
|
||||||
|
ISyncManager<K, T> manager,
|
||||||
|
Function<Entity, Optional<T>> getter
|
||||||
|
) {
|
||||||
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
|
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||||
|
Objects.requireNonNull(getter, "Data getter function cannot be null");
|
||||||
|
|
||||||
|
typedEntries.put(key, new TypedSyncEntry<>(manager, getter::apply));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 向后兼容的注册方法(只注册管理器,不注册数据提供者)
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param manager the manager
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void registerManager(ResourceLocation key, ISyncManager<?, ? extends ISyncData<?>> manager) {
|
public void registerManager(ResourceLocation key, ISyncManager<?, ? extends ISyncData<?>> manager) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
Objects.requireNonNull(manager, "Sync manager cannot be null");
|
||||||
|
|
||||||
// 创建一个虚拟的 TypedSyncEntry,但 capability 为 null
|
// 创建一个没有数据提供者的 TypedSyncEntry
|
||||||
// 注意:这种方法会限制类型安全的功能
|
|
||||||
typedEntries.put(key, new TypedSyncEntry<>(
|
typedEntries.put(key, new TypedSyncEntry<>(
|
||||||
(ISyncManager<?, ISyncData<?>>) manager,
|
(ISyncManager<?, ISyncData<?>>) manager,
|
||||||
null
|
null
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets manager.
|
||||||
|
*
|
||||||
|
* @param <K> the type parameter
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @return the manager
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <K, T extends ISyncData<?>> Optional<ISyncManager<K, T>> getManager(ResourceLocation key) {
|
public <K, T extends ISyncData<?>> Optional<ISyncManager<K, T>> getManager(ResourceLocation key) {
|
||||||
TypedSyncEntry<?,?> entry = typedEntries.get(key);
|
TypedSyncEntry<?,?> entry = typedEntries.get(key);
|
||||||
return entry != null ? Optional.of((ISyncManager<K,T>) entry.manager) : Optional.empty();
|
return entry != null ? Optional.of((ISyncManager<K,T>) entry.manager) : Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets data provider.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @return the data provider
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T extends ISyncData<?>> Optional<Capability<T>> getCapability(ResourceLocation key) {
|
public <T extends ISyncData<?>> Optional<DataProvider<Entity, T>> getDataProvider(ResourceLocation key) {
|
||||||
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
||||||
if (entry != null && entry.capability != null) {
|
if (entry != null && entry.dataProvider != null) {
|
||||||
return Optional.of((Capability<T>) entry.capability);
|
return Optional.of((DataProvider<Entity, T>) entry.dataProvider);
|
||||||
}
|
}
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取实体数据
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param entity the entity
|
||||||
|
* @return the entity data
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T extends ISyncData<?>> Optional<T> getEntityData(ResourceLocation key, Entity entity) {
|
||||||
|
return getDataProvider(key)
|
||||||
|
.flatMap(provider -> {
|
||||||
|
Optional<ISyncData<?>> result = provider.getData(entity);
|
||||||
|
return (Optional<T>) result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow entity class.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param classes the classes
|
||||||
|
*/
|
||||||
public final void allowEntityClass(ResourceLocation key, Class<?>... classes) {
|
public final void allowEntityClass(ResourceLocation key, Class<?>... classes) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
Objects.requireNonNull(classes, "Classes array cannot be null");
|
Objects.requireNonNull(classes, "Classes array cannot be null");
|
||||||
|
|
@ -87,6 +192,9 @@ public class SyncData2Manager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除允许的实体类
|
* 移除允许的实体类
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param classes the classes
|
||||||
*/
|
*/
|
||||||
public final void disallowEntityClass(ResourceLocation key, Class<?>... classes) {
|
public final void disallowEntityClass(ResourceLocation key, Class<?>... classes) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
|
|
@ -95,39 +203,59 @@ public class SyncData2Manager {
|
||||||
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
||||||
if (entry != null && classes.length > 0) {
|
if (entry != null && classes.length > 0) {
|
||||||
Arrays.asList(classes).forEach(entry.allowedClasses::remove);
|
Arrays.asList(classes).forEach(entry.allowedClasses::remove);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绑定能力(用于分离注册的情况)
|
* 绑定数据提供者(用于分离注册的情况)
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param dataProvider the data provider
|
||||||
*/
|
*/
|
||||||
public <T extends ISyncData<?>> void bindCapability(ResourceLocation key, Capability<T> capability) {
|
public <T extends ISyncData<?>> void bindDataProvider(ResourceLocation key, DataProvider<Entity, T> dataProvider) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
Objects.requireNonNull(capability, "Capability cannot be null");
|
Objects.requireNonNull(dataProvider, "Data provider cannot be null");
|
||||||
|
|
||||||
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
// 更新现有条目的能力
|
// 更新现有条目的数据提供者
|
||||||
updateCapabilityInEntry(key, entry, capability);
|
updateDataProviderInEntry(key, entry, dataProvider);
|
||||||
} else throw new IllegalArgumentException("No manager found for " + key);
|
} else {
|
||||||
|
throw new IllegalArgumentException("No manager found for " + key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解绑能力
|
* 绑定简单的数据获取器
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param getter the data getter function
|
||||||
*/
|
*/
|
||||||
public void unbindCapability(ResourceLocation key) {
|
public <T extends ISyncData<?>> void bindDataGetter(ResourceLocation key, Function<Entity, Optional<T>> getter) {
|
||||||
|
bindDataProvider(key, getter::apply);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解绑数据提供者
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
*/
|
||||||
|
public void unbindDataProvider(ResourceLocation key) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
|
|
||||||
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
// 将能力设置为null,但保留管理器和其他配置
|
// 将数据提供者设置为null,但保留管理器和其他配置
|
||||||
updateCapabilityInEntry(key, entry, null);
|
updateDataProviderInEntry(key, entry, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清除允许的实体类
|
* 清除允许的实体类
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
*/
|
*/
|
||||||
public void clearAllowedEntityClasses(ResourceLocation key) {
|
public void clearAllowedEntityClasses(ResourceLocation key) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
|
|
@ -138,24 +266,38 @@ public class SyncData2Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Is entity class allowed boolean.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param entityClass the entity class
|
||||||
|
* @return the boolean
|
||||||
|
*/
|
||||||
public boolean isEntityClassAllowed(ResourceLocation key, Class<?> entityClass) {
|
public boolean isEntityClassAllowed(ResourceLocation key, Class<?> entityClass) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
Objects.requireNonNull(entityClass, "Entity class cannot be null");
|
Objects.requireNonNull(entityClass, "Entity class cannot be null");
|
||||||
|
|
||||||
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
TypedSyncEntry<?, ?> entry = typedEntries.get(key);
|
||||||
boolean isAllowed = false;
|
if (entry == null) {
|
||||||
if (entry != null) {
|
return false;
|
||||||
for (Class<?> allowedClass : entry.allowedClasses) {
|
|
||||||
if (entityClass.isAssignableFrom(allowedClass)) {
|
|
||||||
isAllowed = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return entry != null && isAllowed ;
|
|
||||||
|
// 如果没有设置允许的类,则默认允许所有类
|
||||||
|
if (entry.allowedClasses.isEmpty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查实体类是否在允许的类中
|
||||||
|
return entry.allowedClasses.stream()
|
||||||
|
.anyMatch(allowedClass -> allowedClass.isAssignableFrom(entityClass));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 类型安全的事件处理
|
/**
|
||||||
|
* Track entity for manager.
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param managerId the manager id
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void trackEntityForManager(Entity entity, ResourceLocation managerId) {
|
public void trackEntityForManager(Entity entity, ResourceLocation managerId) {
|
||||||
TypedSyncEntry<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) typedEntries.get(managerId);
|
TypedSyncEntry<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) typedEntries.get(managerId);
|
||||||
|
|
@ -165,12 +307,18 @@ public class SyncData2Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends ISyncData<?>> void trackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry<UUID, T> entry) {
|
private <T extends ISyncData<?>> void trackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry<UUID, T> entry) {
|
||||||
if (entry.capability != null) {
|
if (entry.dataProvider != null) {
|
||||||
entity.getCapability(entry.capability)
|
entry.dataProvider.getData(entity)
|
||||||
.ifPresent(cap -> entry.manager.track(entity.getUUID(), cap));
|
.ifPresent(data -> entry.manager.track(entity.getUUID(), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 类型安全的事件处理 - 取消跟踪实体
|
|
||||||
|
/**
|
||||||
|
* Untrack entity for manager.
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param managerId the manager id
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void untrackEntityForManager(Entity entity, ResourceLocation managerId) {
|
public void untrackEntityForManager(Entity entity, ResourceLocation managerId) {
|
||||||
TypedSyncEntry<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) typedEntries.get(managerId);
|
TypedSyncEntry<UUID, ?> entry = (TypedSyncEntry<UUID, ?>) typedEntries.get(managerId);
|
||||||
|
|
@ -180,14 +328,16 @@ public class SyncData2Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <T extends ISyncData<?>> void untrackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry<UUID, T> entry) {
|
private <T extends ISyncData<?>> void untrackEntityWithTypedEntry(Entity entity, @NotNull TypedSyncEntry<UUID, T> entry) {
|
||||||
if (entry.capability != null) {
|
if (entry.dataProvider != null) {
|
||||||
entity.getCapability(entry.capability)
|
entry.dataProvider.getData(entity)
|
||||||
.ifPresent(cap -> entry.manager.untrack(entity.getUUID(), cap));
|
.ifPresent(data -> entry.manager.untrack(entity.getUUID(), data));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从所有管理器中移除实体跟踪
|
* 从所有管理器中移除实体跟踪
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
*/
|
*/
|
||||||
public void untrackEntityFromAllManagers(Entity entity) {
|
public void untrackEntityFromAllManagers(Entity entity) {
|
||||||
for (ResourceLocation id : getRegisteredKeys()) {
|
for (ResourceLocation id : getRegisteredKeys()) {
|
||||||
|
|
@ -199,6 +349,9 @@ public class SyncData2Manager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量从管理器中移除实体跟踪
|
* 批量从管理器中移除实体跟踪
|
||||||
|
*
|
||||||
|
* @param entities the entities
|
||||||
|
* @param managerId the manager id
|
||||||
*/
|
*/
|
||||||
public void untrackEntitiesForManager(@NotNull Iterable<Entity> entities, ResourceLocation managerId) {
|
public void untrackEntitiesForManager(@NotNull Iterable<Entity> entities, ResourceLocation managerId) {
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
|
|
@ -208,6 +361,8 @@ public class SyncData2Manager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从所有管理器中批量移除实体跟踪
|
* 从所有管理器中批量移除实体跟踪
|
||||||
|
*
|
||||||
|
* @param entities the entities
|
||||||
*/
|
*/
|
||||||
public void untrackEntitiesFromAllManagers(@NotNull Iterable<Entity> entities) {
|
public void untrackEntitiesFromAllManagers(@NotNull Iterable<Entity> entities) {
|
||||||
for (Entity entity : entities) {
|
for (Entity entity : entities) {
|
||||||
|
|
@ -217,6 +372,8 @@ public class SyncData2Manager {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 强制清理管理器中的所有跟踪数据
|
* 强制清理管理器中的所有跟踪数据
|
||||||
|
*
|
||||||
|
* @param managerId the manager id
|
||||||
*/
|
*/
|
||||||
public void clearAllTrackedData(ResourceLocation managerId) {
|
public void clearAllTrackedData(ResourceLocation managerId) {
|
||||||
TypedSyncEntry<?, ?> entry = typedEntries.get(managerId);
|
TypedSyncEntry<?, ?> entry = typedEntries.get(managerId);
|
||||||
|
|
@ -226,7 +383,6 @@ public class SyncData2Manager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private <K, T extends ISyncData<?>> void clearTrackedDataForEntry(@NotNull TypedSyncEntry<K, T> entry) {
|
private <K, T extends ISyncData<?>> void clearTrackedDataForEntry(@NotNull TypedSyncEntry<K, T> entry) {
|
||||||
// 获取当前跟踪的集合并清空
|
|
||||||
Set<T> syncSet = entry.manager.getSyncSet();
|
Set<T> syncSet = entry.manager.getSyncSet();
|
||||||
if (syncSet != null) {
|
if (syncSet != null) {
|
||||||
syncSet.clear();
|
syncSet.clear();
|
||||||
|
|
@ -242,36 +398,62 @@ public class SyncData2Manager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 辅助方法:更新条目的能力
|
// 辅助方法:更新条目的数据提供者
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private <K, T extends ISyncData<?>> void updateCapabilityInEntry(ResourceLocation id, TypedSyncEntry<?,?> entry, Capability<T> newCapability) {
|
private <K, T extends ISyncData<?>> void updateDataProviderInEntry(
|
||||||
TypedSyncEntry<K, T> typedEntry = (TypedSyncEntry<K, T>) entry;
|
ResourceLocation id,
|
||||||
//重构了 TypedSyncEntry 使 capability 可变
|
TypedSyncEntry<?,?> entry,
|
||||||
typedEntry.capability = newCapability;
|
DataProvider<Entity, T> newDataProvider
|
||||||
typedEntries.computeIfPresent(id, (resourceLocation, typedSyncEntry) -> typedEntry);
|
) {
|
||||||
|
// 由于 DataProvider 是 final,我们需要创建一个新的 TypedSyncEntry
|
||||||
|
TypedSyncEntry<K, T> newEntry = new TypedSyncEntry<>(
|
||||||
|
(ISyncManager<K, T>) entry.manager,
|
||||||
|
newDataProvider
|
||||||
|
);
|
||||||
|
newEntry.allowedClasses.addAll(entry.allowedClasses);
|
||||||
|
|
||||||
|
typedEntries.put(id, newEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets registered keys.
|
||||||
|
*
|
||||||
|
* @return the registered keys
|
||||||
|
*/
|
||||||
public Set<ResourceLocation> getRegisteredKeys() {
|
public Set<ResourceLocation> getRegisteredKeys() {
|
||||||
return Collections.unmodifiableSet(typedEntries.keySet());
|
return Collections.unmodifiableSet(typedEntries.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For each.
|
||||||
|
*
|
||||||
|
* @param consumer the consumer
|
||||||
|
*/
|
||||||
public void forEach(BiConsumer<ResourceLocation, ISyncManager<?,?>> consumer) {
|
public void forEach(BiConsumer<ResourceLocation, ISyncManager<?,?>> consumer) {
|
||||||
Objects.requireNonNull(consumer, "Consumer cannot be null");
|
Objects.requireNonNull(consumer, "Consumer cannot be null");
|
||||||
typedEntries.forEach((key, entry) -> consumer.accept(key, entry.manager));
|
typedEntries.forEach((key, entry) -> consumer.accept(key, entry.manager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets manager count.
|
||||||
|
*
|
||||||
|
* @return the manager count
|
||||||
|
*/
|
||||||
public int getManagerCount() {
|
public int getManagerCount() {
|
||||||
return typedEntries.size();
|
return typedEntries.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all.
|
||||||
|
*/
|
||||||
public void clearAll() {
|
public void clearAll() {
|
||||||
typedEntries.clear();
|
typedEntries.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除管理器(包括所有相关配置)
|
* 移除管理器(包括所有相关配置)
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
*/
|
*/
|
||||||
public void removeManager(ResourceLocation key) {
|
public void removeManager(ResourceLocation key) {
|
||||||
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
Objects.requireNonNull(key, "ResourceLocation key cannot be null");
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,24 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Simple language provider.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class SimpleLanguageProvider extends LanguageProvider {
|
public class SimpleLanguageProvider extends LanguageProvider {
|
||||||
private final McLocale language;
|
private final McLocale language;
|
||||||
private final ILangKeyValue langKeyValue;
|
private final ILangKeyValue langKeyValue;
|
||||||
private final Map<String, String> lanKeyMap;
|
private final Map<String, String> lanKeyMap;
|
||||||
private static final List<String> objects = new ArrayList<>();
|
private static final List<String> objects = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Simple language provider.
|
||||||
|
*
|
||||||
|
* @param output the output
|
||||||
|
* @param modId the mod id
|
||||||
|
* @param Lan the lan
|
||||||
|
* @param langKeyValue the lang key value
|
||||||
|
*/
|
||||||
public SimpleLanguageProvider(PackOutput output, String modId, @NotNull McLocale Lan, ILangKeyValue langKeyValue) {
|
public SimpleLanguageProvider(PackOutput output, String modId, @NotNull McLocale Lan, ILangKeyValue langKeyValue) {
|
||||||
super(output, modId, Lan.mcCode());
|
super(output, modId, Lan.mcCode());
|
||||||
this.language = Lan;
|
this.language = Lan;
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,33 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface Lang key value.
|
||||||
|
*/
|
||||||
public interface ILangKeyValue {
|
public interface ILangKeyValue {
|
||||||
|
/**
|
||||||
|
* Gets lang.
|
||||||
|
*
|
||||||
|
* @param locale the locale
|
||||||
|
* @param key the key
|
||||||
|
* @return the lang
|
||||||
|
*/
|
||||||
static String getLang(McLocale locale, @NotNull ILangKeyValue key) {
|
static String getLang(McLocale locale, @NotNull ILangKeyValue key) {
|
||||||
return key.getLang(locale);
|
return key.getLang(locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets lang.
|
||||||
|
*
|
||||||
|
* @param locale the locale
|
||||||
|
* @return the lang
|
||||||
|
*/
|
||||||
String getLang(McLocale locale);
|
String getLang(McLocale locale);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets values.
|
||||||
|
*
|
||||||
|
* @return the values
|
||||||
|
*/
|
||||||
List<ILangKeyValue> getValues();
|
List<ILangKeyValue> getValues();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,21 @@ package top.r3944realms.lib39.datagen.value;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface Locale entry.
|
||||||
|
*/
|
||||||
public interface ILocaleEntry {
|
public interface ILocaleEntry {
|
||||||
|
/**
|
||||||
|
* Mc code string.
|
||||||
|
*
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
String mcCode();
|
String mcCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Java locale locale.
|
||||||
|
*
|
||||||
|
* @return the locale
|
||||||
|
*/
|
||||||
Locale javaLocale();
|
Locale javaLocale();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,42 @@ import org.jetbrains.annotations.NotNull;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Lang key value.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class LangKeyValue implements ILangKeyValue {
|
public class LangKeyValue implements ILangKeyValue {
|
||||||
|
/**
|
||||||
|
* The Supplier.
|
||||||
|
*/
|
||||||
protected final Supplier<?> supplier;
|
protected final Supplier<?> supplier;
|
||||||
|
/**
|
||||||
|
* The Key.
|
||||||
|
*/
|
||||||
protected String key;
|
protected String key;
|
||||||
|
/**
|
||||||
|
* The Us en.
|
||||||
|
*/
|
||||||
protected final String US_EN;
|
protected final String US_EN;
|
||||||
|
/**
|
||||||
|
* The Sim cn.
|
||||||
|
*/
|
||||||
protected final String SIM_CN;
|
protected final String SIM_CN;
|
||||||
|
/**
|
||||||
|
* The Tra cn.
|
||||||
|
*/
|
||||||
protected final String TRA_CN;
|
protected final String TRA_CN;
|
||||||
|
/**
|
||||||
|
* The Lzh.
|
||||||
|
*/
|
||||||
protected final String LZH;
|
protected final String LZH;
|
||||||
|
/**
|
||||||
|
* The Default.
|
||||||
|
*/
|
||||||
protected final Boolean Default;
|
protected final Boolean Default;
|
||||||
|
/**
|
||||||
|
* The Mpe.
|
||||||
|
*/
|
||||||
protected final ModPartEnum MPE;
|
protected final ModPartEnum MPE;
|
||||||
private LangKeyValue(Supplier<?> supplier, String key, ModPartEnum MPE,
|
private LangKeyValue(Supplier<?> supplier, String key, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN, String LZH, Boolean isDefault) {
|
String US_EN, String SIM_CN, String TRA_CN, String LZH, Boolean isDefault) {
|
||||||
|
|
@ -28,42 +55,111 @@ public class LangKeyValue implements ILangKeyValue {
|
||||||
this.Default = isDefault;
|
this.Default = isDefault;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of supplier lang key value.
|
||||||
|
*
|
||||||
|
* @param supplier the supplier
|
||||||
|
* @param MPE the mpe
|
||||||
|
* @param US_EN the us en
|
||||||
|
* @param SIM_CN the sim cn
|
||||||
|
* @param TRA_CN the tra cn
|
||||||
|
* @return the lang key value
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _, _, _ -> new", pure = true)
|
||||||
public static @NotNull LangKeyValue ofSupplier(Supplier<?> supplier, ModPartEnum MPE,
|
public static @NotNull LangKeyValue ofSupplier(Supplier<?> supplier, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN) {
|
String US_EN, String SIM_CN, String TRA_CN) {
|
||||||
return new LangKeyValue(supplier, null, MPE, US_EN, SIM_CN, TRA_CN, null, false);
|
return new LangKeyValue(supplier, null, MPE, US_EN, SIM_CN, TRA_CN, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of supplier lang key value.
|
||||||
|
*
|
||||||
|
* @param supplier the supplier
|
||||||
|
* @param MPE the mpe
|
||||||
|
* @param US_EN the us en
|
||||||
|
* @param SIM_CN the sim cn
|
||||||
|
* @param TRA_CN the tra cn
|
||||||
|
* @param LZH the lzh
|
||||||
|
* @return the lang key value
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
||||||
public static @NotNull LangKeyValue ofSupplier(Supplier<?> supplier, ModPartEnum MPE,
|
public static @NotNull LangKeyValue ofSupplier(Supplier<?> supplier, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN, String LZH) {
|
String US_EN, String SIM_CN, String TRA_CN, String LZH) {
|
||||||
return new LangKeyValue(supplier, null, MPE, US_EN, SIM_CN, TRA_CN, LZH, false);
|
return new LangKeyValue(supplier, null, MPE, US_EN, SIM_CN, TRA_CN, LZH, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of supplier lang key value.
|
||||||
|
*
|
||||||
|
* @param supplier the supplier
|
||||||
|
* @param MPE the mpe
|
||||||
|
* @param US_EN the us en
|
||||||
|
* @param SIM_CN the sim cn
|
||||||
|
* @param TRA_CN the tra cn
|
||||||
|
* @param isDefault the is default
|
||||||
|
* @return the lang key value
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
||||||
public static @NotNull LangKeyValue ofSupplier(Supplier<?> supplier, ModPartEnum MPE,
|
public static @NotNull LangKeyValue ofSupplier(Supplier<?> supplier, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN, Boolean isDefault) {
|
String US_EN, String SIM_CN, String TRA_CN, Boolean isDefault) {
|
||||||
return new LangKeyValue(supplier, null, MPE, US_EN, SIM_CN, TRA_CN, null, isDefault);
|
return new LangKeyValue(supplier, null, MPE, US_EN, SIM_CN, TRA_CN, null, isDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of key lang key value.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param MPE the mpe
|
||||||
|
* @param US_EN the us en
|
||||||
|
* @param SIM_CN the sim cn
|
||||||
|
* @param TRA_CN the tra cn
|
||||||
|
* @return the lang key value
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _, _, _ -> new", pure = true)
|
||||||
public static @NotNull LangKeyValue ofKey(String key, ModPartEnum MPE,
|
public static @NotNull LangKeyValue ofKey(String key, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN) {
|
String US_EN, String SIM_CN, String TRA_CN) {
|
||||||
return new LangKeyValue(null, key, MPE, US_EN, SIM_CN, TRA_CN, null, false);
|
return new LangKeyValue(null, key, MPE, US_EN, SIM_CN, TRA_CN, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of key lang key value.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param MPE the mpe
|
||||||
|
* @param US_EN the us en
|
||||||
|
* @param SIM_CN the sim cn
|
||||||
|
* @param TRA_CN the tra cn
|
||||||
|
* @param LZH the lzh
|
||||||
|
* @return the lang key value
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
||||||
public static @NotNull LangKeyValue ofKey(String key, ModPartEnum MPE,
|
public static @NotNull LangKeyValue ofKey(String key, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN, String LZH) {
|
String US_EN, String SIM_CN, String TRA_CN, String LZH) {
|
||||||
return new LangKeyValue(null, key, MPE, US_EN, SIM_CN, TRA_CN, LZH, false);
|
return new LangKeyValue(null, key, MPE, US_EN, SIM_CN, TRA_CN, LZH, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of key lang key value.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param MPE the mpe
|
||||||
|
* @param US_EN the us en
|
||||||
|
* @param SIM_CN the sim cn
|
||||||
|
* @param TRA_CN the tra cn
|
||||||
|
* @param isDefault the is default
|
||||||
|
* @return the lang key value
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _, _, _, _ -> new", pure = true)
|
||||||
public static @NotNull LangKeyValue ofKey(String key, ModPartEnum MPE,
|
public static @NotNull LangKeyValue ofKey(String key, ModPartEnum MPE,
|
||||||
String US_EN, String SIM_CN, String TRA_CN, Boolean isDefault) {
|
String US_EN, String SIM_CN, String TRA_CN, Boolean isDefault) {
|
||||||
return new LangKeyValue(null, key, MPE, US_EN, SIM_CN, TRA_CN, null, isDefault);
|
return new LangKeyValue(null, key, MPE, US_EN, SIM_CN, TRA_CN, null, isDefault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets key.
|
||||||
|
*
|
||||||
|
* @return the key
|
||||||
|
*/
|
||||||
public String getKey() {
|
public String getKey() {
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,16 +2,49 @@ package top.r3944realms.lib39.datagen.value;
|
||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The enum Mc locale.
|
||||||
|
*/
|
||||||
public enum McLocale implements ILocaleEntry {
|
public enum McLocale implements ILocaleEntry {
|
||||||
|
/**
|
||||||
|
* En us mc locale.
|
||||||
|
*/
|
||||||
EN_US("en_us", Locale.US),
|
EN_US("en_us", Locale.US),
|
||||||
|
/**
|
||||||
|
* Zh cn mc locale.
|
||||||
|
*/
|
||||||
ZH_CN("zh_cn", Locale.SIMPLIFIED_CHINESE),
|
ZH_CN("zh_cn", Locale.SIMPLIFIED_CHINESE),
|
||||||
|
/**
|
||||||
|
* Zh tw mc locale.
|
||||||
|
*/
|
||||||
ZH_TW("zh_tw", Locale.TRADITIONAL_CHINESE),
|
ZH_TW("zh_tw", Locale.TRADITIONAL_CHINESE),
|
||||||
|
/**
|
||||||
|
* The Lzh.
|
||||||
|
*/
|
||||||
LZH("lzh", new Locale("lzh", "ZH")),
|
LZH("lzh", new Locale("lzh", "ZH")),
|
||||||
|
/**
|
||||||
|
* Ja jp mc locale.
|
||||||
|
*/
|
||||||
JA_JP("ja_jp", Locale.JAPAN),
|
JA_JP("ja_jp", Locale.JAPAN),
|
||||||
|
/**
|
||||||
|
* Ko kr mc locale.
|
||||||
|
*/
|
||||||
KO_KR("ko_kr", Locale.KOREA),
|
KO_KR("ko_kr", Locale.KOREA),
|
||||||
|
/**
|
||||||
|
* The Ru ru.
|
||||||
|
*/
|
||||||
RU_RU("ru_ru", new Locale("ru", "RU")),
|
RU_RU("ru_ru", new Locale("ru", "RU")),
|
||||||
|
/**
|
||||||
|
* Fr fr mc locale.
|
||||||
|
*/
|
||||||
FR_FR("fr_fr", Locale.FRANCE),
|
FR_FR("fr_fr", Locale.FRANCE),
|
||||||
|
/**
|
||||||
|
* De de mc locale.
|
||||||
|
*/
|
||||||
DE_DE("de_de", Locale.GERMANY),
|
DE_DE("de_de", Locale.GERMANY),
|
||||||
|
/**
|
||||||
|
* The Es es.
|
||||||
|
*/
|
||||||
ES_ES("es_es", new Locale("es", "ES"));
|
ES_ES("es_es", new Locale("es", "ES"));
|
||||||
|
|
||||||
private final String mcCode;
|
private final String mcCode;
|
||||||
|
|
|
||||||
|
|
@ -7,62 +7,101 @@ import org.jetbrains.annotations.NotNull;
|
||||||
* 模组各部分的类型枚举,用于数据生成与分类。
|
* 模组各部分的类型枚举,用于数据生成与分类。
|
||||||
*/
|
*/
|
||||||
public enum ModPartEnum {
|
public enum ModPartEnum {
|
||||||
/** 默认/未指定类型 */
|
/**
|
||||||
|
* 默认/未指定类型
|
||||||
|
*/
|
||||||
DEFAULT,
|
DEFAULT,
|
||||||
|
|
||||||
/** 物品 */
|
/**
|
||||||
|
* 物品
|
||||||
|
*/
|
||||||
ITEM,
|
ITEM,
|
||||||
|
|
||||||
/** 方块 */
|
/**
|
||||||
|
* 方块
|
||||||
|
*/
|
||||||
BLOCK,
|
BLOCK,
|
||||||
|
|
||||||
/** 附魔 */
|
/**
|
||||||
|
* 附魔
|
||||||
|
*/
|
||||||
ENCHANTMENT,
|
ENCHANTMENT,
|
||||||
|
|
||||||
/** 成就 / 进度 */
|
/**
|
||||||
|
* 成就 / 进度
|
||||||
|
*/
|
||||||
ADVANCEMENT,
|
ADVANCEMENT,
|
||||||
|
|
||||||
/** 创造模式物品栏 */
|
/**
|
||||||
|
* 创造模式物品栏
|
||||||
|
*/
|
||||||
CREATIVE_TAB,
|
CREATIVE_TAB,
|
||||||
|
|
||||||
/** 配置项 */
|
/**
|
||||||
|
* 配置项
|
||||||
|
*/
|
||||||
CONFIG,
|
CONFIG,
|
||||||
|
|
||||||
/** 实体(生物、载具等) */
|
/**
|
||||||
|
* 实体(生物、载具等)
|
||||||
|
*/
|
||||||
ENTITY,
|
ENTITY,
|
||||||
|
|
||||||
/** 图形界面 */
|
/**
|
||||||
|
* 图形界面
|
||||||
|
*/
|
||||||
GUI,
|
GUI,
|
||||||
|
|
||||||
/** 作者信息 */
|
/**
|
||||||
|
* 作者信息
|
||||||
|
*/
|
||||||
AUTHOR,
|
AUTHOR,
|
||||||
|
|
||||||
/** 标题 */
|
/**
|
||||||
|
* 标题
|
||||||
|
*/
|
||||||
TITLE,
|
TITLE,
|
||||||
|
|
||||||
/** 名称 */
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
NAME,
|
NAME,
|
||||||
|
|
||||||
/** 游戏规则(/gamerule) */
|
/**
|
||||||
|
* 游戏规则(/gamerule)
|
||||||
|
*/
|
||||||
GAME_RULE,
|
GAME_RULE,
|
||||||
|
|
||||||
/** 描述文本 */
|
/**
|
||||||
|
* 描述文本
|
||||||
|
*/
|
||||||
DESCRIPTION,
|
DESCRIPTION,
|
||||||
|
|
||||||
/** 一般信息 */
|
/**
|
||||||
|
* 一般信息
|
||||||
|
*/
|
||||||
INFO,
|
INFO,
|
||||||
|
|
||||||
/** 消息(聊天、提示等) */
|
/**
|
||||||
|
* 消息(聊天、提示等)
|
||||||
|
*/
|
||||||
MESSAGE,
|
MESSAGE,
|
||||||
|
|
||||||
/** 命令 */
|
/**
|
||||||
|
* 命令
|
||||||
|
*/
|
||||||
COMMAND,
|
COMMAND,
|
||||||
|
|
||||||
/** 声音资源 */
|
/**
|
||||||
|
* 声音资源
|
||||||
|
*/
|
||||||
SOUND;
|
SOUND;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据枚举类型生成标准化 key 前缀
|
* 根据枚举类型生成标准化 key 前缀
|
||||||
* 例如 ITEM -> "item.", BLOCK -> "block."
|
* 例如 ITEM -> "item.", BLOCK -> "block."
|
||||||
|
*
|
||||||
|
* @return the key prefix
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
public @NotNull String getKeyPrefix() {
|
public @NotNull String getKeyPrefix() {
|
||||||
|
|
@ -91,6 +130,9 @@ public enum ModPartEnum {
|
||||||
/**
|
/**
|
||||||
* 根据枚举类型和具体名称生成完整 key
|
* 根据枚举类型和具体名称生成完整 key
|
||||||
* 例如 ITEM + "example_item" -> "item.example_item"
|
* 例如 ITEM + "example_item" -> "item.example_item"
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @return the full key
|
||||||
*/
|
*/
|
||||||
@Contract(pure = true)
|
@Contract(pure = true)
|
||||||
public @NotNull String getFullKey(String name) {
|
public @NotNull String getFullKey(String name) {
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,15 @@ import net.minecraft.world.item.CreativeModeTabs;
|
||||||
import net.minecraft.world.level.block.Block;
|
import net.minecraft.world.level.block.Block;
|
||||||
import net.minecraftforge.registries.DeferredRegister;
|
import net.minecraftforge.registries.DeferredRegister;
|
||||||
import net.minecraftforge.registries.RegistryObject;
|
import net.minecraftforge.registries.RegistryObject;
|
||||||
import top.r3944realms.lib39.core.event.CommonHandler;
|
import org.jetbrains.annotations.Contract;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import top.r3944realms.lib39.core.event.CommonEventHandler;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Block registry builder.
|
||||||
|
*/
|
||||||
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
@SuppressWarnings({"UnusedReturnValue", "unused"})
|
||||||
public class BlockRegistryBuilder {
|
public class BlockRegistryBuilder {
|
||||||
private String registryName;
|
private String registryName;
|
||||||
|
|
@ -17,22 +22,33 @@ public class BlockRegistryBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建新的构建器实例
|
* 创建新的构建器实例
|
||||||
|
*
|
||||||
|
* @return the block registry builder
|
||||||
*/
|
*/
|
||||||
public static BlockRegistryBuilder create() {
|
@Contract(value = " -> new", pure = true)
|
||||||
|
public static @NotNull BlockRegistryBuilder create() {
|
||||||
return new BlockRegistryBuilder();
|
return new BlockRegistryBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置注册名称
|
* 设置注册名称
|
||||||
|
*
|
||||||
|
* @param name the name
|
||||||
|
* @return the block registry builder
|
||||||
*/
|
*/
|
||||||
public BlockRegistryBuilder withName(String name) {
|
public BlockRegistryBuilder withName(String name) {
|
||||||
this.registryName = name;
|
this.registryName = name;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册方块(不自动注册物品)
|
* 注册方块(不自动注册物品)
|
||||||
|
*
|
||||||
|
* @param blockRegister the block register
|
||||||
|
* @param blockSupplier the block supplier
|
||||||
|
* @return the block registry builder
|
||||||
*/
|
*/
|
||||||
public BlockRegistryBuilder registerBlock(DeferredRegister<Block> blockRegister, Supplier<? extends Block> blockSupplier) {
|
public BlockRegistryBuilder registerBlock(@NotNull DeferredRegister<Block> blockRegister, Supplier<? extends Block> blockSupplier) {
|
||||||
this.blockObject = blockRegister.register(this.registryName, blockSupplier);
|
this.blockObject = blockRegister.register(this.registryName, blockSupplier);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
@ -42,11 +58,15 @@ public class BlockRegistryBuilder {
|
||||||
*/
|
*/
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
private void registerBlockItem(RegistryObject<Block> blockObject, ResourceKey<CreativeModeTab>... creativeTabs) {
|
private void registerBlockItem(RegistryObject<Block> blockObject, ResourceKey<CreativeModeTab>... creativeTabs) {
|
||||||
CommonHandler.Mod.addItemToTabs(blockObject, creativeTabs);
|
CommonEventHandler.Mod.addItemToTabs(blockObject, creativeTabs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册方块和物品到建筑标签页
|
* 注册方块和物品到建筑标签页
|
||||||
|
*
|
||||||
|
* @param blockRegister the block register
|
||||||
|
* @param blockSupplier the block supplier
|
||||||
|
* @return the block registry builder
|
||||||
*/
|
*/
|
||||||
public BlockRegistryBuilder registerWithBuildingTab(DeferredRegister<Block> blockRegister, Supplier<? extends Block> blockSupplier) {
|
public BlockRegistryBuilder registerWithBuildingTab(DeferredRegister<Block> blockRegister, Supplier<? extends Block> blockSupplier) {
|
||||||
registerBlock(blockRegister, blockSupplier);
|
registerBlock(blockRegister, blockSupplier);
|
||||||
|
|
@ -56,6 +76,10 @@ public class BlockRegistryBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册方块和物品到功能标签页
|
* 注册方块和物品到功能标签页
|
||||||
|
*
|
||||||
|
* @param blockRegister the block register
|
||||||
|
* @param blockSupplier the block supplier
|
||||||
|
* @return the block registry builder
|
||||||
*/
|
*/
|
||||||
public BlockRegistryBuilder registerWithFunctionalTab(DeferredRegister<Block> blockRegister, Supplier<? extends Block> blockSupplier) {
|
public BlockRegistryBuilder registerWithFunctionalTab(DeferredRegister<Block> blockRegister, Supplier<? extends Block> blockSupplier) {
|
||||||
registerBlock(blockRegister, blockSupplier);
|
registerBlock(blockRegister, blockSupplier);
|
||||||
|
|
@ -65,6 +89,8 @@ public class BlockRegistryBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取注册的方块对象
|
* 获取注册的方块对象
|
||||||
|
*
|
||||||
|
* @return the registry object
|
||||||
*/
|
*/
|
||||||
public RegistryObject<Block> build() {
|
public RegistryObject<Block> build() {
|
||||||
return this.blockObject;
|
return this.blockObject;
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,18 @@ import net.minecraft.commands.Commands;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Command alias helper.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class CommandAliasHelper {
|
public class CommandAliasHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 注册命令及其别名
|
* 注册命令及其别名
|
||||||
|
*
|
||||||
|
* @param dispatcher the dispatcher
|
||||||
|
* @param mainCommand the main command
|
||||||
|
* @param aliases the aliases
|
||||||
*/
|
*/
|
||||||
public static void registerWithAliases(@NotNull CommandDispatcher<CommandSourceStack> dispatcher,
|
public static void registerWithAliases(@NotNull CommandDispatcher<CommandSourceStack> dispatcher,
|
||||||
LiteralArgumentBuilder<CommandSourceStack> mainCommand,
|
LiteralArgumentBuilder<CommandSourceStack> mainCommand,
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,20 @@ package top.r3944realms.lib39.util.lang;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Pair.
|
||||||
|
*
|
||||||
|
* @param <F> the type parameter
|
||||||
|
* @param <S> the type parameter
|
||||||
|
*/
|
||||||
public final class Pair<F, S> {
|
public final class Pair<F, S> {
|
||||||
|
/**
|
||||||
|
* The First.
|
||||||
|
*/
|
||||||
public F first;
|
public F first;
|
||||||
|
/**
|
||||||
|
* The Second.
|
||||||
|
*/
|
||||||
public S second;
|
public S second;
|
||||||
|
|
||||||
private Pair(F first, S second) {
|
private Pair(F first, S second) {
|
||||||
|
|
@ -12,6 +24,15 @@ public final class Pair<F, S> {
|
||||||
this.second = second;
|
this.second = second;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of @ not null pair.
|
||||||
|
*
|
||||||
|
* @param <F> the type parameter
|
||||||
|
* @param <S> the type parameter
|
||||||
|
* @param first the first
|
||||||
|
* @param second the second
|
||||||
|
* @return the @ not null pair
|
||||||
|
*/
|
||||||
@Contract("null, _ -> fail; !null, null -> fail; !null, !null -> new")
|
@Contract("null, _ -> fail; !null, null -> fail; !null, !null -> new")
|
||||||
public static <F, S> @NotNull Pair<F, S> of(F first, S second) {
|
public static <F, S> @NotNull Pair<F, S> of(F first, S second) {
|
||||||
if (first == null || second == null) {
|
if (first == null || second == null) {
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,26 @@ import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Triple.
|
||||||
|
*
|
||||||
|
* @param <A> the type parameter
|
||||||
|
* @param <B> the type parameter
|
||||||
|
* @param <C> the type parameter
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class Triple<A, B, C> {
|
public final class Triple<A, B, C> {
|
||||||
|
/**
|
||||||
|
* The First.
|
||||||
|
*/
|
||||||
public A first;
|
public A first;
|
||||||
|
/**
|
||||||
|
* The Second.
|
||||||
|
*/
|
||||||
public B second;
|
public B second;
|
||||||
|
/**
|
||||||
|
* The Third.
|
||||||
|
*/
|
||||||
public C third;
|
public C third;
|
||||||
|
|
||||||
private Triple(A first, B second, C third) {
|
private Triple(A first, B second, C third) {
|
||||||
|
|
@ -17,6 +33,17 @@ public final class Triple<A, B, C> {
|
||||||
this.third = third;
|
this.third = third;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of @ not null triple.
|
||||||
|
*
|
||||||
|
* @param <A> the type parameter
|
||||||
|
* @param <B> the type parameter
|
||||||
|
* @param <C> the type parameter
|
||||||
|
* @param first the first
|
||||||
|
* @param second the second
|
||||||
|
* @param third the third
|
||||||
|
* @return the @ not null triple
|
||||||
|
*/
|
||||||
@Contract(value = "_, _, _ -> new", pure = true)
|
@Contract(value = "_, _, _ -> new", pure = true)
|
||||||
public static <A, B, C> @NotNull Triple<A, B, C> of(A first, B second, C third) {
|
public static <A, B, C> @NotNull Triple<A, B, C> of(A first, B second, C third) {
|
||||||
return new Triple<>(first, second, third);
|
return new Triple<>(first, second, third);
|
||||||
|
|
@ -37,8 +64,9 @@ public final class Triple<A, B, C> {
|
||||||
return Objects.hash(first, second, third);
|
return Objects.hash(first, second, third);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Contract(pure = true)
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public @NotNull String toString() {
|
||||||
return "Triple{" +
|
return "Triple{" +
|
||||||
"first=" + first +
|
"first=" + first +
|
||||||
", second=" + second +
|
", second=" + second +
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,9 @@ import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Tuple.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class Tuple {
|
public final class Tuple {
|
||||||
private final List<Object> elements;
|
private final List<Object> elements;
|
||||||
|
|
@ -16,15 +19,33 @@ public final class Tuple {
|
||||||
this.elements = List.of(elements);
|
this.elements = List.of(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Of tuple.
|
||||||
|
*
|
||||||
|
* @param elements the elements
|
||||||
|
* @return the tuple
|
||||||
|
*/
|
||||||
@Contract(value = "_ -> new", pure = true)
|
@Contract(value = "_ -> new", pure = true)
|
||||||
public static @NotNull Tuple of(Object... elements) {
|
public static @NotNull Tuple of(Object... elements) {
|
||||||
return new Tuple(elements);
|
return new Tuple(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size int.
|
||||||
|
*
|
||||||
|
* @return the int
|
||||||
|
*/
|
||||||
public int size() {
|
public int size() {
|
||||||
return elements.size();
|
return elements.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param index the index
|
||||||
|
* @return the t
|
||||||
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> T get(int index) {
|
public <T> T get(int index) {
|
||||||
if (index < 0 || index >= elements.size()) {
|
if (index < 0 || index >= elements.size()) {
|
||||||
|
|
@ -33,27 +54,63 @@ public final class Tuple {
|
||||||
return (T) elements.get(index);
|
return (T) elements.get(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* First t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @return the t
|
||||||
|
*/
|
||||||
public <T> T first() {
|
public <T> T first() {
|
||||||
return get(0);
|
return get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Second t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @return the t
|
||||||
|
*/
|
||||||
public <T> T second() {
|
public <T> T second() {
|
||||||
return get(1);
|
return get(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Third t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @return the t
|
||||||
|
*/
|
||||||
public <T> T third() {
|
public <T> T third() {
|
||||||
return get(2);
|
return get(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Last t.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @return the t
|
||||||
|
*/
|
||||||
public <T> T last() {
|
public <T> T last() {
|
||||||
return get(elements.size() - 1);
|
return get(elements.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Object> toList() {
|
/**
|
||||||
|
* To list list.
|
||||||
|
*
|
||||||
|
* @return the list
|
||||||
|
*/
|
||||||
|
@Contract(value = " -> new", pure = true)
|
||||||
|
public @NotNull List<Object> toList() {
|
||||||
return new ArrayList<>(elements);
|
return new ArrayList<>(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object[] toArray() {
|
/**
|
||||||
|
* To array object [ ].
|
||||||
|
*
|
||||||
|
* @return the object [ ]
|
||||||
|
*/
|
||||||
|
@Contract(pure = true)
|
||||||
|
public Object @NotNull [] toArray() {
|
||||||
return elements.toArray();
|
return elements.toArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,15 +127,26 @@ public final class Tuple {
|
||||||
return Objects.hash(elements);
|
return Objects.hash(elements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Contract(pure = true)
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public @NotNull String toString() {
|
||||||
return "Tuple" + elements;
|
return "Tuple" + elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterator<Object> iterator() {
|
/**
|
||||||
|
* Iterator iterator.
|
||||||
|
*
|
||||||
|
* @return the iterator
|
||||||
|
*/
|
||||||
|
public @NotNull Iterator<Object> iterator() {
|
||||||
return elements.iterator();
|
return elements.iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stream java . util . stream . stream.
|
||||||
|
*
|
||||||
|
* @return the java . util . stream . stream
|
||||||
|
*/
|
||||||
public java.util.stream.Stream<Object> stream() {
|
public java.util.stream.Stream<Object> stream() {
|
||||||
return elements.stream();
|
return elements.stream();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,9 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Consumer;
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Nbt reader.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class NBTReader {
|
public class NBTReader {
|
||||||
private final CompoundTag nbt;
|
private final CompoundTag nbt;
|
||||||
|
|
@ -34,13 +37,23 @@ public class NBTReader {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从CompoundTag创建读取器
|
* 从CompoundTag创建读取器
|
||||||
|
*
|
||||||
|
* @param nbt the nbt
|
||||||
|
* @return the nbt reader
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
public static NBTReader of(@NotNull CompoundTag nbt) {
|
public static NBTReader of(@NotNull CompoundTag nbt) {
|
||||||
return new NBTReader(nbt);
|
return new NBTReader(nbt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 基本读取方法 - 直接赋值给成员变量
|
/**
|
||||||
|
* String nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// 基本读取方法 - 直接赋值给成员变量
|
||||||
public NBTReader string(String key, Consumer<String> setter) {
|
public NBTReader string(String key, Consumer<String> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getString(key));
|
setter.accept(nbt.getString(key));
|
||||||
|
|
@ -48,11 +61,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* String nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader string(String key, @NotNull Consumer<String> setter, String defaultValue) {
|
public NBTReader string(String key, @NotNull Consumer<String> setter, String defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getString(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getString(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader byteValue(String key, Consumer<Byte> setter) {
|
public NBTReader byteValue(String key, Consumer<Byte> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getByte(key));
|
setter.accept(nbt.getByte(key));
|
||||||
|
|
@ -60,11 +88,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Byte value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader byteValue(String key, @NotNull Consumer<Byte> setter, byte defaultValue) {
|
public NBTReader byteValue(String key, @NotNull Consumer<Byte> setter, byte defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getByte(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getByte(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader shortValue(String key, Consumer<Short> setter) {
|
public NBTReader shortValue(String key, Consumer<Short> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getShort(key));
|
setter.accept(nbt.getShort(key));
|
||||||
|
|
@ -72,11 +115,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Short value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader shortValue(String key, @NotNull Consumer<Short> setter, short defaultValue) {
|
public NBTReader shortValue(String key, @NotNull Consumer<Short> setter, short defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getShort(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getShort(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Int value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader intValue(String key, Consumer<Integer> setter) {
|
public NBTReader intValue(String key, Consumer<Integer> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getInt(key));
|
setter.accept(nbt.getInt(key));
|
||||||
|
|
@ -84,11 +142,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Int value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader intValue(String key, @NotNull Consumer<Integer> setter, int defaultValue) {
|
public NBTReader intValue(String key, @NotNull Consumer<Integer> setter, int defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getInt(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getInt(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader longValue(String key, Consumer<Long> setter) {
|
public NBTReader longValue(String key, Consumer<Long> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getLong(key));
|
setter.accept(nbt.getLong(key));
|
||||||
|
|
@ -96,11 +169,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader longValue(String key, @NotNull Consumer<Long> setter, long defaultValue) {
|
public NBTReader longValue(String key, @NotNull Consumer<Long> setter, long defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getLong(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getLong(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Float value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader floatValue(String key, Consumer<Float> setter) {
|
public NBTReader floatValue(String key, Consumer<Float> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getFloat(key));
|
setter.accept(nbt.getFloat(key));
|
||||||
|
|
@ -108,11 +196,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Float value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader floatValue(String key, @NotNull Consumer<Float> setter, float defaultValue) {
|
public NBTReader floatValue(String key, @NotNull Consumer<Float> setter, float defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getFloat(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getFloat(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Double value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader doubleValue(String key, Consumer<Double> setter) {
|
public NBTReader doubleValue(String key, Consumer<Double> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getDouble(key));
|
setter.accept(nbt.getDouble(key));
|
||||||
|
|
@ -120,11 +223,26 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Double value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader doubleValue(String key, @NotNull Consumer<Double> setter, double defaultValue) {
|
public NBTReader doubleValue(String key, @NotNull Consumer<Double> setter, double defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getDouble(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getDouble(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader booleanValue(String key, Consumer<Boolean> setter) {
|
public NBTReader booleanValue(String key, Consumer<Boolean> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getBoolean(key));
|
setter.accept(nbt.getBoolean(key));
|
||||||
|
|
@ -132,12 +250,27 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boolean value nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader booleanValue(String key, @NotNull Consumer<Boolean> setter, boolean defaultValue) {
|
public NBTReader booleanValue(String key, @NotNull Consumer<Boolean> setter, boolean defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getBoolean(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getBoolean(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数组类型
|
/**
|
||||||
|
* Byte array nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// 数组类型
|
||||||
public NBTReader byteArray(String key, Consumer<byte[]> setter) {
|
public NBTReader byteArray(String key, Consumer<byte[]> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getByteArray(key));
|
setter.accept(nbt.getByteArray(key));
|
||||||
|
|
@ -145,6 +278,13 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Int array nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader intArray(String key, Consumer<int[]> setter) {
|
public NBTReader intArray(String key, Consumer<int[]> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getIntArray(key));
|
setter.accept(nbt.getIntArray(key));
|
||||||
|
|
@ -152,6 +292,13 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Long array nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader longArray(String key, Consumer<long[]> setter) {
|
public NBTReader longArray(String key, Consumer<long[]> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getLongArray(key));
|
setter.accept(nbt.getLongArray(key));
|
||||||
|
|
@ -159,7 +306,14 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// UUID
|
/**
|
||||||
|
* Uuid nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// UUID
|
||||||
public NBTReader uuid(String key, Consumer<UUID> setter) {
|
public NBTReader uuid(String key, Consumer<UUID> setter) {
|
||||||
if (nbt.hasUUID(key)) {
|
if (nbt.hasUUID(key)) {
|
||||||
setter.accept(nbt.getUUID(key));
|
setter.accept(nbt.getUUID(key));
|
||||||
|
|
@ -167,12 +321,27 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uuid nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader uuid(String key, @NotNull Consumer<UUID> setter, UUID defaultValue) {
|
public NBTReader uuid(String key, @NotNull Consumer<UUID> setter, UUID defaultValue) {
|
||||||
setter.accept(nbt.hasUUID(key) ? nbt.getUUID(key) : defaultValue);
|
setter.accept(nbt.hasUUID(key) ? nbt.getUUID(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// CompoundTag
|
/**
|
||||||
|
* Compound nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// CompoundTag
|
||||||
public NBTReader compound(String key, Consumer<CompoundTag> setter) {
|
public NBTReader compound(String key, Consumer<CompoundTag> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getCompound(key));
|
setter.accept(nbt.getCompound(key));
|
||||||
|
|
@ -180,12 +349,28 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compound nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader compound(String key, @NotNull Consumer<CompoundTag> setter, CompoundTag defaultValue) {
|
public NBTReader compound(String key, @NotNull Consumer<CompoundTag> setter, CompoundTag defaultValue) {
|
||||||
setter.accept(nbt.contains(key) ? nbt.getCompound(key) : defaultValue);
|
setter.accept(nbt.contains(key) ? nbt.getCompound(key) : defaultValue);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListTag
|
/**
|
||||||
|
* List nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param type the type
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// ListTag
|
||||||
public NBTReader list(String key, int type, Consumer<ListTag> setter) {
|
public NBTReader list(String key, int type, Consumer<ListTag> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
setter.accept(nbt.getList(key, type));
|
setter.accept(nbt.getList(key, type));
|
||||||
|
|
@ -193,7 +378,14 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vec3支持
|
/**
|
||||||
|
* Vec 3 nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// Vec3支持
|
||||||
public NBTReader vec3(String key, Consumer<Vec3> setter) {
|
public NBTReader vec3(String key, Consumer<Vec3> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
CompoundTag vecTag = nbt.getCompound(key);
|
CompoundTag vecTag = nbt.getCompound(key);
|
||||||
|
|
@ -208,6 +400,14 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Vec 3 nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader vec3(String key, Consumer<Vec3> setter, Vec3 defaultValue) {
|
public NBTReader vec3(String key, Consumer<Vec3> setter, Vec3 defaultValue) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
CompoundTag vecTag = nbt.getCompound(key);
|
CompoundTag vecTag = nbt.getCompound(key);
|
||||||
|
|
@ -224,7 +424,16 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 枚举支持
|
/**
|
||||||
|
* Enum value nbt reader.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param enumClass the enum class
|
||||||
|
* @param setter the setter
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// 枚举支持
|
||||||
public <T extends Enum<T>> NBTReader enumValue(String key, Class<T> enumClass, Consumer<T> setter) {
|
public <T extends Enum<T>> NBTReader enumValue(String key, Class<T> enumClass, Consumer<T> setter) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
String value = nbt.getString(key);
|
String value = nbt.getString(key);
|
||||||
|
|
@ -237,6 +446,16 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum value nbt reader.
|
||||||
|
*
|
||||||
|
* @param <T> the type parameter
|
||||||
|
* @param key the key
|
||||||
|
* @param enumClass the enum class
|
||||||
|
* @param setter the setter
|
||||||
|
* @param defaultValue the default value
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public <T extends Enum<T>> NBTReader enumValue(String key, Class<T> enumClass, Consumer<T> setter, T defaultValue) {
|
public <T extends Enum<T>> NBTReader enumValue(String key, Class<T> enumClass, Consumer<T> setter, T defaultValue) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
String value = nbt.getString(key);
|
String value = nbt.getString(key);
|
||||||
|
|
@ -250,7 +469,14 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 嵌套读取支持
|
/**
|
||||||
|
* Nested nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param consumer the consumer
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// 嵌套读取支持
|
||||||
public NBTReader nested(String key, Consumer<NBTReader> consumer) {
|
public NBTReader nested(String key, Consumer<NBTReader> consumer) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
consumer.accept(new NBTReader(nbt.getCompound(key)));
|
consumer.accept(new NBTReader(nbt.getCompound(key)));
|
||||||
|
|
@ -258,6 +484,14 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nested nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param consumer the consumer
|
||||||
|
* @param orElse the or else
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader nested(String key, Consumer<NBTReader> consumer, Runnable orElse) {
|
public NBTReader nested(String key, Consumer<NBTReader> consumer, Runnable orElse) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
consumer.accept(new NBTReader(nbt.getCompound(key)));
|
consumer.accept(new NBTReader(nbt.getCompound(key)));
|
||||||
|
|
@ -267,7 +501,14 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 条件读取
|
/**
|
||||||
|
* If present nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param action the action
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
|
// 条件读取
|
||||||
public NBTReader ifPresent(String key, Runnable action) {
|
public NBTReader ifPresent(String key, Runnable action) {
|
||||||
if (nbt.contains(key)) {
|
if (nbt.contains(key)) {
|
||||||
action.run();
|
action.run();
|
||||||
|
|
@ -275,6 +516,13 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If absent nbt reader.
|
||||||
|
*
|
||||||
|
* @param key the key
|
||||||
|
* @param action the action
|
||||||
|
* @return the nbt reader
|
||||||
|
*/
|
||||||
public NBTReader ifAbsent(String key, Runnable action) {
|
public NBTReader ifAbsent(String key, Runnable action) {
|
||||||
if (!nbt.contains(key)) {
|
if (!nbt.contains(key)) {
|
||||||
action.run();
|
action.run();
|
||||||
|
|
@ -282,13 +530,24 @@ public class NBTReader {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取原始NBT
|
/**
|
||||||
|
* Gets raw.
|
||||||
|
*
|
||||||
|
* @return the raw
|
||||||
|
*/
|
||||||
|
// 获取原始NBT
|
||||||
@NotNull
|
@NotNull
|
||||||
public CompoundTag getRaw() {
|
public CompoundTag getRaw() {
|
||||||
return nbt;
|
return nbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 便捷的静态方法(保持原有功能)
|
/**
|
||||||
|
* Read vec 3 vec 3.
|
||||||
|
*
|
||||||
|
* @param nbt the nbt
|
||||||
|
* @return the vec 3
|
||||||
|
*/
|
||||||
|
// 便捷的静态方法(保持原有功能)
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Vec3 readVec3(@NotNull CompoundTag nbt) {
|
public static Vec3 readVec3(@NotNull CompoundTag nbt) {
|
||||||
if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) {
|
if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) {
|
||||||
|
|
@ -302,6 +561,12 @@ public class NBTReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read vec 3 safe vec 3.
|
||||||
|
*
|
||||||
|
* @param nbt the nbt
|
||||||
|
* @return the vec 3
|
||||||
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Vec3 readVec3Safe(@NotNull CompoundTag nbt) {
|
public static Vec3 readVec3Safe(@NotNull CompoundTag nbt) {
|
||||||
if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) {
|
if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) {
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -24,13 +24,17 @@ import java.util.Queue;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding applier.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingApplier {
|
public class RidingApplier {
|
||||||
/**
|
/**
|
||||||
* 应用骑乘关系(在服务器端调用)
|
* 应用骑乘关系(在服务器端调用)
|
||||||
* @param relationship 骑乘关系
|
*
|
||||||
|
* @param relationship 骑乘关系
|
||||||
* @param entityProvider 实体提供器(根据UUID获取实体)
|
* @param entityProvider 实体提供器(根据UUID获取实体)
|
||||||
* @return 应用成功的实体数量
|
* @return 应用成功的实体数量 int
|
||||||
*/
|
*/
|
||||||
public static int applyRidingRelationship(RidingRelationship relationship,
|
public static int applyRidingRelationship(RidingRelationship relationship,
|
||||||
Function<UUID, Entity> entityProvider) {
|
Function<UUID, Entity> entityProvider) {
|
||||||
|
|
@ -87,8 +91,12 @@ public class RidingApplier {
|
||||||
|
|
||||||
return appliedCount;
|
return appliedCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量应用骑乘关系(适用于世界加载时)
|
* 批量应用骑乘关系(适用于世界加载时)
|
||||||
|
*
|
||||||
|
* @param relationships the relationships
|
||||||
|
* @param entityProvider the entity provider
|
||||||
*/
|
*/
|
||||||
public static void applyRidingRelationships(Collection<RidingRelationship> relationships,
|
public static void applyRidingRelationships(Collection<RidingRelationship> relationships,
|
||||||
Function<UUID, Entity> entityProvider) {
|
Function<UUID, Entity> entityProvider) {
|
||||||
|
|
@ -108,6 +116,10 @@ public class RidingApplier {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从JSON字符串应用骑乘关系
|
* 从JSON字符串应用骑乘关系
|
||||||
|
*
|
||||||
|
* @param json the json
|
||||||
|
* @param entityProvider the entity provider
|
||||||
|
* @return the int
|
||||||
*/
|
*/
|
||||||
public static int applyRidingRelationshipFromJson(String json,
|
public static int applyRidingRelationshipFromJson(String json,
|
||||||
Function<UUID, Entity> entityProvider) {
|
Function<UUID, Entity> entityProvider) {
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,20 @@ package top.r3944realms.lib39.util.riding;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding cycle exception.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingCycleException extends IllegalStateException {
|
public class RidingCycleException extends IllegalStateException {
|
||||||
private final UUID entityId;
|
private final UUID entityId;
|
||||||
private final UUID vehicleId;
|
private final UUID vehicleId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Riding cycle exception.
|
||||||
|
*
|
||||||
|
* @param entityId the entity id
|
||||||
|
* @param vehicleId the vehicle id
|
||||||
|
*/
|
||||||
public RidingCycleException(UUID entityId, UUID vehicleId) {
|
public RidingCycleException(UUID entityId, UUID vehicleId) {
|
||||||
super(String.format("Cyclic riding reference detected. " +
|
super(String.format("Cyclic riding reference detected. " +
|
||||||
"Entity %s cannot be added as passenger to vehicle %s " +
|
"Entity %s cannot be added as passenger to vehicle %s " +
|
||||||
|
|
@ -31,10 +40,20 @@ public class RidingCycleException extends IllegalStateException {
|
||||||
this.vehicleId = vehicleId;
|
this.vehicleId = vehicleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets entity id.
|
||||||
|
*
|
||||||
|
* @return the entity id
|
||||||
|
*/
|
||||||
public UUID getEntityId() {
|
public UUID getEntityId() {
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets vehicle id.
|
||||||
|
*
|
||||||
|
* @return the vehicle id
|
||||||
|
*/
|
||||||
public UUID getVehicleId() {
|
public UUID getVehicleId() {
|
||||||
return vehicleId;
|
return vehicleId;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,15 @@ import net.minecraft.world.entity.Entity;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding dismounts.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingDismounts {
|
public class RidingDismounts {
|
||||||
/**
|
/**
|
||||||
* 解除单个实体的骑乘关系
|
* 解除单个实体的骑乘关系
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
*/
|
*/
|
||||||
public static void dismountEntity(Entity entity) {
|
public static void dismountEntity(Entity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
|
@ -41,6 +46,8 @@ public class RidingDismounts {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解除实体及其所有乘客的骑乘关系(非递归)
|
* 解除实体及其所有乘客的骑乘关系(非递归)
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
*/
|
*/
|
||||||
public static void dismountAllPassengers(Entity entity) {
|
public static void dismountAllPassengers(Entity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
|
@ -65,6 +72,8 @@ public class RidingDismounts {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 解除根实体的骑乘关系(包括从载具下车)
|
* 解除根实体的骑乘关系(包括从载具下车)
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
*/
|
*/
|
||||||
public static void dismountRootEntity(Entity entity) {
|
public static void dismountRootEntity(Entity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
|
@ -86,6 +95,10 @@ public class RidingDismounts {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 安全解除骑乘关系(带超时保护)
|
* 安全解除骑乘关系(带超时保护)
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param maxIterations the max iterations
|
||||||
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
public static boolean safeDismountAll(Entity entity, int maxIterations) {
|
public static boolean safeDismountAll(Entity entity, int maxIterations) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
|
@ -118,6 +131,8 @@ public class RidingDismounts {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量解除多个实体的骑乘关系
|
* 批量解除多个实体的骑乘关系
|
||||||
|
*
|
||||||
|
* @param entities the entities
|
||||||
*/
|
*/
|
||||||
public static void dismountEntities(Collection<Entity> entities) {
|
public static void dismountEntities(Collection<Entity> entities) {
|
||||||
if (entities == null || entities.isEmpty()) {
|
if (entities == null || entities.isEmpty()) {
|
||||||
|
|
@ -151,6 +166,9 @@ public class RidingDismounts {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据骑乘关系数据结构解除骑乘
|
* 根据骑乘关系数据结构解除骑乘
|
||||||
|
*
|
||||||
|
* @param relationship the relationship
|
||||||
|
* @param entityProvider the entity provider
|
||||||
*/
|
*/
|
||||||
public static void dismountByRelationship(RidingRelationship relationship,
|
public static void dismountByRelationship(RidingRelationship relationship,
|
||||||
Function<UUID, Entity> entityProvider) {
|
Function<UUID, Entity> entityProvider) {
|
||||||
|
|
@ -181,6 +199,8 @@ public class RidingDismounts {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立即解除所有骑乘关系(强制方式)
|
* 立即解除所有骑乘关系(强制方式)
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
*/
|
*/
|
||||||
public static void forceDismountAll(Entity entity) {
|
public static void forceDismountAll(Entity entity) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,17 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding finder.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingFinder {
|
public class RidingFinder {
|
||||||
/**
|
/**
|
||||||
* 从JSON字符串应用骑乘关系
|
* 从JSON字符串应用骑乘关系
|
||||||
|
*
|
||||||
|
* @param ship the ship
|
||||||
|
* @param entityProvider the entity provider
|
||||||
|
* @return the entity from riding ship
|
||||||
*/
|
*/
|
||||||
public static @NotNull List<Entity> getEntityFromRidingShip(RidingRelationship ship,
|
public static @NotNull List<Entity> getEntityFromRidingShip(RidingRelationship ship,
|
||||||
Function<UUID, Entity> entityProvider) {
|
Function<UUID, Entity> entityProvider) {
|
||||||
|
|
@ -42,8 +49,12 @@ public class RidingFinder {
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找根载具
|
* 查找根载具
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @return the entity
|
||||||
*/
|
*/
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Entity findRootVehicle(@Nullable Entity entity) {
|
public static Entity findRootVehicle(@Nullable Entity entity) {
|
||||||
|
|
@ -64,6 +75,9 @@ public class RidingFinder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有乘客(包括嵌套乘客)
|
* 获取所有乘客(包括嵌套乘客)
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @return the all passengers
|
||||||
*/
|
*/
|
||||||
public static List<Entity> getAllPassengers(@Nullable Entity entity) {
|
public static List<Entity> getAllPassengers(@Nullable Entity entity) {
|
||||||
return getAllPassengers(entity, true);
|
return getAllPassengers(entity, true);
|
||||||
|
|
@ -71,6 +85,10 @@ public class RidingFinder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有乘客(包括嵌套乘客)
|
* 获取所有乘客(包括嵌套乘客)
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param findRoot the find root
|
||||||
|
* @return the all passengers
|
||||||
*/
|
*/
|
||||||
public static List<Entity> getAllPassengers(@Nullable Entity entity, boolean findRoot) {
|
public static List<Entity> getAllPassengers(@Nullable Entity entity, boolean findRoot) {
|
||||||
if (entity == null) {
|
if (entity == null) {
|
||||||
|
|
|
||||||
|
|
@ -26,46 +26,93 @@ public class RidingRelationship {
|
||||||
private UUID vehicleId;
|
private UUID vehicleId;
|
||||||
private List<RidingRelationship> passengers;
|
private List<RidingRelationship> passengers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Riding relationship.
|
||||||
|
*/
|
||||||
public RidingRelationship() {
|
public RidingRelationship() {
|
||||||
this.passengers = new ArrayList<>();
|
this.passengers = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instantiates a new Riding relationship.
|
||||||
|
*
|
||||||
|
* @param passengers the passengers
|
||||||
|
* @param vehicleId the vehicle id
|
||||||
|
* @param entityId the entity id
|
||||||
|
*/
|
||||||
public RidingRelationship(List<RidingRelationship> passengers, UUID vehicleId, UUID entityId) {
|
public RidingRelationship(List<RidingRelationship> passengers, UUID vehicleId, UUID entityId) {
|
||||||
this.passengers = passengers != null ? passengers : new ArrayList<>();
|
this.passengers = passengers != null ? passengers : new ArrayList<>();
|
||||||
this.vehicleId = vehicleId;
|
this.vehicleId = vehicleId;
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets entity id.
|
||||||
|
*
|
||||||
|
* @return the entity id
|
||||||
|
*/
|
||||||
public UUID getEntityId() {
|
public UUID getEntityId() {
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets entity id.
|
||||||
|
*
|
||||||
|
* @param entityId the entity id
|
||||||
|
*/
|
||||||
public void setEntityId(UUID entityId) {
|
public void setEntityId(UUID entityId) {
|
||||||
this.entityId = entityId;
|
this.entityId = entityId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets passengers.
|
||||||
|
*
|
||||||
|
* @return the passengers
|
||||||
|
*/
|
||||||
public List<RidingRelationship> getPassengers() {
|
public List<RidingRelationship> getPassengers() {
|
||||||
return Collections.unmodifiableList(passengers);
|
return Collections.unmodifiableList(passengers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets passengers.
|
||||||
|
*
|
||||||
|
* @param passengers the passengers
|
||||||
|
*/
|
||||||
public void setPassengers(List<RidingRelationship> passengers) {
|
public void setPassengers(List<RidingRelationship> passengers) {
|
||||||
this.passengers = passengers != null ? passengers : new ArrayList<>();
|
this.passengers = passengers != null ? passengers : new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add passenger.
|
||||||
|
*
|
||||||
|
* @param passenger the passenger
|
||||||
|
*/
|
||||||
public void addPassenger(RidingRelationship passenger) {
|
public void addPassenger(RidingRelationship passenger) {
|
||||||
this.passengers.add(passenger);
|
this.passengers.add(passenger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets vehicle id.
|
||||||
|
*
|
||||||
|
* @return the vehicle id
|
||||||
|
*/
|
||||||
public UUID getVehicleId() {
|
public UUID getVehicleId() {
|
||||||
return vehicleId;
|
return vehicleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets vehicle id.
|
||||||
|
*
|
||||||
|
* @param vehicleId the vehicle id
|
||||||
|
*/
|
||||||
public void setVehicleId(UUID vehicleId) {
|
public void setVehicleId(UUID vehicleId) {
|
||||||
this.vehicleId = vehicleId;
|
this.vehicleId = vehicleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有嵌套乘客的数量
|
* 获取所有嵌套乘客的数量
|
||||||
|
*
|
||||||
|
* @return the total passenger count
|
||||||
*/
|
*/
|
||||||
public int getTotalPassengerCount() {
|
public int getTotalPassengerCount() {
|
||||||
int count = passengers.size();
|
int count = passengers.size();
|
||||||
|
|
@ -77,6 +124,9 @@ public class RidingRelationship {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查是否包含特定实体
|
* 检查是否包含特定实体
|
||||||
|
*
|
||||||
|
* @param entityId the entity id
|
||||||
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
public boolean containsEntity(UUID entityId) {
|
public boolean containsEntity(UUID entityId) {
|
||||||
if (Objects.equals(this.entityId, entityId)) {
|
if (Objects.equals(this.entityId, entityId)) {
|
||||||
|
|
|
||||||
|
|
@ -25,10 +25,16 @@ import top.r3944realms.lib39.util.lang.Pair;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding saver.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingSaver {
|
public class RidingSaver {
|
||||||
/**
|
/**
|
||||||
* 保存骑乘关系
|
* 保存骑乘关系
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @return the riding relationship
|
||||||
*/
|
*/
|
||||||
@Contract("null -> new")
|
@Contract("null -> new")
|
||||||
public static @NotNull RidingRelationship save(@Nullable Entity entity) {
|
public static @NotNull RidingRelationship save(@Nullable Entity entity) {
|
||||||
|
|
@ -37,6 +43,10 @@ public class RidingSaver {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存骑乘关系
|
* 保存骑乘关系
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param findRoot the find root
|
||||||
|
* @return the riding relationship
|
||||||
*/
|
*/
|
||||||
@Contract("null, _ -> new")
|
@Contract("null, _ -> new")
|
||||||
public static @NotNull RidingRelationship save(@Nullable Entity entity, boolean findRoot) {
|
public static @NotNull RidingRelationship save(@Nullable Entity entity, boolean findRoot) {
|
||||||
|
|
@ -98,6 +108,11 @@ public class RidingSaver {
|
||||||
// 传入一个实体提供器 Function<UUID, Entity>,通常在服务器侧就是 level::getEntity
|
// 传入一个实体提供器 Function<UUID, Entity>,通常在服务器侧就是 level::getEntity
|
||||||
private static Function<UUID, Entity> entityProvider;
|
private static Function<UUID, Entity> entityProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets entity provider.
|
||||||
|
*
|
||||||
|
* @param provider the provider
|
||||||
|
*/
|
||||||
public static void setEntityProvider(Function<UUID, Entity> provider) {
|
public static void setEntityProvider(Function<UUID, Entity> provider) {
|
||||||
entityProvider = provider;
|
entityProvider = provider;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,18 @@ package top.r3944realms.lib39.util.riding;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding serializer.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingSerializer {
|
public class RidingSerializer {
|
||||||
private static final Gson GSON = new Gson();
|
private static final Gson GSON = new Gson();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 序列化骑乘关系
|
* 序列化骑乘关系
|
||||||
|
*
|
||||||
|
* @param relationship the relationship
|
||||||
|
* @return the string
|
||||||
*/
|
*/
|
||||||
public static String serialize(RidingRelationship relationship) {
|
public static String serialize(RidingRelationship relationship) {
|
||||||
return GSON.toJson(relationship);
|
return GSON.toJson(relationship);
|
||||||
|
|
@ -29,6 +36,9 @@ public class RidingSerializer {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 反序列化骑乘关系
|
* 反序列化骑乘关系
|
||||||
|
*
|
||||||
|
* @param json the json
|
||||||
|
* @return the riding relationship
|
||||||
*/
|
*/
|
||||||
public static RidingRelationship deserialize(String json) {
|
public static RidingRelationship deserialize(String json) {
|
||||||
return GSON.fromJson(json, RidingRelationship.class);
|
return GSON.fromJson(json, RidingRelationship.class);
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,17 @@ import net.minecraft.world.entity.Entity;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Riding validator.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class RidingValidator {
|
public class RidingValidator {
|
||||||
/**
|
/**
|
||||||
* 检查骑乘是否会产生循环引用
|
* 检查骑乘是否会产生循环引用
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param vehicle the vehicle
|
||||||
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
public static boolean wouldCreateCycle(Entity entity, Entity vehicle) {
|
public static boolean wouldCreateCycle(Entity entity, Entity vehicle) {
|
||||||
// 如果实体就是载具本身,直接产生循环
|
// 如果实体就是载具本身,直接产生循环
|
||||||
|
|
@ -37,6 +44,10 @@ public class RidingValidator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查target是否是entity的间接乘客
|
* 检查target是否是entity的间接乘客
|
||||||
|
*
|
||||||
|
* @param target the target
|
||||||
|
* @param entity the entity
|
||||||
|
* @return the boolean
|
||||||
*/
|
*/
|
||||||
public static boolean isIndirectPassenger(Entity target, Entity entity) {
|
public static boolean isIndirectPassenger(Entity target, Entity entity) {
|
||||||
Queue<Entity> queue = new LinkedList<>();
|
Queue<Entity> queue = new LinkedList<>();
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,43 @@ package top.r3944realms.lib39.util.shape;
|
||||||
import com.mojang.math.Axis;
|
import com.mojang.math.Axis;
|
||||||
import org.joml.Quaternionf;
|
import org.joml.Quaternionf;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Quaternions.
|
||||||
|
*/
|
||||||
public final class Quaternions {
|
public final class Quaternions {
|
||||||
|
/**
|
||||||
|
* The constant XP_90.
|
||||||
|
*/
|
||||||
public static final Quaternionf XP_90 = Axis.XP.rotationDegrees(90);
|
public static final Quaternionf XP_90 = Axis.XP.rotationDegrees(90);
|
||||||
|
/**
|
||||||
|
* The constant XP_180.
|
||||||
|
*/
|
||||||
public static final Quaternionf XP_180 = Axis.XP.rotationDegrees(180);
|
public static final Quaternionf XP_180 = Axis.XP.rotationDegrees(180);
|
||||||
|
/**
|
||||||
|
* The constant XN_90.
|
||||||
|
*/
|
||||||
public static final Quaternionf XN_90 = Axis.XN.rotationDegrees(90);
|
public static final Quaternionf XN_90 = Axis.XN.rotationDegrees(90);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constant YP_90.
|
||||||
|
*/
|
||||||
public static final Quaternionf YP_90 = Axis.YP.rotationDegrees(90);
|
public static final Quaternionf YP_90 = Axis.YP.rotationDegrees(90);
|
||||||
|
/**
|
||||||
|
* The constant YN_90.
|
||||||
|
*/
|
||||||
public static final Quaternionf YN_90 = Axis.YN.rotationDegrees(90);
|
public static final Quaternionf YN_90 = Axis.YN.rotationDegrees(90);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The constant ZP_90.
|
||||||
|
*/
|
||||||
public static final Quaternionf ZP_90 = Axis.ZP.rotationDegrees(90);
|
public static final Quaternionf ZP_90 = Axis.ZP.rotationDegrees(90);
|
||||||
|
/**
|
||||||
|
* The constant ZP_180.
|
||||||
|
*/
|
||||||
public static final Quaternionf ZP_180 = Axis.ZP.rotationDegrees(180);
|
public static final Quaternionf ZP_180 = Axis.ZP.rotationDegrees(180);
|
||||||
|
/**
|
||||||
|
* The constant ZN_90.
|
||||||
|
*/
|
||||||
public static final Quaternionf ZN_90 = Axis.ZN.rotationDegrees(90);
|
public static final Quaternionf ZN_90 = Axis.ZN.rotationDegrees(90);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,10 +4,14 @@ import net.minecraft.core.Direction;
|
||||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
||||||
import net.minecraft.world.phys.shapes.Shapes;
|
import net.minecraft.world.phys.shapes.Shapes;
|
||||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||||
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Shape util.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class ShapeUtil {
|
public class ShapeUtil {
|
||||||
|
|
||||||
|
|
@ -15,6 +19,14 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建基于像素的碰撞箱(将像素坐标转换为方块坐标)
|
* 创建基于像素的碰撞箱(将像素坐标转换为方块坐标)
|
||||||
|
*
|
||||||
|
* @param minX the min x
|
||||||
|
* @param minY the min y
|
||||||
|
* @param minZ the min z
|
||||||
|
* @param maxX the max x
|
||||||
|
* @param maxY the max y
|
||||||
|
* @param maxZ the max z
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
public static @NotNull VoxelShape createPixelBasedShape(double minX, double minY, double minZ,
|
public static @NotNull VoxelShape createPixelBasedShape(double minX, double minY, double minZ,
|
||||||
double maxX, double maxY, double maxZ) {
|
double maxX, double maxY, double maxZ) {
|
||||||
|
|
@ -24,6 +36,14 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 便捷方法:创建方块碰撞箱
|
* 便捷方法:创建方块碰撞箱
|
||||||
|
*
|
||||||
|
* @param minX the min x
|
||||||
|
* @param minY the min y
|
||||||
|
* @param minZ the min z
|
||||||
|
* @param maxX the max x
|
||||||
|
* @param maxY the max y
|
||||||
|
* @param maxZ the max z
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
public static @NotNull VoxelShape createBox(double minX, double minY, double minZ,
|
public static @NotNull VoxelShape createBox(double minX, double minY, double minZ,
|
||||||
double maxX, double maxY, double maxZ) {
|
double maxX, double maxY, double maxZ) {
|
||||||
|
|
@ -34,15 +54,22 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建单一形状的方向映射
|
* 创建单一形状的方向映射
|
||||||
|
*
|
||||||
|
* @param shape the shape
|
||||||
|
* @return the map
|
||||||
*/
|
*/
|
||||||
public static Map<Direction, VoxelShape> createUniformDirectionMap(VoxelShape shape) {
|
public static @NotNull Map<Direction, VoxelShape> createUniformDirectionMap(VoxelShape shape) {
|
||||||
return createRotatedDirectionMap(shape);
|
return createRotatedDirectionMap(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建原版双方块的形状映射
|
* 创建原版双方块的形状映射
|
||||||
|
*
|
||||||
|
* @param lowerShape the lower shape
|
||||||
|
* @param upperShape the upper shape
|
||||||
|
* @return the map
|
||||||
*/
|
*/
|
||||||
public static Map<DoubleBlockHalf, Map<Direction, VoxelShape>> createDoubleBlockShapeMap(VoxelShape lowerShape, VoxelShape upperShape) {
|
public static @NotNull Map<DoubleBlockHalf, Map<Direction, VoxelShape>> createDoubleBlockShapeMap(VoxelShape lowerShape, VoxelShape upperShape) {
|
||||||
EnumMap<DoubleBlockHalf, Map<Direction, VoxelShape>> shapeMap = new EnumMap<>(DoubleBlockHalf.class);
|
EnumMap<DoubleBlockHalf, Map<Direction, VoxelShape>> shapeMap = new EnumMap<>(DoubleBlockHalf.class);
|
||||||
shapeMap.put(DoubleBlockHalf.LOWER, createRotatedDirectionMap(lowerShape));
|
shapeMap.put(DoubleBlockHalf.LOWER, createRotatedDirectionMap(lowerShape));
|
||||||
shapeMap.put(DoubleBlockHalf.UPPER, createRotatedDirectionMap(upperShape));
|
shapeMap.put(DoubleBlockHalf.UPPER, createRotatedDirectionMap(upperShape));
|
||||||
|
|
@ -53,6 +80,9 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 顺时针旋转碰撞箱(Y轴旋转)
|
* 顺时针旋转碰撞箱(Y轴旋转)
|
||||||
|
*
|
||||||
|
* @param shape the shape
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
public static @NotNull VoxelShape rotateVoxelShapeClockwise(@NotNull VoxelShape shape) {
|
public static @NotNull VoxelShape rotateVoxelShapeClockwise(@NotNull VoxelShape shape) {
|
||||||
final List<VoxelShape> generatedShapes = new ArrayList<>();
|
final List<VoxelShape> generatedShapes = new ArrayList<>();
|
||||||
|
|
@ -65,6 +95,9 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绕X轴旋转碰撞箱
|
* 绕X轴旋转碰撞箱
|
||||||
|
*
|
||||||
|
* @param shape the shape
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
public static @NotNull VoxelShape rotateVoxelShapeXAxis(@NotNull VoxelShape shape) {
|
public static @NotNull VoxelShape rotateVoxelShapeXAxis(@NotNull VoxelShape shape) {
|
||||||
final List<VoxelShape> generatedShapes = new ArrayList<>();
|
final List<VoxelShape> generatedShapes = new ArrayList<>();
|
||||||
|
|
@ -77,6 +110,9 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 绕Z轴旋转碰撞箱
|
* 绕Z轴旋转碰撞箱
|
||||||
|
*
|
||||||
|
* @param shape the shape
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("SuspiciousNameCombination")
|
@SuppressWarnings("SuspiciousNameCombination")
|
||||||
public static @NotNull VoxelShape rotateVoxelShapeZAxis(@NotNull VoxelShape shape) {
|
public static @NotNull VoxelShape rotateVoxelShapeZAxis(@NotNull VoxelShape shape) {
|
||||||
|
|
@ -90,6 +126,10 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 按指定角度旋转碰撞箱
|
* 按指定角度旋转碰撞箱
|
||||||
|
*
|
||||||
|
* @param shape the shape
|
||||||
|
* @param degrees the degrees
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
public static @NotNull VoxelShape rotateShape(@NotNull VoxelShape shape, int degrees) {
|
public static @NotNull VoxelShape rotateShape(@NotNull VoxelShape shape, int degrees) {
|
||||||
int rotations = (degrees / 90) % 4;
|
int rotations = (degrees / 90) % 4;
|
||||||
|
|
@ -107,7 +147,7 @@ public class ShapeUtil {
|
||||||
* 组合多个形状列表
|
* 组合多个形状列表
|
||||||
*/
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
private static VoxelShape combineShapes(List<VoxelShape> shapes) {
|
private static VoxelShape combineShapes(@NotNull List<VoxelShape> shapes) {
|
||||||
if (shapes.isEmpty()) {
|
if (shapes.isEmpty()) {
|
||||||
return Shapes.block();
|
return Shapes.block();
|
||||||
}
|
}
|
||||||
|
|
@ -122,6 +162,9 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 组合多个形状
|
* 组合多个形状
|
||||||
|
*
|
||||||
|
* @param shapes the shapes
|
||||||
|
* @return the voxel shape
|
||||||
*/
|
*/
|
||||||
public static @NotNull VoxelShape combineShapes(VoxelShape... shapes) {
|
public static @NotNull VoxelShape combineShapes(VoxelShape... shapes) {
|
||||||
return combineShapes(Arrays.asList(shapes));
|
return combineShapes(Arrays.asList(shapes));
|
||||||
|
|
@ -132,7 +175,7 @@ public class ShapeUtil {
|
||||||
/**
|
/**
|
||||||
* 创建旋转方向映射
|
* 创建旋转方向映射
|
||||||
*/
|
*/
|
||||||
private static Map<Direction, VoxelShape> createRotatedDirectionMap(VoxelShape baseShape) {
|
private static @NotNull Map<Direction, VoxelShape> createRotatedDirectionMap(VoxelShape baseShape) {
|
||||||
EnumMap<Direction, VoxelShape> directionMap = new EnumMap<>(Direction.class);
|
EnumMap<Direction, VoxelShape> directionMap = new EnumMap<>(Direction.class);
|
||||||
directionMap.put(Direction.NORTH, baseShape);
|
directionMap.put(Direction.NORTH, baseShape);
|
||||||
directionMap.put(Direction.EAST, rotateShape(baseShape, 90));
|
directionMap.put(Direction.EAST, rotateShape(baseShape, 90));
|
||||||
|
|
@ -150,23 +193,56 @@ public class ShapeUtil {
|
||||||
public static class ShapeBuilder {
|
public static class ShapeBuilder {
|
||||||
private final List<VoxelShape> shapes = new ArrayList<>();
|
private final List<VoxelShape> shapes = new ArrayList<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add pixel box shape builder.
|
||||||
|
*
|
||||||
|
* @param minX the min x
|
||||||
|
* @param minY the min y
|
||||||
|
* @param minZ the min z
|
||||||
|
* @param maxX the max x
|
||||||
|
* @param maxY the max y
|
||||||
|
* @param maxZ the max z
|
||||||
|
* @return the shape builder
|
||||||
|
*/
|
||||||
public ShapeBuilder addPixelBox(double minX, double minY, double minZ,
|
public ShapeBuilder addPixelBox(double minX, double minY, double minZ,
|
||||||
double maxX, double maxY, double maxZ) {
|
double maxX, double maxY, double maxZ) {
|
||||||
shapes.add(createPixelBasedShape(minX, minY, minZ, maxX, maxY, maxZ));
|
shapes.add(createPixelBasedShape(minX, minY, minZ, maxX, maxY, maxZ));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add box shape builder.
|
||||||
|
*
|
||||||
|
* @param minX the min x
|
||||||
|
* @param minY the min y
|
||||||
|
* @param minZ the min z
|
||||||
|
* @param maxX the max x
|
||||||
|
* @param maxY the max y
|
||||||
|
* @param maxZ the max z
|
||||||
|
* @return the shape builder
|
||||||
|
*/
|
||||||
public ShapeBuilder addBox(double minX, double minY, double minZ,
|
public ShapeBuilder addBox(double minX, double minY, double minZ,
|
||||||
double maxX, double maxY, double maxZ) {
|
double maxX, double maxY, double maxZ) {
|
||||||
shapes.add(createBox(minX, minY, minZ, maxX, maxY, maxZ));
|
shapes.add(createBox(minX, minY, minZ, maxX, maxY, maxZ));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add shape shape builder.
|
||||||
|
*
|
||||||
|
* @param shape the shape
|
||||||
|
* @return the shape builder
|
||||||
|
*/
|
||||||
public ShapeBuilder addShape(VoxelShape shape) {
|
public ShapeBuilder addShape(VoxelShape shape) {
|
||||||
shapes.add(shape);
|
shapes.add(shape);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build voxel shape.
|
||||||
|
*
|
||||||
|
* @return the voxel shape
|
||||||
|
*/
|
||||||
public VoxelShape build() {
|
public VoxelShape build() {
|
||||||
return combineShapes(shapes);
|
return combineShapes(shapes);
|
||||||
}
|
}
|
||||||
|
|
@ -174,8 +250,11 @@ public class ShapeUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建形状构建器
|
* 创建形状构建器
|
||||||
|
*
|
||||||
|
* @return the shape builder
|
||||||
*/
|
*/
|
||||||
public static ShapeBuilder builder() {
|
@Contract(" -> new")
|
||||||
|
public static @NotNull ShapeBuilder builder() {
|
||||||
return new ShapeBuilder();
|
return new ShapeBuilder();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -3,12 +3,22 @@ package top.r3944realms.lib39.util.sound;
|
||||||
import net.minecraft.sounds.SoundEvent;
|
import net.minecraft.sounds.SoundEvent;
|
||||||
import net.minecraft.sounds.SoundSource;
|
import net.minecraft.sounds.SoundSource;
|
||||||
import net.minecraft.world.entity.LivingEntity;
|
import net.minecraft.world.entity.LivingEntity;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type Sound util.
|
||||||
|
*/
|
||||||
public class SoundUtil {
|
public class SoundUtil {
|
||||||
/**
|
/**
|
||||||
* 为实体播放声音
|
* 为实体播放声音
|
||||||
|
*
|
||||||
|
* @param entity the entity
|
||||||
|
* @param soundEvent the sound event
|
||||||
|
* @param soundCategory the sound category
|
||||||
|
* @param volume the volume
|
||||||
|
* @param pitch the pitch
|
||||||
*/
|
*/
|
||||||
public static void playSoundForEntity(LivingEntity entity, SoundEvent soundEvent, SoundSource soundCategory, float volume, float pitch) {
|
public static void playSoundForEntity(@NotNull LivingEntity entity, SoundEvent soundEvent, SoundSource soundCategory, float volume, float pitch) {
|
||||||
entity.level().playSound(null, entity.getX(), entity.getY(), entity.getZ(), soundEvent, soundCategory, volume, pitch);
|
entity.level().playSound(null, entity.getX(), entity.getY(), entity.getZ(), soundEvent, soundCategory, volume, pitch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user