From 8d5b91e54aebe0cabf2793d33f310f368c075511 Mon Sep 17 00:00:00 2001 From: 3944Realms Date: Thu, 16 Oct 2025 18:29:27 +0800 Subject: [PATCH] =?UTF-8?q?API=E9=87=8D=E6=9E=84=E5=B7=A5=E4=BD=9C=20#1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 138 +++++- gradle.properties | 6 +- .../superleadrope/CommonEventHandler.java | 43 +- .../superleadrope/SuperLeadRope.java | 1 + .../superleadrope/api/SLPCapability.java | 27 ++ .../superleadrope/api/SuperLeadRopeApi.java | 83 ++++ .../api/event/SuperLeadRopeEvent.java | 73 +++ .../api/type/capabilty/ILeashData.java | 149 ++++++ .../type/capabilty}/ILeashState.java | 2 +- .../api/type/capabilty/LeashInfo.java | 347 +++++++++++++ .../api/type/util/ILeashHelper.java | 319 ++++++++++++ .../api/workspace/IWorkSpaceHelper.java | 34 ++ .../superleadrope/api/workspace/Services.java | 31 ++ .../client/renderer/LeashRenderHandler.java | 16 +- .../client/renderer/SuperLeashRenderer.java | 12 +- .../resolver/SuperLeashStateResolver.java | 25 +- .../renderer/state/SuperLeashRenderState.java | 2 +- .../config/LeashCommonConfig.java | 6 +- .../config/LeashConfigManager.java | 7 +- .../content/capability/CapabilityHandler.java | 13 +- .../capability/CapabilityRemainder.java | 6 +- .../capability/impi/LeashDataImpl.java | 455 +++++++++++------- .../capability/impi/LeashStateImpl.java | 2 +- .../content/capability/inter/ILeashData.java | 209 -------- .../provider/LeashDataProvider.java | 6 +- .../provider/LeashStateProvider.java | 6 +- .../content/command/LeashDataCommand.java | 61 +-- .../content/entity/SuperLeashKnotEntity.java | 22 +- .../content/item/SuperLeadRopeItem.java | 20 +- .../core/hook/LeashRenderHook.java | 4 +- .../core/leash/LeashInteractHandler.java | 12 +- .../core/leash/LeashSyncManager.java | 4 +- .../network/toClient/LeashDataSyncPacket.java | 4 +- .../toClient/LeashStateSyncPacket.java | 4 +- ...ashDataAPI.java => LeashDataInnerAPI.java} | 41 +- ...hStateAPI.java => LeashStateInnerAPI.java} | 14 +- .../superleadrope/util/file/ConfigUtil.java | 3 +- .../superleadrope/util/nbt/NBTReader.java | 1 + .../superleadrope/util/nbt/NBTWriter.java | 1 + .../util/riding/RindingLeash.java | 1 - .../superleadrope/workspace/LeashHelper.java | 74 +++ .../workspace/WorkSpaceHelper.java | 62 +++ ...perleadrope.api.workspace.IWorkSpaceHelper | 1 + .../superleadropetest/Placeholder.java | 2 - 44 files changed, 1791 insertions(+), 558 deletions(-) create mode 100644 src/main/java/top/r3944realms/superleadrope/api/SLPCapability.java create mode 100644 src/main/java/top/r3944realms/superleadrope/api/SuperLeadRopeApi.java create mode 100644 src/main/java/top/r3944realms/superleadrope/api/event/SuperLeadRopeEvent.java create mode 100644 src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashData.java rename src/main/java/top/r3944realms/superleadrope/{content/capability/inter => api/type/capabilty}/ILeashState.java (98%) create mode 100644 src/main/java/top/r3944realms/superleadrope/api/type/capabilty/LeashInfo.java create mode 100644 src/main/java/top/r3944realms/superleadrope/api/type/util/ILeashHelper.java create mode 100644 src/main/java/top/r3944realms/superleadrope/api/workspace/IWorkSpaceHelper.java create mode 100644 src/main/java/top/r3944realms/superleadrope/api/workspace/Services.java delete mode 100644 src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashData.java rename src/main/java/top/r3944realms/superleadrope/util/capability/{LeashDataAPI.java => LeashDataInnerAPI.java} (90%) rename src/main/java/top/r3944realms/superleadrope/util/capability/{LeashStateAPI.java => LeashStateInnerAPI.java} (96%) create mode 100644 src/main/java/top/r3944realms/superleadrope/workspace/LeashHelper.java create mode 100644 src/main/java/top/r3944realms/superleadrope/workspace/WorkSpaceHelper.java create mode 100644 src/main/resources/META-INF/services/top.r3944realms.superleadrope.api.workspace.IWorkSpaceHelper diff --git a/build.gradle b/build.gradle index 4d29570..c9e6b68 100644 --- a/build.gradle +++ b/build.gradle @@ -71,6 +71,22 @@ repositories { includeModule 'me.lucko', 'spark-api' } } + maven { + name "KosmX's maven" + url 'https://maven.kosmx.dev/' + } + maven { + name = "Curios" + url = uri("https://maven.theillusivec4.top/") + } + maven { + name = 'GeckoLib' + url 'https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/' + content { + includeGroupByRegex("software\\.bernie.*") + includeGroup("com.eliotlash.mclib") + } + } mavenCentral() flatDir { dir "libs" @@ -98,7 +114,7 @@ legacyForge { systemProperty 'forge.enabledGameTestNamespaces', project.mod_id // // 设置 RenderDoc library 路径 // // 系统属性,使用项目相对路径 -// systemProperty 'neoforge.rendernurse.renderdoc.library', file('RenderDoc_1.40_64/renderdoc.dll').absolutePath +// systemProperty 'neoforged.rendernurse.renderdoc.library', file('RenderDoc_1.40_64/renderdoc.dll').absolutePath // // // JVM 参数 // jvmArgument "-javaagent:${file('libs/RenderNurse-0.0.9.jar').absolutePath}" @@ -150,10 +166,19 @@ dependencies { modRuntimeOnly("curse.maven:debug-utils-forge-783008:5337491") modCompileOnly("blank:curtain-1.20.1:1.3.2") modRuntimeOnly("blank:curtain-1.20.1:1.3.2") + modImplementation("dev.kosmx.player-anim:player-animation-lib-forge:${player_anim_version}") + modImplementation("curse.maven:bendy-lib-623373:4550371") + modImplementation("software.bernie.geckolib:geckolib-forge-${minecraft_version}:${geckolib_version}") + implementation("com.eliotlash.mclib:mclib:20") + modCompileOnly("top.theillusivec4.curios:curios-forge:${curios_version}:api") + modCompileOnly("top.theillusivec4.curios:curios-forge:${curios_version}") + modRuntimeOnly("top.theillusivec4.curios:curios-forge:${curios_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-forge-api:${jei_version}") modCompileOnly("mezz.jei:jei-${minecraft_version}-common-api:${jei_version}") modRuntimeOnly("mezz.jei:jei-${minecraft_version}-forge:${jei_version}") modRuntimeOnly("curse.maven:spark-361579:4738952") + compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1")) + modImplementation("io.github.llamalad7:mixinextras-forge:0.4.1") compileOnly ('me.lucko:spark-api:0.1-SNAPSHOT') implementation 'org.ow2.asm:asm:9.6' implementation 'org.ow2.asm:asm-tree:9.6' @@ -170,6 +195,45 @@ dokkaJavadoc { outputDirectory = file("$buildDir/javadoc") } +// ========== API Jar 配置 ========== +tasks.register('apiJar', Jar) { + archiveClassifier.set('api') + from sourceSets.main.output + include "top/r3944realms/superleadrope/api/**/*" + include "top/r3944realms/superleadrope/SuperLeadRopeAPI.class" + + manifest { + attributes([ + 'Specification-Title' : "${mod_id}-api", + 'Specification-Vendor' : mod_authors, + 'Specification-Version' : '1', + 'Implementation-Title' : "${project.name}-api", + 'Implementation-Version' : archiveVersion, + 'Implementation-Vendor' : mod_authors, + 'Implementation-Timestamp': new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"), + 'FMLModType' : 'GAMELIBRARY' + ]) + } + + // 确保包含 API 相关的源文件 + dependsOn classes +} + +// 创建包含源码的 API Jar +tasks.register('sourcesApiJar', Jar) { + archiveClassifier.set('api-sources') + from sourceSets.main.allSource + include "top/r3944realms/superleadrope/api/**/*" + include "top/r3944realms/superleadrope/SuperLeadRopeAPI.java" +} + +// 创建 API Javadoc Jar +tasks.register('javadocApiJar', Jar) { + archiveClassifier.set('api-javadoc') + from dokkaJavadoc + dependsOn dokkaJavadoc +} + // ========== 打包配置 ========== jar { manifest { @@ -184,6 +248,10 @@ jar { ]) } archiveFileName = "${mod_id}-${mod_version}-origin.jar" + + // 可选:排除 API 类(如果你不想在主 jar 中包含 API) + // exclude "top/r3944realms/superleadrope/api/**/*" + finalizedBy 'proguard' } @@ -215,19 +283,6 @@ shadowJar { outputs.upToDateWhen { false } } -// 本地 Maven 发布 -publishing { - publications { - create('mavenJava', MavenPublication) { - artifact jar - } - } - repositories { - maven { - url "file://${project.projectDir}/mcmodsrepo" - } - } -} // 新建一个可解析配置专门给 ProGuard configurations { proguardLibs { @@ -279,12 +334,62 @@ afterEvaluate { } } +// ========== 发布配置 ========== +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + // 添加 API 相关构件 + artifact apiJar + artifact sourcesApiJar + artifact javadocApiJar + + // POM 配置,便于其他模组依赖 + pom { + name = "${mod_name} API" + description = "The API for ${mod_name}" + url = "https://github.com/3944Realms/SuperLeadMod" + + licenses { + license { + name = mod_license + url = "https://opensource.org/licenses/MIT" + } + } + + developers { + developer { + id = "r3944realms" + name = mod_authors + } + } + } + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} + +// ========== 构建任务依赖 ========== +// 确保构建任务包含 API Jar +tasks.named('build') { + dependsOn apiJar, sourcesApiJar, javadocApiJar +} + +// 清理任务 +tasks.named('clean') { + delete fileTree(dir: "${project.projectDir}/mcmodsrepo") +} + tasks.register("runWithRenderDoc", Exec) { group = "minecraft" description = "Run Minecraft with RenderDoc using runClientAuth configuration" dependsOn("classes") // 确保源码编译完成 def jdwpArgs = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005" - + def renderDocCmd = file("RenderDoc_1.40_64/renderdoccmd.exe").absolutePath def captureDir = file("$buildDir/renderdoc/capture").absolutePath @@ -314,11 +419,10 @@ tasks.register("runWithRenderDoc", Exec) { } } - // IDEA 支持 idea { module { downloadSources = true downloadJavadoc = true } -} +} \ No newline at end of file diff --git a/gradle.properties b/gradle.properties index d87591e..b005df4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,6 +12,10 @@ neoForge.parchment.mappingsVersion=2023.09.03 enableProguard=false # Jei Version jei_version=15.20.0.112 +#Other Mods Version +player_anim_version=1.0.2-rc1+1.20 +geckolib_version=4.2.1 +curios_version=5.5.0+1.20.1 ## Environment Properties # The Minecraft version must agree with the Forge version to get a valid artifact @@ -55,7 +59,7 @@ mod_name=Super Lead Rope # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. mod_license=GPLv3 # The mod version. See https://semver.org/ -mod_version=0.0.0.3 +mod_version=0.0.0.4 # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # This should match the base package used for the mod sources. # See https://maven.apache.org/guides/mini/guide-naming-conventions.html diff --git a/src/main/java/top/r3944realms/superleadrope/CommonEventHandler.java b/src/main/java/top/r3944realms/superleadrope/CommonEventHandler.java index cbc6763..526c4a9 100644 --- a/src/main/java/top/r3944realms/superleadrope/CommonEventHandler.java +++ b/src/main/java/top/r3944realms/superleadrope/CommonEventHandler.java @@ -23,12 +23,9 @@ import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.Pose; import net.minecraft.world.entity.item.ItemEntity; import net.minecraft.world.entity.player.Player; -import net.minecraft.world.entity.vehicle.Boat; -import net.minecraft.world.entity.vehicle.Minecart; import net.minecraft.world.item.CreativeModeTabs; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.Level; @@ -53,14 +50,16 @@ import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.event.config.ModConfigEvent; import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; import org.jetbrains.annotations.NotNull; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; import top.r3944realms.superleadrope.config.LeashCommonConfig; import top.r3944realms.superleadrope.config.LeashConfigManager; import top.r3944realms.superleadrope.content.capability.CapabilityHandler; import top.r3944realms.superleadrope.content.capability.CapabilityRemainder; import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; import top.r3944realms.superleadrope.content.capability.inter.IEternalPotato; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; import top.r3944realms.superleadrope.content.command.MotionCommand; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.content.gamerule.server.TeleportWithLeashedEntities; @@ -74,8 +73,8 @@ import top.r3944realms.superleadrope.core.register.SLPItems; import top.r3944realms.superleadrope.core.util.PotatoMode; import top.r3944realms.superleadrope.core.util.PotatoModeHelper; import top.r3944realms.superleadrope.datagen.data.SLPLangKeyValue; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; -import top.r3944realms.superleadrope.util.capability.LeashStateAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; +import top.r3944realms.superleadrope.util.capability.LeashStateInnerAPI; import top.r3944realms.superleadrope.util.model.RidingRelationship; import top.r3944realms.superleadrope.util.riding.RidingApplier; import top.r3944realms.superleadrope.util.riding.RidingDismounts; @@ -97,8 +96,8 @@ public class CommonEventHandler { Entity entity = event.getEntity(); if (entity.level().isClientSide) return; if (LeashDataImpl.isLeashable(entity)) { - LeashDataAPI.getLeashData(entity).ifPresent(LeashSyncManager.Data::track); - LeashStateAPI.getLeashState(entity).ifPresent(LeashSyncManager.State::track); + LeashDataInnerAPI.getLeashData(entity).ifPresent(LeashSyncManager.Data::track); + LeashStateInnerAPI.getLeashState(entity).ifPresent(LeashSyncManager.State::track); if (entity instanceof ServerPlayer serverPlayer) { LeashSyncManager.Data.forEach(i -> { if (i.isLeashedBy(serverPlayer) && i.isInDelayedLeash(serverPlayer.getUUID())) { @@ -121,8 +120,8 @@ public class CommonEventHandler { } }); } - LeashDataAPI.getLeashData(entity).ifPresent(LeashSyncManager.Data::untrack); - LeashStateAPI.getLeashState(entity).ifPresent(LeashSyncManager.State::untrack); + LeashDataInnerAPI.getLeashData(entity).ifPresent(LeashSyncManager.Data::untrack); + LeashStateInnerAPI.getLeashState(entity).ifPresent(LeashSyncManager.State::untrack); } } @SubscribeEvent @@ -157,6 +156,12 @@ public class CommonEventHandler { } } } + + public static ServerLevel getServerLevel() { + return sl; + } + + private static ServerLevel sl; @SubscribeEvent public static void onServerStarting(ServerStartingEvent event) { PotatoMode mode = PotatoModeHelper.getCurrentMode(); @@ -169,6 +174,7 @@ public class CommonEventHandler { if (serverLevel.dimension() == Level.OVERWORLD) { EternalPotatoFacade.initSavedData(serverLevel); RidingSaver.setEntityProvider(serverLevel::getEntity); + sl = serverLevel; } } } @@ -179,6 +185,7 @@ public class CommonEventHandler { // 只在主世界卸载时清空 if (serverLevel.dimension() == Level.OVERWORLD) { EternalPotatoFacade.clear(); + sl = null; } } } @@ -256,10 +263,10 @@ public class CommonEventHandler { if (!(level instanceof ServerLevel serverLevel)) return; // 获取范围内可被拴住实体 - List entities = LeashDataImpl.leashableInArea(telEntity); + List entities = SuperLeadRopeApi.leashableInArea(telEntity); //规则关闭则禁止 if(!SLPGameruleRegistry.getGameruleBoolValue(event.getEntity().level(), TeleportWithLeashedEntities.ID)) { - entities.forEach(entity -> LeashDataAPI.LeashOperations.detach(entity, telEntity)); + entities.forEach(entity -> LeashDataInnerAPI.LeashOperations.detach(entity, telEntity)); return; } for (Entity beLeashedEntity : entities) { @@ -270,8 +277,8 @@ public class CommonEventHandler { float originalPitch = beLeashedEntity.getXRot(); Vec3 originalDeltaMovement = beLeashedEntity.getDeltaMovement(); - AtomicReference originalLeashInfo = new AtomicReference<>(); - LeashDataAPI.getLeashData(beLeashedEntity).ifPresent(data -> { + AtomicReference originalLeashInfo = new AtomicReference<>(); + LeashDataInnerAPI.getLeashData(beLeashedEntity).ifPresent(data -> { originalLeashInfo.set(data.getLeashInfo(telEntity).orElse(null)); data.removeLeash(telEntity); }); @@ -306,10 +313,10 @@ public class CommonEventHandler { } // --- 将holder替换 --- - ILeashData.LeashInfo leashInfo = Optional.ofNullable(originalLeashInfo.get()) - .orElse(ILeashData.LeashInfo.EMPTY); + LeashInfo leashInfo = Optional.ofNullable(originalLeashInfo.get()) + .orElse(LeashInfo.EMPTY); - LeashDataAPI.LeashOperations.attachWithInfo(beLeashedEntity, telEntity, leashInfo); + LeashDataInnerAPI.LeashOperations.attachWithInfo(beLeashedEntity, telEntity, leashInfo); // --- 重新应用骑乘关系,仅保留白名单根载具 --- RidingRelationship filteredRelationship = RidingSaver.filterByWhitelistRoot(originalRidingRelationship); diff --git a/src/main/java/top/r3944realms/superleadrope/SuperLeadRope.java b/src/main/java/top/r3944realms/superleadrope/SuperLeadRope.java index fe5853b..2ccee29 100644 --- a/src/main/java/top/r3944realms/superleadrope/SuperLeadRope.java +++ b/src/main/java/top/r3944realms/superleadrope/SuperLeadRope.java @@ -31,6 +31,7 @@ import top.r3944realms.superleadrope.network.NetworkHandler; import top.r3944realms.superleadrope.util.file.ConfigUtil; @Mod(value = SuperLeadRope.MOD_ID) +//TODO: API规范化 public class SuperLeadRope { public static final Logger logger = LoggerFactory.getLogger(SuperLeadRope.class); diff --git a/src/main/java/top/r3944realms/superleadrope/api/SLPCapability.java b/src/main/java/top/r3944realms/superleadrope/api/SLPCapability.java new file mode 100644 index 0000000..f7fb229 --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/SLPCapability.java @@ -0,0 +1,27 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api; + +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.common.capabilities.CapabilityManager; +import net.minecraftforge.common.capabilities.CapabilityToken; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; + +public class SLPCapability { + public static final Capability LEASH_DATA_CAP = CapabilityManager.get(new CapabilityToken<>(){}); + public static final Capability LEASH_STATE_CAP = CapabilityManager.get(new CapabilityToken<>() {}); +} diff --git a/src/main/java/top/r3944realms/superleadrope/api/SuperLeadRopeApi.java b/src/main/java/top/r3944realms/superleadrope/api/SuperLeadRopeApi.java new file mode 100644 index 0000000..42bbd3e --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/SuperLeadRopeApi.java @@ -0,0 +1,83 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import top.r3944realms.superleadrope.api.type.util.ILeashHelper; +import top.r3944realms.superleadrope.api.workspace.Services; +import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; + +import java.util.List; +import java.util.UUID; +import java.util.function.Predicate; + +@SuppressWarnings("unused") +public class SuperLeadRopeApi { + public static final Logger LOGGER = LoggerFactory.getLogger(SuperLeadRopeApi.class); + public static String MOD_ID = "superleadrope"; + public static ILeashHelper getLeashHelper() { + return Services.WORK_SPACE.getLeashHelper(); + } + public static @NotNull List leashableInArea(Level pLevel, Vec3 pPos, Predicate filter) { + return leashableInArea(pLevel, pPos, filter, 1024D); + } + public static @NotNull List leashableInArea(@NotNull Entity entity, Predicate filter, double fetchDistance) { + return leashableInArea(entity.level(), entity.getBoundingBox().getCenter(), filter, fetchDistance); + } + public static @NotNull List leashableInArea(@NotNull Level pLevel, Vec3 pPos, Predicate filter, double fetchDistance) { + return Services.WORK_SPACE.leashableInArea(pLevel, pPos, filter, fetchDistance); + } + public static @NotNull List leashableInArea(Entity entity, Predicate filter) { + return leashableInArea(entity, filter, 1024D); + } + public static @NotNull List leashableInArea(Entity holder) { + return leashableInArea(holder, i -> isLeashHolder(i, holder), 1024D); + } + public static boolean isSuperLeadKnot(Entity entity) { + return Services.WORK_SPACE.isSuperLeadKnot(entity); + } + public static BlockPos getSuperLeadKnotPos(Entity entity) { + return Services.WORK_SPACE.getSuperLeadPos(entity); + } + public static boolean isLeashable(Entity entity) { + return Services.WORK_SPACE.isLeashable(entity); + } + + public static boolean isLeashHolder(@NotNull Entity pEntity, Entity pTestHolder) { + return pTestHolder instanceof SuperLeashKnotEntity superLeashKnotEntity ? + isLeashHolder(pEntity, superLeashKnotEntity.getPos()) : + isLeashHolder(pEntity, pTestHolder.getUUID()); + } + + public static boolean isLeashHolder(@NotNull Entity pEntity, UUID pHolderUUID) { + return LeashDataInnerAPI.getLeashData(pEntity) + .map(leashData -> leashData.isLeashedBy(pHolderUUID)) + .orElse(false); + } + + public static boolean isLeashHolder(@NotNull Entity pEntity, BlockPos pKnotPos) { + return LeashDataInnerAPI.getLeashData(pEntity) + .map(leashData -> leashData.isLeashedBy(pKnotPos)) + .orElse(false); + } +} diff --git a/src/main/java/top/r3944realms/superleadrope/api/event/SuperLeadRopeEvent.java b/src/main/java/top/r3944realms/superleadrope/api/event/SuperLeadRopeEvent.java new file mode 100644 index 0000000..f289324 --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/event/SuperLeadRopeEvent.java @@ -0,0 +1,73 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api.event; + +import net.minecraft.world.entity.Entity; +import net.minecraftforge.eventbus.api.Cancelable; +import net.minecraftforge.eventbus.api.Event; +import net.minecraftforge.fml.event.IModBusEvent; +import org.jetbrains.annotations.Nullable; + +public abstract class SuperLeadRopeEvent extends Event implements IModBusEvent { + private final Entity LeashedEntity; + + protected SuperLeadRopeEvent(Entity leashedEntity) { + LeashedEntity = leashedEntity; + } + + public Entity getLeashedEntity() { + return LeashedEntity; + } + + @Cancelable + public static class AddLeash extends SuperLeadRopeEvent { + private final Entity holderEntity; + @Nullable + private final Double maxLeashDistance; + @Nullable + private final Double elasticDistanceScale; + protected AddLeash(Entity leashedEntity, Entity holderEntity) { + super(leashedEntity); + this.holderEntity = holderEntity; + this.maxLeashDistance = null; + this.elasticDistanceScale = null; + } + public Entity getHolderEntity() { + return holderEntity; + } + public @Nullable Double getMaxLeashDistance() { + return maxLeashDistance; + } + public @Nullable Double getElasticDistanceScale() { + return elasticDistanceScale; + } + } + // ADD LEASH + + // TRANSFORM LEASH + + // REMOVE LEASH + + // MODIFY LEASH MAX_LEASH_LENGTH / ELASTIC_DISTANCE_SCALE + + // HAS FOCUS + + // KEEP NOT BREAK TICK + + // TELEPORT + + +} diff --git a/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashData.java b/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashData.java new file mode 100644 index 0000000..8729fd7 --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashData.java @@ -0,0 +1,149 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api.type.capabilty; + +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.player.Player; +import net.minecraftforge.common.util.INBTSerializable; + +import java.util.*; + +/** + * Capability interface for managing leash data of entities and knots. + */ +@SuppressWarnings("unused") +public interface ILeashData extends INBTSerializable { + Double getStaticMaxDistance(); + void setStaticMaxDistance(Double distance); + double getDefaultMaxDistance(); + double getCurrentMaxDistance(); + void updateAllMaxDistance(); + Double getStaticElasticDistanceScale(); + void setStaticElasticDistanceScale(Double distance); + double getDefaultElasticDistanceScale(); + double getCurrentElasticDistanceScale(); + void updateAllElasticDistanceScale(); + default void updateAll() { + updateAllMaxDistance(); + updateAllElasticDistanceScale(); + } + /* ---------------------- + * Add / removeApplyEntity leashes + * ---------------------- */ + boolean addLeash(Entity holder); + boolean addLeash(Entity holder, String reserved); + boolean addLeash(Entity holder, Double maxDistance); + boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale); + boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, int maxKeepTicks); + boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, String reserved); + boolean addLeash(Entity holder, Double maxDistance, String reserved); + boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, int maxKeepTicks, String reserved); + + void addLeash(Entity holder, LeashInfo info); + + void addDelayedLeash(Player holderPlayer); + void removeDelayedLeash(UUID onceHolderPlayerUUID); + + boolean removeLeash(Entity holder); + boolean removeLeash(UUID holderUUID); + boolean removeLeash(BlockPos knotPos); + + void removeAllLeashes(); + void removeAllHolderLeashes(); + void removeAllKnotLeashes(); + + /* ---------------------- + * Modify leash properties + * ---------------------- */ + boolean setMaxDistance(Entity holder, Double distance); + boolean setMaxDistance(Entity holder, Double distance, int maxKeepTicks); + boolean setMaxDistance(Entity holder, Double distance, int maxKeepTicks, String reserved); + + boolean setMaxDistance(UUID holderUUID, Double distance); + boolean setMaxDistance(UUID holderUUID, Double distance, int maxKeepTicks); + boolean setMaxDistance(UUID holderUUID, Double distance, int maxKeepTicks, String reserved); + + boolean setMaxDistance(BlockPos knotPos, Double distance); + boolean setMaxDistance(BlockPos knotPos, Double distance, int maxKeepTicks); + boolean setMaxDistance(BlockPos knotPos, Double distance, int maxKeepTicks, String reserved); + + boolean setElasticDistanceScale(Entity holder, Double scale); + boolean setElasticDistanceScale(Entity holder, Double scale, int maxKeepTicks); + boolean setElasticDistanceScale(Entity holder, Double scale, int maxKeepTicks, String reserved); + + boolean setElasticDistanceScale(UUID holderUUID, Double scale); + boolean setElasticDistanceScale(UUID holderUUID, Double scale, int maxKeepTicks); + boolean setElasticDistanceScale(UUID holderUUID, Double scale, int maxKeepTicks, String reserved); + + boolean setElasticDistanceScale(BlockPos knotPos, Double scale); + boolean setElasticDistanceScale(BlockPos knotPos, Double scale, int maxKeepTicks); + boolean setElasticDistanceScale(BlockPos knotPos, Double scale, int maxKeepTicks, String reserved); + + /* ---------------------- + * Apply physics + * ---------------------- */ + void applyLeashForces(); + + /* ---------------------- + * Transfer leash holders + * ---------------------- */ + boolean transferLeash(Entity holder, Entity newHolder); + boolean transferLeash(Entity holder, Entity newHolder, String reserved); + + boolean transferLeash(UUID holderUUID, Entity newHolder); + boolean transferLeash(UUID holderUUID, Entity newHolder, String reserved); + + boolean transferLeash(BlockPos knotPos, Entity newHolder); + boolean transferLeash(BlockPos knotPos, Entity newHolder, String reserved); + + /* ---------------------- + * Query state + * ---------------------- */ + boolean hasLeash(); + boolean hasKnotLeash(); + boolean hasHolderLeash(); + + Collection getAllLeashes(); + + boolean isLeashedBy(Entity holder); + boolean isLeashedBy(UUID holderUUID); + boolean isLeashedBy(BlockPos knotPos); + + boolean isInDelayedLeash(UUID holderUUID); + + Optional getLeashInfo(Entity holder); + Optional getLeashInfo(UUID holderUUID); + Optional getLeashInfo(BlockPos knotPos); + + boolean canBeLeashed(); + boolean canBeAttachedTo(Entity entity); + + /* ---------------------- + * Occupy / sync + * ---------------------- */ + /** + * 抢占位(已离线玩家)。 + * 用于解决玩家下线后所持有对象会移除持有者的问题(实际上是占用个弱集合) + */ + Optional occupyLeash(); + + void markForSync(); + void immediateSync(); + void checkSync(); + +} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashState.java b/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashState.java similarity index 98% rename from src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashState.java rename to src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashState.java index 81418f8..8928ff6 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashState.java +++ b/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/ILeashState.java @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -package top.r3944realms.superleadrope.content.capability.inter; +package top.r3944realms.superleadrope.api.type.capabilty; import net.minecraft.core.BlockPos; import net.minecraft.nbt.CompoundTag; diff --git a/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/LeashInfo.java b/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/LeashInfo.java new file mode 100644 index 0000000..f92279a --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/type/capabilty/LeashInfo.java @@ -0,0 +1,347 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api.type.capabilty; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Unmodifiable; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; + +import java.util.*; + +/* ---------------------- + * Data record + * ---------------------- */ +@SuppressWarnings({"RegExpRedundantEscape", "DuplicatedCode"}) +public record LeashInfo( + Optional blockPosOpt, + Optional holderUUIDOpt, + Optional holderIdOpt, // Only for client side use + Set marks, // 标记字段 + String reserved, // 保留字段 + Double maxDistance, // 最大距离 (可null,null则用全局&默认) + Double elasticDistanceScale, // 弹性距离比例 (可null,null则用全局&默认) + int keepLeashTicks, // 剩余 Tick 数 + int maxKeepLeashTicks // 最大保持 Tick 数 +) { + // 预定义的标记常量 + public static final String MARK_NOT_UPDATE = "NOT_UPDATE"; + public static final String MARK_ONLY_NOT_UPDATE_MAX_DISTANCE = "NOT_UPDATE_MAX_DISTANCE"; + public static final String MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE = "NOT_UPDATE_ELASTIC_DISTANCE_SCALE"; + + public static final LeashInfo EMPTY = new LeashInfo( + Optional.empty(), Optional.empty(), Optional.empty(), + Set.of(), "", 12.0D, 6.0D, 0, 0 + ); + + /* ---------- Factory ---------- */ + public static LeashInfo create( + Entity entity, + Set marks, + String reserved, + Double maxDistance, + Double elasticDistanceScale, + int keepTicks, + int maxKeepTicks + ) { + return SuperLeadRopeApi.isSuperLeadKnot(entity) + ? new LeashInfo(SuperLeadRopeApi.getSuperLeadKnotPos(entity), entity.getId(), marks, reserved, + maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks) + : new LeashInfo(entity.getUUID(), entity.getId(), marks, reserved, maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks); + } + + // 向后兼容的工厂方法 + public static LeashInfo create( + Entity entity, + String reserved, + Double maxDistance, + Double elasticDistanceScale, + int keepTicks, + int maxKeepTicks + ) { + return create(entity, Set.of(), reserved, maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks); + } + + public LeashInfo(UUID holderUUID, int holderId, String reserved, + Double maxDistance, Double elasticDistanceScale, int keepTicks, int maxKeepTicks) { + this(Optional.empty(), Optional.of(holderUUID), Optional.of(holderId), + Set.of(), reserved, maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks); + } + + public LeashInfo(UUID holderUUID, int holderId, Set marks, String reserved, + Double maxDistance, Double elasticDistanceScale, int keepTicks, int maxKeepTicks) { + this(Optional.empty(), Optional.of(holderUUID), Optional.of(holderId), + marks, reserved, maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks); + } + + public LeashInfo(BlockPos knotPos, int holderId, String reserved, + Double maxDistance, Double elasticDistanceScale, int keepTicks, int maxKeepTicks) { + this(Optional.of(knotPos), Optional.empty(), Optional.of(holderId), + Set.of(), reserved, maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks); + } + + public LeashInfo(BlockPos knotPos, int holderId, Set marks, String reserved, + Double maxDistance, Double elasticDistanceScale, int keepTicks, int maxKeepTicks) { + this(Optional.of(knotPos), Optional.empty(), Optional.of(holderId), + marks, reserved, maxDistance, elasticDistanceScale, keepTicks, maxKeepTicks); + } + + /* ---------- State updates ---------- */ + public LeashInfo decrementKeepTicks() { + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, marks, reserved, + maxDistance, elasticDistanceScale, + Math.max(0, keepLeashTicks - 1), maxKeepLeashTicks); + } + + public LeashInfo resetKeepTicks() { + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, marks, reserved, + maxDistance, elasticDistanceScale, + maxKeepLeashTicks, maxKeepLeashTicks); + } + + public LeashInfo transferHolder(Entity entity) { + return transferHolder(entity, reserved); + } + + public LeashInfo transferHolder(Entity entity, String newReserved) { + boolean isKnot = SuperLeadRopeApi.isSuperLeadKnot(entity); + return new LeashInfo( + isKnot ? Optional.of(SuperLeadRopeApi.getSuperLeadKnotPos(entity)) : Optional.empty(), + !isKnot ? Optional.of(entity.getUUID()) : Optional.empty(), + Optional.of(entity.getId()), + marks, newReserved, maxDistance, elasticDistanceScale, + keepLeashTicks, maxKeepLeashTicks + ); + } + + /** + * 修改保留字段 + */ + public LeashInfo withReserved(String newReserved) { + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, marks, newReserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks); + } + + /** + * 修改标记集合 + */ + public LeashInfo withMarks(Set newMarks) { + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, Set.copyOf(newMarks), reserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks); + } + + /* ---------- 标记管理方法(基于Set的新实现) ---------- */ + + /** + * 添加无需更新标记(如果不存在则添加) + */ + public LeashInfo markNotUpdate() { + return hasMark(MARK_NOT_UPDATE) ? this : addMark(MARK_NOT_UPDATE); + } + + public LeashInfo markNotUpdateDistance() { + if (hasMark(MARK_NOT_UPDATE)) { + return this; + } else { + if (hasMark(MARK_ONLY_NOT_UPDATE_MAX_DISTANCE)) { + return this; + } else if (hasMark(MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE)) { + return this.removeMark(MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE).addMark(MARK_NOT_UPDATE); + } + } + return this.addMark(MARK_ONLY_NOT_UPDATE_MAX_DISTANCE); + } + + public LeashInfo markNotUpdateScale() { + if (hasMark(MARK_NOT_UPDATE)) { + return this; + } else { + if (hasMark(MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE)) { + return this; + } else if (hasMark(MARK_ONLY_NOT_UPDATE_MAX_DISTANCE)) { + return this.removeMark(MARK_ONLY_NOT_UPDATE_MAX_DISTANCE).addMark(MARK_NOT_UPDATE); + } + } + return this.addMark(MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE); + } + + /** + * 移除无需更新标记 + */ + public LeashInfo unmarkNotUpdate() { + return removeMarks(MARK_NOT_UPDATE, MARK_ONLY_NOT_UPDATE_MAX_DISTANCE, MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE); + } + + /** + * 移除无需更新距离标记 + */ + public LeashInfo unmarkNotUpdateDistance() { + return removeMarks(MARK_NOT_UPDATE, MARK_ONLY_NOT_UPDATE_MAX_DISTANCE); + } + + /** + * 移除无需更新比例标记 + */ + public LeashInfo unmarkNotUpdateScale() { + return removeMarks(MARK_NOT_UPDATE, MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE); + } + + /** + * 检查是否包含无需更新标记 + */ + @SuppressWarnings("BooleanMethodIsAlwaysInverted") + public boolean isNotUpdate() { + return hasMark(MARK_NOT_UPDATE); + } + + /** + * 是否需距离更新标记 + */ + public boolean isNeedUpdateDistance() { + return !isNotUpdate() && !hasMark(MARK_ONLY_NOT_UPDATE_MAX_DISTANCE); + } + + /** + * 是否需比例更新 + */ + public boolean isNeedUpdateScale() { + return !isNotUpdate() && !hasMark(MARK_ONLY_NOT_UPDATE_ELASTIC_DISTANCE_SCALE); + } + + /** + * 添加标记(如果不存在则添加) + */ + public LeashInfo addMark(String mark) { + if (marks.contains(mark)) { + return this; + } + Set newMarks = new HashSet<>(marks); + newMarks.add(mark); + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, newMarks, reserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks); + } + + /** + * 添加多个标记(自动检测并跳过重复标记) + */ + public LeashInfo addMarks(String @NotNull ... marksToAdd) { + Set newMarks = new HashSet<>(marks); + boolean changed = false; + for (String mark : marksToAdd) { + if (newMarks.add(mark)) { + changed = true; + } + } + return changed ? new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, newMarks, reserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks) : this; + } + + /** + * 添加多个标记(集合版本) + */ + public LeashInfo addMarks(@NotNull Collection marksToAdd) { + return addMarks(marksToAdd.toArray(new String[0])); + } + + /** + * 移除单个标记 + */ + public LeashInfo removeMark(String mark) { + if (!marks.contains(mark)) { + return this; + } + Set newMarks = new HashSet<>(marks); + newMarks.remove(mark); + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, newMarks, reserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks); + } + + /** + * 移除多个标记 + */ + public LeashInfo removeMarks(String @NotNull ... marksToRemove) { + Set newMarks = new HashSet<>(marks); + boolean changed = false; + for (String mark : marksToRemove) { + if (newMarks.remove(mark)) { + changed = true; + } + } + return changed ? new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, newMarks, reserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks) : this; + } + + /** + * 移除多个标记(集合版本) + */ + public LeashInfo removeMarks(@NotNull Collection marksToRemove) { + return removeMarks(marksToRemove.toArray(new String[0])); + } + + /** + * 检查是否包含指定标记 + */ + public boolean hasMark(String mark) { + return marks.contains(mark); + } + + /** + * 检查是否包含所有指定标记 + */ + @Contract(pure = true) + public boolean hasAllMarks(String @NotNull ... marksToCheck) { + for (String mark : marksToCheck) { + if (!marks.contains(mark)) { + return false; + } + } + return true; + } + + /** + * 检查是否包含任意指定标记 + */ + @Contract(pure = true) + public boolean hasAnyMark(String @NotNull ... marksToCheck) { + for (String mark : marksToCheck) { + if (marks.contains(mark)) { + return true; + } + } + return false; + } + + /** + * 获取所有标记(不可修改的视图) + */ + @Contract(pure = true) + public @Unmodifiable Set getMarks() { + return Set.copyOf(marks); + } + + /** + * 清除所有标记 + */ + public LeashInfo clearAllMarks() { + if (marks.isEmpty()) { + return this; + } + return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, Set.of(), reserved, + maxDistance, elasticDistanceScale, keepLeashTicks, maxKeepLeashTicks); + } +} diff --git a/src/main/java/top/r3944realms/superleadrope/api/type/util/ILeashHelper.java b/src/main/java/top/r3944realms/superleadrope/api/type/util/ILeashHelper.java new file mode 100644 index 0000000..d975c5f --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/type/util/ILeashHelper.java @@ -0,0 +1,319 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api.type.util; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import org.jetbrains.annotations.NotNull; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; + +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.function.Supplier; + +public interface ILeashHelper { + IHolder getHolderHelper(Entity holder); + ILeashed getLeashedHelper(Entity leashed); + interface IHolder { + Entity getHolderEntity(); + + /** + * 获取该实体持有的所有拴绳数据 + */ + Set getAllLeashData(); + + /** + * 获取该实体持有的拴绳数量 + */ + default int getLeashCount() { + return getAllLeashData().size(); + } + + /** + * 检查是否持有任何拴绳 + */ + default boolean hasLeashes() { + return !getAllLeashData().isEmpty(); + } + + /** + * 释放所有持有的拴绳 + */ + default void releaseAllLeashes() { + getAllLeashData().forEach(i -> i.removeLeash(getHolderEntity())); + } + + /** + * 检查是否持有特定实体的拴绳 + */ + default boolean isHoldingLeash(Entity entity) { + return getAllLeashData().stream().anyMatch(i -> i.isLeashedBy(entity)); + } + + /** + * 检查是否持有特定实体的拴绳 + */ + default boolean isHoldingLeash(UUID uuid) { + return getAllLeashData().stream().anyMatch(i -> i.isLeashedBy(uuid)); + } + + /** + * 检查是否持有特定实体的拴绳 + */ + default boolean isHoldingLeash(BlockPos blockPos) { + return getAllLeashData().stream().anyMatch(i -> i.isLeashedBy(blockPos)); + } + /** + * 拴住另一个实体 + */ + default boolean leashEntity(Entity target) { + if (SuperLeadRopeApi.isLeashable(target)) { + if (isHoldingLeash(target)) { + return false; + } else return leashEntity(target.getUUID()); + } + return false; + } + boolean leashEntity(UUID uuid); + /** + * 解拴另一个实体 + */ + default boolean unleashEntity(Entity target) { + if (SuperLeadRopeApi.isLeashable(target)) { + if (!isHoldingLeash(target)) { + return false; + } else return unleashEntity(target.getUUID()); + } + return false; + } + boolean unleashEntity(UUID uuid); + } + + interface ILeashed { + /** + * 获取该实体的拴绳数据 + */ + ILeashData getLeashData(); + + /** + * 绑定拴绳到实体 + */ + default boolean attachLeash(Entity holder) { + return getLeashData().addLeash(holder); + } + /** + * 绑定拴绳到实体 + */ + default boolean attachLeash(Entity holder, String reserved) { + return getLeashData().addLeash(holder, reserved); + } + /** + * 绑定拴绳并设置参数 + */ + default boolean attachLeash(Entity holder, Double maxDistance, Double elasticDistanceScale) { + return getLeashData().addLeash(holder, maxDistance, elasticDistanceScale); + } + /** + * 绑定拴绳并设置参数 + */ + default boolean attachLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, String reserved) { + return getLeashData().addLeash(holder, maxDistance, elasticDistanceScale, reserved); + } + /** + * 绑定拴绳并设置参数 + */ + default boolean attachLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, int maxKeepTicks) { + return getLeashData().addLeash(holder, maxDistance, elasticDistanceScale, maxKeepTicks); + } + /** + * 绑定拴绳并设置参数 + */ + default boolean attachLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, int maxKeepTicks, String reserved) { + return getLeashData().addLeash(holder, maxDistance, elasticDistanceScale, maxKeepTicks, reserved); + } + /** + * 解绑拴绳(自动判断类型) + */ + default boolean detachLeash(Entity entity) { + return getLeashData().removeLeash(entity); + } + /** + * 解绑拴绳 + */ + default boolean detachLeash(UUID uuid) { + return getLeashData().removeLeash(uuid); + } + /** + * 解绑拴绳 + */ + default boolean detachLeash(BlockPos blockPos) { + return getLeashData().removeLeash(blockPos); + } + + /** + * 解绑所有拴绳 + */ + default void detachAllLeashes() { + getLeashData().removeAllLeashes(); + } + /** + * 解绑所有实体拴绳 + */ + default void removeAllHolderLeashes() { + getLeashData().removeAllHolderLeashes(); + } + /** + * 解绑所有绳结拴绳 + */ + default void removeAllKnotLeashes() { + getLeashData().removeAllKnotLeashes(); + } + /** + * 检查是否被拴住 + */ + default boolean isLeashed() { + return getLeashData().hasLeash(); + } + /** + * 检查是否被持有者拴住 + */ + default boolean hasHolderLeashed() { + return getLeashData().hasHolderLeash(); + } + /** + * 检查是否被绳结拴住 + */ + default boolean isKnotLeashed() { + return getLeashData().hasKnotLeash(); + } + /** + * 检查是否被特定实体拴住(自动判断类型) + */ + default boolean isLeashedBy(Entity entity) { + return getLeashData().isLeashedBy(entity); + } + + /** + * 检查是否被特定UUID实体拴住 + */ + default boolean isLeashedBy(UUID uuid) { + return getLeashData().isLeashedBy(uuid); + } + + /** + * 检查是否被特定绳结实体拴住 + */ + default boolean isLeashedBy(BlockPos blockPos) { + return getLeashData().isLeashedBy(blockPos); + } + + /** + * 获取拴绳信息(自动判断类型) + */ + default Optional getLeashInfo(Entity entity) { + return getLeashData().getLeashInfo(entity); + } + /** + * 获取拴绳信息 + */ + default Optional getLeashInfo(UUID holderUUID) { + return getLeashData().getLeashInfo(holderUUID); + } + /** + * 获取拴绳信息 + */ + default Optional getLeashInfo(BlockPos knotPos) { + return getLeashData().getLeashInfo(knotPos); + } + /** + * 转移拴绳到新持有者(自动判断类型) + */ + default boolean transferLeash(Entity fromEntity, Entity toEntity) { + return getLeashData().transferLeash(fromEntity, toEntity); + } + /** + * 转移拴绳到新持有者(自动判断类型) + */ + default boolean transferLeash(Entity fromEntity, Entity toEntity, String reserved) { + return getLeashData().transferLeash(fromEntity, toEntity, reserved); + } + /** + * 转移拴绳到新持有者 + */ + default boolean transferLeash(UUID fromEntityUUID, Entity toEntity) { + return getLeashData().transferLeash(fromEntityUUID, toEntity); + } + /** + * 转移拴绳到新持有者 + */ + default boolean transferLeash(UUID fromEntityUUID, Entity toEntity, String reserved) { + return getLeashData().transferLeash(fromEntityUUID, toEntity, reserved); + } + /** + * 转移拴绳到新持有者 + */ + default boolean transferLeash(BlockPos fromKnotBlockPos, Entity toEntity) { + return getLeashData().transferLeash(fromKnotBlockPos, toEntity); + } + /** + * 转移拴绳到新持有者 + */ + default boolean transferLeash(BlockPos fromKnotBlockPos, Entity toEntity, String reserved) { + return getLeashData().transferLeash(fromKnotBlockPos, toEntity, reserved); + } + default boolean isInDelayedLeash(UUID holderUUID) { + return getLeashData().isInDelayedLeash(holderUUID); + } + + + /** + * 应用拴绳物理效果 + */ + default void applyLeashPhysics() { + getLeashData().applyLeashForces(); + } + + /** + * 检查是否可以被拴绳 + */ + default boolean canBeLeashed() { + return getLeashData().canBeLeashed(); + } + + /** + * 检查是否可以拴到特定目标 + */ + default boolean canBeAttachedTo(Entity holder) { + return getLeashData().canBeAttachedTo(holder); + } + } + static boolean chooseMethodWithBooleanRet(@NotNull Supplier cond, Supplier trueSupplier, Supplier falseSupplier) { + if (cond.get()) { + return trueSupplier.get(); + } + return falseSupplier.get(); + } + static void chooseMethodWithVoidRet(@NotNull Supplier cond, Supplier trueSupplier, Supplier falseSupplier) { + if (cond.get()) { + trueSupplier.get(); + return; + } + falseSupplier.get(); + } +} diff --git a/src/main/java/top/r3944realms/superleadrope/api/workspace/IWorkSpaceHelper.java b/src/main/java/top/r3944realms/superleadrope/api/workspace/IWorkSpaceHelper.java new file mode 100644 index 0000000..decee96 --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/workspace/IWorkSpaceHelper.java @@ -0,0 +1,34 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api.workspace; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import top.r3944realms.superleadrope.api.type.util.ILeashHelper; + +import java.util.List; +import java.util.function.Predicate; + +public interface IWorkSpaceHelper { + @NotNull List leashableInArea(@NotNull Level pLevel, Vec3 pPos, Predicate filter, double fetchDistance); + ILeashHelper getLeashHelper(); + boolean isSuperLeadKnot(Entity pEntity); + BlockPos getSuperLeadPos(Entity pEntity) throws IllegalArgumentException; + boolean isLeashable(@NotNull Entity pEntity); +} diff --git a/src/main/java/top/r3944realms/superleadrope/api/workspace/Services.java b/src/main/java/top/r3944realms/superleadrope/api/workspace/Services.java new file mode 100644 index 0000000..7e92924 --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/api/workspace/Services.java @@ -0,0 +1,31 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.api.workspace; + +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; + +import java.util.ServiceLoader; + +public class Services { + public static final IWorkSpaceHelper WORK_SPACE = load(IWorkSpaceHelper.class); + public static T load(Class clazz) { + final T loadedService = ServiceLoader.load(clazz) + .findFirst() + .orElseThrow(() -> new NullPointerException("Failed to load service for " + clazz.getName())); + SuperLeadRopeApi.LOGGER.debug("Loaded {} for service {}", loadedService, clazz); + return loadedService; + } +} diff --git a/src/main/java/top/r3944realms/superleadrope/client/renderer/LeashRenderHandler.java b/src/main/java/top/r3944realms/superleadrope/client/renderer/LeashRenderHandler.java index de1974a..45c8bfb 100644 --- a/src/main/java/top/r3944realms/superleadrope/client/renderer/LeashRenderHandler.java +++ b/src/main/java/top/r3944realms/superleadrope/client/renderer/LeashRenderHandler.java @@ -23,10 +23,10 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.Level; import top.r3944realms.superleadrope.SuperLeadRope; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; import top.r3944realms.superleadrope.client.renderer.resolver.SuperLeashStateResolver; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.Optional; import java.util.UUID; @@ -46,17 +46,17 @@ public class LeashRenderHandler { // 遍历摄像机附近所有实体 for (Entity entity : level.getEntitiesOfClass(Entity.class, - cameraEntity.getBoundingBox().inflate(100))) { + cameraEntity.getBoundingBox().inflate(32*16))) { - LeashDataAPI.getLeashData(entity).ifPresent(leashData -> { - for (ILeashData.LeashInfo leashInfo : leashData.getAllLeashes()) { + LeashDataInnerAPI.getLeashData(entity).ifPresent(leashData -> { + for (LeashInfo leashInfo : leashData.getAllLeashes()) { renderLeashFromInfo(entity, leashInfo, poseStack, bufferSource, partialTick); } }); } } - private static void renderLeashFromInfo(Entity entity, ILeashData.LeashInfo leashInfo, + private static void renderLeashFromInfo(Entity entity, LeashInfo leashInfo, PoseStack poseStack, MultiBufferSource bufferSource, float partialTick) { try { @@ -76,10 +76,10 @@ public class LeashRenderHandler { } } - private static Optional getHolderFromLeashInfo(Level level, ILeashData.LeashInfo leashInfo) { + private static Optional getHolderFromLeashInfo(Level level, LeashInfo leashInfo) { if (leashInfo.blockPosOpt().isPresent()) { BlockPos pos = leashInfo.blockPosOpt().get(); - return Optional.of(SuperLeashKnotEntity.getOrCreateKnot(level, pos)); + return SuperLeashKnotEntity.get(level,pos).map(Entity.class::cast); } else if (leashInfo.holderUUIDOpt().isPresent()) { UUID holderUUID = leashInfo.holderUUIDOpt().get(); for (Entity e : ((ClientLevel)level).entitiesForRendering()) { diff --git a/src/main/java/top/r3944realms/superleadrope/client/renderer/SuperLeashRenderer.java b/src/main/java/top/r3944realms/superleadrope/client/renderer/SuperLeashRenderer.java index a2ab1b3..80543ca 100644 --- a/src/main/java/top/r3944realms/superleadrope/client/renderer/SuperLeashRenderer.java +++ b/src/main/java/top/r3944realms/superleadrope/client/renderer/SuperLeashRenderer.java @@ -108,7 +108,7 @@ public class SuperLeashRenderer { // 颜色渐变 private static float[] computeColor(SuperLeashRenderState state, int index, boolean reversePass) { float distance = (float) state.startPos().distanceTo(state.endPos()); - float ratio = Mth.clamp(distance / (state.maxDistance() * 2f), 0f, 1f); + float ratio = (float) Mth.clamp(distance / (state.maxDistance() * 2f), 0f, 1f); // 定义颜色 float rStart = 0.42f; // 深棕 R @@ -154,11 +154,11 @@ public class SuperLeashRenderer { return mc.level.getBrightness(LightLayer.BLOCK, pos); } - private static int getSkyLight(BlockPos pos) { - Minecraft mc = Minecraft.getInstance(); - if (mc.level == null) return 15; // 默认亮度,防止空指针 - return mc.level.getBrightness(LightLayer.SKY, pos); - } +// private static int getSkyLight(BlockPos pos) { +// Minecraft mc = Minecraft.getInstance(); +// if (mc.level == null) return 15; // 默认亮度,防止空指针 +// return mc.level.getBrightness(LightLayer.SKY, pos); +// } /** 横纵偏移数据 */ private static class Offsets { diff --git a/src/main/java/top/r3944realms/superleadrope/client/renderer/resolver/SuperLeashStateResolver.java b/src/main/java/top/r3944realms/superleadrope/client/renderer/resolver/SuperLeashStateResolver.java index 905d76d..83a9f66 100644 --- a/src/main/java/top/r3944realms/superleadrope/client/renderer/resolver/SuperLeashStateResolver.java +++ b/src/main/java/top/r3944realms/superleadrope/client/renderer/resolver/SuperLeashStateResolver.java @@ -23,13 +23,16 @@ import net.minecraft.world.entity.HumanoidArm; import net.minecraft.world.entity.player.Player; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; import top.r3944realms.superleadrope.client.renderer.state.SuperLeashRenderState; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; -import top.r3944realms.superleadrope.util.capability.LeashStateAPI; +import top.r3944realms.superleadrope.util.capability.LeashStateInnerAPI; -import java.util.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.UUID; //TODO: 未来实现更高级的渲染 public class SuperLeashStateResolver { @@ -48,11 +51,11 @@ public class SuperLeashStateResolver { /* ------------------------ 主解析方法 ------------------------ */ public static Optional resolve(Entity holder, Entity leashedEntity, - ILeashData.LeashInfo leashInfo, float partialTicks) { + LeashInfo leashInfo, float partialTicks) { if (holder == null || leashedEntity == null) return Optional.empty(); - Optional leashedEntityStateOpt = LeashStateAPI.getLeashState(leashedEntity); + Optional leashedEntityStateOpt = LeashStateInnerAPI.getLeashState(leashedEntity); if (leashedEntityStateOpt.isEmpty()) return Optional.empty(); ILeashState leashedEntityState = leashedEntityStateOpt.get(); @@ -95,7 +98,7 @@ public class SuperLeashStateResolver { // 物理参数 double distance = currentHolderPos.distanceTo(currentEntityPos); double maxDistance = leashInfo.maxDistance(); - double elasticDistance = leashInfo.elasticDistance(); + double elasticDistance = leashInfo.elasticDistanceScale(); float tension = calculateTension(distance, maxDistance, elasticDistance); float stretchRatio = (float) (distance / maxDistance); boolean isCritical = distance > maxDistance * 1.5; @@ -120,7 +123,7 @@ public class SuperLeashStateResolver { selectColor(tension, isCritical), THICKNESS_BASE + tension * THICKNESS_TENSION, swing.angle(), swing.speed(), - (float) leashInfo.maxDistance(), + leashInfo.maxDistance(), isFirstPerson, holder.blockPosition() @@ -129,7 +132,7 @@ public class SuperLeashStateResolver { /* ------------------------ 实体偏移计算 ------------------------ */ private static @NotNull Vec3 getEntityLeashOffset(Entity entity, ILeashState.@NotNull LeashState leashState) { - Optional entityStateOpt = LeashStateAPI.getLeashState(entity); + Optional entityStateOpt = LeashStateInnerAPI.getLeashState(entity); Vec3 baseOffset = entityStateOpt .map(eState -> eState.getLeashApplyEntityLocationOffset() .orElse(eState.getDefaultLeashApplyEntityLocationOffset())) @@ -137,8 +140,8 @@ public class SuperLeashStateResolver { return baseOffset.add(leashState.applyEntityLocationOffset()); } private static Vec3 getHolderOffset(Entity holder, ILeashState.LeashState leashState) { - if (LeashStateAPI.Query.hasLeashState(holder)) { - Optional holderStateOpt = LeashStateAPI.getLeashState(holder); + if (LeashStateInnerAPI.Query.hasLeashState(holder)) { + Optional holderStateOpt = LeashStateInnerAPI.getLeashState(holder); if (holderStateOpt.isPresent()) { ILeashState holderState = holderStateOpt.get(); return holderState.getLeashApplyEntityLocationOffset() diff --git a/src/main/java/top/r3944realms/superleadrope/client/renderer/state/SuperLeashRenderState.java b/src/main/java/top/r3944realms/superleadrope/client/renderer/state/SuperLeashRenderState.java index 1c6ab79..46436a2 100644 --- a/src/main/java/top/r3944realms/superleadrope/client/renderer/state/SuperLeashRenderState.java +++ b/src/main/java/top/r3944realms/superleadrope/client/renderer/state/SuperLeashRenderState.java @@ -31,7 +31,7 @@ public record SuperLeashRenderState( float thickness, // 线宽(根据张力变化) float swingAngle, // 当前摆动角度(弧度) float swingSpeed, // 摆动速度(弧度/tick) - float maxDistance, // 最大距离 + Double maxDistance, // 最大距离 boolean isFirstPerson, // 是否是第一人称 BlockPos belowBlockPos // 持有者位置 ) { diff --git a/src/main/java/top/r3944realms/superleadrope/config/LeashCommonConfig.java b/src/main/java/top/r3944realms/superleadrope/config/LeashCommonConfig.java index ffedb3f..5b2a086 100644 --- a/src/main/java/top/r3944realms/superleadrope/config/LeashCommonConfig.java +++ b/src/main/java/top/r3944realms/superleadrope/config/LeashCommonConfig.java @@ -27,7 +27,7 @@ public class LeashCommonConfig { // Leash settings public final ForgeConfigSpec.DoubleValue maxLeashLength; - public final ForgeConfigSpec.DoubleValue elasticDistance; + public final ForgeConfigSpec.DoubleValue elasticDistanceScale; public final ForgeConfigSpec.DoubleValue extremeSnapFactor; public final ForgeConfigSpec.DoubleValue springDampening; public final ForgeConfigSpec.ConfigValue> axisSpecificElasticity; @@ -84,9 +84,9 @@ public class LeashCommonConfig { .comment("Maximum leash distance (in blocks) for any entity") .defineInRange("maxLeashLength", 12.0, 6.0, 256.0); - elasticDistance = builder + elasticDistanceScale = builder .comment("Default elastic distance for the Super Lead rope") - .defineInRange("elasticDistance", 6.0, 6.0, 128.0); + .defineInRange("elasticDistanceScale", 1.0, 0.2, 4.0); extremeSnapFactor = builder .comment("Leash break factor = maxDistance * factor") diff --git a/src/main/java/top/r3944realms/superleadrope/config/LeashConfigManager.java b/src/main/java/top/r3944realms/superleadrope/config/LeashConfigManager.java index c493728..17266a8 100644 --- a/src/main/java/top/r3944realms/superleadrope/config/LeashConfigManager.java +++ b/src/main/java/top/r3944realms/superleadrope/config/LeashConfigManager.java @@ -51,7 +51,7 @@ public class LeashConfigManager { private volatile double mobSpringFactor = 0.5; private volatile double maxLeashLength = 12.0; - private volatile double elasticDistance = 6.0; + private volatile double elasticDistanceScale = 1.0; private volatile double extremeSnapFactor = 2.0; private volatile double springDampening = 0.7; private volatile List axisElasticity = List.of(0.8, 0.2, 0.8); @@ -186,9 +186,8 @@ public class LeashConfigManager { public double getMobSpringFactor() { return mobSpringFactor; } public double getMaxLeashLength() { return maxLeashLength; } - public double getElasticDistance() { return elasticDistance; } + public double getElasticDistanceScale() { return elasticDistanceScale; } public double getExtremeSnapFactor() { return extremeSnapFactor; } - public double getBreakDistance() { return maxLeashLength * extremeSnapFactor; } public double getSpringDampening() { return springDampening; } public List getAxisElasticity() { return Collections.unmodifiableList(axisElasticity); } public double getXElasticity() { return !axisElasticity.isEmpty() ? axisElasticity.get(0) : 0.8; } @@ -209,7 +208,7 @@ public class LeashConfigManager { commandPrefixEnabledCache = LeashCommonConfig.COMMON.enableSLPModCommandPrefix.get(); maxLeashLength = LeashCommonConfig.COMMON.maxLeashLength.get(); - elasticDistance = LeashCommonConfig.COMMON.elasticDistance.get(); + elasticDistanceScale = LeashCommonConfig.COMMON.elasticDistanceScale.get(); extremeSnapFactor = LeashCommonConfig.COMMON.extremeSnapFactor.get(); springDampening = LeashCommonConfig.COMMON.springDampening.get(); axisElasticity = new ArrayList<>(LeashCommonConfig.COMMON.axisSpecificElasticity.get()); diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityHandler.java b/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityHandler.java index fd844f4..b00ee38 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityHandler.java +++ b/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityHandler.java @@ -22,26 +22,25 @@ import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityToken; import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; import net.minecraftforge.event.AttachCapabilitiesEvent; +import org.jetbrains.annotations.NotNull; import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; import top.r3944realms.superleadrope.content.capability.inter.IEternalPotato; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; import top.r3944realms.superleadrope.content.capability.provider.EternalPotatoProvider; import top.r3944realms.superleadrope.content.capability.provider.LeashDataProvider; import top.r3944realms.superleadrope.content.capability.provider.LeashStateProvider; import top.r3944realms.superleadrope.content.item.EternalPotatoItem; public class CapabilityHandler { - public static final Capability LEASH_DATA_CAP = CapabilityManager.get(new CapabilityToken<>(){}); - public static Capability LEASH_STATE_CAP = CapabilityManager.get(new CapabilityToken<>() {}); - public static Capability ETERNAL_POTATO_CAP = CapabilityManager.get(new CapabilityToken<>() {}); - public static void registerCapability(RegisterCapabilitiesEvent event) { + public static final Capability ETERNAL_POTATO_CAP = CapabilityManager.get(new CapabilityToken<>() {}); + public static void registerCapability(@NotNull RegisterCapabilitiesEvent event) { event.register(ILeashData.class); event.register(IEternalPotato.class); event.register(ILeashState.class); } - public static void attachCapability(AttachCapabilitiesEvent event) { + public static void attachCapability(@NotNull AttachCapabilitiesEvent event) { Object object = event.getObject(); if(object instanceof Entity entity && (LeashDataImpl.isLeashable(entity))//只对活体 船 矿车添加CAP diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityRemainder.java b/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityRemainder.java index b1d2146..81c1697 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityRemainder.java +++ b/src/main/java/top/r3944realms/superleadrope/content/capability/CapabilityRemainder.java @@ -18,7 +18,7 @@ package top.r3944realms.superleadrope.content.capability; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.player.Player; import net.minecraftforge.event.entity.player.PlayerEvent; -import top.r3944realms.superleadrope.util.capability.LeashStateAPI; +import top.r3944realms.superleadrope.util.capability.LeashStateInnerAPI; public class CapabilityRemainder { public static void onPlayerClone(PlayerEvent.Clone event) { @@ -26,9 +26,9 @@ public class CapabilityRemainder { if(newEntity instanceof ServerPlayer newPlayer) { Player original = event.getOriginal(); original.reviveCaps(); - LeashStateAPI.getLeashState(original) + LeashStateInnerAPI.getLeashState(original) .ifPresent(oldCap -> - LeashStateAPI.getLeashState(newPlayer) + LeashStateInnerAPI.getLeashState(newPlayer) .ifPresent(newData -> newData.copy(oldCap, newEntity) ) diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashDataImpl.java b/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashDataImpl.java index 3ce2797..e3e7788 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashDataImpl.java +++ b/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashDataImpl.java @@ -29,30 +29,31 @@ import net.minecraft.world.entity.animal.horse.Llama; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.entity.vehicle.Boat; -import net.minecraft.world.level.Level; -import net.minecraft.world.level.pathfinder.Path; -import net.minecraft.world.phys.AABB; +import net.minecraft.world.level.ClipContext; +import net.minecraft.world.phys.BlockHitResult; +import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; +import net.minecraftforge.fml.loading.FMLEnvironment; import net.minecraftforge.network.PacketDistributor; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import top.r3944realms.superleadrope.CommonEventHandler; import top.r3944realms.superleadrope.SuperLeadRope; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; import top.r3944realms.superleadrope.compat.CurtainCompat; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.core.register.SLPSoundEvents; import top.r3944realms.superleadrope.network.NetworkHandler; import top.r3944realms.superleadrope.network.toClient.LeashDataSyncPacket; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; -import top.r3944realms.superleadrope.util.capability.LeashStateAPI; +import top.r3944realms.superleadrope.util.capability.LeashStateInnerAPI; import top.r3944realms.superleadrope.util.riding.RindingLeash; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import java.util.function.Function; -import java.util.function.Predicate; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -89,6 +90,12 @@ public class LeashDataImpl implements ILeashData { private final Entity entity; private boolean needsSync = false; private long lastSyncTime; + @Nullable + private Double staticMaxDistance; + private double defaultMaxDistance; + @Nullable + private Double staticElasticDistanceScale; + private double defaultElasticDistanceScale; private final Set delayedHolders = new CopyOnWriteArraySet<>(); private final Map leashHolders = new ConcurrentHashMap<>(); // 引入解决 绳结不保存导致第二进入持有者不存在的问题 @@ -143,38 +150,124 @@ public class LeashDataImpl implements ILeashData { needsSync = false; } + @Override + public @Nullable Double getStaticMaxDistance() { + return staticMaxDistance; + } + + @Override + public void setStaticMaxDistance(@Nullable Double distance) { + staticMaxDistance = distance; + } + + @Override + public double getDefaultMaxDistance() { + boolean isNotClient = !FMLEnvironment.dist.isClient(); + if (isNotClient) { + defaultMaxDistance = CommonEventHandler.leashConfigManager.getMaxLeashLength(); + } + return defaultMaxDistance; + } + + @Override + public double getCurrentMaxDistance() { + return staticMaxDistance != null ? staticMaxDistance : defaultMaxDistance; + } + + @Override + public void updateAllMaxDistance() { + leashHolders.forEach((uuid, leashInfo) -> { + if (leashInfo.isNeedUpdateDistance()) { + setMaxDistance(uuid, getCurrentMaxDistance()); + } + }); + leashKnots.forEach((blockPos, leashInfo) -> { + if (leashInfo.isNeedUpdateDistance()) { + setMaxDistance(blockPos, getCurrentMaxDistance()); + } + }); + } + + @Override + public @Nullable Double getStaticElasticDistanceScale() { + return staticElasticDistanceScale; + } + + @Override + public void setStaticElasticDistanceScale(@Nullable Double distance) { + staticElasticDistanceScale = distance; + } + + @Override + public double getDefaultElasticDistanceScale() { + boolean isNotClient = !FMLEnvironment.dist.isClient(); + if (isNotClient) { + defaultElasticDistanceScale = CommonEventHandler.leashConfigManager.getElasticDistanceScale(); + } + return defaultElasticDistanceScale; + } + + @Override + public double getCurrentElasticDistanceScale() { + return staticElasticDistanceScale != null ? staticElasticDistanceScale : defaultElasticDistanceScale; + } + + @Override + public void updateAllElasticDistanceScale() { + leashHolders.forEach((uuid, leashInfo) -> { + if (leashInfo.isNeedUpdateScale()) { + setElasticDistanceScale(uuid, getCurrentElasticDistanceScale()); + } + }); + leashKnots.forEach((blockPos, leashInfo) -> { + if (leashInfo.isNeedUpdateScale()) { + setElasticDistanceScale(blockPos, getCurrentMaxDistance()); + } + }); + } + @Override public boolean addLeash(Entity holder) { - return addLeash(holder, CommonEventHandler.leashConfigManager.getMaxLeashLength()); + return addLeash(holder, (Double) null); } @Override public boolean addLeash(Entity holder, String reserved) { - return addLeash(holder, CommonEventHandler.leashConfigManager.getMaxLeashLength(), reserved); + return addLeash(holder, null, reserved); } // 添加拴绳(支持自定义最大长度) @Override - public boolean addLeash(Entity holder, double maxDistance) { - return addLeash(holder, maxDistance, CommonEventHandler.leashConfigManager.getElasticDistance(), 0, ""); + public boolean addLeash(Entity holder, Double maxDistance) { + return addLeash(holder, maxDistance, null, 0, ""); + } + + @Override + public boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale) { + return addLeash(holder, maxDistance, elasticDistanceScale, 0); } // 添加拴绳(支持自定义最大长度和弹性距离) @Override - public boolean addLeash(Entity holder, double maxDistance, double elasticDistance, int maxKeepLeashTicks) { - return addLeash(holder, maxDistance, elasticDistance, maxKeepLeashTicks, ""); + public boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, int maxKeepLeashTicks) { + return addLeash(holder, maxDistance, elasticDistanceScale, maxKeepLeashTicks, ""); + } + + @Override + public boolean addLeash(Entity holder, Double maxDistance, Double elasticDistanceScale, String reserved) { + return addLeash(holder, maxDistance, elasticDistanceScale, 0, reserved); } // 添加拴绳(支持自定义最大长度 + reserved 字段) @Override - public boolean addLeash(Entity holder, double maxDistance, String reserved) { - return addLeash(holder, maxDistance, CommonEventHandler.leashConfigManager.getElasticDistance(), 0, reserved); + public boolean addLeash(Entity holder, Double maxDistance, String reserved) { + return addLeash(holder, maxDistance, null, 0, reserved); } // 添加拴绳(最终实现:支持最大长度、弹性距离、保持 Tick、reserved) @Override - public boolean addLeash(Entity holder, double maxDistance, - double elasticDistance, int maxKeepLeashTicks, String reserved) { + public boolean addLeash(Entity holder, Double maxDistance, + Double elasticDistanceScale, int maxKeepLeashTicks, String reserved) { boolean isSuperKnot = holder instanceof SuperLeashKnotEntity; if ((!isSuperKnot && leashHolders.containsKey(holder.getUUID())) || (isSuperKnot && leashKnots.containsKey(((SuperLeashKnotEntity) holder).getPos()))) { @@ -193,7 +286,7 @@ public class LeashDataImpl implements ILeashData { holder, reserved, maxDistance, - elasticDistance, + elasticDistanceScale, maxKeepLeashTicks, maxKeepLeashTicks ); @@ -203,24 +296,24 @@ public class LeashDataImpl implements ILeashData { } else { leashHolders.put(holder.getUUID(), info); } - LeashStateAPI.Offset.setHolderFor(entity, holder); + LeashStateInnerAPI.Offset.setHolderFor(entity, holder); markForSync(); return true; } // 使用已有的 LeashInfo 添加拴绳(直接走最终实现) @Override - public void addLeash(Entity holder, LeashInfo leashInfo) { + public void addLeash(Entity holder, @NotNull LeashInfo leashInfo) { addLeash(holder, leashInfo.maxDistance(), - leashInfo.elasticDistance(), + leashInfo.elasticDistanceScale(), leashInfo.maxKeepLeashTicks(), leashInfo.reserved() ); } @Override - public void addDelayedLeash(Player holderPlayer) { + public void addDelayedLeash(@NotNull Player holderPlayer) { delayedHolders.add(holderPlayer.getUUID()); } @@ -230,7 +323,7 @@ public class LeashDataImpl implements ILeashData { } private boolean updateLeashInfo( - Map map, + @NotNull Map map, K key, Function updater ) { @@ -246,21 +339,21 @@ public class LeashDataImpl implements ILeashData { } @Override - public boolean setMaxDistance(Entity holder, double newMaxDistance) { + public boolean setMaxDistance(Entity holder, @Nullable Double newMaxDistance) { return holder instanceof SuperLeashKnotEntity superLeashKnotEntity ? setMaxDistance(superLeashKnotEntity.getPos(), newMaxDistance) : setMaxDistance(holder.getUUID(), newMaxDistance); } @Override - public boolean setMaxDistance(Entity holder, double newMaxDistance, int newMaxKeepLeashTicks) { + public boolean setMaxDistance(Entity holder, @Nullable Double newMaxDistance, int newMaxKeepLeashTicks) { return holder instanceof SuperLeashKnotEntity superLeashKnotEntity ? setMaxDistance(superLeashKnotEntity.getPos(), newMaxDistance, newMaxKeepLeashTicks) : setMaxDistance(holder.getUUID(), newMaxDistance, newMaxKeepLeashTicks); } @Override - public boolean setMaxDistance(Entity holder, double distance, int maxKeepTicks, String reserved) { + public boolean setMaxDistance(Entity holder, @Nullable Double distance, int maxKeepTicks, String reserved) { return holder instanceof SuperLeashKnotEntity superLeashKnotEntity ? setMaxDistance(superLeashKnotEntity.getPos(), distance, maxKeepTicks, reserved) : setMaxDistance(holder.getUUID(), distance, maxKeepTicks, reserved); @@ -268,13 +361,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setMaxDistance(UUID holderUUID, double newMaxDistance) { + public boolean setMaxDistance(UUID holderUUID, @Nullable Double newMaxDistance) { return updateLeashInfo(leashHolders, holderUUID, old -> new LeashInfo( old.holderUUIDOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), newMaxDistance, - old.elasticDistance(), + old.elasticDistanceScale(), old.keepLeashTicks(), old.maxKeepLeashTicks() )); @@ -282,13 +376,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setMaxDistance(UUID holderUUID, double newMaxDistance, int newMaxKeepLeashTicks) { + public boolean setMaxDistance(UUID holderUUID, @Nullable Double newMaxDistance, int newMaxKeepLeashTicks) { return updateLeashInfo(leashHolders, holderUUID, old -> new LeashInfo( old.holderUUIDOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), newMaxDistance, - old.elasticDistance(), + old.elasticDistanceScale(), Math.min(old.keepLeashTicks(), newMaxKeepLeashTicks), newMaxKeepLeashTicks )); @@ -296,13 +391,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setMaxDistance(UUID holderUUID, double distance, int maxKeepTicks, String reserved) { + public boolean setMaxDistance(UUID holderUUID, @Nullable Double distance, int maxKeepTicks, String reserved) { return updateLeashInfo(leashHolders, holderUUID, old -> new LeashInfo( old.holderUUIDOpt().get(), old.holderIdOpt().get(), + old.marks(), reserved, distance, - old.elasticDistance(), + old.elasticDistanceScale(), Math.min(old.keepLeashTicks(), maxKeepTicks), maxKeepTicks )); @@ -310,13 +406,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setMaxDistance(BlockPos knotPos, double newMaxDistance) { + public boolean setMaxDistance(BlockPos knotPos, @Nullable Double newMaxDistance) { return updateLeashInfo(leashKnots, knotPos, old -> new LeashInfo( old.blockPosOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), newMaxDistance, - old.elasticDistance(), + old.elasticDistanceScale(), old.keepLeashTicks(), old.maxKeepLeashTicks() )); @@ -324,13 +421,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setMaxDistance(BlockPos knotPos, double newMaxDistance, int newMaxKeepLeashTicks) { + public boolean setMaxDistance(BlockPos knotPos, @Nullable Double newMaxDistance, int newMaxKeepLeashTicks) { return updateLeashInfo(leashKnots, knotPos, old -> new LeashInfo( old.blockPosOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), newMaxDistance, - old.elasticDistance(), + old.elasticDistanceScale(), Math.min(old.keepLeashTicks(), newMaxKeepLeashTicks), newMaxKeepLeashTicks )); @@ -338,35 +436,37 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setMaxDistance(BlockPos knotPos, double distance, int maxKeepTicks, String reserved) { + public boolean setMaxDistance(BlockPos knotPos, @Nullable Double distance, int maxKeepTicks, String reserved) { return updateLeashInfo(leashKnots, knotPos, old -> new LeashInfo( old.blockPosOpt().get(), old.holderIdOpt().get(), + old.marks(), reserved, distance, - old.elasticDistance(), + old.elasticDistanceScale(), Math.min(old.keepLeashTicks(), maxKeepTicks), maxKeepTicks )); } @Override - public boolean setElasticDistance(Entity holder, double newElasticDistance) { + public boolean setElasticDistanceScale(Entity holder, @Nullable Double scale) { return holder instanceof SuperLeashKnotEntity superLeashKnotEntity ? - setElasticDistance(superLeashKnotEntity.getPos(), newElasticDistance) : - setElasticDistance(holder.getUUID(), newElasticDistance); + setElasticDistanceScale(superLeashKnotEntity.getPos(), scale) : + setElasticDistanceScale(holder.getUUID(), scale); } // 动态修改弹性距离 @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setElasticDistance(UUID holderUUID, double newElasticDistance) { + public boolean setElasticDistanceScale(UUID holderUUID, @Nullable Double scale) { return updateLeashInfo(leashHolders, holderUUID, old -> new LeashInfo( old.holderUUIDOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), old.maxDistance(), - newElasticDistance, + scale, old.keepLeashTicks(), old.maxKeepLeashTicks() )); @@ -374,42 +474,44 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setElasticDistance(BlockPos knotPos, double newElasticDistance) { + public boolean setElasticDistanceScale(BlockPos knotPos, @Nullable Double scale) { return updateLeashInfo(leashKnots, knotPos, old -> new LeashInfo( old.blockPosOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), old.maxDistance(), - newElasticDistance, + scale, old.keepLeashTicks(), old.maxKeepLeashTicks() )); } @Override - public boolean setElasticDistance(Entity holder, double newElasticDistance, int newMaxKeepLeashTicks) { + public boolean setElasticDistanceScale(Entity holder, @Nullable Double scale, int newMaxKeepLeashTicks) { return holder instanceof SuperLeashKnotEntity superLeashKnotEntity ? - setElasticDistance(superLeashKnotEntity.getPos(), newElasticDistance, newMaxKeepLeashTicks) : - setElasticDistance(holder.getUUID(), newElasticDistance, newMaxKeepLeashTicks); + setElasticDistanceScale(superLeashKnotEntity.getPos(), scale, newMaxKeepLeashTicks) : + setElasticDistanceScale(holder.getUUID(), scale, newMaxKeepLeashTicks); } @Override - public boolean setElasticDistance(Entity holder, double distance, int maxKeepTicks, String reserved) { + public boolean setElasticDistanceScale(Entity holder, @Nullable Double scale, int maxKeepTicks, String reserved) { return holder instanceof SuperLeashKnotEntity superLeashKnotEntity ? - setElasticDistance(superLeashKnotEntity.getPos(), distance, maxKeepTicks, reserved) : - setElasticDistance(holder.getUUID(), distance, maxKeepTicks, reserved); + setElasticDistanceScale(superLeashKnotEntity.getPos(), scale, maxKeepTicks, reserved) : + setElasticDistanceScale(holder.getUUID(), scale, maxKeepTicks, reserved); } // 动态修改弹性距离 @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setElasticDistance(UUID holderUUID, double newElasticDistance, int newMaxKeepLeashTicks) { + public boolean setElasticDistanceScale(UUID holderUUID, @Nullable Double scale, int newMaxKeepLeashTicks) { return updateLeashInfo(leashHolders, holderUUID, old -> new LeashInfo( old.holderUUIDOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), old.maxDistance(), - newElasticDistance, + scale, Math.min(old.keepLeashTicks(), newMaxKeepLeashTicks), newMaxKeepLeashTicks )); @@ -417,13 +519,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setElasticDistance(UUID holderUUID, double distance, int maxKeepTicks, String reserved) { + public boolean setElasticDistanceScale(UUID holderUUID, @Nullable Double scale, int maxKeepTicks, String reserved) { return updateLeashInfo(leashHolders, holderUUID, old -> new LeashInfo( old.holderUUIDOpt().get(), old.holderIdOpt().get(), + old.marks(), reserved, old.maxDistance(), - distance, + scale, Math.min(old.keepLeashTicks(), maxKeepTicks), maxKeepTicks )); @@ -431,13 +534,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setElasticDistance(BlockPos knotPos, double newElasticDistance, int newMaxKeepLeashTicks) { + public boolean setElasticDistanceScale(BlockPos knotPos, @Nullable Double scale, int newMaxKeepLeashTicks) { return updateLeashInfo(leashKnots, knotPos, old -> new LeashInfo( old.blockPosOpt().get(), old.holderIdOpt().get(), + old.marks(), old.reserved(), old.maxDistance(), - newElasticDistance, + scale, old.keepLeashTicks(), old.maxKeepLeashTicks() )); @@ -445,13 +549,14 @@ public class LeashDataImpl implements ILeashData { @SuppressWarnings("OptionalGetWithoutIsPresent") @Override - public boolean setElasticDistance(BlockPos knotPos, double newElasticDistance, int newMaxKeepLeashTicks, String reserved) { + public boolean setElasticDistanceScale(BlockPos knotPos, @Nullable Double scale, int newMaxKeepLeashTicks, String reserved) { return updateLeashInfo(leashKnots, knotPos, old -> new LeashInfo( old.blockPosOpt().get(), old.holderIdOpt().get(), + old.marks(), reserved, old.maxDistance(), - newElasticDistance, + scale, Math.min(old.keepLeashTicks(), newMaxKeepLeashTicks), newMaxKeepLeashTicks )); @@ -509,7 +614,7 @@ public class LeashDataImpl implements ILeashData { /** * 给非玩家实体施加拴绳力(取消阻力) */ - private void applyForceToNonPlayerEntity(Entity entity, Vec3 combinedForce, + private void applyForceToNonPlayerEntity(@NotNull Entity entity, Vec3 combinedForce, int validLeashes, Vec3 combinedDirection) { // 直接施加合力,不再加阻力 entity.setDeltaMovement(entity.getDeltaMovement().add(combinedForce)); @@ -517,10 +622,12 @@ public class LeashDataImpl implements ILeashData { // 如果是生物,处理导航 if (entity instanceof Mob mob) { - if (validLeashes > 0 && canMobMove(mob)) { - moveMobTowardsCombinedDirection(mob, combinedDirection, validLeashes, combinedForce.length()); - } else { - mob.getNavigation().stop(); + if(mob.tickCount % 5 == 0){ + if (validLeashes > 0 && canMobMove(mob)) { + moveMobTowardsCombinedDirection(mob, combinedDirection, combinedForce.length()); + } else { + mob.getNavigation().stop(); + } } } } @@ -528,77 +635,97 @@ public class LeashDataImpl implements ILeashData { /** * 检查生物是否能够移动 */ - private boolean canMobMove(Mob mob) { + private boolean canMobMove(@NotNull Mob mob) { // 检查各种无法移动的情况 - return !mob.isNoGravity() && // 有重力才能移动 - !mob.isSleeping() && // 没有在睡觉 - !mob.isDeadOrDying() && // 没有死亡或濒死 - !mob.isFreezing() && // 没有被冻结 - mob.canUpdate() && // 可以更新 + return !mob.isDeadOrDying() && // 没有死亡或濒死 mob.isEffectiveAi() && // AI有效 - mob.getDeltaMovement().lengthSqr() < 100.0; // 移动速度不是特别快(防止异常情况) + mob.getDeltaMovement().lengthSqr() < 25.0; // 降低速度阈值 } /** * 让生物朝着合力方向移动 */ - private void moveMobTowardsCombinedDirection(Mob mob, Vec3 combinedDirection, int leashCount, double forceMagnitude) { + private void moveMobTowardsCombinedDirection(Mob mob, @NotNull Vec3 combinedDirection, double forceMagnitude) { if (combinedDirection.equals(Vec3.ZERO) || !canMobMove(mob)) { - mob.getNavigation().stop(); - return; + return;// 减少不必要的stop调用 } - // 计算平均方向 - Vec3 averageDirection = combinedDirection.scale(1.0 / leashCount).normalize(); + // 计算平均方向(简化计算) + Vec3 averageDirection = combinedDirection.normalize(); // 根据力的大小调整移动速度 double speed = calculateMobSpeed(mob, forceMagnitude); - // 计算目标位置(在合力方向上稍微超前一点) - Vec3 targetPos = mob.position().add(averageDirection.scale(3.0)); // 3格距离 + // 计算目标位置(缩短距离) + Vec3 targetPos = mob.position().add(averageDirection.scale(2.0)); // 从3格减少到2格 - // 检查目标位置是否可达 - if (isPositionReachable(mob, targetPos)) { + // 使用快速可达性检查 + if (isPositionQuickReachable(mob, targetPos)) { // 设置移动目标 mob.getNavigation().moveTo(targetPos.x, targetPos.y, targetPos.z, speed); - // 设置生物朝向合力方向 - mob.getLookControl().setLookAt(targetPos); - } else { - // 位置不可达时停止导航 - mob.getNavigation().stop(); + // 降低朝向更新频率 + if (mob.tickCount % 10 == 0) { + mob.getLookControl().setLookAt(targetPos); + } } } - /** - * 检查位置是否可达 + * 快速可达性检查(替代原来的路径查找) */ - private boolean isPositionReachable(Mob mob, Vec3 targetPos) { - // 简单的距离检查 - if (mob.position().distanceTo(targetPos) > 20.0) return false;// 距离太远 - // 检查是否有导航路径 - Path path = mob.getNavigation().createPath(targetPos.x, targetPos.y, targetPos.z, 0); - return path != null && !path.isDone(); + private boolean isPositionQuickReachable(@NotNull Mob mob, Vec3 targetPos) { + // 1. 距离检查(缩短最大距离) + double distance = mob.position().distanceTo(targetPos); + if (distance > 10.0) return false; // 从20格减少到10格 + + // 2. 高度差检查 + double heightDiff = Math.abs(targetPos.y - mob.position().y); + if (heightDiff > 2.0) return false; + + // 3. 简单的视线检查 + // 如果性能仍然有问题,可以注释掉这个检查 + if (mob.level().isLoaded(BlockPos.containing(targetPos))) { + BlockHitResult hitResult = mob.level().clip(new ClipContext( + mob.position(), + targetPos, + ClipContext.Block.COLLIDER, + ClipContext.Fluid.NONE, + mob + )); + return hitResult.getType() == HitResult.Type.MISS; + } + + return true; } +// /** +// * 检查位置是否可达 +// */ +// private boolean isPositionReachable(Mob mob, Vec3 targetPos) { +// // 简单的距离检查 +// if (mob.position().distanceTo(targetPos) > 20.0) return false;// 距离太远 +// // 检查是否有导航路径 +// Path path = mob.getNavigation().createPath(targetPos.x, targetPos.y, targetPos.z, 0); +// return path != null && !path.isDone(); +// } + /** - * 根据生物类型和力的大小计算移动速度 + * 根据生物类型和力的大小计算移动速度(优化版) */ private double calculateMobSpeed(Mob mob, double forceMagnitude) { - double baseSpeed = mob instanceof Llama ? 2.0 : 1.0; + double baseSpeed = mob instanceof Llama ? 1.5 : 1.0; // 降低基础速度 - // 力越大,移动速度越快(但有上限) - double forceFactor = Math.min(forceMagnitude * 0.5, 2.0); // 限制最大加速2倍 + // 力越大,移动速度越快(降低加速效果) + double forceFactor = Math.min(forceMagnitude * 0.3, 1.5); // 降低加速系数和上限 return baseSpeed * (1.0 + forceFactor); } - /** * 为UUID拴绳计算力 */ - private Vec3 calculateLeashForceForUUID(Map.Entry entry) { + private @Nullable Vec3 calculateLeashForceForUUID(Map.@NotNull Entry entry) { UUID uuid = entry.getKey(); Entity uuidHolder = ((ServerLevel) entity.level()).getEntity(uuid); if (uuidHolder != null) { @@ -615,80 +742,90 @@ public class LeashDataImpl implements ILeashData { /** * 为方块位置拴绳计算力 */ - private Vec3 calculateLeashForceForBlockPos(Map.Entry entry) { + private Vec3 calculateLeashForceForBlockPos(Map.@NotNull Entry entry) { SuperLeashKnotEntity orCreateKnot = SuperLeashKnotEntity.getOrCreateKnot(entity.level(), entry.getKey()); return calculateLeashForce(orCreateKnot, entry); } - /** - * 计算单个拴绳的力 - */ - private Vec3 calculateLeashForce(Entity holder, Map.Entry entry) { + private @Nullable Vec3 calculateLeashForce(@NotNull Entity holder, Map.@NotNull Entry entry) { Vec3 holderPos = holder.position().add(0, holder.getBbHeight() * 0.7, 0); LeashInfo info = entry.getValue(); Vec3 entityPos = entity.position(); double distance = holderPos.distanceTo(entityPos); - double extremeSnapDist = CommonEventHandler.leashConfigManager.getBreakDistance(); + double maxDistance = info.maxDistance() == null ? getCurrentMaxDistance() : info.maxDistance(); + double extremeSnapDist = maxDistance * CommonEventHandler.leashConfigManager.getExtremeSnapFactor(); + double elasticDistanceScale = info.elasticDistanceScale() == null ? getCurrentElasticDistanceScale() : info.elasticDistanceScale(); + // 修正:计算弹性限度距离 + double elasticLimitDistance = maxDistance * elasticDistanceScale; // 1. 检查是否超出断裂距离 if (distance > extremeSnapDist) { if (info.keepLeashTicks() > 0) { // 计算临界拉力 - Vec3 pullForce = calculateCriticalPullForce(holderPos, entityPos, distance, info); + Vec3 pullForce = calculateCriticalPullForce(holderPos, entityPos, distance, maxDistance, elasticLimitDistance); entry.setValue(info.decrementKeepTicks()); return pullForce; } // 断裂 removeLeash(holder); - //TODO: 是不是应该考虑让断裂统一发出声音,还是就这样由断裂发出 entity.level().playSound(null, holder.getOnPos(), SLPSoundEvents.LEAD_BREAK.get(), SoundSource.PLAYERS); return null; } + + // 2. 正常弹性拉力逻辑 Vec3 pullForce = Vec3.ZERO; - if (distance > info.elasticDistance()) { - pullForce = calculatePullForce(holderPos, entityPos, distance, info); + if (distance > elasticLimitDistance) { + pullForce = calculatePullForce(holderPos, entityPos, distance, maxDistance, elasticLimitDistance); } // 3. 重置缓冲Tick - if (distance <= info.maxDistance() && info.keepLeashTicks() < info.maxKeepLeashTicks()) { + if (distance <= extremeSnapDist && info.keepLeashTicks() < info.maxKeepLeashTicks()) { entry.setValue(info.resetKeepTicks()); } return pullForce; } - // 计算正常拉力(保持不变) - @Contract("_, _, _, _ -> new") - private @NotNull Vec3 calculatePullForce(@NotNull Vec3 holderPos, Vec3 entityPos, double distance, @NotNull LeashInfo info) { + // 计算正常拉力 + @Contract("_, _, _, _, _ -> new") + private @NotNull Vec3 calculatePullForce(@NotNull Vec3 holderPos, Vec3 entityPos, double distance, double maxDistance, double elasticLimitDistance) { Vec3 pullDirection = holderPos.subtract(entityPos).normalize(); double pullStrength = 0.2; - if (distance > info.maxDistance()) { - double excessRatio = (distance - info.maxDistance()) / info.maxDistance(); + // 计算超过弹性限度的距离 + double excessDistance = distance - elasticLimitDistance; + + if (distance > maxDistance) { + double excessRatio = (distance - maxDistance) / (maxDistance - elasticLimitDistance); pullStrength += excessRatio * 0.8; } + // 拉力与超过弹性限度的距离成正比 Vec3 pullForce = pullDirection.scale( - (distance - info.elasticDistance()) * pullStrength * CommonEventHandler.leashConfigManager.getSpringDampening() + excessDistance * pullStrength * CommonEventHandler.leashConfigManager.getSpringDampening() ); return new Vec3( pullForce.x * CommonEventHandler.leashConfigManager.getXElasticity(), - pullForce.y * CommonEventHandler.leashConfigManager.getXElasticity(), + pullForce.y * CommonEventHandler.leashConfigManager.getYElasticity(), // 修正:应该是 YElasticity pullForce.z * CommonEventHandler.leashConfigManager.getZElasticity() ); } - // 计算临界拉力(保持不变) - private @NotNull Vec3 calculateCriticalPullForce(@NotNull Vec3 holderPos, Vec3 entityPos, double distance, @NotNull LeashInfo info) { + // 计算临界拉力(修正版) + private @NotNull Vec3 calculateCriticalPullForce(@NotNull Vec3 holderPos, Vec3 entityPos, double distance, double maxDistance, double elasticLimitDistance) { Vec3 pullDirection = holderPos.subtract(entityPos).normalize(); - double excessRatio = (distance - info.maxDistance()) / info.maxDistance(); + + double excessRatio = (distance - maxDistance) / maxDistance; double pullStrength = 1.0 + excessRatio * 2.0; + // 计算超过弹性限度的距离 + double excessDistance = distance - elasticLimitDistance; + Vec3 pullForce = pullDirection.scale( - (distance - info.elasticDistance()) * pullStrength * CommonEventHandler.leashConfigManager.getSpringDampening() + excessDistance * pullStrength * CommonEventHandler.leashConfigManager.getSpringDampening() ); return new Vec3( @@ -709,7 +846,7 @@ public class LeashDataImpl implements ILeashData { public boolean removeLeash(UUID holderUUID) { boolean removed = leashHolders.remove(holderUUID) != null; if (removed) { - LeashStateAPI.Operations.detach(entity, holderUUID); + LeashStateInnerAPI.Operations.detach(entity, holderUUID); markForSync(); } return removed; @@ -719,7 +856,7 @@ public class LeashDataImpl implements ILeashData { public boolean removeLeash(BlockPos knotPos) { boolean removed = leashKnots.remove(knotPos) != null; if (removed) { - LeashStateAPI.Operations.detach(entity, knotPos); + LeashStateInnerAPI.Operations.detach(entity, knotPos); markForSync(); } return removed; @@ -729,21 +866,21 @@ public class LeashDataImpl implements ILeashData { public void removeAllLeashes() { leashHolders.clear(); leashKnots.clear(); - LeashStateAPI.Offset.removeHolderAll(entity); + LeashStateInnerAPI.Offset.removeHolderAll(entity); markForSync(); } @Override public void removeAllHolderLeashes() { leashHolders.clear(); - LeashStateAPI.Offset.removeAllHolderUUIDs(entity); + LeashStateInnerAPI.Offset.removeAllHolderUUIDs(entity); markForSync(); } @Override public void removeAllKnotLeashes() { leashKnots.clear(); - LeashStateAPI.Offset.removeAllHolderBlockPoses(entity); + LeashStateInnerAPI.Offset.removeAllHolderBlockPoses(entity); markForSync(); } @@ -773,7 +910,7 @@ public class LeashDataImpl implements ILeashData { LeashInfo leashInfo = info.transferHolder(newHolder); leashHolders.put(newHolder.getUUID(), leashInfo); } - LeashStateAPI.Operations.transfer(entity, oldHolderUUID, newHolder); + LeashStateInnerAPI.Operations.transfer(entity, oldHolderUUID, newHolder); markForSync(); return true; } @@ -788,7 +925,7 @@ public class LeashDataImpl implements ILeashData { LeashInfo leashInfo = info.transferHolder(newHolder, reserved); leashHolders.put(newHolder.getUUID(), leashInfo); } - LeashStateAPI.Operations.transfer(entity, oldHolderUUID, newHolder); + LeashStateInnerAPI.Operations.transfer(entity, oldHolderUUID, newHolder); markForSync(); return true; } @@ -804,7 +941,7 @@ public class LeashDataImpl implements ILeashData { LeashInfo leashInfo = info.transferHolder(newHolder); leashHolders.put(newHolder.getUUID(), leashInfo); } - LeashStateAPI.Operations.transfer(entity, knotPos, newHolder); + LeashStateInnerAPI.Operations.transfer(entity, knotPos, newHolder); markForSync(); return true; } @@ -820,7 +957,7 @@ public class LeashDataImpl implements ILeashData { LeashInfo leashInfo = info.transferHolder(newHolder, reserved); leashHolders.put(newHolder.getUUID(), leashInfo); } - LeashStateAPI.Operations.transfer(entity, knotPos, newHolder); + LeashStateInnerAPI.Operations.transfer(entity, knotPos, newHolder); markForSync(); return true; } @@ -841,7 +978,7 @@ public class LeashDataImpl implements ILeashData { } //只能系在这些实体上,在这里,其它情况一律忽略 - //TODO: 标签支持控制 + //TODO: 未来更新计划 - 标签支持控制 public static boolean isLeashable(Entity entity) { return entity instanceof LivingEntity || entity instanceof Boat || entity instanceof AbstractMinecart; } @@ -901,6 +1038,10 @@ public class LeashDataImpl implements ILeashData { CompoundTag tag = new CompoundTag(); ListTag holdersList = new ListTag(); ListTag delayedHolderList = new ListTag(); + if (staticMaxDistance != null) tag.putDouble("StaticMaxDistance", staticMaxDistance); + tag.putDouble("DefaultMaxDistance", defaultMaxDistance); + if (staticElasticDistanceScale != null) tag.putDouble("StaticElasticDistanceScale", staticElasticDistanceScale); + tag.putDouble("DefaultElasticDistanceScale", defaultElasticDistanceScale); for (LeashInfo info : leashHolders.values()) { CompoundTag infoTag = generateCompoundTagFromUUIDLeashInfo(info); holdersList.add(infoTag); @@ -947,7 +1088,7 @@ public class LeashDataImpl implements ILeashData { infoTag.putInt("HolderID", info.holderIdOpt().get()); infoTag.putString("LeashItem", info.reserved()); infoTag.putDouble("MaxDistance", info.maxDistance()); - infoTag.putDouble("ElasticDistance", info.elasticDistance()); + infoTag.putDouble("ElasticDistance", info.elasticDistanceScale()); infoTag.putInt("KeepLeashTicks", info.keepLeashTicks()); infoTag.putInt("MaxKeepLeashTicks", info.maxKeepLeashTicks()); return infoTag; @@ -958,6 +1099,19 @@ public class LeashDataImpl implements ILeashData { leashHolders.clear(); leashKnots.clear(); delayedHolders.clear(); + if (nbt.contains("DefaultMaxDistance")) { + defaultMaxDistance = nbt.getDouble("DefaultMaxDistance"); + if (nbt.contains("StaticMaxDistance")) { + staticMaxDistance = nbt.getDouble("StaticMaxDistance"); + } else staticMaxDistance = null; + + } else defaultMaxDistance = CommonEventHandler.leashConfigManager.getMaxLeashLength(); + if(nbt.contains("DefaultElasticDistanceScale")) { + staticElasticDistanceScale = nbt.getDouble("DefaultElasticDistanceScale"); + if (nbt.contains("StaticElasticDistanceScale")) { + staticElasticDistanceScale = nbt.getDouble("StaticElasticDistanceScale"); + } else staticElasticDistanceScale = null; + } else staticElasticDistanceScale = CommonEventHandler.leashConfigManager.getElasticDistanceScale(); if (nbt.contains("LeashHolders", ListTag.TAG_LIST)) { ListTag holdersList = nbt.getList("LeashHolders", ListTag.TAG_COMPOUND); @@ -1046,47 +1200,12 @@ public class LeashDataImpl implements ILeashData { return Optional.empty(); // 理论上不会到这里 } - - - public static @NotNull List leashableInArea(Level pLevel, Vec3 pPos, Predicate filter) { - return leashableInArea(pLevel, pPos, filter, 1024D); - } - public static @NotNull List leashableInArea(@NotNull Level pLevel, Vec3 pPos, Predicate filter, double fetchDistance) { - AABB box = AABB.ofSize(pPos, fetchDistance, fetchDistance, fetchDistance); - return pLevel.getEntitiesOfClass(Entity.class, box, e -> LeashDataImpl.isLeashable(e) && filter.test(e)); - } - public static @NotNull List leashableInArea(@NotNull Entity entity, Predicate filter, double fetchDistance) { - return leashableInArea(entity.level(), entity.getBoundingBox().getCenter(), filter, fetchDistance); - } - public static @NotNull List leashableInArea(Entity entity, Predicate filter) { - return leashableInArea(entity, filter, 1024D); - } - public static @NotNull List leashableInArea(Entity holder) { - return leashableInArea(holder, i -> isLeashHolder(i, holder), 1024D); - } public boolean canBeAttachedTo(Entity pEntity) { if (pEntity == entity) { return false; } else { Optional leashInfo = getLeashInfo(pEntity); - return leashInfo.isEmpty() && (entity.distanceTo(pEntity) <= CommonEventHandler.leashConfigManager.getElasticDistance() * CommonEventHandler.leashConfigManager.getExtremeSnapFactor()) && canBeLeashed();//距离最大,则不可以被固定或转移 + return leashInfo.isEmpty() && (entity.distanceTo(pEntity) <= CommonEventHandler.leashConfigManager.getElasticDistanceScale() * CommonEventHandler.leashConfigManager.getExtremeSnapFactor()) && canBeLeashed();//距离最大,则不可以被固定或转移 } } - public static boolean isLeashHolder(@NotNull Entity pEntity, Entity pTestHolder) { - return pTestHolder instanceof SuperLeashKnotEntity superLeashKnotEntity ? - isLeashHolder(pEntity, superLeashKnotEntity.getPos()) : - isLeashHolder(pEntity, pTestHolder.getUUID()); - } - - public static boolean isLeashHolder(@NotNull Entity pEntity, UUID pHolderUUID) { - return LeashDataAPI.getLeashData(pEntity) - .map(leashData -> leashData.isLeashedBy(pHolderUUID)) - .orElse(false); - } - - public static boolean isLeashHolder(@NotNull Entity pEntity, BlockPos pKnotPos) { - return LeashDataAPI.getLeashData(pEntity) - .map(leashData -> leashData.isLeashedBy(pKnotPos)) - .orElse(false); - } } diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashStateImpl.java b/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashStateImpl.java index 012d7d2..b987d93 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashStateImpl.java +++ b/src/main/java/top/r3944realms/superleadrope/content/capability/impi/LeashStateImpl.java @@ -28,7 +28,7 @@ import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import top.r3944realms.superleadrope.CommonEventHandler; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.network.NetworkHandler; import top.r3944realms.superleadrope.network.toClient.LeashStateSyncPacket; diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashData.java b/src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashData.java deleted file mode 100644 index 4508b3b..0000000 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/inter/ILeashData.java +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Super Lead rope mod - * Copyright (C) 2025 R3944Realms - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package top.r3944realms.superleadrope.content.capability.inter; - -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.util.INBTSerializable; -import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; - -import java.util.Collection; -import java.util.Optional; -import java.util.UUID; - -/** - * Capability interface for managing leash data of entities and knots. - */ -public interface ILeashData extends INBTSerializable { - - /* ---------------------- - * Add / removeApplyEntity leashes - * ---------------------- */ - boolean addLeash(Entity holder); - boolean addLeash(Entity holder, String reserved); - boolean addLeash(Entity holder, double maxDistance); - boolean addLeash(Entity holder, double maxDistance, double elasticDistance, int maxKeepTicks); - boolean addLeash(Entity holder, double maxDistance, String reserved); - boolean addLeash(Entity holder, double maxDistance, double elasticDistance, int maxKeepTicks, String reserved); - - void addLeash(Entity holder, LeashInfo info); - - void addDelayedLeash(Player holderPlayer); - void removeDelayedLeash(UUID onceHolderPlayerUUID); - - boolean removeLeash(Entity holder); - boolean removeLeash(UUID holderUUID); - boolean removeLeash(BlockPos knotPos); - - void removeAllLeashes(); - void removeAllHolderLeashes(); - void removeAllKnotLeashes(); - - /* ---------------------- - * Modify leash properties - * ---------------------- */ - boolean setMaxDistance(Entity holder, double distance); - boolean setMaxDistance(Entity holder, double distance, int maxKeepTicks); - boolean setMaxDistance(Entity holder, double distance, int maxKeepTicks, String reserved); - - boolean setMaxDistance(UUID holderUUID, double distance); - boolean setMaxDistance(UUID holderUUID, double distance, int maxKeepTicks); - boolean setMaxDistance(UUID holderUUID, double distance, int maxKeepTicks, String reserved); - - boolean setMaxDistance(BlockPos knotPos, double distance); - boolean setMaxDistance(BlockPos knotPos, double distance, int maxKeepTicks); - boolean setMaxDistance(BlockPos knotPos, double distance, int maxKeepTicks, String reserved); - - boolean setElasticDistance(Entity holder, double distance); - boolean setElasticDistance(Entity holder, double distance, int maxKeepTicks); - boolean setElasticDistance(Entity holder, double distance, int maxKeepTicks, String reserved); - - boolean setElasticDistance(UUID holderUUID, double distance); - boolean setElasticDistance(UUID holderUUID, double distance, int maxKeepTicks); - boolean setElasticDistance(UUID holderUUID, double distance, int maxKeepTicks, String reserved); - - boolean setElasticDistance(BlockPos knotPos, double distance); - boolean setElasticDistance(BlockPos knotPos, double distance, int maxKeepTicks); - boolean setElasticDistance(BlockPos knotPos, double distance, int maxKeepTicks, String reserved); - - /* ---------------------- - * Apply physics - * ---------------------- */ - void applyLeashForces(); - - /* ---------------------- - * Transfer leash holders - * ---------------------- */ - boolean transferLeash(Entity holder, Entity newHolder); - boolean transferLeash(Entity holder, Entity newHolder, String reserved); - - boolean transferLeash(UUID holderUUID, Entity newHolder); - boolean transferLeash(UUID holderUUID, Entity newHolder, String reserved); - - boolean transferLeash(BlockPos knotPos, Entity newHolder); - boolean transferLeash(BlockPos knotPos, Entity newHolder, String reserved); - - /* ---------------------- - * Query state - * ---------------------- */ - boolean hasLeash(); - boolean hasKnotLeash(); - boolean hasHolderLeash(); - - Collection getAllLeashes(); - - boolean isLeashedBy(Entity holder); - boolean isLeashedBy(UUID holderUUID); - boolean isLeashedBy(BlockPos knotPos); - - boolean isInDelayedLeash(UUID holderUUID); - - Optional getLeashInfo(Entity holder); - Optional getLeashInfo(UUID holderUUID); - Optional getLeashInfo(BlockPos knotPos); - - boolean canBeLeashed(); - boolean canBeAttachedTo(Entity entity); - - /* ---------------------- - * Occupy / sync - * ---------------------- */ - /** - * 抢占位(已离线玩家)。 - * 用于解决玩家下线后所持有对象会移除持有者的问题(实际上是占用个弱集合) - */ - Optional occupyLeash(); - - void markForSync(); - void immediateSync(); - void checkSync(); - - /* ---------------------- - * Data record - * ---------------------- */ - record LeashInfo( - Optional blockPosOpt, - Optional holderUUIDOpt, - Optional holderIdOpt, // Only for client side use - String reserved, // 保留字段 - double maxDistance, - double elasticDistance, - int keepLeashTicks, // 剩余 Tick 数 - int maxKeepLeashTicks // 最大保持 Tick 数 - ) { - public static final LeashInfo EMPTY = new LeashInfo( - Optional.empty(), Optional.empty(), Optional.empty(), - "", 12.0D, 6.0D, 0, 0 - ); - - /* ---------- Factory ---------- */ - public static LeashInfo create( - Entity entity, - String reserved, - double maxDistance, - double elasticDistance, - int keepTicks, - int maxKeepTicks - ) { - return entity instanceof SuperLeashKnotEntity knot - ? new LeashInfo(knot.getPos(), entity.getId(), reserved, - maxDistance, elasticDistance, keepTicks, maxKeepTicks) - : new LeashInfo(entity.getUUID(), entity.getId(), reserved, maxDistance, elasticDistance, keepTicks, maxKeepTicks); - } - - public LeashInfo(UUID holderUUID, int holderId, String reserved, - double maxDistance, double elasticDistance, int keepTicks, int maxKeepTicks) { - this(Optional.empty(), Optional.of(holderUUID), Optional.of(holderId), - reserved, maxDistance, elasticDistance, keepTicks, maxKeepTicks); - } - - public LeashInfo(BlockPos knotPos, int holderId, String reserved, - double maxDistance, double elasticDistance, int keepTicks, int maxKeepTicks) { - this(Optional.of(knotPos), Optional.empty(), Optional.of(holderId), - reserved, maxDistance, elasticDistance, keepTicks, maxKeepTicks); - } - - /* ---------- State updates ---------- */ - public LeashInfo decrementKeepTicks() { - return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, reserved, - maxDistance, elasticDistance, - Math.max(0, keepLeashTicks - 1), maxKeepLeashTicks); - } - - public LeashInfo resetKeepTicks() { - return new LeashInfo(blockPosOpt, holderUUIDOpt, holderIdOpt, reserved, - maxDistance, elasticDistance, - maxKeepLeashTicks, maxKeepLeashTicks); - } - - public LeashInfo transferHolder(Entity entity) { - return transferHolder(entity, reserved); - } - - public LeashInfo transferHolder(Entity entity, String newReserved) { - boolean isKnot = entity instanceof SuperLeashKnotEntity; - return new LeashInfo( - isKnot ? Optional.of(((SuperLeashKnotEntity) entity).getPos()) : Optional.empty(), - !isKnot ? Optional.of(entity.getUUID()) : Optional.empty(), - Optional.of(entity.getId()), - newReserved, maxDistance, elasticDistance, - keepLeashTicks, maxKeepLeashTicks - ); - } - } -} \ No newline at end of file diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashDataProvider.java b/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashDataProvider.java index ecedaaa..8448a62 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashDataProvider.java +++ b/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashDataProvider.java @@ -25,9 +25,9 @@ import net.minecraftforge.common.util.LazyOptional; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import top.r3944realms.superleadrope.SuperLeadRope; -import top.r3944realms.superleadrope.content.capability.CapabilityHandler; +import top.r3944realms.superleadrope.api.SLPCapability; import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; public class LeashDataProvider implements ICapabilitySerializable { public static final ResourceLocation LEASH_DATA_REL = new ResourceLocation(SuperLeadRope.MOD_ID, "leash_data"); @@ -39,7 +39,7 @@ public class LeashDataProvider implements ICapabilitySerializable { } @Override public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { - return CapabilityHandler.LEASH_DATA_CAP.orEmpty(cap, optional); + return SLPCapability.LEASH_DATA_CAP.orEmpty(cap, optional); } @Override diff --git a/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashStateProvider.java b/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashStateProvider.java index 6b6db94..760ee6f 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashStateProvider.java +++ b/src/main/java/top/r3944realms/superleadrope/content/capability/provider/LeashStateProvider.java @@ -26,9 +26,9 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import top.r3944realms.superleadrope.CommonEventHandler; import top.r3944realms.superleadrope.SuperLeadRope; -import top.r3944realms.superleadrope.content.capability.CapabilityHandler; +import top.r3944realms.superleadrope.api.SLPCapability; import top.r3944realms.superleadrope.content.capability.impi.LeashStateImpl; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; public class LeashStateProvider implements ICapabilitySerializable { public static final ResourceLocation LEASH_STATE_REL = new ResourceLocation(SuperLeadRope.MOD_ID, "leash_state"); @@ -40,7 +40,7 @@ public class LeashStateProvider implements ICapabilitySerializable } @Override public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { - return CapabilityHandler.LEASH_STATE_CAP.orEmpty(cap, optional); + return SLPCapability.LEASH_STATE_CAP.orEmpty(cap, optional); } @Override diff --git a/src/main/java/top/r3944realms/superleadrope/content/command/LeashDataCommand.java b/src/main/java/top/r3944realms/superleadrope/content/command/LeashDataCommand.java index cad924b..d6e1343 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/command/LeashDataCommand.java +++ b/src/main/java/top/r3944realms/superleadrope/content/command/LeashDataCommand.java @@ -16,14 +16,16 @@ package top.r3944realms.superleadrope.content.command; import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.arguments.*; +import com.mojang.brigadier.arguments.DoubleArgumentType; +import com.mojang.brigadier.arguments.IntegerArgumentType; +import com.mojang.brigadier.arguments.StringArgumentType; import com.mojang.brigadier.builder.LiteralArgumentBuilder; import com.mojang.brigadier.builder.RequiredArgumentBuilder; import com.mojang.brigadier.context.CommandContext; import com.mojang.brigadier.exceptions.CommandSyntaxException; import net.minecraft.commands.CommandSourceStack; import net.minecraft.commands.Commands; -import net.minecraft.commands.arguments.*; +import net.minecraft.commands.arguments.EntityArgument; import net.minecraft.commands.arguments.coordinates.BlockPosArgument; import net.minecraft.commands.arguments.selector.EntitySelector; import net.minecraft.core.BlockPos; @@ -33,11 +35,11 @@ import net.minecraft.world.entity.Entity; import org.jetbrains.annotations.Nullable; import top.r3944realms.superleadrope.CommonEventHandler; import top.r3944realms.superleadrope.SuperLeadRope; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.content.gamerule.server.CreateSuperLeashKnotEntityIfAbsent; import top.r3944realms.superleadrope.core.register.SLPGameruleRegistry; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.ArrayList; import java.util.Collection; @@ -45,7 +47,6 @@ import java.util.List; import java.util.Optional; import static top.r3944realms.superleadrope.content.command.Command.*; -import static top.r3944realms.superleadrope.content.command.Command.SHOULD_USE_PREFIX; public class LeashDataCommand { public static final String SLP_LEASH_MESSAGE_ = SuperLeadRope.MOD_ID + ".command.leash.message."; public static final String LEASH_DATA_GET_ = SLP_LEASH_MESSAGE_ + ".get.", @@ -67,19 +68,19 @@ public class LeashDataCommand { .then(Commands.argument("maxDistance", DoubleArgumentType.doubleArg(1.0, 256.0)) .executes(context -> addLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"))) - .then(Commands.argument("elasticDistance", DoubleArgumentType.doubleArg(1.0, 128.0)) + .then(Commands.argument("elasticDistanceScale", DoubleArgumentType.doubleArg(1.0, 128.0)) .executes(context -> addLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"), - DoubleArgumentType.getDouble(context, "elasticDistance"))) + DoubleArgumentType.getDouble(context, "elasticDistanceScale"))) .then(Commands.argument("keepTicks", IntegerArgumentType.integer(0)) .executes(context -> addLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"), - DoubleArgumentType.getDouble(context, "elasticDistance"), + DoubleArgumentType.getDouble(context, "elasticDistanceScale"), IntegerArgumentType.getInteger(context, "keepTicks"))) .then(Commands.argument("reserved", StringArgumentType.string()) .executes(context -> addLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"), - DoubleArgumentType.getDouble(context, "elasticDistance"), + DoubleArgumentType.getDouble(context, "elasticDistanceScale"), IntegerArgumentType.getInteger(context, "keepTicks"), StringArgumentType.getString(context, "reserved"))) ) @@ -92,19 +93,19 @@ public class LeashDataCommand { .then(Commands.argument("maxDistance", DoubleArgumentType.doubleArg(1.0, 256.0)) .executes(context -> addBlockLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"))) - .then(Commands.argument("elasticDistance", DoubleArgumentType.doubleArg(1.0, 128.0)) + .then(Commands.argument("elasticDistanceScale", DoubleArgumentType.doubleArg(1.0, 128.0)) .executes(context -> addBlockLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"), - DoubleArgumentType.getDouble(context, "elasticDistance"), 0, "")) + DoubleArgumentType.getDouble(context, "elasticDistanceScale"), 0, "")) .then(Commands.argument("keepTicks", IntegerArgumentType.integer(0)) .executes(context -> addBlockLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"), - DoubleArgumentType.getDouble(context, "elasticDistance"), + DoubleArgumentType.getDouble(context, "elasticDistanceScale"), IntegerArgumentType.getInteger(context, "keepTicks"))) .then(Commands.argument("reserved", StringArgumentType.string()) .executes(context -> addBlockLeash(context, DoubleArgumentType.getDouble(context, "maxDistance"), - DoubleArgumentType.getDouble(context, "elasticDistance"), + DoubleArgumentType.getDouble(context, "elasticDistanceScale"), IntegerArgumentType.getInteger(context, "keepTicks"), StringArgumentType.getString(context, "reserved"))) ) @@ -189,7 +190,7 @@ public class LeashDataCommand { ) // 设置弹性距离 - .then(Commands.literal("elasticDistance") + .then(Commands.literal("elasticDistanceScale") .then(Commands.argument("distance", DoubleArgumentType.doubleArg(1.0, 128.0)) .executes(context -> setElasticDistance(context, 0, "")) .then(Commands.argument("keepTicks", IntegerArgumentType.integer(0)) @@ -222,7 +223,7 @@ public class LeashDataCommand { ) // 设置弹性距离 - .then(Commands.literal("elasticDistance") + .then(Commands.literal("elasticDistanceScale") .then(Commands.argument("distance", DoubleArgumentType.doubleArg(1.0, 128.0)) .executes(LeashDataCommand::setBlockElasticDistance) .then(Commands.argument("keepTicks", IntegerArgumentType.integer(0)) @@ -350,18 +351,18 @@ public class LeashDataCommand { CommandSourceStack source = context.getSource(); for (Entity target : targets) { - Collection leashes = LeashDataAPI.QueryOperations.getAllLeashes(target); + Collection leashes = LeashDataInnerAPI.QueryOperations.getAllLeashes(target); // +++ source.sendSuccess(() -> Component.literal("=== Leash Data for " + target.getName().getString() + " ==="), false); source.sendSuccess(() -> Component.literal("Total leashes: " + leashes.size()), false); // TODO:翻译支持 HoverTip实现部分信息简化显示 - for (ILeashData.LeashInfo leash : leashes) { + for (LeashInfo leash : leashes) { StringBuilder info = new StringBuilder(); leash.blockPosOpt().ifPresent(pos -> info.append("Block: ").append(pos.toShortString()).append(" ")); leash.holderUUIDOpt().ifPresent(uuid -> info.append("UUID: ").append(uuid).append(" ")); info.append("Max: ").append(leash.maxDistance()).append(" "); - info.append("Elastic: ").append(leash.elasticDistance()).append(" "); + info.append("Elastic: ").append(leash.elasticDistanceScale()).append(" "); info.append("Keep: ").append(leash.keepLeashTicks()).append("/").append(leash.maxKeepLeashTicks()); if (!leash.reserved().isEmpty()) { info.append(" Reserved: ").append(leash.reserved()); @@ -374,12 +375,12 @@ public class LeashDataCommand { return targets.size(); } private static int addLeash(CommandContext context) throws CommandSyntaxException { - return addLeash(context, CommonEventHandler.leashConfigManager.getMaxLeashLength(), CommonEventHandler.leashConfigManager.getElasticDistance(), 0, ""); + return addLeash(context, CommonEventHandler.leashConfigManager.getMaxLeashLength(), CommonEventHandler.leashConfigManager.getElasticDistanceScale(), 0, ""); } private static int addLeash(CommandContext context, double maxDistance) throws CommandSyntaxException { - return addLeash(context, maxDistance, CommonEventHandler.leashConfigManager.getElasticDistance(), 0, ""); + return addLeash(context, maxDistance, CommonEventHandler.leashConfigManager.getElasticDistanceScale(), 0, ""); } private static int addLeash(CommandContext context, @@ -398,7 +399,7 @@ public class LeashDataCommand { CommandSourceStack source = context.getSource(); List successful = new ArrayList<>(), failed = new ArrayList<>(); for (Entity target : targets) { - if(LeashDataAPI.LeashOperations.attach(target, holder, maxDistance, elasticDistance, keepTicks, reserved)) { + if(LeashDataInnerAPI.LeashOperations.attach(target, holder, maxDistance, elasticDistance, keepTicks, reserved)) { successful.add(target); } else failed.add(target); } @@ -406,11 +407,11 @@ public class LeashDataCommand { return successful.size(); } private static int addBlockLeash(CommandContext context) throws CommandSyntaxException { - return addBlockLeash(context, CommonEventHandler.leashConfigManager.getMaxLeashLength(), CommonEventHandler.leashConfigManager.getElasticDistance(), 0, ""); + return addBlockLeash(context, CommonEventHandler.leashConfigManager.getMaxLeashLength(), CommonEventHandler.leashConfigManager.getElasticDistanceScale(), 0, ""); } private static int addBlockLeash(CommandContext context, double maxDistance) throws CommandSyntaxException { - return addBlockLeash(context, maxDistance, CommonEventHandler.leashConfigManager.getElasticDistance(), 0, ""); + return addBlockLeash(context, maxDistance, CommonEventHandler.leashConfigManager.getElasticDistanceScale(), 0, ""); } private static int addBlockLeash(CommandContext context, double maxDistance, double elasticDistance, int keepTicks) throws CommandSyntaxException { @@ -435,7 +436,7 @@ public class LeashDataCommand { } List successful = new ArrayList<>(), failed = new ArrayList<>(); for (Entity target : targets) { - if(LeashDataAPI.LeashOperations.attach(target, knotEntity, maxDistance, elasticDistance, keepTicks, reserved)) { + if(LeashDataInnerAPI.LeashOperations.attach(target, knotEntity, maxDistance, elasticDistance, keepTicks, reserved)) { successful.add(target); } else failed.add(target); } @@ -450,7 +451,7 @@ public class LeashDataCommand { int successCount = 0; for (Entity target : targets) { - boolean success = LeashDataAPI.LeashOperations.detach(target, holder); + boolean success = LeashDataInnerAPI.LeashOperations.detach(target, holder); if (success) { successCount++; @@ -472,7 +473,7 @@ public class LeashDataCommand { int successCount = 0; for (Entity target : targets) { - boolean success = LeashDataAPI.LeashOperations.detach(target, pos); + boolean success = LeashDataInnerAPI.LeashOperations.detach(target, pos); if (success) { successCount++; @@ -492,7 +493,7 @@ public class LeashDataCommand { CommandSourceStack source = context.getSource(); for (Entity target : targets) { - LeashDataAPI.LeashOperations.detachAll(target); + LeashDataInnerAPI.LeashOperations.detachAll(target); source.sendSuccess(() -> Component.literal("Removed all leashes from " + target.getName().getString()), false); } @@ -512,8 +513,8 @@ public class LeashDataCommand { for (Entity target : targets) { boolean success = reserved.isEmpty() ? - LeashDataAPI.TransferOperations.transfer(target, from, to) : - LeashDataAPI.TransferOperations.transfer(target, from, to, reserved); + LeashDataInnerAPI.TransferOperations.transfer(target, from, to) : + LeashDataInnerAPI.TransferOperations.transfer(target, from, to, reserved); if (success) { successCount++; @@ -532,7 +533,7 @@ public class LeashDataCommand { CommandSourceStack source = context.getSource(); for (Entity target : targets) { - LeashDataAPI.PhysicsOperations.applyForces(target); + LeashDataInnerAPI.PhysicsOperations.applyForces(target); source.sendSuccess(() -> Component.literal("Applied leash forces to " + target.getName().getString()), false); } diff --git a/src/main/java/top/r3944realms/superleadrope/content/entity/SuperLeashKnotEntity.java b/src/main/java/top/r3944realms/superleadrope/content/entity/SuperLeashKnotEntity.java index 765f91a..8f13555 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/entity/SuperLeashKnotEntity.java +++ b/src/main/java/top/r3944realms/superleadrope/content/entity/SuperLeashKnotEntity.java @@ -34,9 +34,9 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.phys.AABB; import org.jetbrains.annotations.NotNull; -import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; import top.r3944realms.superleadrope.core.register.SLPEntityTypes; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.Arrays; import java.util.List; @@ -81,9 +81,9 @@ public class SuperLeashKnotEntity extends LeashFenceKnotEntity { this.kill(); this.markHurt(); this.playSound(SoundEvents.LEASH_KNOT_BREAK); - List entities = LeashDataImpl.leashableInArea(this.level(), pos.getCenter(), entity -> LeashDataImpl.isLeashHolder(entity, this)); + List entities = SuperLeadRopeApi.leashableInArea(this.level(), pos.getCenter(), entity -> SuperLeadRopeApi.isLeashHolder(entity, this)); entities.forEach(entity -> - LeashDataAPI.getLeashData(entity) + LeashDataInnerAPI.getLeashData(entity) .map(iLeashDataCapability -> iLeashDataCapability.removeLeash(this)) ); } @@ -96,8 +96,8 @@ public class SuperLeashKnotEntity extends LeashFenceKnotEntity { public boolean survives() { boolean supportBlock = SuperLeashKnotEntity.isSupportBlock(this.level().getBlockState(this.pos)); if (!supportBlock) { - for (Entity entity : LeashDataImpl.leashableInArea(this)) { - LeashDataAPI.LeashOperations.detach(entity, this); + for (Entity entity : SuperLeadRopeApi.leashableInArea(this)) { + LeashDataInnerAPI.LeashOperations.detach(entity, this); } } return supportBlock; @@ -193,10 +193,10 @@ public class SuperLeashKnotEntity extends LeashFenceKnotEntity { return InteractionResult.SUCCESS; } AtomicBoolean isTransferLeash = new AtomicBoolean(false); - List entities = LeashDataImpl.leashableInArea(player); + List entities = SuperLeadRopeApi.leashableInArea(player); for(Entity entity : entities) { - if (LeashDataImpl.isLeashHolder(entity, player.getUUID())) - LeashDataAPI.getLeashData(entity) + if (SuperLeadRopeApi.isLeashHolder(entity, player.getUUID())) + LeashDataInnerAPI.getLeashData(entity) .ifPresent(i -> { i.transferLeash(player.getUUID(), this); isTransferLeash.set(true); @@ -207,9 +207,9 @@ public class SuperLeashKnotEntity extends LeashFenceKnotEntity { if (((ServerPlayer) player).gameMode.getGameModeForPlayer() != GameType.ADVENTURE) { this.playSound(SoundEvents.LEASH_KNOT_BREAK); this.discard(); - List entities1 = LeashDataImpl.leashableInArea(this); + List entities1 = SuperLeadRopeApi.leashableInArea(this); entities1.forEach(entity -> - LeashDataAPI.getLeashData(entity) + LeashDataInnerAPI.getLeashData(entity) .ifPresent(iLeashDataCapability -> { iLeashDataCapability.removeLeash(this); isRemoveLeashKnot.set(true); diff --git a/src/main/java/top/r3944realms/superleadrope/content/item/SuperLeadRopeItem.java b/src/main/java/top/r3944realms/superleadrope/content/item/SuperLeadRopeItem.java index f4341e2..e30f8d4 100644 --- a/src/main/java/top/r3944realms/superleadrope/content/item/SuperLeadRopeItem.java +++ b/src/main/java/top/r3944realms/superleadrope/content/item/SuperLeadRopeItem.java @@ -30,12 +30,12 @@ import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraftforge.common.extensions.IForgeItem; import org.jetbrains.annotations.NotNull; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; import top.r3944realms.superleadrope.content.SLPToolTier; -import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; import top.r3944realms.superleadrope.core.register.SLPSoundEvents; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.List; import java.util.Optional; @@ -121,13 +121,13 @@ public class SuperLeadRopeItem extends TieredItem implements IForgeItem { boolean isSuccess = false; // 查找当前玩家持有的可拴生物 - List list = LeashDataImpl.leashableInArea( + List list = SuperLeadRopeApi.leashableInArea( level, pos.getCenter(), - entity -> LeashDataImpl.isLeashHolder(entity, player.getUUID()) + entity -> SuperLeadRopeApi.isLeashHolder(entity, player.getUUID()) ); for (Entity e : list) { - Optional leashDataOpt = LeashDataAPI.getLeashData(e); + Optional leashDataOpt = LeashDataInnerAPI.getLeashData(e); if (leashDataOpt.map(i -> i.canBeAttachedTo(newHolder)).orElse(false)) { leashDataOpt.ifPresent(i -> i.transferLeash(player.getUUID(), newHolder)); @@ -170,8 +170,8 @@ public class SuperLeadRopeItem extends TieredItem implements IForgeItem { AtomicBoolean isSuccess = new AtomicBoolean(false); UUID uuid = player.getUUID(); - List list = LeashDataImpl.leashableInArea(level, pos.getCenter(), - entity -> LeashDataImpl.isLeashHolder(entity, uuid)); + List list = SuperLeadRopeApi.leashableInArea(level, pos.getCenter(), + entity -> SuperLeadRopeApi.isLeashHolder(entity, uuid)); // 情况一:拴自己到新 knot if (shouldBindSelf && list.isEmpty()) { @@ -182,7 +182,7 @@ public class SuperLeadRopeItem extends TieredItem implements IForgeItem { knot.playPlacementSound(); SuperLeashKnotEntity finalKnot = knot; - LeashDataAPI.getLeashData(player).ifPresent(i -> { + LeashDataInnerAPI.getLeashData(player).ifPresent(i -> { if (i.canBeAttachedTo(finalKnot)) { if (!level.isClientSide) i.addLeash(finalKnot); isSuccess.set(true); @@ -198,7 +198,7 @@ public class SuperLeadRopeItem extends TieredItem implements IForgeItem { } SuperLeashKnotEntity finalKnot = knot; - LeashDataAPI.getLeashData(e).ifPresent(i -> { + LeashDataInnerAPI.getLeashData(e).ifPresent(i -> { if (i.canBeAttachedTo(finalKnot)) { if (!level.isClientSide) i.transferLeash(uuid, finalKnot); isSuccess.set(true); diff --git a/src/main/java/top/r3944realms/superleadrope/core/hook/LeashRenderHook.java b/src/main/java/top/r3944realms/superleadrope/core/hook/LeashRenderHook.java index 6173335..7511fd1 100644 --- a/src/main/java/top/r3944realms/superleadrope/core/hook/LeashRenderHook.java +++ b/src/main/java/top/r3944realms/superleadrope/core/hook/LeashRenderHook.java @@ -19,7 +19,7 @@ import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Mob; import top.r3944realms.superleadrope.SuperLeadRope; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; @@ -28,7 +28,7 @@ public class LeashRenderHook { public static boolean shouldRenderExtra(Mob mob, Frustum camera) { SuperLeadRope.logger.debug("[SuperLeash] Checking entity: {} at position: {}, {}, {}", mob.getName().getString(), mob.getX(), mob.getY(), mob.getZ()); AtomicBoolean flag = new AtomicBoolean(false); - LeashDataAPI.getLeashData(mob).ifPresent(i -> { + LeashDataInnerAPI.getLeashData(mob).ifPresent(i -> { i.getAllLeashes().forEach(j -> { Optional i1 = j.holderIdOpt(); if (i1.isPresent()) { diff --git a/src/main/java/top/r3944realms/superleadrope/core/leash/LeashInteractHandler.java b/src/main/java/top/r3944realms/superleadrope/core/leash/LeashInteractHandler.java index 1f98b1f..d73e250 100644 --- a/src/main/java/top/r3944realms/superleadrope/core/leash/LeashInteractHandler.java +++ b/src/main/java/top/r3944realms/superleadrope/core/leash/LeashInteractHandler.java @@ -16,7 +16,6 @@ package top.r3944realms.superleadrope.core.leash; -import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.world.InteractionHand; @@ -28,12 +27,13 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraftforge.event.entity.player.AttackEntityEvent; import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; import top.r3944realms.superleadrope.content.item.SuperLeadRopeItem; import top.r3944realms.superleadrope.core.register.SLPItems; import top.r3944realms.superleadrope.core.register.SLPSoundEvents; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.Optional; @@ -61,7 +61,7 @@ public class LeashInteractHandler { if (!LeashDataImpl.isLeashable(target)) { return; } - Optional LeashCap = LeashDataAPI.getLeashData(target); + Optional LeashCap = LeashDataInnerAPI.getLeashData(target); if (LeashCap.isEmpty()) { return; } @@ -82,7 +82,7 @@ public class LeashInteractHandler { event.setCancellationResult(InteractionResult.SUCCESS); } } else { - if (LeashDataImpl.isLeashHolder(target, player)) { + if (SuperLeadRopeApi.isLeashHolder(target, player)) { LeashCap.ifPresent( iLeashDataCapability -> iLeashDataCapability.removeLeash(player.getUUID()) ); @@ -127,7 +127,7 @@ public class LeashInteractHandler { } } else { if (flag) { - LeashDataAPI.getLeashData(target).ifPresent(leashDataCapability -> { + LeashDataInnerAPI.getLeashData(target).ifPresent(leashDataCapability -> { if (leashDataCapability.hasLeash()){ int size = leashDataCapability.getAllLeashes().size(); if (player.isSecondaryUseActive()) diff --git a/src/main/java/top/r3944realms/superleadrope/core/leash/LeashSyncManager.java b/src/main/java/top/r3944realms/superleadrope/core/leash/LeashSyncManager.java index c34eace..01360cd 100644 --- a/src/main/java/top/r3944realms/superleadrope/core/leash/LeashSyncManager.java +++ b/src/main/java/top/r3944realms/superleadrope/core/leash/LeashSyncManager.java @@ -15,8 +15,8 @@ package top.r3944realms.superleadrope.core.leash; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; import java.util.Collections; import java.util.Set; diff --git a/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashDataSyncPacket.java b/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashDataSyncPacket.java index 990ff18..5eff45f 100644 --- a/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashDataSyncPacket.java +++ b/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashDataSyncPacket.java @@ -21,7 +21,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.Entity; import net.minecraftforge.network.NetworkEvent; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; import java.util.function.Supplier; @@ -42,7 +42,7 @@ public record LeashDataSyncPacket(int entityId, CompoundTag leashData) { if (level != null) { Entity entity = level.getEntity(msg.entityId); if (entity != null) { - LeashDataAPI.getLeashData(entity).ifPresent(cap -> { + LeashDataInnerAPI.getLeashData(entity).ifPresent(cap -> { // 只在数据确实变化时更新 CompoundTag current = cap.serializeNBT(); if (!current.equals(msg.leashData)) { diff --git a/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashStateSyncPacket.java b/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashStateSyncPacket.java index dd16ebf..322ae9b 100644 --- a/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashStateSyncPacket.java +++ b/src/main/java/top/r3944realms/superleadrope/network/toClient/LeashStateSyncPacket.java @@ -21,7 +21,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.world.entity.Entity; import net.minecraftforge.network.NetworkEvent; -import top.r3944realms.superleadrope.content.capability.CapabilityHandler; +import top.r3944realms.superleadrope.api.SLPCapability; import java.util.function.Supplier; @@ -41,7 +41,7 @@ public record LeashStateSyncPacket(int entityId, CompoundTag leashState) { if (level != null) { Entity entity = level.getEntity(msg.entityId); if (entity != null) { - entity.getCapability(CapabilityHandler.LEASH_STATE_CAP).ifPresent(cap -> { + entity.getCapability(SLPCapability.LEASH_STATE_CAP).ifPresent(cap -> { // 只在数据确实变化时更新 CompoundTag current = cap.serializeNBT(); if (!current.equals(msg.leashState)) { diff --git a/src/main/java/top/r3944realms/superleadrope/util/capability/LeashDataAPI.java b/src/main/java/top/r3944realms/superleadrope/util/capability/LeashDataInnerAPI.java similarity index 90% rename from src/main/java/top/r3944realms/superleadrope/util/capability/LeashDataAPI.java rename to src/main/java/top/r3944realms/superleadrope/util/capability/LeashDataInnerAPI.java index 020049b..bae4cce 100644 --- a/src/main/java/top/r3944realms/superleadrope/util/capability/LeashDataAPI.java +++ b/src/main/java/top/r3944realms/superleadrope/util/capability/LeashDataInnerAPI.java @@ -18,9 +18,11 @@ package top.r3944realms.superleadrope.util.capability; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import top.r3944realms.superleadrope.content.capability.CapabilityHandler; -import top.r3944realms.superleadrope.content.capability.inter.ILeashData; +import top.r3944realms.superleadrope.api.SLPCapability; +import top.r3944realms.superleadrope.api.type.capabilty.LeashInfo; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; import java.util.*; @@ -28,11 +30,12 @@ import java.util.*; * 拴绳数据API - 提供统一的API接口操作拴绳数据能力 */ @SuppressWarnings("unused") -public final class LeashDataAPI { +@ApiStatus.Internal +public final class LeashDataInnerAPI { // ==================== 基础能力获取 ==================== - public static Optional getLeashData(@NotNull Entity entity) { + public static @NotNull Optional getLeashData(@NotNull Entity entity) { Objects.requireNonNull(entity, "Entity cannot be null"); - return entity.getCapability(CapabilityHandler.LEASH_DATA_CAP).resolve(); + return entity.getCapability(SLPCapability.LEASH_DATA_CAP).resolve(); } // ==================== 拴绳数据管理 API ==================== @@ -64,7 +67,7 @@ public final class LeashDataAPI { return getLeashData(entity).map(data -> data.addLeash(holder, maxDistance, elasticDistance, maxKeepTicks, reserved)).orElse(false); } - public static void attachWithInfo(Entity entity, Entity holder, ILeashData.LeashInfo info) { + public static void attachWithInfo(Entity entity, Entity holder, LeashInfo info) { getLeashData(entity).ifPresent(data -> data.addLeash(holder, info)); } @@ -147,39 +150,39 @@ public final class LeashDataAPI { // ---------------------- 设置弹性距离 ---------------------- public static boolean setElasticDistance(Entity entity, Entity holder, double distance) { - return getLeashData(entity).map(data -> data.setElasticDistance(holder, distance)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(holder, distance)).orElse(false); } public static boolean setElasticDistance(Entity entity, Entity holder, double distance, int maxKeepTicks) { - return getLeashData(entity).map(data -> data.setElasticDistance(holder, distance, maxKeepTicks)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(holder, distance, maxKeepTicks)).orElse(false); } public static boolean setElasticDistance(Entity entity, Entity holder, double distance, int maxKeepTicks, String reserved) { - return getLeashData(entity).map(data -> data.setElasticDistance(holder, distance, maxKeepTicks, reserved)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(holder, distance, maxKeepTicks, reserved)).orElse(false); } public static boolean setElasticDistance(Entity entity, UUID holderUUID, double distance) { - return getLeashData(entity).map(data -> data.setElasticDistance(holderUUID, distance)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(holderUUID, distance)).orElse(false); } public static boolean setElasticDistance(Entity entity, UUID holderUUID, double distance, int maxKeepTicks) { - return getLeashData(entity).map(data -> data.setElasticDistance(holderUUID, distance, maxKeepTicks)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(holderUUID, distance, maxKeepTicks)).orElse(false); } public static boolean setElasticDistance(Entity entity, UUID holderUUID, double distance, int maxKeepTicks, String reserved) { - return getLeashData(entity).map(data -> data.setElasticDistance(holderUUID, distance, maxKeepTicks, reserved)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(holderUUID, distance, maxKeepTicks, reserved)).orElse(false); } public static boolean setElasticDistance(Entity entity, BlockPos knotPos, double distance) { - return getLeashData(entity).map(data -> data.setElasticDistance(knotPos, distance)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(knotPos, distance)).orElse(false); } public static boolean setElasticDistance(Entity entity, BlockPos knotPos, double distance, int maxKeepTicks) { - return getLeashData(entity).map(data -> data.setElasticDistance(knotPos, distance, maxKeepTicks)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(knotPos, distance, maxKeepTicks)).orElse(false); } public static boolean setElasticDistance(Entity entity, BlockPos knotPos, double distance, int maxKeepTicks, String reserved) { - return getLeashData(entity).map(data -> data.setElasticDistance(knotPos, distance, maxKeepTicks, reserved)).orElse(false); + return getLeashData(entity).map(data -> data.setElasticDistanceScale(knotPos, distance, maxKeepTicks, reserved)).orElse(false); } } @@ -240,7 +243,7 @@ public final class LeashDataAPI { return getLeashData(entity).map(ILeashData::hasHolderLeash).orElse(false); } - public static Collection getAllLeashes(Entity entity) { + public static Collection getAllLeashes(Entity entity) { return getLeashData(entity).map(ILeashData::getAllLeashes).orElse(Collections.emptyList()); } @@ -260,15 +263,15 @@ public final class LeashDataAPI { return getLeashData(entity).map(data -> data.isInDelayedLeash(holderUUID)).orElse(false); } - public static Optional getLeashInfo(Entity entity, Entity holder) { + public static Optional getLeashInfo(Entity entity, Entity holder) { return getLeashData(entity).flatMap(data -> data.getLeashInfo(holder)); } - public static Optional getLeashInfo(Entity entity, UUID holderUUID) { + public static Optional getLeashInfo(Entity entity, UUID holderUUID) { return getLeashData(entity).flatMap(data -> data.getLeashInfo(holderUUID)); } - public static Optional getLeashInfo(Entity entity, BlockPos knotPos) { + public static Optional getLeashInfo(Entity entity, BlockPos knotPos) { return getLeashData(entity).flatMap(data -> data.getLeashInfo(knotPos)); } diff --git a/src/main/java/top/r3944realms/superleadrope/util/capability/LeashStateAPI.java b/src/main/java/top/r3944realms/superleadrope/util/capability/LeashStateInnerAPI.java similarity index 96% rename from src/main/java/top/r3944realms/superleadrope/util/capability/LeashStateAPI.java rename to src/main/java/top/r3944realms/superleadrope/util/capability/LeashStateInnerAPI.java index d362395..ac2fd54 100644 --- a/src/main/java/top/r3944realms/superleadrope/util/capability/LeashStateAPI.java +++ b/src/main/java/top/r3944realms/superleadrope/util/capability/LeashStateInnerAPI.java @@ -18,9 +18,10 @@ package top.r3944realms.superleadrope.util.capability; import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; -import top.r3944realms.superleadrope.content.capability.CapabilityHandler; -import top.r3944realms.superleadrope.content.capability.inter.ILeashState; +import top.r3944realms.superleadrope.api.SLPCapability; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashState; import java.util.Map; import java.util.Objects; @@ -28,14 +29,15 @@ import java.util.Optional; import java.util.UUID; @SuppressWarnings("unused") -public final class LeashStateAPI { +@ApiStatus.Internal +public final class LeashStateInnerAPI { - private LeashStateAPI() { + private LeashStateInnerAPI() { } // 防止实例化 - public static Optional getLeashState(@NotNull Entity entity) { + public static @NotNull Optional getLeashState(@NotNull Entity entity) { Objects.requireNonNull(entity, "Entity cannot be null"); - return entity.getCapability(CapabilityHandler.LEASH_STATE_CAP).resolve(); + return entity.getCapability(SLPCapability.LEASH_STATE_CAP).resolve(); } // ==================== 查询操作 ==================== diff --git a/src/main/java/top/r3944realms/superleadrope/util/file/ConfigUtil.java b/src/main/java/top/r3944realms/superleadrope/util/file/ConfigUtil.java index 29aac66..2bb9f30 100644 --- a/src/main/java/top/r3944realms/superleadrope/util/file/ConfigUtil.java +++ b/src/main/java/top/r3944realms/superleadrope/util/file/ConfigUtil.java @@ -19,6 +19,7 @@ import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.config.ModConfig; import net.minecraftforge.fml.loading.FMLPaths; +import org.jetbrains.annotations.NotNull; import top.r3944realms.superleadrope.SuperLeadRope; import java.io.File; @@ -48,7 +49,7 @@ public class ConfigUtil { } public static void registerConfig ( - ModLoadingContext context, + @NotNull ModLoadingContext context, ModConfig.Type type, ForgeConfigSpec configSpec, String folderName, diff --git a/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTReader.java b/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTReader.java index 98989e4..c51c238 100644 --- a/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTReader.java +++ b/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTReader.java @@ -19,6 +19,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.phys.Vec3; public class NBTReader { + private NBTReader() {} public static Vec3 readVec3(CompoundTag nbt) { if (nbt.contains("X") && nbt.contains("Y") && nbt.contains("Z")) { return new Vec3( diff --git a/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTWriter.java b/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTWriter.java index 83ae6f2..a3284b2 100644 --- a/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTWriter.java +++ b/src/main/java/top/r3944realms/superleadrope/util/nbt/NBTWriter.java @@ -19,6 +19,7 @@ import net.minecraft.nbt.CompoundTag; import net.minecraft.world.phys.Vec3; public class NBTWriter { + private NBTWriter() {} public static CompoundTag writeVec3(Vec3 vec) { CompoundTag nbt = new CompoundTag(); if (vec == null) throw new IllegalArgumentException("Vec3 cannot be null"); diff --git a/src/main/java/top/r3944realms/superleadrope/util/riding/RindingLeash.java b/src/main/java/top/r3944realms/superleadrope/util/riding/RindingLeash.java index 8750ed3..a543611 100644 --- a/src/main/java/top/r3944realms/superleadrope/util/riding/RindingLeash.java +++ b/src/main/java/top/r3944realms/superleadrope/util/riding/RindingLeash.java @@ -17,7 +17,6 @@ package top.r3944realms.superleadrope.util.riding; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.goal.Goal; import net.minecraft.world.entity.animal.Animal; import net.minecraft.world.phys.Vec3; diff --git a/src/main/java/top/r3944realms/superleadrope/workspace/LeashHelper.java b/src/main/java/top/r3944realms/superleadrope/workspace/LeashHelper.java new file mode 100644 index 0000000..05a5e5e --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/workspace/LeashHelper.java @@ -0,0 +1,74 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.workspace; + +import net.minecraft.world.entity.Entity; +import top.r3944realms.superleadrope.CommonEventHandler; +import top.r3944realms.superleadrope.api.SLPCapability; +import top.r3944realms.superleadrope.api.SuperLeadRopeApi; +import top.r3944realms.superleadrope.api.type.capabilty.ILeashData; +import top.r3944realms.superleadrope.api.type.util.ILeashHelper; +import top.r3944realms.superleadrope.util.capability.LeashDataInnerAPI; + +import java.util.Optional; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class LeashHelper implements ILeashHelper { + @Override + public IHolder getHolderHelper(Entity holder) { + return new IHolder() { + @Override + public Entity getHolderEntity() { + return holder; + } + + @Override + public Set getAllLeashData() { + return SuperLeadRopeApi.leashableInArea(getHolderEntity()) + .stream() + .map(i -> i.getCapability(SLPCapability.LEASH_DATA_CAP).resolve()) + .filter(Optional::isPresent) + .map(Optional::get) + .collect(Collectors.toSet()); + } + + @Override + public boolean leashEntity(UUID uuid) { + Entity entity = CommonEventHandler.Game.getServerLevel().getEntity(uuid); + if (entity != null && SuperLeadRopeApi.isLeashable(entity)) { + return LeashDataInnerAPI.getLeashData(entity).map(i-> i.addLeash(entity)).orElse(false); + } + return false; + } + + @Override + public boolean unleashEntity(UUID uuid) { + Entity entity = CommonEventHandler.Game.getServerLevel().getEntity(uuid); + if (entity != null && SuperLeadRopeApi.isLeashable(entity)) { + return LeashDataInnerAPI.getLeashData(entity).map(i-> i.removeLeash(entity)).orElse(false); + } + return false; + } + }; + } + + @Override + public ILeashed getLeashedHelper(Entity leashed) { + return () -> LeashDataInnerAPI.getLeashData(leashed).orElseThrow(); + } +} diff --git a/src/main/java/top/r3944realms/superleadrope/workspace/WorkSpaceHelper.java b/src/main/java/top/r3944realms/superleadrope/workspace/WorkSpaceHelper.java new file mode 100644 index 0000000..59a24d8 --- /dev/null +++ b/src/main/java/top/r3944realms/superleadrope/workspace/WorkSpaceHelper.java @@ -0,0 +1,62 @@ +/* + * Super Lead rope mod + * Copyright (C) 2025 R3944Realms + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package top.r3944realms.superleadrope.workspace; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; +import top.r3944realms.superleadrope.api.type.util.ILeashHelper; +import top.r3944realms.superleadrope.api.workspace.IWorkSpaceHelper; +import top.r3944realms.superleadrope.content.capability.impi.LeashDataImpl; +import top.r3944realms.superleadrope.content.entity.SuperLeashKnotEntity; + +import java.util.List; +import java.util.function.Predicate; + +public class WorkSpaceHelper implements IWorkSpaceHelper { + @Override + public @NotNull List leashableInArea(@NotNull Level pLevel, Vec3 pPos, Predicate filter, double fetchDistance) { + AABB box = AABB.ofSize(pPos, fetchDistance, fetchDistance, fetchDistance); + return pLevel.getEntitiesOfClass(Entity.class, box, e -> LeashDataImpl.isLeashable(e) && filter.test(e)); + } + + @Override + public ILeashHelper getLeashHelper() { + return new LeashHelper(); + } + + @Override + public boolean isSuperLeadKnot(Entity pEntity) { + return pEntity instanceof SuperLeashKnotEntity; + } + + @Override + public BlockPos getSuperLeadPos(Entity pEntity) throws IllegalArgumentException { + if (isSuperLeadKnot(pEntity)) { + return (((SuperLeashKnotEntity) pEntity).getPos()); + } + else throw new IllegalArgumentException(pEntity.getClass().getName() + " is not a superlead knot"); + } + + @Override + public boolean isLeashable(@NotNull Entity pEntity) { + return LeashDataImpl.isLeashable(pEntity); + } + +} diff --git a/src/main/resources/META-INF/services/top.r3944realms.superleadrope.api.workspace.IWorkSpaceHelper b/src/main/resources/META-INF/services/top.r3944realms.superleadrope.api.workspace.IWorkSpaceHelper new file mode 100644 index 0000000..18a0109 --- /dev/null +++ b/src/main/resources/META-INF/services/top.r3944realms.superleadrope.api.workspace.IWorkSpaceHelper @@ -0,0 +1 @@ +top.r3944realms.superleadrope.workspace.WorkSpaceHelper \ No newline at end of file diff --git a/src/test/java/top/r3944realms/superleadropetest/Placeholder.java b/src/test/java/top/r3944realms/superleadropetest/Placeholder.java index 537557d..efffa56 100644 --- a/src/test/java/top/r3944realms/superleadropetest/Placeholder.java +++ b/src/test/java/top/r3944realms/superleadropetest/Placeholder.java @@ -15,8 +15,6 @@ package top.r3944realms.superleadropetest; -import top.r3944realms.superleadrope.util.capability.LeashDataAPI; - public class Placeholder { }