diff --git a/build.gradle b/build.gradle index 3100a71..6a0b807 100644 --- a/build.gradle +++ b/build.gradle @@ -115,6 +115,10 @@ repositories { name = "Illusive Soulworks maven" url = "https://maven.theillusivec4.top/" } + maven { + name = "LTD Maven" + url = "https://nexus.bot.leisuretimedock.top/repository/maven-public/" + } } jarJar.enable() @@ -130,10 +134,7 @@ dependencies { implementation fg.deobf("dev.kosmx.player-anim:player-animation-lib-forge:1.0.2-rc1+1.20") implementation fg.deobf("io.github.kosmx.bendy-lib:bendy-lib-forge:4.0.0") - -// implementation fg.deobf("curse.maven:cloth-config-348521:5729105") -// implementation fg.deobf("curse.maven:better-combat-by-daedelus-639842:5625757") -// implementation fg.deobf("curse.maven:freecam-by-zergatul-618947:5402097") + implementation("io.zershyan:sccore:1.20.1-1.0.0") } tasks.named('processResources', ProcessResources).configure { @@ -151,6 +152,7 @@ tasks.named('processResources', ProcessResources).configure { mod_description: mod_description, mod_credits: mod_credits, mod_url: mod_url, + sccore_verson: sccore_verson ] inputs.properties replaceProperties diff --git a/gradle.properties b/gradle.properties index 6e2d71e..94bc71d 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,9 +12,10 @@ mapping_version=2023.09.03-1.20.1 mod_id=animcore mod_name=AnimationCore mod_license=GPL 3.0 -mod_version=1.20.1-26H4 +mod_version=1.20.1-26H7 mod_group_id=top.leisuiretimedock.animationcore -mod_authors=LostInLinearPast, R3944Realms -mod_description=A lib about player animator(modified by R3944Realms). +sccore_verson=1.0.0 +mod_authors=R3944Realms +mod_description= mod_credits= -mod_url=https://github.com/LeisureTimeDock/AnimCore +mod_url=https://github.com/LeisureTimeDock/AnimationCore diff --git a/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac b/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac deleted file mode 100644 index cda856c..0000000 --- a/src/generated/resources/.cache/2a65ee2815744be1ef1ffdae1c9a37f2a9cbe2ac +++ /dev/null @@ -1,2 +0,0 @@ -// 1.20.1 2026-01-13T10:48:06.5809965 Languages: zh_cn -28620aef6acf68c887244c604393f326e8d7a2ef assets/animcore/lang/zh_cn.json diff --git a/src/generated/resources/.cache/7f03ba6e657d7cfe0009cfdf678b3b794c6aaf37 b/src/generated/resources/.cache/7f03ba6e657d7cfe0009cfdf678b3b794c6aaf37 deleted file mode 100644 index fcdaac7..0000000 --- a/src/generated/resources/.cache/7f03ba6e657d7cfe0009cfdf678b3b794c6aaf37 +++ /dev/null @@ -1,2 +0,0 @@ -// 1.20.1 2026-01-13T10:48:06.5779981 Animation Layer Data: animcore -643d9b82415b5fbac109dcfb4476752f16363326 data/animcore/ac_animations/animation.layer.json diff --git a/src/generated/resources/.cache/8d4a9f2e2cfb72704a9beb2c8fd13d8c15f78bd2 b/src/generated/resources/.cache/8d4a9f2e2cfb72704a9beb2c8fd13d8c15f78bd2 deleted file mode 100644 index 48e07bf..0000000 --- a/src/generated/resources/.cache/8d4a9f2e2cfb72704a9beb2c8fd13d8c15f78bd2 +++ /dev/null @@ -1,3 +0,0 @@ -// 1.20.1 2026-01-13T10:48:06.5819961 Animations: animcore -730671616cc7fa1e8763c64f8cdcf5ce981583d2 data/animcore/ac_animations/waltz_gentleman.anim.json -ea25ceb6798cd833d1b613517e5016df989b4d40 data/animcore/ac_animations/waltz_lady.anim.json diff --git a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 b/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 deleted file mode 100644 index d6126d0..0000000 --- a/src/generated/resources/.cache/c622617f6fabf890a00b9275cd5f643584a8a2c8 +++ /dev/null @@ -1,2 +0,0 @@ -// 1.20.1 2026-01-13T10:48:06.5829971 Languages: en_us -12951874f3a152154b6a388d367095c1bb30d2b3 assets/animcore/lang/en_us.json diff --git a/src/generated/resources/assets/animcore/lang/en_us.json b/src/generated/resources/assets/animcore/lang/en_us.json deleted file mode 100644 index 806122c..0000000 --- a/src/generated/resources/assets/animcore/lang/en_us.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "translation.animcore.command.animation.accept_apply_success": "%s has accepted the application of %s.", - "translation.animcore.command.animation.accept_invite_success": "Invitation accepted.", - "translation.animcore.command.animation.accept_message_click": "Click here to accept.", - "translation.animcore.command.animation.accept_request_success": "Request accepted.", - "translation.animcore.command.animation.animation_cooldown": "You cannot perform this operation: Cooling down (%s second(s)).", - "translation.animcore.command.animation.animation_expire": "You cannot perform this operation: It has expired.", - "translation.animcore.command.animation.animation_json_path": "%s", - "translation.animcore.command.animation.animation_operation_cancelled": "Exception: Operation cancelled.", - "translation.animcore.command.animation.animation_operation_unsupported": "Error: Unsupported operation.", - "translation.animcore.command.animation.animation_out_range": "You cannot perform this operation: The distance is not within %s blocks.", - "translation.animcore.command.animation.animation_resource_not_found": "Error: Resource not found, please check if there are any errors in the resource or operation : %s", - "translation.animcore.command.animation.animation_to_json": "The animation %s has been stored in the path on %s:", - "translation.animcore.command.animation.applied_join_message": "%S§b§l Apply for §r to join your animation. ", - "translation.animcore.command.animation.apply_join_message": "Application sent.", - "translation.animcore.command.animation.apply_success": "%s has accepted your animation application.", - "translation.animcore.command.animation.clear_animations": "Animation cleared.", - "translation.animcore.command.animation.command_run_fail": "Command run fail.", - "translation.animcore.command.animation.command_run_success": "Command run success.", - "translation.animcore.command.animation.invite_message": "Invitation sent.", - "translation.animcore.command.animation.invite_success": "%s has accepted your animation invitation.", - "translation.animcore.command.animation.invited_message": "%s§c§l invites§r you to animation: %s. ", - "translation.animcore.command.animation.list_animation_resource": "The %2$s on %1$s has : %s", - "translation.animcore.command.animation.play_animation_fail": "Fail to play animation with: %s", - "translation.animcore.command.animation.play_animation_success": "Successfully played animation on %s player(s).", - "translation.animcore.command.animation.refresh_animations": "Animation refreshed.", - "translation.animcore.command.animation.remove_animation_fail": "Fail to remove animation with: %s", - "translation.animcore.command.animation.remove_animation_success": "Successfully removed animation on %s player(s).", - "translation.animcore.command.animation.request_message": "Request sent.", - "translation.animcore.command.animation.request_success": "%s has accepted your animation request.", - "translation.animcore.command.animation.requested_message": "%s§d§l requests§r you to animation: %s. " -} \ No newline at end of file diff --git a/src/generated/resources/assets/animcore/lang/zh_cn.json b/src/generated/resources/assets/animcore/lang/zh_cn.json deleted file mode 100644 index 8bb8f92..0000000 --- a/src/generated/resources/assets/animcore/lang/zh_cn.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "translation.animcore.command.animation.accept_apply_success": "%s 接受了 %s 的申请。", - "translation.animcore.command.animation.accept_invite_success": "已接受邀请。", - "translation.animcore.command.animation.accept_message_click": "单击此处同意。", - "translation.animcore.command.animation.accept_request_success": "已接受请求。", - "translation.animcore.command.animation.animation_cooldown": "你不能执行该操作: 冷却中(%s秒)。", - "translation.animcore.command.animation.animation_expire": "你不能执行该操作: 已过期。", - "translation.animcore.command.animation.animation_json_path": "%s", - "translation.animcore.command.animation.animation_operation_cancelled": "异常: 操作被取消。", - "translation.animcore.command.animation.animation_operation_unsupported": "错误: 不支持这样做。", - "translation.animcore.command.animation.animation_out_range": "你不能执行该操作: 距离不在%s格以内。", - "translation.animcore.command.animation.animation_resource_not_found": "错误: 资源未找到,请检查资源或操作是否有误: %s", - "translation.animcore.command.animation.animation_to_json": "动画%s已经存储到%s路径:", - "translation.animcore.command.animation.applied_join_message": "%s§b§l 申请§r加入动画。", - "translation.animcore.command.animation.apply_join_message": "已发送申请。", - "translation.animcore.command.animation.apply_success": "%s 接受了你的动画申请。", - "translation.animcore.command.animation.clear_animations": "动画已清除。", - "translation.animcore.command.animation.command_run_fail": "命令执行失败。", - "translation.animcore.command.animation.command_run_success": "命令执行成功。", - "translation.animcore.command.animation.invite_message": "已发送邀请。", - "translation.animcore.command.animation.invite_success": "%s 接受了你的动画邀请。", - "translation.animcore.command.animation.invited_message": "%s§c§l 邀请§r你进行动画:%s。", - "translation.animcore.command.animation.list_animation_resource": "%s侧的%s有:%s", - "translation.animcore.command.animation.play_animation_fail": "在这些玩家上播放动画失败:%s", - "translation.animcore.command.animation.play_animation_success": "在%s个玩家上播放动画成功。", - "translation.animcore.command.animation.refresh_animations": "动画同步状态已刷新。", - "translation.animcore.command.animation.remove_animation_fail": "在这些玩家上移除动画失败:%s", - "translation.animcore.command.animation.remove_animation_success": "在%s个玩家上移除动画成功。", - "translation.animcore.command.animation.request_message": "已发送请求。", - "translation.animcore.command.animation.request_success": "%s 接受了你的动画请求。", - "translation.animcore.command.animation.requested_message": "%s§d§l 请求§r你进行动画:%s。" -} \ No newline at end of file diff --git a/src/generated/resources/data/animcore/ac_animations/animation.layer.json b/src/generated/resources/data/animcore/ac_animations/animation.layer.json deleted file mode 100644 index 9344877..0000000 --- a/src/generated/resources/data/animcore/ac_animations/animation.layer.json +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "key": "animcore:normal_layers", - "priority": 42 - } -] \ No newline at end of file diff --git a/src/generated/resources/data/animcore/ac_animations/waltz_gentleman.anim.json b/src/generated/resources/data/animcore/ac_animations/waltz_gentleman.anim.json deleted file mode 100644 index 9caeb0c..0000000 --- a/src/generated/resources/data/animcore/ac_animations/waltz_gentleman.anim.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "camPosOffset": { - "relative": true, - "x": 0.0, - "y": 0.0, - "z": 1.0 - }, - "heightModifier": 1.0, - "key": "animcore:waltz_gentleman", - "name": "Waltz-Gentleman", - "priority": 0, - "withRide": { - "componentsAnimation": [ - "animcore:waltz_lady" - ], - "existTick": 0, - "offset": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "xRot": 0.0, - "yRot": 0.0 - } -} \ No newline at end of file diff --git a/src/generated/resources/data/animcore/ac_animations/waltz_lady.anim.json b/src/generated/resources/data/animcore/ac_animations/waltz_lady.anim.json deleted file mode 100644 index 7dc0c2b..0000000 --- a/src/generated/resources/data/animcore/ac_animations/waltz_lady.anim.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "camYaw": 180.0, - "heightModifier": 1.0, - "key": "animcore:waltz_lady", - "name": "Waltz-Lady", - "priority": 0, - "withRide": { - "componentsAnimation": [ - "animcore:waltz_gentleman" - ], - "existTick": 0, - "offset": { - "x": 0.0, - "y": 0.0, - "z": 0.0 - }, - "xRot": 0.0, - "yRot": 0.0 - } -} \ No newline at end of file diff --git a/src/main/java/top/leisuretimedock/animationcore/AnimationCore.java b/src/main/java/top/leisuretimedock/animationcore/AnimationCore.java index cc99d22..81eba2b 100644 --- a/src/main/java/top/leisuretimedock/animationcore/AnimationCore.java +++ b/src/main/java/top/leisuretimedock/animationcore/AnimationCore.java @@ -16,46 +16,29 @@ package top.leisuretimedock.animationcore; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.core.ModChannel; -import top.leisuretimedock.animationcore.core.ModCommands; -import top.leisuretimedock.animationcore.core.configs.ModConfigs; -import top.leisuretimedock.animationcore.example.animation.ModAnimation; -import top.leisuretimedock.animationcore.example.capability.ModCapability; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.ModLoadingContext; +import net.minecraftforge.event.AddReloadListenerEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.config.ModConfig; -import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; -import net.minecraftforge.fml.loading.FMLEnvironment; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import top.leisuretimedock.animationcore.animation.AnimationDataManager; +import top.leisuretimedock.animationcore.animation.LayerDataManager; @Mod(AnimationCore.MOD_ID) public class AnimationCore { - public static final Logger log = LoggerFactory.getLogger(AnimationCore.class); + public static final Logger LOGGER = LoggerFactory.getLogger(AnimationCore.class); public static final String MOD_ID = "animcore"; - public static final String ENABLE_EXAMPLES_PROPERTY_KEY = "animcore.enable_examples"; public AnimationCore() { - ModLoadingContext modLoadingContext = ModLoadingContext.get(); - modLoadingContext.registerConfig(ModConfig.Type.SERVER, ModConfigs.Server.SPEC); - - IEventBus modBus = FMLJavaModLoadingContext.get().getModEventBus(); - IEventBus forgeBus = MinecraftForge.EVENT_BUS; - - CapabilityUtils.registerHandler(forgeBus); - ModChannel.register(); - IAnimationService.register(forgeBus, modBus); - ModCommands.registerCommands(forgeBus, modBus); - - if(!FMLEnvironment.production || Boolean.getBoolean(ENABLE_EXAMPLES_PROPERTY_KEY)) { - ModCapability.register(); - ModCapability.addListenerToEvent(forgeBus); - ModAnimation.register(forgeBus, modBus); - } + LOGGER.info("Loading Animation Core"); } + @Mod.EventBusSubscriber(modid = MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) + public static class CommonGame { + @SubscribeEvent + public static void onAddReloadListeners(AddReloadListenerEvent event) { + event.addListener(AnimationDataManager.INSTANCE); + event.addListener(LayerDataManager.INSTANCE); + } + } } diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/AnimationApi.java b/src/main/java/top/leisuretimedock/animationcore/animation/AnimationApi.java deleted file mode 100644 index f19137d..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/AnimationApi.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation; - -import top.leisuretimedock.animationcore.animation.helper.AnimationDataHelper; -import top.leisuretimedock.animationcore.animation.helper.AnimationHelper; -import top.leisuretimedock.animationcore.animation.helper.AnimationJsonHelper; -import top.leisuretimedock.animationcore.animation.helper.AnimationServiceGetterHelper; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.entity.player.Player; - -public class AnimationApi { - public static AnimationJsonHelper getJsonHelper(MinecraftServer server) { - return AnimationJsonHelper.getHelper(server); - } - - public static AnimationDataHelper getDataHelper() { - return AnimationDataHelper.getHelper(); - } - - public static AnimationServiceGetterHelper getServiceGetterHelper(ResourceLocation location) { - return new AnimationServiceGetterHelper(location); - } - - public static AnimationServiceGetterHelper getServiceGetterHelper() { - return new AnimationServiceGetterHelper(); - } - - public static AnimationHelper getHelper(Player player) { - return AnimationHelper.getHelper(player); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/AnimationDataBuilder.java b/src/main/java/top/leisuretimedock/animationcore/animation/AnimationDataBuilder.java similarity index 93% rename from src/main/java/top/leisuretimedock/animationcore/animation/data/AnimationDataBuilder.java rename to src/main/java/top/leisuretimedock/animationcore/animation/AnimationDataBuilder.java index 4e14b98..70f3724 100644 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/AnimationDataBuilder.java +++ b/src/main/java/top/leisuretimedock/animationcore/animation/AnimationDataBuilder.java @@ -13,8 +13,12 @@ * along with this program. If not, see . */ -package top.leisuretimedock.animationcore.animation.data; +package top.leisuretimedock.animationcore.animation; +import io.zershyan.sccore.animation.data.AnimationData; +import io.zershyan.sccore.animation.data.GenericAnimationData; +import io.zershyan.sccore.animation.data.RawAnimationData; +import io.zershyan.sccore.animation.data.Ride; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; @@ -260,24 +264,23 @@ public class AnimationDataBuilder { AnimationData animationData; if (isGeneric) { - GenericAnimationData genericData = new GenericAnimationData(key); - genericData.heightModifier = heightModifier; - genericData.name = genericName; - animationData = genericData; + animationData = GenericAnimationData.create(key) + .withHeightModifier(heightModifier) + .withName(genericName); } else { - animationData = new RawAnimationData(key); + animationData = RawAnimationData.create(key); } // Apply common properties - animationData.camYaw = camYaw; - animationData.camPitch = camPitch; - animationData.camRoll = camRoll; - animationData.camComputePriority = camComputePriority; - animationData.setCamPosOffset(camPosOffset); - animationData.camPosOffsetRelative = camPosOffsetRelative; - animationData.setLyingType(lyingType); - animationData.ride = ride; - + animationData + .withCamYaw(camYaw) + .withCamPitch(camPitch) + .withCamRoll(camRoll) + .withCamComputePriority(camComputePriority) + .setCamPosOffset(camPosOffset) + .withCamPosOffsetRelative(camPosOffsetRelative) + .withRide(ride) + .setLyingType(lyingType); // Apply post-build actions for (Consumer action : postBuildActions) { action.accept(animationData); diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/AnimationDataManager.java b/src/main/java/top/leisuretimedock/animationcore/animation/AnimationDataManager.java new file mode 100644 index 0000000..6d5e8c4 --- /dev/null +++ b/src/main/java/top/leisuretimedock/animationcore/animation/AnimationDataManager.java @@ -0,0 +1,113 @@ +/* + * Anim Core mod + * Copyright (C) 2026 LeisureTimeDock + * 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.leisuretimedock.animationcore.animation; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import io.zershyan.sccore.animation.data.AnimationData; +import io.zershyan.sccore.animation.data.GenericAnimationData; +import io.zershyan.sccore.animation.data.util.AnimJson; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.GsonHelper; +import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; +import top.leisuretimedock.animationcore.AnimationCore; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +public class AnimationDataManager extends SimpleJsonResourceReloadListener { + public static final AnimationDataManager INSTANCE = new AnimationDataManager(); + public static final Map ANIMATIONS = new LinkedHashMap<>(); + private AnimationDataManager() { + super(new GsonBuilder() + .setPrettyPrinting() + .disableHtmlEscaping() + .create(), "ac_animations"); + } + + @Override + protected void apply(@NotNull Map resources, + @NotNull ResourceManager resourceManager, + @NotNull ProfilerFiller profiler) { + ANIMATIONS.clear(); + AnimationCore.LOGGER.info("Loading animations from data packs..."); + + Map sorted = new LinkedHashMap<>(); + + // Sort resources by priority + resourceManager.listPacks().forEach(packResources -> { + Set namespaces = packResources.getNamespaces(PackType.SERVER_DATA); + namespaces.forEach(namespace -> + packResources.listResources(PackType.SERVER_DATA, namespace, "ac_animations", + (resourceLocation, inputStreamIoSupplier) -> { + String path = resourceLocation.getPath(); + if (path.endsWith(".anim.json")) { + ResourceLocation rl = new ResourceLocation(namespace, + path.substring("ac_animations/".length(), path.length() - ".json".length())); + + JsonElement el = resources.get(rl); + if (el != null) { + rl = new ResourceLocation(namespace, + path.substring("ac_animations/".length(), path.length() - ".anim.json".length())); + sorted.put(rl, el); + } + } + } + ) + ); + }); + + int loadedCount = 0; + for (Map.Entry entry : sorted.entrySet()) { + ResourceLocation animKey = entry.getKey(); + + try { + JsonObject json = GsonHelper.convertToJsonObject(entry.getValue(), "animation"); + + // Parse animation using existing AnimJson.Reader + AnimJson.Reader animReader = AnimJson.Reader.stream(json); + GenericAnimationData anim = animReader.parse(); + + // Ensure the key matches + if (!anim.getKey().equals(animKey)) { + AnimationCore.LOGGER.warn("Animation key mismatch: file={}, expected={}, actual={}", + entry.getKey(), animKey, anim.getKey()); + anim = anim.withName(animKey.getPath()); // Create a copy with correct key if possible + } + + registerAnimation(animKey, anim); + loadedCount++; + AnimationCore.LOGGER.debug("Loaded animation: {} -> {}", animKey, anim.getName()); + + } catch (IllegalArgumentException | JsonParseException e) { + AnimationCore.LOGGER.error("Parsing error loading animation {}", animKey, e); + } + } + + AnimationCore.LOGGER.info("Loaded {} animations from data packs", loadedCount); + } + + public static void registerAnimation(ResourceLocation key, GenericAnimationData animation) { + ANIMATIONS.put(key, animation); + } +} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/LayerDataManager.java b/src/main/java/top/leisuretimedock/animationcore/animation/LayerDataManager.java new file mode 100644 index 0000000..3cb14b8 --- /dev/null +++ b/src/main/java/top/leisuretimedock/animationcore/animation/LayerDataManager.java @@ -0,0 +1,114 @@ +/* + * Anim Core mod + * Copyright (C) 2026 LeisureTimeDock + * 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.leisuretimedock.animationcore.animation; + +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import io.zershyan.sccore.animation.data.util.AnimLayerJson; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.PackType; +import net.minecraft.server.packs.resources.ResourceManager; +import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; +import net.minecraft.util.profiling.ProfilerFiller; +import org.jetbrains.annotations.NotNull; +import top.leisuretimedock.animationcore.AnimationCore; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Set; + +public class LayerDataManager extends SimpleJsonResourceReloadListener { + public static final LayerDataManager INSTANCE = new LayerDataManager(); + public static final Map LAYERS = new LinkedHashMap<>(); + + private LayerDataManager() { + super(new GsonBuilder() + .setPrettyPrinting() + .disableHtmlEscaping() + .create(), "ac_animations"); + } + + @Override + protected void apply(@NotNull Map resources, + @NotNull ResourceManager resourceManager, + @NotNull ProfilerFiller profiler) { + LAYERS.clear(); + AnimationCore.LOGGER.info("Loading layer configurations from data packs..."); + + Map sorted = new LinkedHashMap<>(); + + // Sort resources by priority + resourceManager.listPacks().forEach(packResources -> { + Set namespaces = packResources.getNamespaces(PackType.SERVER_DATA); + namespaces.forEach(namespace -> + packResources.listResources(PackType.SERVER_DATA, namespace, "ac_animations", + (resourceLocation, inputStreamIoSupplier) -> { + String path = resourceLocation.getPath(); + if (path.endsWith("animation.layer.json")) { + ResourceLocation rl = new ResourceLocation(namespace, "animation.layer"); + + JsonElement el = resources.get(rl); + if (el != null) { + rl = new ResourceLocation(namespace, "animation_layer"); + sorted.put(rl, el); + } + } + } + ) + ); + }); + + int loadedCount = 0; + for (Map.Entry entry : sorted.entrySet()) { + try { + Map parsedLayers = getResourceLocationIntegerMap(entry); + + loadedCount += parsedLayers.size(); + AnimationCore.LOGGER.debug("Loaded {} layer configurations from {}", + parsedLayers.size(), entry.getKey().getNamespace()); + + } catch (IllegalArgumentException | JsonParseException e) { + AnimationCore.LOGGER.error("Parsing error loading layer configuration", e); + } + } + + AnimationCore.LOGGER.info("Loaded {} layer configurations from data packs", loadedCount); + } + + private static @NotNull Map getResourceLocationIntegerMap(Map.Entry entry) { + JsonElement json = entry.getValue(); + AnimLayerJson.Reader layerReader = AnimLayerJson.Reader.stream(json); + Map parsedLayers = layerReader.parse(); + + // Merge layer configurations + parsedLayers.forEach((layerKey, priority) -> { + if (containsKey(layerKey)) { + AnimationCore.LOGGER.debug("Overriding layer {} with priority {}", layerKey, priority); + } + registerLayer(layerKey, priority); + }); + return parsedLayers; + } + + public static void registerLayer(ResourceLocation key, int priority) { + LAYERS.put(key, priority); + } + + public static boolean containsKey(ResourceLocation key) { + return LAYERS.containsKey(key); + } +} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/capability/AnimationDataCapability.java b/src/main/java/top/leisuretimedock/animationcore/animation/capability/AnimationDataCapability.java deleted file mode 100644 index 6b4b443..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/capability/AnimationDataCapability.java +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.capability; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationCapabilityPacket; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.player.SimplePlayerCapabilitySync; -import top.leisuretimedock.animationcore.capability.network.SimpleCapabilityPacket; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; - -public class AnimationDataCapability extends SimplePlayerCapabilitySync implements IAnimationCapability { - public static final ResourceLocation key = new ResourceLocation(AnimationCore.MOD_ID, "animation_data"); - - public static final String AnimMap = "AnimMap"; - public static final String RideAnimLayer = "RideAnimLayer"; - public static final String RideAnimation = "RideAnimation"; - - private final Map animMap = new HashMap<>(); - private ResourceLocation rideAnimLayer; - private ResourceLocation rideAnimation; - - @Override - public void mergeAnimations(Map animations) { - animations.forEach((key, value) -> { - if (AnimationRegistry.getLayers().containsKey(key)) { - if (AnimationService.INSTANCE.isAnimationPresent(value)) { - if(Objects.equals(rideAnimLayer, key)) { - removeRiderAnimation(); - } - this.animMap.put(key, value); - setDirty(true); - } - } - }); - } - - @Override - public boolean mergeAnimation(ResourceLocation layer, ResourceLocation animation) { - if (AnimationRegistry.getLayers().containsKey(layer)) { - if (AnimationService.INSTANCE.isAnimationPresent(animation)) { - if(Objects.equals(rideAnimLayer, layer)) { - removeRiderAnimation(); - } - this.animMap.put(layer, animation); - setDirty(true); - return true; - } - } - return false; - } - - @Override - public boolean removeAnimation(ResourceLocation layer) { - ResourceLocation remove = this.animMap.remove(layer); - if(remove != null) { - setDirty(true); - return true; - } - return false; - } - - @Nullable - @Override - public ResourceLocation getAnimation(ResourceLocation layer) { - return animMap.getOrDefault(layer, null); - } - - @Override - public Map getAnimations() { - return Map.copyOf(animMap); - } - - @Override - public void clearAnimations() { - this.animMap.clear(); - setDirty(true); - } - - @Override - public boolean isAnimationPresent(ResourceLocation layer) { - return animMap.containsKey(layer); - } - - @Override - public ResourceLocation getRiderAnimLayer() { - return rideAnimLayer; - } - - @Override - public ResourceLocation getRiderAnimation() { - return rideAnimation; - } - - @Override - public void setRiderAnimation(@NotNull ResourceLocation layer, @NotNull ResourceLocation animation) { - if(AnimationService.INSTANCE.isAnimationLayerPresent(layer)) { - this.rideAnimLayer = layer; - this.rideAnimation = animation; - if(animMap.get(layer) != null) { - animMap.remove(layer); - } - setDirty(true); - } - } - - @Override - public void removeRiderAnimation() { - this.rideAnimLayer = null; - this.rideAnimation = null; - setDirty(true); - } - - @Override - public void copyFrom(ICapabilitySync oldData) { - IAnimationCapability data = (IAnimationCapability) oldData; - this.animMap.clear(); - this.animMap.putAll(data.getAnimations()); - this.rideAnimLayer = data.getRiderAnimLayer(); - this.rideAnimation = data.getRiderAnimation(); - } - - @Override - public CompoundTag toTag(CompoundTag tag) { - if(!animMap.isEmpty()) { - CompoundTag animMapTag = new CompoundTag(); - animMap.forEach((string, animation) -> - animMapTag.putString(string.toString(), animation.toString()) - ); - tag.put(AnimMap, animMapTag); - } - if(rideAnimLayer != null) tag.putString(RideAnimLayer, rideAnimLayer.toString()); - if(rideAnimation != null) tag.putString(RideAnimation, rideAnimation.toString()); - return tag; - } - - @Override - public void fromTag(CompoundTag tag) { - this.animMap.clear(); - this.rideAnimLayer = null; - this.rideAnimation = null; - if(tag.contains(AnimMap)) { - CompoundTag animMapTag = tag.getCompound(AnimMap); - animMapTag.getAllKeys().forEach(key -> this.animMap.put( - new ResourceLocation(key), - new ResourceLocation(animMapTag.getString(key)) - )); - } - if(tag.contains(RideAnimLayer)) this.rideAnimLayer = new ResourceLocation(tag.getString(RideAnimLayer)); - if(tag.contains(RideAnimation)) this.rideAnimation = new ResourceLocation(tag.getString(RideAnimation)); - } - - @Override - public ResourceLocation getKey() { - return key; - } - - @Override - public SimpleCapabilityPacket getDefaultPacket() { - return new AnimationCapabilityPacket(this); - } - - @Override - public void attachInit(Player player) { - Map map = new HashMap<>(this.animMap); - map.forEach((key, value) -> { - if(!AnimationService.INSTANCE.isAnimationLayerPresent(key)) this.animMap.remove(key); - if(!AnimationService.INSTANCE.isAnimationPresent(value)) this.animMap.remove(key); - }); - if(rideAnimLayer != null && !AnimationService.INSTANCE.isAnimationLayerPresent(rideAnimLayer)) { - removeRiderAnimation(); - } - } - - public static Optional getCapability(Player player){ - return Optional.ofNullable(CapabilityUtils.getPlayerCapability( - player, AnimationDataCapability.key, IAnimationCapability.class - )); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/capability/RawAnimationDataCapability.java b/src/main/java/top/leisuretimedock/animationcore/animation/capability/RawAnimationDataCapability.java deleted file mode 100644 index fbc97f5..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/capability/RawAnimationDataCapability.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.capability; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.network.toclient.RawAnimationCapabilityPacket; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.player.SimplePlayerCapabilitySync; -import top.leisuretimedock.animationcore.capability.network.SimpleCapabilityPacket; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; - -public class RawAnimationDataCapability extends SimplePlayerCapabilitySync { - public static final ResourceLocation key = new ResourceLocation(AnimationCore.MOD_ID, "raw_animation_data"); - - public static final String AnimMap = "AnimMap"; - - private final Map animMap = new HashMap<>(); - - public boolean mergeAnimation(ResourceLocation layer, ResourceLocation animation) { - if (AnimationRegistry.getLayers().containsKey(layer)) { - this.animMap.put(layer, animation); - setDirty(true); - return true; - } - return false; - } - - public boolean removeAnimation(ResourceLocation layer) { - ResourceLocation remove = this.animMap.remove(layer); - if(remove != null) { - setDirty(true); - return true; - } - return false; - } - - @Nullable - public ResourceLocation getAnimation(ResourceLocation layer) { - return animMap.getOrDefault(layer, null); - } - - public Map getAnimations() { - return Map.copyOf(animMap); - } - - public void clearAnimations() { - this.animMap.clear(); - setDirty(true); - } - - public boolean isAnimationPresent(ResourceLocation layer) { - return animMap.containsKey(layer); - } - - @Override - public void copyFrom(ICapabilitySync oldData) { - RawAnimationDataCapability data = (RawAnimationDataCapability) oldData; - this.animMap.clear(); - this.animMap.putAll(data.getAnimations()); - } - - @Override - public CompoundTag toTag(CompoundTag tag) { - if(!animMap.isEmpty()) { - CompoundTag animMapTag = new CompoundTag(); - animMap.forEach((string, animation) -> - animMapTag.putString(string.toString(), animation.toString()) - ); - tag.put(AnimMap, animMapTag); - } - return tag; - } - - @Override - public void fromTag(CompoundTag tag) { - this.animMap.clear(); - if(tag.contains(AnimMap)) { - CompoundTag animMapTag = tag.getCompound(AnimMap); - animMapTag.getAllKeys().forEach(key -> this.animMap.put( - new ResourceLocation(key), - new ResourceLocation(animMapTag.getString(key)) - )); - } - } - - @Override - public ResourceLocation getKey() { - return key; - } - - @Override - public SimpleCapabilityPacket getDefaultPacket() { - return new RawAnimationCapabilityPacket(this); - } - - @Override - public void attachInit(Player entity) { - clearAnimations(); - } - - public static Optional getCapability(Player player){ - return Optional.ofNullable(CapabilityUtils.getPlayerCapability( - player, RawAnimationDataCapability.key, RawAnimationDataCapability.class - )); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/capability/inter/IAnimationCapability.java b/src/main/java/top/leisuretimedock/animationcore/animation/capability/inter/IAnimationCapability.java deleted file mode 100644 index a008f15..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/capability/inter/IAnimationCapability.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.capability.inter; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import org.jetbrains.annotations.Nullable; - -import java.util.Map; - -public interface IAnimationCapability extends ICapabilitySync { - void mergeAnimations(Map animations); - boolean mergeAnimation(ResourceLocation layer, ResourceLocation animation); - boolean removeAnimation(ResourceLocation layer); - @Nullable ResourceLocation getAnimation(ResourceLocation layer); - Map getAnimations(); - void clearAnimations(); - boolean isAnimationPresent(ResourceLocation layer); - - ResourceLocation getRiderAnimLayer(); - ResourceLocation getRiderAnimation(); - void setRiderAnimation(ResourceLocation layer, ResourceLocation animation); - void removeRiderAnimation(); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/ApplyCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/ApplyCommand.java deleted file mode 100644 index c84dfd4..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/ApplyCommand.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.command.exception.ApiBackException; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.core.configs.ModConfigs; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; - -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - -public class ApplyCommand { - public static void register(LiteralArgumentBuilder animCommand) { - animCommand - .then(literal("apply") - .then(argument("target", EntityArgument.player()) - .executes(ApplyCommand::apply) - ) - .then(literal("accept") - .then(argument("player", EntityArgument.player()) - .executes(ApplyCommand::acceptApply) - ) - ) - ); - } - - private static int apply(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - ServerPlayer target = EntityArgument.getPlayer(context, "target"); - ServerPlayer player = source.getPlayerOrException(); - - Entity vehicle = target.getVehicle(); - if(vehicle == null) throw new ApiBackException(ApiBack.UNSUPPORTED); - - ApiBack back = AnimationApi.getHelper(player).applyAnimation(target); - if(back == ApiBack.COOLDOWN) { - int cooldown = ModConfigs.Server.applyCooldown.get(); - throw ApiBackException.withCooldown(cooldown); - } - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - //click event - Style pStyle = Style.EMPTY.withBold(true).withColor(ChatFormatting.GREEN).withClickEvent( - new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animcore anim apply accept " + player.getName().getString()) - ).withUnderlined(true); - - //send message to all participants - for (Entity passenger : vehicle.getPassengers()) { - passenger.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.APPLIED_JOIN_MESSAGE.getKey(), - player.getName().copy() - ).append(Component.translatable( - ModLang.TranslatableMessage.ACCEPT_MESSAGE_CLICK.getKey() - ).setStyle(pStyle))); - } - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.APPLY_JOIN_MESSAGE.getKey() - ).withStyle(ChatFormatting.GREEN), true); - return 1; - } catch (ApiBackException e) { - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - } - - private static int acceptApply(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - ServerPlayer player = source.getPlayerOrException(); - ServerPlayer applier = EntityArgument.getPlayer(context, "applier"); - - Entity vehicle = player.getVehicle(); - if(vehicle == null) throw new ApiBackException(ApiBack.UNSUPPORTED); - - ApiBack back = AnimationApi.getHelper(player).acceptApply(applier); - if(back == ApiBack.OUT_RANGE) throw ApiBackException.withOutRange(ModConfigs.Server.applyValidDistance.get()); - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - //define message - MutableComponent successMessage = Component.translatable( - ModLang.TranslatableMessage.ACCEPT_APPLY_SUCCESS.getKey(), - player.getName().copy(), applier.getName().copy() - ).withStyle(ChatFormatting.GREEN); - - //send message - source.sendSuccess(() -> successMessage, true); - for (Entity passenger : vehicle.getPassengers()) { - if(!passenger.getUUID().equals(player.getUUID()) && !passenger.getUUID().equals(applier.getUUID())) { - passenger.sendSystemMessage(successMessage); - } - } - applier.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.APPLY_SUCCESS.getKey(), - player.getName().copy() - ).withStyle(ChatFormatting.GREEN)); - } catch (ApiBackException e) { - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - return 0; - } - return 1; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/InviteCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/InviteCommand.java deleted file mode 100644 index 90d21c0..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/InviteCommand.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationArgument; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationLayerArgument; -import top.leisuretimedock.animationcore.animation.command.exception.ApiBackException; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.core.configs.ModConfigs; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Style; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; - -import java.util.Collection; -import java.util.List; -import java.util.UUID; - -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - -public class InviteCommand { - public static void register(LiteralArgumentBuilder animCommand) { - animCommand.then(literal("invite") - .then(argument("players", EntityArgument.players()) - .then(argument("layer", AnimationLayerArgument.layer()) - .then(argument("anim", AnimationArgument.animation()) - .executes(InviteCommand::invite) - ) - ) - ) - .then(literal("accept") - .then(argument("player", EntityArgument.player()) - .executes(InviteCommand::acceptInvite) - ) - ) - ); - } - - private static int invite(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - ServerPlayer player = source.getPlayerOrException(); - Collection players = EntityArgument.getPlayers(context, "players"); - - String layerString = AnimationLayerArgument.getLayer(context, "layer"); - String animString = AnimationArgument.getAnimation(context, "anim"); - ResourceLocation layer = new ResourceLocation(layerString); - ResourceLocation anim = new ResourceLocation(animString); - - //test info present - List targets = players.stream().map(Entity::getUUID).toList(); - ApiBack back = AnimationApi.getHelper(player).inviteAnimation(layer, anim, targets); - if(back == ApiBack.COOLDOWN) { - int cooldown = ModConfigs.Server.inviteCooldown.get(); - throw ApiBackException.withCooldown(cooldown); - } - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - //click event - Style pStyle = Style.EMPTY.withBold(true).withColor(ChatFormatting.GREEN).withClickEvent( - new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animcore anim invite accept " + player.getName().getString()) - ).withUnderlined(true); - //send message - for (ServerPlayer target : players) { - target.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.INVITED_MESSAGE.getKey(), - player.getName().copy(), - anim.toString() - ).append(Component.translatable( - ModLang.TranslatableMessage.ACCEPT_MESSAGE_CLICK.getKey() - ).setStyle(pStyle))); - } - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.INVITE_MESSAGE.getKey() - ).withStyle(ChatFormatting.GREEN), true); - return 1; - } catch (ApiBackException e) { - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - } - - private static int acceptInvite(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - ServerPlayer player = source.getPlayerOrException(); - ServerPlayer inviter = EntityArgument.getPlayer(context, "player"); - - //play animation - ApiBack back = AnimationApi.getHelper(player).acceptInvite(inviter); - if(back == ApiBack.OUT_RANGE) throw ApiBackException.withOutRange(ModConfigs.Server.inviteValidDistance.get()); - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - //send message - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.ACCEPT_INVITE_SUCCESS.getKey() - ).withStyle(ChatFormatting.GREEN), true); - inviter.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.INVITE_SUCCESS.getKey(), - player.getName().copy() - ).withStyle(ChatFormatting.GREEN)); - return 1; - } catch (ApiBackException e) { - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/JsonCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/JsonCommand.java deleted file mode 100644 index 0cc1c91..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/JsonCommand.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.helper.AnimationJsonHelper; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; - -import java.nio.file.Path; - -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - -public class JsonCommand { - public static void register(LiteralArgumentBuilder animCommand) { - animCommand.then(literal("json").requires(cs -> cs.hasPermission(2)) - .then(literal("clearFile").executes(JsonCommand::clearJson)) - .then(literal("generate") - .then(literal("anim") - .then(literal("example").executes(JsonCommand::generateExample)) - .executes(context -> generateJson(context, false, false)) - .then(argument("reset", BoolArgumentType.bool()) - .executes(context -> - generateJson(context, false, BoolArgumentType.getBool(context, "reset")) - ) - ) - ) - .then(literal("layer") - .executes(context -> generateJson(context, true, false)) - .then(argument("reset", BoolArgumentType.bool()) - .executes(context -> - generateJson(context, true, BoolArgumentType.getBool(context, "reset")) - ) - ) - ) - ) - ); - } - - private static int generateJson(CommandContext context, boolean isLayer, boolean isReset) { - CommandSourceStack source = context.getSource(); - try { - //generate - AnimationJsonHelper helper = AnimationJsonHelper.getHelper(source.getServer()); - Path path = helper.generateJson(isLayer, isReset); - - if(path == null) throw new Exception(); - MutableComponent component; - String key = ModLang.TranslatableMessage.ANIMATION_TO_JSON.getKey(); - if(isLayer) component = Component.translatable(key, "layer", "Server"); - else component = Component.translatable(key, "anim", "Server"); - - component.withStyle(ChatFormatting.GREEN).append(Component.translatable( - ModLang.TranslatableMessage.ANIMATION_JSON_PATH.getKey(), - path.toString() - )); - - source.sendSuccess(() -> component, true); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - return 0; - } - return 1; - } - - private static int clearJson(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - //clear path - AnimationJsonHelper.getHelper(source.getServer()).clearPath(); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - return 0; - } - return 1; - } - - private static int generateExample(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - //generate - AnimationJsonHelper helper = AnimationJsonHelper.getHelper(source.getServer()); - Path path = helper.generateExample(); - if(path == null) throw new Exception(); - - //send message - MutableComponent component = Component.translatable( - ModLang.TranslatableMessage.ANIMATION_TO_JSON.getKey(), - "anim example", "Server" - ).withStyle(ChatFormatting.GREEN); - component.append(Component.translatable( - ModLang.TranslatableMessage.ANIMATION_JSON_PATH.getKey(), - path.toString() - )); - source.sendSuccess(() -> component, true); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - return 0; - } - return 1; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/ListServerCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/ListServerCommand.java deleted file mode 100644 index 9ad1e22..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/ListServerCommand.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command; - -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.network.chat.Style; -import net.minecraft.resources.ResourceLocation; - -import java.util.List; -import java.util.Random; - -import static net.minecraft.commands.Commands.literal; - -public class ListServerCommand { - public static void register(LiteralArgumentBuilder animCommand) { - animCommand.then(literal("list") - .then(literal("layers").executes(ListServerCommand::listLayers)) - .then(literal("serverAnimations") - .executes(ListServerCommand::listAnimations) - ) - ); - } - - private static int listAnimations(CommandContext context) { - try { - CommandSourceStack source = context.getSource(); - List list = AnimationRegistry.getAnimations().keySet().stream().toList(); - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.LIST_ANIMATION_RESOURCE.getKey(), - "Server", "Animations", getString(list) - ), false); - return 1; - } catch (Exception ignored) {} - return 0; - } - - private static int listLayers(CommandContext context) { - try { - CommandSourceStack source = context.getSource(); - List list = AnimationRegistry.getLayers().keySet().stream().toList(); - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.LIST_ANIMATION_RESOURCE.getKey(), - "Server", "Layers", getString(list) - ), false); - return 1; - } catch (Exception ignored) {} - return 0; - } - - public static Component getString(List list) { - MutableComponent component = Component.empty(); - Random random = new Random(System.currentTimeMillis()); - for (int i = 0; i < list.size(); i++) { - component.append(Component.literal(list.get(i).toString()).withStyle(randomColor(random))); - if(i < list.size()-1){ - component.append(", ").withStyle(ChatFormatting.WHITE); - } - } - component.append(".").withStyle(Style.EMPTY.withColor(ChatFormatting.RED)); - return component; - } - - private static ChatFormatting randomColor(Random random){ - int i = random.nextInt(14) + 1; - ChatFormatting byId = ChatFormatting.getById(i); - return byId == null ? ChatFormatting.WHITE : byId; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/PlayCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/PlayCommand.java deleted file mode 100644 index 1db3e67..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/PlayCommand.java +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationArgument; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationLayerArgument; -import top.leisuretimedock.animationcore.animation.command.exception.ApiBackException; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.helper.AnimationHelper; -import top.leisuretimedock.animationcore.animation.helper.AnimationServiceGetterHelper; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationClearPacket; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import top.leisuretimedock.animationcore.animation.service.RawAnimationService; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.core.ModChannel; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Set; - -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - -public class PlayCommand { - public static void register(LiteralArgumentBuilder animCommand){ - animCommand - .then(literal("play") - .then(argument("players", EntityArgument.players()) - .requires(cs -> cs.hasPermission(2)) - .then(argument("layer", AnimationLayerArgument.layer()) - .then(argument("animation", AnimationArgument.animation()) - .executes(context -> playAnimation(context, false)) - .then(argument("withRide", BoolArgumentType.bool()) - .executes(context -> playAnimation( - context, BoolArgumentType.getBool(context, "withRide") - )) - .then(argument("forced", BoolArgumentType.bool()) - .executes(context -> playAnimation( - context, BoolArgumentType.getBool(context, "withRide")) - ) - ) - ) - ) - ) - ) - .then(literal("self") - .then(argument("layer", AnimationLayerArgument.layer()) - .then(argument("animation", AnimationArgument.animation()) - .executes(context -> playAnimation(context, false)) - .then(argument("withRide", BoolArgumentType.bool()) - .executes(context -> playAnimation( - context, BoolArgumentType.getBool(context, "withRide") - )) - ) - ) - ) - ) - ) - .then(literal("clear") - .executes(PlayCommand::clearAnimation) - .then(argument("players", EntityArgument.players()) - .requires(cs -> cs.hasPermission(2)) - .executes(PlayCommand::clearAnimation) - .then(argument("layer", AnimationLayerArgument.layer()) - .executes(PlayCommand::removeAnimation) - ) - ) - .then(argument("layer", AnimationLayerArgument.layer()) - .executes(PlayCommand::removeAnimation) - ) - ); - } - - private static int playAnimation(CommandContext context, boolean withRide) { - CommandSourceStack source = context.getSource(); - try { - Collection targets = new ArrayList<>(); - ServerPlayer player = source.getPlayerOrException(); - try { targets.addAll(EntityArgument.getPlayers(context, "players"));} - catch (Exception ignored) {} - String layerString = AnimationLayerArgument.getLayer(context, "layer"); - String animString = AnimationArgument.getAnimation(context, "animation"); - ResourceLocation layer = new ResourceLocation(layerString); - ResourceLocation anim = new ResourceLocation(animString); - - //play with players - IAnimationService helper = AnimationServiceGetterHelper.create(anim).getService(); - if (helper == null) throw new ApiBackException(ApiBack.RESOURCE_NOT_FOUND); - AnimationData animationData = helper.getAnimation(anim); - if(animationData == null) throw new ApiBackException(ApiBack.RESOURCE_NOT_FOUND); - if(!targets.isEmpty()) { - Set playerSet = Set.copyOf(targets); - playerSet.forEach(p -> { - if(withRide) { - boolean forced = false; - try { forced = BoolArgumentType.getBool(context, "forced");} - catch (Exception ignored) {} - ApiBack back = helper.playAnimationWithRide(p, layer, animationData, forced); - if(back == ApiBack.SUCCESS) targets.remove(p); - } else { - ApiBack back = helper.playAnimation(p, layer, animationData); - if (back == ApiBack.SUCCESS) targets.remove(p); - } - }); - - int successNum = playerSet.size() - targets.size(); - if(successNum > 0) { - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.PLAY_ANIMATION_SUCCESS.getKey(), - successNum - ).withStyle(ChatFormatting.GREEN), true); - } - List list = targets.stream().toList(); - if(!list.isEmpty()) { - MutableComponent failPlayers = Component.literal(""); - for (int i = 0; i < list.size(); i++) { - failPlayers.append(list.get(i).getName().copy()); - if (i < list.size() - 1) { - failPlayers.append(", "); - } - } - failPlayers.append("."); - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.PLAY_ANIMATION_FAIL.getKey(), - failPlayers - ).withStyle(ChatFormatting.RED)); - } - } else { - //play with self - ApiBack back; - RawAnimationService instance = RawAnimationService.INSTANCE; - if(withRide) back = instance.playAnimationWithRide(player, layer, animationData, false); - else back = instance.playAnimation(player, layer, animationData); - - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_SUCCESS.getKey() - ).withStyle(ChatFormatting.GREEN), true); - } - return 1; - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - - } - return 0; - } - - private static int removeAnimation(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - Collection targets = new ArrayList<>(); - ServerPlayer player = source.getPlayerOrException(); - try { targets.addAll(EntityArgument.getPlayers(context, "players"));} - catch (Exception ignored) {} - String layer = AnimationLayerArgument.getLayer(context, "layer"); - ResourceLocation layerLocation = new ResourceLocation(layer); - - //remove with players - if(!targets.isEmpty()) { - Set playerSet = Set.copyOf(targets); - playerSet.forEach(p -> { - ApiBack back = AnimationApi.getHelper(p).removeAnimation(layerLocation); - if (back == ApiBack.SUCCESS) targets.remove(p); - }); - int successNum = playerSet.size() - targets.size(); - if(successNum > 0) { - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.REMOVE_ANIMATION_SUCCESS.getKey(), - successNum - ).withStyle(ChatFormatting.GREEN), true); - } - List list = targets.stream().toList(); - if(!list.isEmpty()) { - MutableComponent failPlayers = Component.literal(""); - for (int i = 0; i < list.size(); i++) { - failPlayers.append(list.get(i).getName().copy()); - if (i < list.size() - 1) { - failPlayers.append(", "); - } - } - failPlayers.append("."); - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.REMOVE_ANIMATION_FAIL.getKey(), - failPlayers - ).withStyle(ChatFormatting.RED)); - } - } else { - ApiBack back = AnimationApi.getHelper(player).removeAnimation(layerLocation); - if (back != ApiBack.SUCCESS) throw new ApiBackException(back); - - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_SUCCESS.getKey() - ).withStyle(ChatFormatting.GREEN), true); - } - return 1; - } catch (ApiBackException e){ - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - } - - private static int clearAnimation(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - Collection players; - try {players = EntityArgument.getPlayers(context, "players");} - catch (Exception ignored) { players = Set.of(source.getPlayerOrException()); } - Set.copyOf(players).forEach(player -> { - AnimationHelper helper = AnimationApi.getHelper(player); - helper.clearAnimation(); - helper.detachAnimation(); - ModChannel.sendToPlayer(new AnimationClearPacket((ResourceLocation) null), player); - }); - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.CLEAR_ANIMATIONS.getKey() - ).withStyle(ChatFormatting.GREEN), true); - return 1; - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/RequestCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/RequestCommand.java deleted file mode 100644 index 735544f..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/RequestCommand.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationArgument; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationLayerArgument; -import top.leisuretimedock.animationcore.animation.command.exception.ApiBackException; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.core.configs.ModConfigs; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.arguments.BoolArgumentType; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.ChatFormatting; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.arguments.EntityArgument; -import net.minecraft.network.chat.ClickEvent; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Style; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; - -import static net.minecraft.commands.Commands.argument; -import static net.minecraft.commands.Commands.literal; - -/** - * Request target player play animation. - */ -public class RequestCommand { - public static void register(LiteralArgumentBuilder animCommand) { - animCommand.then(literal("request") - .then(argument("player", EntityArgument.player()).then( - argument("layer", AnimationLayerArgument.layer()) - .then(argument("animation", AnimationArgument.animation()) - .requires(cs -> cs.hasPermission(2)) - .executes(context -> request(context, false)) - .then(argument("withRide", BoolArgumentType.bool()) - .executes(context -> request( - context, BoolArgumentType.getBool(context, "withRide") - )) - ) - ) - )) - .then(literal("acceptRequest") - .then(argument("player", EntityArgument.player()) - .executes(RequestCommand::acceptRequest) - ) - ) - ); - } - - private static int request(CommandContext context, boolean withRide) { - CommandSourceStack source = context.getSource(); - try { - ServerPlayer player = source.getPlayerOrException(); - ServerPlayer target = EntityArgument.getPlayer(context, "player"); - String layerString = AnimationLayerArgument.getLayer(context, "layer"); - String animString = AnimationArgument.getAnimation(context, "animation"); - ResourceLocation layer = new ResourceLocation(layerString); - ResourceLocation anim = new ResourceLocation(animString); - - ApiBack back = AnimationApi.getHelper(player).requestAnimation(target, layer, anim, withRide); - if(back == ApiBack.COOLDOWN) { - int cooldown = ModConfigs.Server.requestCooldown.get(); - throw ApiBackException.withCooldown(cooldown); - } - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - //click event - Style pStyle = Style.EMPTY.withBold(true).withColor(ChatFormatting.GREEN).withClickEvent( - new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animcore anim request acceptRequest " + player.getName().getString()) - ).withUnderlined(true); - - //send message - target.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.REQUESTED_MESSAGE.getKey(), - player.getName().copy(), - anim.toString() - ).append(Component.translatable( - ModLang.TranslatableMessage.ACCEPT_MESSAGE_CLICK.getKey() - ).setStyle(pStyle))); - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.REQUEST_MESSAGE.getKey() - ).withStyle(ChatFormatting.GREEN), true); - return 1; - } catch (ApiBackException e) { - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - } - - private static int acceptRequest(CommandContext context) { - CommandSourceStack source = context.getSource(); - try { - ServerPlayer player = source.getPlayerOrException(); - ServerPlayer requestor = EntityArgument.getPlayer(context, "requestor"); - - //play - ApiBack back = AnimationApi.getHelper(player).acceptRequest(requestor); - if(back != ApiBack.SUCCESS) throw new ApiBackException(back); - - //send message - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.ACCEPT_REQUEST_SUCCESS.getKey() - ).withStyle(ChatFormatting.GREEN), true); - requestor.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.REQUEST_SUCCESS.getKey(), - player.getName().copy() - ).withStyle(ChatFormatting.GREEN)); - return 1; - } catch (ApiBackException e) { - source.sendFailure(e.getCommandFailBack().withStyle(ChatFormatting.RED)); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - } - return 0; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/argument/AnimationArgument.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/argument/AnimationArgument.java deleted file mode 100644 index b14d3b5..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/argument/AnimationArgument.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command.argument; - -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.register.RawAnimationRegistry; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.SharedSuggestionProvider; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; - -public class AnimationArgument implements ArgumentType { - private static final Supplier> EXAMPLES = AnimationArgument::getAnimationNames; - - private static Supplier> animationNames; - public AnimationArgument() { - resetAnimationNames(); - } - - public static void resetAnimationNames() { - Set set = new HashSet<>(getAnimationNames()); - Set strings = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, () -> - AnimationArgument::getAnimationNamesClient - ); - if (strings != null && !strings.isEmpty()) set.addAll(strings); - animationNames = () -> set; - } - - private static Set getAnimationNames(){ - Set set = new HashSet<>(); - AnimationRegistry.getAnimations().forEach((key, value) -> { - String name = value.getName(); - if(name != null && !set.contains(name)) { - set.add(name); - } else set.add(key.toString()); - }); - return set; - } - - @OnlyIn(Dist.CLIENT) - private static Set getAnimationNamesClient() { - Set set = new HashSet<>(); - RawAnimationRegistry.getAnimations().keySet().forEach(location -> - set.add(location.toString()) - ); - return set; - } - - public static AnimationArgument animation() { - return new AnimationArgument(); - } - - @Nullable - private static ResourceLocation getAnimationByName(String name) { - for (GenericAnimationData animation : AnimationRegistry.getAnimations().values()) { - if (Objects.equals(animation.getName(), name)) { - return animation.getKey(); - } - } - return null; - } - - public static String getAnimation(CommandContext context, String name) { - String argument = context.getArgument(name, String.class); - if(argument.contains(":")) return argument; - ResourceLocation animationByName = getAnimationByName(argument); - if(animationByName == null) return argument; - else return animationByName.toString(); - } - - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - return SharedSuggestionProvider.suggest(animationNames.get(), builder); - } - - public Collection getExamples() { - return EXAMPLES.get(); - } - - public String parse(StringReader reader) { - int start = reader.getCursor(); - while (reader.canRead() && canRead(reader.peek())) { - reader.skip(); - } - return reader.getString().substring(start, reader.getCursor()); - } - - private static boolean canRead(char peek) { - boolean origin = StringReader.isAllowedInUnquotedString(peek); - return origin || peek == ':'; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/argument/AnimationLayerArgument.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/argument/AnimationLayerArgument.java deleted file mode 100644 index e3f5876..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/argument/AnimationLayerArgument.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command.argument; - -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; -import com.mojang.brigadier.suggestion.Suggestions; -import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.SharedSuggestionProvider; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; - -import java.util.Collection; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.function.Supplier; -import java.util.stream.Collectors; - -public class AnimationLayerArgument implements ArgumentType { - private static final Supplier> EXAMPLES = () -> AnimationRegistry.getLayers().keySet().stream() - .map(ResourceLocation::toString).collect(Collectors.toSet()); - private static final DynamicCommandExceptionType UNKNOWN_TYPE = new DynamicCommandExceptionType( - layer -> Component.literal("Unknow layer : " + layer.toString()) - ); - - private final Supplier> animationLayers; - public AnimationLayerArgument() { - this.animationLayers = () -> AnimationRegistry.getLayers().keySet().stream() - .map(ResourceLocation::toString).collect(Collectors.toSet()); - } - - public static AnimationLayerArgument layer() { - return new AnimationLayerArgument(); - } - - public static String getLayer(CommandContext context, String name) { - return context.getArgument(name, String.class); - } - - public CompletableFuture listSuggestions(CommandContext context, SuggestionsBuilder builder) { - return SharedSuggestionProvider.suggest(animationLayers.get(), builder); - } - - public Collection getExamples() { - return EXAMPLES.get(); - } - - public String parse(StringReader reader) throws CommandSyntaxException { - int start = reader.getCursor(); - while (reader.canRead() && canRead(reader.peek())) { - reader.skip(); - } - String s = reader.getString().substring(start, reader.getCursor()); - if (!animationLayers.get().contains(s)) { - throw UNKNOWN_TYPE.create(s); - } else { - return s; - } - } - - private static boolean canRead(char peek) { - boolean origin = StringReader.isAllowedInUnquotedString(peek); - return origin || peek == ':'; - } - -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/client/ListClientCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/client/ListClientCommand.java deleted file mode 100644 index 66650fd..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/client/ListClientCommand.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command.client; - -import top.leisuretimedock.animationcore.animation.command.ListServerCommand; -import top.leisuretimedock.animationcore.animation.register.RawAnimationRegistry; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.List; - -import static net.minecraft.commands.Commands.literal; - -@OnlyIn(Dist.CLIENT) -public class ListClientCommand { - public static void register(LiteralArgumentBuilder animCommand) { - animCommand.then(literal("list").then(literal("clientAnimations") - .executes(ListClientCommand::listAnimations)) - ); - } - - private static int listAnimations(CommandContext context) { - try { - CommandSourceStack source = context.getSource(); - List list = RawAnimationRegistry.getAnimations().keySet().stream().toList(); - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.LIST_ANIMATION_RESOURCE.getKey(), - "Client", "Animations", ListServerCommand.getString(list) - ), false); - return 1; - } catch (Exception ignored) {} - return 0; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/client/RefreshCommand.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/client/RefreshCommand.java deleted file mode 100644 index 9d4e7fb..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/client/RefreshCommand.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command.client; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import com.mojang.brigadier.context.CommandContext; -import dev.kosmx.playerAnim.api.layered.IAnimation; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -import java.util.Set; - -import static net.minecraft.commands.Commands.literal; - -@OnlyIn(Dist.CLIENT) -public class RefreshCommand { - public static void register(LiteralArgumentBuilder animCommand){ - animCommand.then(literal("refresh").executes(RefreshCommand::refresh)); - } - - private static int refresh(CommandContext ctx){ - CommandSourceStack source = ctx.getSource(); - try { - Minecraft instance = Minecraft.getInstance(); - LocalPlayer player = instance.player; - if(player == null) throw new RuntimeException(); - AnimationApi.getHelper(player).refreshAnimation(); - - for (ResourceLocation layer : Set.copyOf(AnimationRegistry.getLayers().keySet())) { - PlayerAnimationAccess.PlayerAssociatedAnimationData playerAssociatedData = PlayerAnimationAccess.getPlayerAssociatedData(player); - IAnimation iAnimation = playerAssociatedData.get(layer); - if(iAnimation == null) continue; - ResourceLocation playing = AnimationApi.getHelper(player).getAnimationPlaying(layer); - if(playing == null) playerAssociatedData.set(layer, null); - } - - source.sendSuccess(() -> Component.translatable( - ModLang.TranslatableMessage.REFRESH_ANIMATIONS.getKey() - ).withStyle(ChatFormatting.GREEN), true); - } catch (Exception e) { - source.sendFailure(Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey() - ).withStyle(ChatFormatting.RED)); - AnimationCore.log.error(e.getMessage()); - return 0; - } - return 1; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/exception/ApiBackException.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/exception/ApiBackException.java deleted file mode 100644 index 45c1dc4..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/exception/ApiBackException.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command.exception; - -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; - -public class ApiBackException extends Exception { - private final ApiBack apiBack; - private Object[] args; - public ApiBackException(ApiBack apiBack) { - this.apiBack = apiBack; - } - - public ApiBackException(ApiBack apiBack, Object... args) { - this.apiBack = apiBack; - this.args = args; - } - - public static ApiBackException withCooldown(Integer cooldown) { - return new ApiBackException(ApiBack.COOLDOWN, cooldown); - } - - public static ApiBackException withOutRange(Integer distance) { - return new ApiBackException(ApiBack.OUT_RANGE, distance); - } - - public MutableComponent getCommandFailBack() { - if(args != null && args.length > 0) { - return Component.translatable(getLang(), args); - } else { - return Component.translatable(getLang()); - } - } - - public String getLang() { - return switch (apiBack) { - case FAIL -> ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey(); - case UNSUPPORTED -> ModLang.TranslatableMessage.ANIMATION_OPERATION_UNSUPPORTED.getKey(); - case COOLDOWN -> ModLang.TranslatableMessage.ANIMATION_COOLDOWN.getKey(); - case OUT_RANGE -> ModLang.TranslatableMessage.ANIMATION_OUT_RANGE.getKey(); - case OPERATION_EXPIRE -> ModLang.TranslatableMessage.ANIMATION_EXPIRE.getKey(); - case RESOURCE_NOT_FOUND -> ModLang.TranslatableMessage.ANIMATION_RESOURCE_NOT_FOUND.getKey(); - case SUCCESS -> ModLang.TranslatableMessage.COMMAND_RUN_SUCCESS.getKey(); - case BE_CANCELLED -> ModLang.TranslatableMessage.ANIMATION_OPERATION_CANCELLED.getKey(); - }; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/command/exception/CommandComponentException.java b/src/main/java/top/leisuretimedock/animationcore/animation/command/exception/CommandComponentException.java deleted file mode 100644 index d0181d0..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/command/exception/CommandComponentException.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.command.exception; - -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import net.minecraft.ChatFormatting; -import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.Style; - -public class CommandComponentException extends Exception { - private final Component component; - private final boolean isCommandFail; - public CommandComponentException(ModLang.TranslatableMessage message, Object ... args) { - super("Expected command exception."); - this.component = Component.translatable( - message.getKey(), - args - ).withStyle(ChatFormatting.RED); - this.isCommandFail = true; - } - public CommandComponentException(ModLang.TranslatableMessage message, Style style, Object ... args) { - super("Expected command exception."); - this.component = Component.translatable( - message.getKey(), - args - ).withStyle(style); - this.isCommandFail = false; - } - - public Component getCommandFailBack() { - return isCommandFail ? Component.translatable( - ModLang.TranslatableMessage.COMMAND_RUN_FAIL.getKey(), - component - ).withStyle(ChatFormatting.RED) : component; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/ACAnimationLayerProvider.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/ACAnimationLayerProvider.java similarity index 97% rename from src/main/java/top/leisuretimedock/animationcore/animation/data/util/ACAnimationLayerProvider.java rename to src/main/java/top/leisuretimedock/animationcore/animation/data/ACAnimationLayerProvider.java index 84cedd9..d8dd40f 100644 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/ACAnimationLayerProvider.java +++ b/src/main/java/top/leisuretimedock/animationcore/animation/data/ACAnimationLayerProvider.java @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -package top.leisuretimedock.animationcore.animation.data.util; +package top.leisuretimedock.animationcore.animation.data; import com.google.gson.JsonArray; import com.google.gson.JsonObject; @@ -58,7 +58,7 @@ public abstract class ACAnimationLayerProvider implements DataProvider { try { return DataProvider.saveStable(output, jsonArray, outputPath); } catch (Exception e) { - AnimationCore.log.error("Failed to save animation layer data", e); + AnimationCore.LOGGER.error("Failed to save animation layer data", e); return CompletableFuture.failedFuture(e); } } diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/ACAnimationProvider.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/ACAnimationProvider.java similarity index 96% rename from src/main/java/top/leisuretimedock/animationcore/animation/data/util/ACAnimationProvider.java rename to src/main/java/top/leisuretimedock/animationcore/animation/data/ACAnimationProvider.java index dbd73f0..8ed56d4 100644 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/ACAnimationProvider.java +++ b/src/main/java/top/leisuretimedock/animationcore/animation/data/ACAnimationProvider.java @@ -13,11 +13,11 @@ * along with this program. If not, see . */ -package top.leisuretimedock.animationcore.animation.data.util; +package top.leisuretimedock.animationcore.animation.data; import com.google.gson.JsonObject; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.Ride; +import io.zershyan.sccore.animation.data.GenericAnimationData; +import io.zershyan.sccore.animation.data.Ride; import net.minecraft.data.CachedOutput; import net.minecraft.data.DataGenerator; import net.minecraft.data.DataProvider; @@ -170,4 +170,4 @@ public abstract class ACAnimationProvider implements DataProvider { } return json; } -} \ No newline at end of file +} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/AnimationData.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/AnimationData.java deleted file mode 100644 index 8ca549f..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/AnimationData.java +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data; - -import dev.kosmx.playerAnim.core.data.KeyframeAnimation; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.StringTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.util.INBTSerializable; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; - -public class AnimationData implements INBTSerializable { - protected ResourceLocation key; - float camYaw; - float camPitch; - float camRoll; - int camComputePriority; - private Vec3 camPosOffset = new Vec3(0.0F, 0.0F, 0.0F); - boolean camPosOffsetRelative; - private @Nullable GenericAnimationData.LyingType lyingType; - protected @Nullable Ride ride; - - public enum LyingType { - RIGHT("RIGHT", 0), - LEFT("LEFT", 1), - FRONT("FRONT", 2), - BACK("BACK", 3); - private final String name; - private final int id; - LyingType(String name, int id) { - this.name = name; - this.id = id; - } - - public String getName() { - return name; - } - - public int getId() { - return id; - } - - @Nullable - public static LyingType getLyingType(int id) { - for (LyingType type : LyingType.values()) { - if (type.id == id) { - return type; - } - } - return null; - } - } - - public ResourceLocation getKey() { - return key; - } - - @Nullable - @OnlyIn(Dist.CLIENT) - public KeyframeAnimation getAnimation() { - return PlayerAnimationRegistry.getAnimation(key); - } - - public @Nullable Ride getRide() { - return ride; - } - - public void setLyingType(@Nullable LyingType lyingType) { - this.lyingType = lyingType; - } - - public float getCamRoll() { - return camRoll; - } - - public float getCamPitch() { - return camPitch; - } - - public float getCamYaw() { - return camYaw; - } - - public int getCamComputePriority() { - return camComputePriority; - } - - public boolean isCamPosOffsetRelative() { - return camPosOffsetRelative; - } - - public Vec3 getCamPosOffset() { - return camPosOffset; - } - - public @Nullable GenericAnimationData.LyingType getLyingType() { - return lyingType; - } - - public AnimationData withRide(Ride ride) { - this.ride = ride; - return this; - } - - public AnimationData withCamYaw(float camYaw) { - this.camYaw = camYaw; - return this; - } - - public AnimationData withCamPitch(float camPitch) { - this.camPitch = camPitch; - return this; - } - - public AnimationData withCamRoll(float camRoll) { - this.camRoll = camRoll; - return this; - } - - public AnimationData withCamComputePriority(int camPosPriority) { - this.camComputePriority = camPosPriority; - return this; - } - - public AnimationData addCamPosOffset(Vec3 camPosOffset) { - this.camPosOffset = this.camPosOffset.add(camPosOffset); - return this; - } - - public AnimationData setCamPosOffset(Vec3 camPosOffset) { - this.camPosOffset = camPosOffset; - return this; - } - - public AnimationData withCamPosOffsetRelative(boolean camPosOffsetRelative) { - this.camPosOffsetRelative = camPosOffsetRelative; - return this; - } - - public AnimationData withLyingType(@Nullable AnimationData.LyingType lyingType) { - this.lyingType = lyingType; - if(lyingType == null) return this; - this.camPosOffset = new Vec3(0, -1.3f, 0); - this.camPitch = -90.0f; - switch (lyingType) { - case RIGHT -> { - this.camRoll = 90.0f; - this.camYaw = 90.0f; - } - case LEFT -> { - this.camRoll = -90.0f; - this.camYaw = -90.0f; - } - case BACK -> this.camPitch = 90.0f; - } - return this; - } - - @Override - public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - tag.putString("key", key.toString()); - tag.putInt("priority", camComputePriority); - if(lyingType != null) tag.putInt("lyingType", lyingType.getId()); - tag.putFloat("camYaw", camYaw); - tag.putFloat("camPitch", camPitch); - tag.putFloat("camRoll", camRoll); - CompoundTag camOffset = new CompoundTag(); - camOffset.putDouble("x", camPosOffset.x); - camOffset.putDouble("y", camPosOffset.y); - camOffset.putDouble("z", camPosOffset.z); - camOffset.putBoolean("relative", camPosOffsetRelative); - tag.put("camOffset", camOffset); - if (ride != null) { - CompoundTag rideTag = new CompoundTag(); - Vec3 offset = ride.getOffset(); - rideTag.putDouble("x", offset.x); - rideTag.putDouble("y", offset.y); - rideTag.putDouble("z", offset.z); - rideTag.putInt("existTick", ride.getExistTick()); - rideTag.putFloat("xRot", ride.getXRot()); - rideTag.putFloat("yRot", ride.getYRot()); - List componentAnimations = ride.getComponentAnimations(); - ListTag listTag = new ListTag(); - for (ResourceLocation animation : componentAnimations) { - listTag.add(StringTag.valueOf(animation.toString())); - } - rideTag.put("subAnimations", listTag); - tag.put("ride", rideTag); - } - return tag; - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - String string = nbt.getString("key"); - this.key = new ResourceLocation(string); - this.camComputePriority = nbt.getInt("priority"); - if(nbt.contains("lyingType")) this.lyingType = LyingType.getLyingType(nbt.getInt("lyingType")); - else this.lyingType = null; - this.camYaw = nbt.getFloat("camYaw"); - this.camPitch = nbt.getFloat("camPitch"); - this.camRoll = nbt.getFloat("camRoll"); - CompoundTag camOffset = nbt.getCompound("camOffset"); - this.camPosOffset = new Vec3( - camOffset.getDouble("x"), - camOffset.getDouble("y"), - camOffset.getDouble("z") - ); - this.camPosOffsetRelative = camOffset.getBoolean("relative"); - try { - if(nbt.contains("ride")) { - CompoundTag rideTag = nbt.getCompound("ride"); - Vec3 offset = new Vec3( - rideTag.getDouble("x"), - rideTag.getDouble("y"), - rideTag.getDouble("z") - ); - int existTick = rideTag.getInt("existTick"); - float xRot = rideTag.getFloat("xRot"); - float yRot = rideTag.getFloat("yRot"); - List componentAnimations = new ArrayList<>(); - rideTag.getList("subAnimations", 8).forEach(tag -> - componentAnimations.add(new ResourceLocation(tag.getAsString())) - ); - this.ride = Ride.create() - .withOffset(offset) - .withExistTick(existTick) - .withXRot(xRot) - .withYRot(yRot) - .setComponentAnimations(componentAnimations); - return; - } - } catch (Exception ignored) {} - this.ride = null; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/GenericAnimationData.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/GenericAnimationData.java deleted file mode 100644 index 7ecc8be..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/GenericAnimationData.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data; - -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.Nullable; - -import java.util.regex.Pattern; - -public class GenericAnimationData extends AnimationData { - @Nullable - String name; - float heightModifier = 1.0f; - - GenericAnimationData(ResourceLocation key) { - this.key = key; - } - public GenericAnimationData(){} - - public static GenericAnimationData create(ResourceLocation name) { - return new GenericAnimationData(name); - } - - public GenericAnimationData withHeightModifier(float heightModifier) { - this.heightModifier = heightModifier; - return this; - } - - public GenericAnimationData withRide(Ride ride) { - this.ride = ride; - return this; - } - - @Override - public GenericAnimationData withLyingType(@Nullable LyingType lyingType) { - this.heightModifier = 0.3f; - return (GenericAnimationData) super.withLyingType(lyingType); - } - - public GenericAnimationData withName(String name) { - String regex = "^[a-zA-Z0-9_-]+$"; - Pattern pattern = Pattern.compile(regex); - if (!pattern.matcher(name).matches()) { - throw new IllegalArgumentException( - "Invalid animation name: " + name + ", must match " + regex - ); - } - this.name = name; - return this; - } - - public float getHeightModifier() { - return heightModifier; - } - - public @Nullable String getName() { - return name; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/RawAnimationData.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/RawAnimationData.java deleted file mode 100644 index 4f894ed..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/RawAnimationData.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data; - -import net.minecraft.resources.ResourceLocation; - -public class RawAnimationData extends AnimationData{ - RawAnimationData(ResourceLocation key) { - this.key = key; - } - public RawAnimationData(){} - - public static RawAnimationData create(ResourceLocation name) { - return new RawAnimationData(name); - } - - public RawAnimationData withRide(Ride ride) { - this.ride = ride; - return this; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/Ride.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/Ride.java deleted file mode 100644 index 80914d4..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/Ride.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data; - -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.phys.Vec3; - -import java.util.ArrayList; -import java.util.List; - -public class Ride { - private final List componentAnimations = new ArrayList<>(); - private Vec3 offset = new Vec3(0.0D, 0.0D, 0.0D); - private int existTick; - private float xRot; - private float yRot; - - - public static Ride create() { - return new Ride(); - } - - public Ride withOffset(Vec3 offset) { - this.offset = offset; - return this; - } - - public Ride withExistTick(int existTick) { - this.existTick = existTick; - return this; - } - - public Ride withXRot(float xRot) { - this.xRot = xRot; - return this; - } - - public Ride withYRot(float yRot) { - this.yRot = yRot; - return this; - } - - public Ride setComponentAnimations(List animations) { - this.componentAnimations.clear(); - this.componentAnimations.addAll(animations); - return this; - } - - public Ride addComponentAnimation(ResourceLocation animation) { - this.componentAnimations.add(animation); - return this; - } - - public float getXRot() { - return xRot; - } - - public void setXRot(float xRot) { - this.xRot = xRot; - } - - public float getYRot() { - return yRot; - } - - public void setYRot(float yRot) { - this.yRot = yRot; - } - - public Vec3 getOffset() { - return offset; - } - - public void setOffset(Vec3 offset) { - this.offset = offset; - } - - public int getExistTick() { - return existTick; - } - - public void setExistTick(int existTick) { - this.existTick = existTick; - } - - public List getComponentAnimations() { - return componentAnimations; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/AnimJson.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/util/AnimJson.java deleted file mode 100644 index 5ba95ed..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/AnimJson.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data.util; - -import com.google.gson.*; -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.Ride; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.Nullable; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.FileWriter; -import java.nio.file.Files; -import java.nio.file.Path; - -public class AnimJson { - private static final String Key = "key"; - private static final String Name = "name"; - private static final String LyingType = "lyingType"; - private static final String HeightModifier = "heightModifier"; - private static final String CamPitch = "camPitch"; - private static final String CamRoll = "camRoll"; - private static final String CamYaw = "camYaw"; - private static final String CamPosOffset = "camPosOffset"; - private static final String Relative = "relative"; - private static final String Priority = "priority"; - private static final String WithRide = "withRide"; - private static final String Offset = "offset"; - private static final String XRot = "xRot"; - private static final String YRot = "yRot"; - private static final String ExistTick = "existTick"; - private static final String ComponentsAnimation = "componentsAnimation"; - - public static class Reader { - private final JsonElement originElement; - Reader(Path jsonFile) throws Exception { - File file = jsonFile.toFile(); - if (!file.exists()) { - throw new FileNotFoundException("File does not exist: " + file.getAbsolutePath()); - } - this.originElement = JsonParser.parseReader(new FileReader(file)); - } - - Reader(JsonElement originElement) { - this.originElement = originElement; - } - - public static Reader stream(Path path) throws Exception { - return new Reader(path); - } - - public static Reader stream(JsonElement jsonElement) { - return new Reader(jsonElement); - } - - public GenericAnimationData parse() { - return fromJson(); - } - - public GenericAnimationData fromJson() { - try { - JsonObject json = originElement.getAsJsonObject(); - GenericAnimationData animation = GenericAnimationData.create(new ResourceLocation(json.get(Key).getAsString())); - if(json.has(Name)) animation.withName(json.get(Name).getAsString()); - if(json.has(LyingType)) animation.withLyingType(AnimationData.LyingType.valueOf(json.get(LyingType).getAsString())); - if(json.has(HeightModifier)) animation.withHeightModifier(json.get(HeightModifier).getAsFloat()); - if(json.has(Priority)) animation.withCamComputePriority(json.get(Priority).getAsInt()); - if(json.has(CamPitch)) animation.withCamPitch(json.get(CamPitch).getAsFloat()); - if(json.has(CamRoll)) animation.withCamRoll(json.get(CamRoll).getAsFloat()); - if(json.has(CamYaw)) animation.withCamYaw(json.get(CamYaw).getAsFloat()); - if(json.has(CamPosOffset)) { - JsonObject camOffset = json.get(CamPosOffset).getAsJsonObject(); - Vec3 vec3 = Vec3.ZERO; - if(camOffset.has("x")) vec3 = vec3.add(camOffset.get("x").getAsDouble(), 0, 0); - if(camOffset.has("y")) vec3 = vec3.add(0, camOffset.get("y").getAsDouble(), 0); - if(camOffset.has("z")) vec3 = vec3.add(0, 0, camOffset.get("z").getAsDouble()); - if(!vec3.equals(Vec3.ZERO)) animation.setCamPosOffset(vec3); - if(camOffset.has(Relative)) animation.withCamPosOffsetRelative(camOffset.get(Relative).getAsBoolean()); - } - if(json.has(WithRide)){ - Ride ride = Ride.create(); - JsonObject withRide = json.get(WithRide).getAsJsonObject(); - if(withRide.has(ExistTick)) ride.setExistTick(withRide.get(ExistTick).getAsInt()); - if(withRide.has(XRot)) ride.setXRot(withRide.get(XRot).getAsFloat()); - if(withRide.has(YRot)) ride.setYRot(withRide.get(YRot).getAsFloat()); - if(withRide.has(Offset)) { - JsonObject offsetJson = withRide.get(Offset).getAsJsonObject(); - Vec3 offset = new Vec3( - offsetJson.get("x").getAsDouble(), - offsetJson.get("y").getAsDouble(), - offsetJson.get("z").getAsDouble() - ); - ride.withOffset(offset); - } - if(withRide.has(ComponentsAnimation)){ - JsonArray elements = withRide.get(ComponentsAnimation).getAsJsonArray(); - for (JsonElement element : elements) { - String componentKeyString = element.getAsString(); - ResourceLocation componentKey = new ResourceLocation(componentKeyString); - ride.addComponentAnimation(componentKey); - } - } - animation.withRide(ride); - } - return animation; - } catch (Exception e) { - throw new JsonParseException(e); - } - } - } - - public static class Writer { - private static final String example = "example"; - private final @Nullable Path file; - private final GenericAnimationData animation; - Writer(@Nullable Path file, GenericAnimationData animation) { - this.animation = animation; - this.file = file; - } - - public static Writer stream(Path path, GenericAnimationData animation) { - return new Writer(path, animation); - } - - public static Writer stream(GenericAnimationData animation) { - return new Writer(null, animation); - } - - public static Path syntaxExample(Path directory) throws Exception { - ResourceLocation exampleLocation = new ResourceLocation(AnimationCore.MOD_ID, Writer.example); - GenericAnimationData example = (GenericAnimationData) GenericAnimationData - .create(exampleLocation) - .withName(Writer.example) - .withLyingType(GenericAnimationData.LyingType.RIGHT) - .withHeightModifier(0.3f) - .setCamPosOffset(new Vec3(0.0f, -1.3f, 0.0f)) - .withCamComputePriority(0) - .withCamPosOffsetRelative(false) - .withCamPitch(-90.0f) - .withCamRoll(90.0f) - .withCamYaw(90.0f) - .withRide(Ride.create() - .withOffset(new Vec3(0.0f, 1.0f, 0.0f)) - .withExistTick(200) - .withXRot(180) - .withYRot(0) - .addComponentAnimation(exampleLocation) - ); - Writer writer = stream(directory, example); - return writer.syntax(); - } - - public Path syntax() throws Exception { - if(file == null) throw new NullPointerException("file is null"); - Path modIdPath = file.resolve(animation.getKey().getNamespace()); - Path resultPath = modIdPath.resolve(animation.getKey().getPath() + ".anim.json"); - if(animation.getName() != null) { - resultPath = modIdPath.resolve(animation.getName() + ".anim.json"); - if(resultPath.toFile().exists()) { - resultPath = modIdPath.resolve(animation.getKey().getPath() + ".anim.json"); - } - } - if(resultPath.toFile().exists()) return resultPath; - if(!Files.exists(modIdPath)) Files.createDirectories(modIdPath); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - try (FileWriter writer = new FileWriter(resultPath.toFile())) { - gson.toJson(toJson(), writer); - return resultPath; - } - } - - - public JsonElement toJson() { - JsonObject json = new JsonObject(); - ResourceLocation key = animation.getKey(); - json.addProperty(Key, key.toString()); - if (animation.getName() != null) json.addProperty(Name, animation.getName()); - json.addProperty(Priority, animation.getCamComputePriority()); - if (animation.getLyingType() != null) json.addProperty(LyingType, animation.getLyingType().getName()); - json.addProperty(HeightModifier, animation.getHeightModifier()); - JsonObject camOffset = new JsonObject(); - camOffset.addProperty("x", animation.getCamPosOffset().x); - camOffset.addProperty("y", animation.getCamPosOffset().y); - camOffset.addProperty("z", animation.getCamPosOffset().z); - camOffset.addProperty(Relative, animation.isCamPosOffsetRelative()); - json.add(CamPosOffset, camOffset); - json.addProperty(CamPitch, animation.getCamPitch()); - json.addProperty(CamRoll, animation.getCamRoll()); - json.addProperty(CamYaw, animation.getCamYaw()); - Ride ride = animation.getRide(); - if(ride != null) { - JsonObject jsonRide = new JsonObject(); - JsonObject jsonOffset = new JsonObject(); - Vec3 offset = ride.getOffset(); - jsonOffset.addProperty("x", offset.x); - jsonOffset.addProperty("y", offset.y); - jsonOffset.addProperty("z", offset.z); - jsonRide.add(Offset, jsonOffset); - jsonRide.addProperty(XRot, ride.getXRot()); - jsonRide.addProperty(YRot, ride.getYRot()); - jsonRide.addProperty(ExistTick, ride.getExistTick()); - - if(!ride.getComponentAnimations().isEmpty()) { - JsonArray jsonComponents = new JsonArray(); - ride.getComponentAnimations().forEach(component -> - jsonComponents.add(component.toString()) - ); - jsonRide.add(ComponentsAnimation, jsonComponents); - } - json.add(WithRide, jsonRide); - } - return json; - } - - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/AnimLayerJson.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/util/AnimLayerJson.java deleted file mode 100644 index 884bbec..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/AnimLayerJson.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data.util; - -import com.google.gson.*; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import net.minecraft.resources.ResourceLocation; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; -import java.util.stream.Collectors; - -public class AnimLayerJson { - - private static final String Key = "key"; - private static final String Priority = "priority"; - - public static class Reader { - private final JsonElement originElement; - - Reader(Path jsonFile) throws Exception { - File file = jsonFile.toFile(); - if (!file.exists()) { - throw new FileNotFoundException("File does not exist: " + file.getAbsolutePath()); - } - this.originElement = JsonParser.parseReader(new FileReader(file)); - } - - Reader(JsonElement originElement) { - this.originElement = originElement; - } - - public static Reader stream(Path path) throws Exception { - return new Reader(path); - } - - public static Reader stream(JsonElement jsonElement) { - return new Reader(jsonElement); - } - - public Map parse() { - return fromJson(); - } - - private Map fromJson() { - try { - JsonArray jsonArray = originElement.getAsJsonArray(); - Map map = new HashMap<>(); - for (JsonElement element : jsonArray) { - JsonObject jsonObject = element.getAsJsonObject(); - ResourceLocation location = new ResourceLocation(jsonObject.get(Key).getAsString()); - int priority = jsonObject.get(Priority).getAsInt(); - map.put(location, priority); - } - return map; - } catch (Exception e) { - throw new JsonParseException(e); - } - } - } - - public static class Writer { - private final Path file; - private final Map layers = AnimationRegistry.getLayers(); - private final Map> layerNames = new HashMap<>(); - Writer(Path file) { - this.file = file; - for (ResourceLocation location : layers.keySet()) { - String namespace = location.getNamespace(); - Set locationSet = layerNames.getOrDefault(namespace, new HashSet<>()); - locationSet.add(location); - layerNames.put(namespace, locationSet); - } - } - - public static Writer stream(Path path) { - return new Writer(path); - } - - public static Path syntaxImmediately(Path directory) throws IOException { - Writer writer = stream(directory); - return writer.syntax(); - } - - public Map allToJson() { - Map map = new HashMap<>(); - for (String namespace : layerNames.keySet()) { - Set locationSet = layerNames.get(namespace); - JsonElement json = toJson(locationSet); - map.put(namespace, json); - } - return map; - } - - public Path syntax(String ... namespaces) throws IOException { - Set namespaceSet; - if(namespaces.length == 0) { - namespaceSet = layerNames.keySet(); - } else { - namespaceSet = Arrays.stream(namespaces).collect(Collectors.toSet()); - } - - for (String name : namespaceSet) { - Set locationSet = layerNames.get(name); - Path modIdPath = file.resolve(name); - Path resultPath = modIdPath.resolve("animation.layer.json"); - if(!Files.exists(modIdPath)) Files.createDirectories(modIdPath); - Gson gson = new GsonBuilder().setPrettyPrinting().create(); - try (FileWriter writer = new FileWriter(resultPath.toFile())) { - gson.toJson(toJson(locationSet), writer); - } - } - return file; - } - - private JsonElement toJson(Set locationSet) { - JsonArray jsonArray = new JsonArray(); - for (ResourceLocation location : locationSet) { - if(layers.containsKey(location)) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty(Key, location.toString()); - jsonObject.addProperty(Priority, layers.get(location)); - jsonArray.add(jsonObject); - } - } - return jsonArray; - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/RawAnimJson.java b/src/main/java/top/leisuretimedock/animationcore/animation/data/util/RawAnimJson.java deleted file mode 100644 index d53c647..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/data/util/RawAnimJson.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.data.util; - -import com.google.gson.*; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.RawAnimationData; -import top.leisuretimedock.animationcore.animation.data.Ride; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.phys.Vec3; - -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.nio.file.Path; - -public class RawAnimJson { - private static final String Key = "key"; - private static final String LyingType = "lyingType"; - private static final String CamPitch = "camPitch"; - private static final String CamRoll = "camRoll"; - private static final String CamYaw = "camYaw"; - private static final String CamPosOffset = "camPosOffset"; - private static final String Relative = "relative"; - private static final String Priority = "priority"; - private static final String WithRide = "withRide"; - private static final String Offset = "offset"; - private static final String XRot = "xRot"; - private static final String YRot = "yRot"; - private static final String ExistTick = "existTick"; - private static final String ComponentsAnimation = "componentsAnimation"; - - public static class Reader { - private final JsonElement originElement; - Reader(Path jsonFile) throws Exception { - File file = jsonFile.toFile(); - if (!file.exists()) { - throw new FileNotFoundException("File does not exist: " + file.getAbsolutePath()); - } - this.originElement = JsonParser.parseReader(new FileReader(file)); - } - - Reader(JsonElement originElement) { - this.originElement = originElement; - } - - public static RawAnimJson.Reader stream(Path path) throws Exception { - return new RawAnimJson.Reader(path); - } - - public static RawAnimJson.Reader stream(JsonElement jsonElement) { - return new RawAnimJson.Reader(jsonElement); - } - - public RawAnimationData parse() { - return fromJson(); - } - - public RawAnimationData fromJson() { - try { - JsonObject json = originElement.getAsJsonObject(); - RawAnimationData animation = RawAnimationData.create(new ResourceLocation(json.get(Key).getAsString())); - if(json.has(LyingType)) animation.withLyingType(AnimationData.LyingType.valueOf(json.get(LyingType).getAsString())); - if(json.has(Priority)) animation.withCamComputePriority(json.get(Priority).getAsInt()); - if(json.has(CamPitch)) animation.withCamPitch(json.get(CamPitch).getAsFloat()); - if(json.has(CamRoll)) animation.withCamRoll(json.get(CamRoll).getAsFloat()); - if(json.has(CamYaw)) animation.withCamYaw(json.get(CamYaw).getAsFloat()); - if(json.has(CamPosOffset)) { - JsonObject camOffset = json.get(CamPosOffset).getAsJsonObject(); - Vec3 vec3 = Vec3.ZERO; - if(camOffset.has("x")) vec3 = vec3.add(camOffset.get("x").getAsDouble(), 0, 0); - if(camOffset.has("y")) vec3 = vec3.add(0, camOffset.get("y").getAsDouble(), 0); - if(camOffset.has("z")) vec3 = vec3.add(0, 0, camOffset.get("z").getAsDouble()); - if(!vec3.equals(Vec3.ZERO)) animation.setCamPosOffset(vec3); - if(camOffset.has(Relative)) animation.withCamPosOffsetRelative(camOffset.get(Relative).getAsBoolean()); - } - if(json.has(WithRide)){ - Ride ride = Ride.create(); - JsonObject withRide = json.get(WithRide).getAsJsonObject(); - if(withRide.has(ExistTick)) ride.setExistTick(withRide.get(ExistTick).getAsInt()); - if(withRide.has(XRot)) ride.setXRot(withRide.get(XRot).getAsFloat()); - if(withRide.has(YRot)) ride.setYRot(withRide.get(YRot).getAsFloat()); - if(withRide.has(Offset)) { - JsonObject offsetJson = withRide.get(Offset).getAsJsonObject(); - Vec3 offset = new Vec3( - offsetJson.get("x").getAsDouble(), - offsetJson.get("y").getAsDouble(), - offsetJson.get("z").getAsDouble() - ); - ride.withOffset(offset); - } - if(withRide.has(ComponentsAnimation)){ - JsonArray elements = withRide.get(ComponentsAnimation).getAsJsonArray(); - for (JsonElement element : elements) { - String componentKeyString = element.getAsString(); - ResourceLocation componentKey = new ResourceLocation(componentKeyString); - ride.addComponentAnimation(componentKey); - } - } - animation.withRide(ride); - } - return animation; - } catch (Exception e) { - throw new JsonParseException(e); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/entity/AnimationRideEntity.java b/src/main/java/top/leisuretimedock/animationcore/animation/entity/AnimationRideEntity.java deleted file mode 100644 index 5e2f4b9..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/entity/AnimationRideEntity.java +++ /dev/null @@ -1,223 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.entity; - -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.Ride; -import top.leisuretimedock.animationcore.animation.register.AnimationEntities; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import net.minecraft.core.BlockPos; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.game.ClientGamePacketListener; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.network.NetworkHooks; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; - -public class AnimationRideEntity extends Entity { - public AnimationRideEntity(Level pLevel) { - super(AnimationEntities.RIDE.get(), pLevel); - this.noPhysics = true; - } - - private final Set players = new HashSet<>(); - private final Map animationPair = new HashMap<>(); - private AnimationData animation; - private ServerPlayer player; - private ResourceLocation layer; - public AnimationRideEntity(ServerPlayer pPlayer, ResourceLocation layer, AnimationData animation) { - this(pPlayer.level()); - this.player = pPlayer; - this.layer = layer; - this.animation = animation; - Ride ride = animation.getRide(); - if(ride != null) { - List componentAnimations = ride.getComponentAnimations(); - for (ResourceLocation componentAnimation : componentAnimations) { - animationPair.put(componentAnimation, null); - } - } - } - - public ResourceLocation getLayer() { - return layer; - } - - public Set getPlayers() { - return players; - } - - public ServerPlayer getPlayer() { - return player; - } - - public AnimationData getAnimation() { - return animation; - } - - @Override - protected void defineSynchedData() {} - - @Override - protected void readAdditionalSaveData(@NotNull CompoundTag pCompound) {} - - @Override - protected void addAdditionalSaveData(@NotNull CompoundTag pCompound) {} - - @Override - public void tick() { - super.tick(); - if(!this.level().isClientSide) { - Ride ride = animation == null ? null : animation.getRide(); - if(!this.getPassengers().contains(player) || (ride != null && ride.getExistTick() > 0 && this.tickCount >= ride.getExistTick())) { - this.remove(RemovalReason.DISCARDED); - } - } - } - - @Override - public double getPassengersRidingOffset() { - return 0.0; - } - - @Override - protected boolean canRide(@NotNull Entity entity) { - return true; - } - - @Override - public boolean shouldRiderSit() { - return false; - } - - @Override - public @NotNull Packet getAddEntityPacket(){ - return NetworkHooks.getEntitySpawningPacket(this); - } - - @Nullable - public static AnimationRideEntity create(ServerPlayer pPlayer, ResourceLocation layer, AnimationData anim, boolean force, Vec3 pos) { - if(anim == null) return null; - if(anim.getRide() == null) return null; - IAnimationCapability data = AnimationDataCapability.getCapability(pPlayer).orElse(null); - if(data == null) return null; - data.setRiderAnimation(layer, anim.getKey()); - AnimationRideEntity seat = new AnimationRideEntity(pPlayer, layer, anim); - float xRot = anim.getRide().getXRot(); - float yRot = anim.getRide().getYRot(); - if(xRot == 0 && yRot == 0) seat.setRot(pPlayer.getXRot(), pPlayer.getYRot()); - else seat.setRot(yRot, xRot); - pos.add(anim.getRide().getOffset()); - seat.setPos(pos.x, pos.y + 0.35f, pos.z); - pPlayer.level().addFreshEntity(seat); - pPlayer.startRiding(seat, force); - return seat; - } - - @Nullable - public static AnimationRideEntity create(ServerPlayer pPlayer, ResourceLocation layer, AnimationData anim, boolean force) { - return create(pPlayer, layer, anim, force, pPlayer.position()); - } - - @Nullable - public static AnimationRideEntity create(ServerPlayer pPlayer, ResourceLocation layer, AnimationData anim, boolean force, BlockPos pos) { - return create(pPlayer, layer, anim, force, pos.getCenter()); - } - - @Override - protected void positionRider(@NotNull Entity pPassenger, @NotNull MoveFunction pCallback) { - super.positionRider(pPassenger, pCallback); - pPassenger.setYBodyRot(this.getYRot()); - } - - @Override - public void onPassengerTurned(@NotNull Entity pEntityToUpdate) { - pEntityToUpdate.setYBodyRot(this.getYRot()); - } - - @Override - public @NotNull Vec3 getDismountLocationForPassenger(@NotNull LivingEntity entity) { - Ride ride = animation.getRide(); - if(ride != null) { - Vec3 position = entity.position(); - return position.subtract(ride.getOffset()); - } - return entity.position(); - } - - @Override - protected void addPassenger(@NotNull Entity entity) { - int passengerNum = getPassengers().size(); - super.addPassenger(entity); - if(passengerNum == 0) return; - if(entity instanceof ServerPlayer serverPlayer) { - Ride ride = animation.getRide(); - if(ride == null) return; - List componentAnimations = ride.getComponentAnimations(); - if(componentAnimations.isEmpty()) return; - if(passengerNum > componentAnimations.size()) return; - ResourceLocation animLocation = null; - for (ResourceLocation location : animationPair.keySet()) { - if(animationPair.get(location) == null) - animLocation = location; - } - if(animLocation == null) return; - animationPair.put(animLocation, serverPlayer.getUUID()); - IAnimationCapability data = AnimationDataCapability.getCapability(serverPlayer).orElse(null); - if(data == null) return; - data.setRiderAnimation(layer, animLocation); - AnimationService.INSTANCE.syncAnimation(serverPlayer, player); - players.add(serverPlayer); - } - } - - @Override - protected void removePassenger(@NotNull Entity entity) { - super.removePassenger(entity); - if(entity instanceof ServerPlayer serverPlayer) { - AnimationService.INSTANCE.removeAnimation(serverPlayer, layer); - players.remove(serverPlayer); - new HashMap<>(animationPair).forEach((key, value) -> { - if(Objects.equals(value, serverPlayer.getUUID())) { - animationPair.put(key, null); - } - }); - AnimationDataCapability.getCapability(serverPlayer).ifPresent( - IAnimationCapability::removeRiderAnimation - ); - } - } - - @Override - public boolean canAddPassenger(@NotNull Entity pPassenger) { - boolean isServerPlayer = pPassenger instanceof ServerPlayer; - int size = players.size(); - Ride ride = animation.getRide(); - if(ride == null) return false; - int maxSize = ride.getComponentAnimations().size(); - return isServerPlayer && size < maxSize; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/entity/renderer/AnimationRideRenderer.java b/src/main/java/top/leisuretimedock/animationcore/animation/entity/renderer/AnimationRideRenderer.java deleted file mode 100644 index 9959b4e..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/entity/renderer/AnimationRideRenderer.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.entity.renderer; - -import top.leisuretimedock.animationcore.animation.entity.AnimationRideEntity; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.culling.Frustum; -import net.minecraft.client.renderer.entity.EntityRenderer; -import net.minecraft.client.renderer.entity.EntityRendererProvider; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; - -public class AnimationRideRenderer extends EntityRenderer { - public AnimationRideRenderer(EntityRendererProvider.Context pContext) { - super(pContext); - } - - @Override - public @NotNull ResourceLocation getTextureLocation(@NotNull AnimationRideEntity pEntity) { - return new ResourceLocation(""); - } - - @Override - public boolean shouldRender(@NotNull AnimationRideEntity pLivingEntity, @NotNull Frustum pCamera, double pCamX, double pCamY, double pCamZ) { - return false; - } - - @Override - public void render(@NotNull AnimationRideEntity pEntity, float pEntityYaw, float pPartialTick, @NotNull PoseStack pPoseStack, @NotNull MultiBufferSource pBuffer, int pPackedLight) {} - - @Override - protected void renderNameTag(@NotNull AnimationRideEntity pEntity, @NotNull Component pDisplayName, @NotNull PoseStack pPoseStack, @NotNull MultiBufferSource pBuffer, int pPackedLight) {} -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/event/PlayerTickEvent.java b/src/main/java/top/leisuretimedock/animationcore/animation/event/PlayerTickEvent.java deleted file mode 100644 index 5379165..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/event/PlayerTickEvent.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.event; - -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.entity.AnimationRideEntity; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; - -public class PlayerTickEvent { - @SubscribeEvent - public static void onPlayerTickEvent(TickEvent.PlayerTickEvent event) { - if (event.side.isServer() && event.phase == TickEvent.Phase.END) { - if(event.player.tickCount % 20 == 0) { - Player player = event.player; - if(!(player.getVehicle() instanceof AnimationRideEntity)){ - AnimationDataCapability.getCapability(player).ifPresent(capability -> { - if(capability.getRiderAnimLayer() != null) { - capability.removeRiderAnimation(); - } - }); - } - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/event/client/CameraModify.java b/src/main/java/top/leisuretimedock/animationcore/animation/event/client/CameraModify.java deleted file mode 100644 index f90c977..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/event/client/CameraModify.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.event.client; - -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.RawAnimationData; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import dev.kosmx.playerAnim.core.util.MathHelper; -import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.ViewportEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; - -@OnlyIn(Dist.CLIENT) -public class CameraModify { - private static float targetYaw = 0.0F; - private static float targetPitch = 0.0F; - private static float targetRoll = 0.0F; - private static float currentYaw = 0.0F; - private static float currentPitch = 0.0F; - private static float currentRoll = 0.0F; - - @SubscribeEvent - public static void changeCameraView(ViewportEvent.ComputeCameraAngles event){ - Camera camera = event.getCamera(); - Entity entity = camera.getEntity(); - Minecraft minecraft = Minecraft.getInstance(); - if (entity == minecraft.player && minecraft.options.getCameraType().isFirstPerson()) { - LocalPlayer player = minecraft.player; - if (player != null) { - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - if(data == null) return; - AnimationData animation = AnimationUtils.getPredicateAnimationData(animationData -> { - float camYaw = animationData.getCamYaw(); - float camPitch = animationData.getCamPitch(); - float camRoll = animationData.getCamRoll(); - return !(camYaw == camPitch && camPitch == camRoll && camYaw == 0); - }); - - if(animation != null) { - targetPitch = animation.getCamPitch(); - targetYaw = animation.getCamYaw(); - targetRoll = animation.getCamRoll(); - } else { - targetYaw = 0.0F; - targetPitch = 0.0F; - targetRoll = 0.0F; - } - } - float var3 = Minecraft.getInstance().getDeltaFrameTime(); - float var4 = var3 / 5.0F; - if (var4 == 0.0F) { - var4 = 0.0022857143F; - } - - currentPitch = MathHelper.lerp(var4, currentPitch, targetPitch); - currentYaw = MathHelper.lerp(var4, currentYaw, targetYaw); - currentRoll = MathHelper.lerp(var4, currentRoll, targetRoll); - event.setPitch(event.getPitch() + currentPitch); - event.setYaw(event.getYaw() + currentYaw); - event.setRoll(event.getRoll() + currentRoll); - } - } - - private static Vec3 targetOffset = Vec3.ZERO; - private static Vec3 currentOffset = Vec3.ZERO; - - @SubscribeEvent - public static void changeCameraPos(ViewportEvent.ComputeCameraAngles event) { - Camera camera = event.getCamera(); - Entity entity = camera.getEntity(); - Minecraft minecraft = Minecraft.getInstance(); - if(entity == minecraft.player && minecraft.options.getCameraType().isFirstPerson()) { - LocalPlayer player = minecraft.player; - - AnimationData animation = AnimationUtils.getPredicateAnimationData(animationData -> - !animationData.getCamPosOffset().multiply(1,0,1).equals(Vec3.ZERO) - ); - float var3 = Minecraft.getInstance().getDeltaFrameTime(); - float var4 = var3 / 5.0F; - if (var4 == 0.0F) { - var4 = 0.0022857143F; - } - - targetOffset = Vec3.ZERO; - if(animation != null) { - Vec3 camPosOffset = animation.getCamPosOffset().multiply(1,0,1); - AnimationData data = AnimationUtils.getEyeModifierAnimationData(player); - if(data instanceof RawAnimationData) { - camPosOffset = camPosOffset.add(0, data.getCamPosOffset().y, 0); - } - if(animation.isCamPosOffsetRelative()) { - float yRot = player.yBodyRotO + (player.yBodyRot - player.yBodyRotO) * minecraft.getPartialTick(); - float bodyAngel = -(yRot + 90) * ((float)Math.PI / 180F); - double cos = Math.cos(bodyAngel); - double sin = Math.sin(bodyAngel); - double x = camPosOffset.x; - double z = camPosOffset.z; - targetOffset = new Vec3( - sin * x + cos * z, - camPosOffset.y, - cos * x - sin * z - ); - } else { - if(camPosOffset.distanceToSqr(Vec3.ZERO) <= 10.0 * 10.0 * 10.0) { - targetOffset = camPosOffset; - } - } - } - - currentOffset = new Vec3( - MathHelper.lerp(var4, currentOffset.x, targetOffset.x), - MathHelper.lerp(var4, currentOffset.y, targetOffset.y), - MathHelper.lerp(var4, currentOffset.z, targetOffset.z) - ); - if(!currentOffset.equals(Vec3.ZERO)) { - camera.position = player.getEyePosition(minecraft.getPartialTick()) - .add(currentOffset); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/event/client/ClientPlayerEvent.java b/src/main/java/top/leisuretimedock/animationcore/animation/event/client/ClientPlayerEvent.java deleted file mode 100644 index 924af56..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/event/client/ClientPlayerEvent.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.event.client; - -import top.leisuretimedock.animationcore.animation.AnimationApi; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; - -import java.util.HashMap; -import java.util.Map; - -@OnlyIn(Dist.CLIENT) -public class ClientPlayerEvent { - @SubscribeEvent - public static void onPlayerTick(TickEvent.PlayerTickEvent event) { - if (event.side.isClient() && event.phase == TickEvent.Phase.START) { - Player player = event.player; - if(player.tickCount % 10 != 0) return; - if (!(player instanceof AbstractClientPlayer clientPlayer)) return; - AnimationApi.getHelper(clientPlayer).refreshAnimation(); - } - } - - public static Map> runs = new HashMap<>(); - @SubscribeEvent - public static void delayRuns(TickEvent.PlayerTickEvent event) { - if (event.side.isClient() && event.phase == TickEvent.Phase.END) { - Map.copyOf(runs).forEach((runnable, countMap) -> { - if(countMap.getValue() >= countMap.getKey()) { - runnable.run(); - runs.remove(runnable); - } else { - countMap.setValue(countMap.getValue() + 1); - } - }); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/event/client/EntityRendererRegisterEvent.java b/src/main/java/top/leisuretimedock/animationcore/animation/event/client/EntityRendererRegisterEvent.java deleted file mode 100644 index 48b4acc..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/event/client/EntityRendererRegisterEvent.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.event.client; - -import top.leisuretimedock.animationcore.animation.entity.renderer.AnimationRideRenderer; -import top.leisuretimedock.animationcore.animation.register.AnimationEntities; -import net.minecraftforge.client.event.EntityRenderersEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; - -public class EntityRendererRegisterEvent { - @SubscribeEvent - public static void registerEntityRenderer(EntityRenderersEvent.RegisterRenderers event) { - event.registerEntityRenderer(AnimationEntities.RIDE.get(), AnimationRideRenderer::new); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/event/create/AnimationEvent.java b/src/main/java/top/leisuretimedock/animationcore/animation/event/create/AnimationEvent.java deleted file mode 100644 index 19a8c1d..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/event/create/AnimationEvent.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.event.create; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.eventbus.api.Cancelable; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.fml.LogicalSide; -import org.jetbrains.annotations.Nullable; - -@Cancelable -@Event.HasResult -public class AnimationEvent extends Event { - public final LogicalSide side; - - AnimationEvent(LogicalSide side) { - this.side = side; - } - - public enum Type { - APPLY, INVITE, REQUEST - } - - public static class Send extends AnimationEvent { - private int validTick; - private int cooldownTick; - public final Type type; - public Send(LogicalSide side, int validTick, int cooldownTick, Type type) { - super(side); - this.validTick = validTick; - this.cooldownTick = cooldownTick; - this.type = type; - } - - public int getValidTick() { - return validTick; - } - public int getCooldownTick() { - return cooldownTick; - } - - public void setValidTick(int validTick) { - this.validTick = validTick; - } - public void setCooldownTick(int cooldownTick) { - this.cooldownTick = cooldownTick; - } - } - - public static class Accept extends AnimationEvent { - private int validDistance; - public final Type type; - public Accept(Type type) { - super(LogicalSide.SERVER); - this.type = type; - } - public Accept(Type type, int validDistance) { - this(type); - this.validDistance = validDistance; - } - - public int getValidDistance() { - return validDistance; - } - public void setValidDistance(int validDistance) { - this.validDistance = validDistance; - } - } - - public static class Play extends AnimationEvent { - private final @Nullable Player player; - private final ResourceLocation layer; - private final AnimationData animation; - public Play(LogicalSide side, @Nullable Player player, ResourceLocation layer, AnimationData animation) { - super(side); - this.player = player; - this.layer = layer; - this.animation = animation; - } - - public @Nullable Player getPlayer() { - return player; - } - public ResourceLocation getLayer() { - return layer; - } - public AnimationData getAnimation() { - return animation; - } - } - - public static class Join extends AnimationEvent { - private final Player player; - private final Player target; - private boolean force; - public Join(Player player, Player target, boolean force) { - super(LogicalSide.SERVER); - this.player = player; - this.target = target; - this.force = force; - } - - public Player getPlayer() { - return player; - } - public Player getTarget() { - return target; - } - public boolean isForce() { - return force; - } - - public void setForce(boolean force) { - this.force = force; - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/event/create/AnimationRegisterEvent.java b/src/main/java/top/leisuretimedock/animationcore/animation/event/create/AnimationRegisterEvent.java deleted file mode 100644 index af7dff0..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/event/create/AnimationRegisterEvent.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.event.create; - -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.RawAnimationData; -import top.leisuretimedock.animationcore.animation.register.RawAnimationRegistry; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.eventbus.api.Event; - -import java.util.HashMap; -import java.util.Map; - -public class AnimationRegisterEvent extends Event { - public static class Layer extends AnimationRegisterEvent { - private final Map layers = new HashMap<>(); - - public Map getLayers() { - return layers; - } - - public void registerLayer(ResourceLocation key, Integer value) { - layers.put(key, value); - } - } - - public static class Animation extends AnimationRegisterEvent { - private final Map animations = new HashMap<>(); - - public Map getAnimations() { - return new HashMap<>(animations); - } - - public void registerAnimation(ResourceLocation location, GenericAnimationData animation) { - animations.put(location, animation); - } - } - - public static class RawAnimation extends AnimationRegisterEvent { - private final Map animations = new HashMap<>(); - - public Map getAnimations() { - return new HashMap<>(animations); - } - - public void registerAnimation(ResourceLocation location, RawAnimationData animation) { - if (RawAnimationRegistry.validateLocation(location)) { - animations.put(location, animation); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationDataHelper.java b/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationDataHelper.java deleted file mode 100644 index 1861f4f..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationDataHelper.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.helper; - -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.register.RawAnimationRegistry; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; -import java.util.Set; - -public class AnimationDataHelper { - AnimationDataHelper() {} - public static AnimationDataHelper getHelper() { - return new AnimationDataHelper(); - } - - public Set getAllAnimations() { - Set set = new HashSet<>(getAnimationNames()); - Set strings = DistExecutor.unsafeCallWhenOn(Dist.CLIENT, - () -> this::getAnimationsClient); - if (strings != null && !strings.isEmpty()) set.addAll(strings); - return set; - } - - @OnlyIn(Dist.CLIENT) - private Set getAnimationsClient() { - return new HashSet<>(RawAnimationRegistry.getAnimations().keySet()); - } - - private Set getAnimationNames(){ - return new HashSet<>(AnimationRegistry.getAnimations().keySet()); - } - - public Set getLayers() { - return new HashSet<>(AnimationRegistry.getLayers().keySet()); - } - - public boolean isLayerPresent(ResourceLocation location) { - return getLayers().contains(location); - } - - public boolean isAnimationPresent(ResourceLocation location) { - return getAllAnimations().contains(location); - } - - public @Nullable AnimationData getAnimationData(ResourceLocation location) { - IAnimationService helper = AnimationApi.getServiceGetterHelper(location).getService(); - if(helper == null) return null; - return helper.getAnimation(location); - } - - public AnimationData getDataByCompoundTag(CompoundTag tag) { - AnimationData animationData = new AnimationData(); - animationData.deserializeNBT(tag); - IAnimationService service = AnimationApi.getServiceGetterHelper(animationData.getKey()).getService(); - if(service == null) return animationData; - return service.getAnimation(tag); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationHelper.java b/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationHelper.java deleted file mode 100644 index fd68cf1..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationHelper.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.helper; - -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.core.IModLazyRun; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.core.BlockPos; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.UUID; - -public class AnimationHelper { - private final Player player; - private final AnimationLazyHelper lazyRun; - AnimationHelper(Player player) { - this.player = player; - this.lazyRun = new AnimationLazyHelper(player); - } - - public static AnimationHelper getHelper(Player player) { - return new AnimationHelper(player); - } - - public ApiBack playAnimation(ResourceLocation layer, ResourceLocation location) { - IAnimationService service = AnimationApi.getServiceGetterHelper(location).getService(); - if(service == null) return ApiBack.FAIL; - AnimationData data = service.getAnimation(location); - if(data == null) return ApiBack.FAIL; - return lazyRun.testLoadedAndCall( - () -> service.playAnimation(lazyRun.getServerPlayer(), layer, data), - () -> service.playAnimation(lazyRun.getClientPlayer(), layer, location) - ); - } - - public ApiBack playAnimationWithRide(ResourceLocation layer, AnimationData animation, boolean isForce) { - IAnimationService service = AnimationApi.getServiceGetterHelper(animation.getKey()).getService(); - if(service == null) return ApiBack.FAIL; - return lazyRun.testLoadedAndCall( - () -> service.playAnimationWithRide(lazyRun.getServerPlayer(), layer, animation, isForce), - () -> service.playAnimationWithRide(lazyRun.getClientPlayer(), layer, animation.getKey(), isForce) - ); - } - public ApiBack playAnimationWithRide(ResourceLocation layer, AnimationData animation, boolean isForce, Vec3 pos) { - IAnimationService service = AnimationApi.getServiceGetterHelper(animation.getKey()).getService(); - if(service == null) return ApiBack.FAIL; - return lazyRun.testLoadedAndCall( - () -> service.playAnimationWithRide(lazyRun.getServerPlayer(), layer, animation, isForce, pos), - () -> ApiBack.UNSUPPORTED - ); - } - public ApiBack playAnimationWithRide(ResourceLocation layer, AnimationData animation, boolean isForce, BlockPos pos) { - return playAnimationWithRide(layer, animation, isForce, pos.getCenter()); - } - - public void clearAnimation() { - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - lazyRun.testLoadedAndRun( - () -> service.clearAnimations(lazyRun.getServerPlayer()), - () -> service.clearAnimations(lazyRun.getClientPlayer()) - ); - } - } - - public ApiBack detachAnimation() { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack back = lazyRun.testLoadedAndCall(() -> service.detachAnimation(lazyRun.getServerPlayer())); - if(back == ApiBack.SUCCESS) return back; - else result = back; - } - return result; - } - - public ApiBack joinAnimation(Player target, boolean force) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall(() -> { - if(!(target instanceof ServerPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - return service.joinAnimation(lazyRun.getServerPlayer(), targetPlayer, force); - }); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - public ApiBack syncToAnimation(Player target) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall(() -> { - if(!(target instanceof ServerPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - service.syncAnimation(lazyRun.getServerPlayer(), targetPlayer); - return ApiBack.SUCCESS; - }, () -> { - if(!(target instanceof AbstractClientPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - service.syncAnimation(lazyRun.getClientPlayer(), targetPlayer); - return ApiBack.SUCCESS; - }); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - @OnlyIn(Dist.CLIENT) - public void refreshAnimation() { - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - service.refreshAnimation(lazyRun.getClientPlayer()); - } - } - - @OnlyIn(Dist.CLIENT) - public void refreshAnimationUnsafe() { - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - service.refreshAnimationUnsafe(lazyRun.getClientPlayer()); - } - } - - @Nullable - public ResourceLocation getAnimationPlaying(@Nullable ResourceLocation layer) { - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ResourceLocation playing = service.getAnimationPlaying(player, layer); - if(playing != null) return playing; - } - return null; - } - - public ApiBack removeAnimation(ResourceLocation layer) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall( - () -> service.removeAnimation(lazyRun.getServerPlayer(), layer), - () -> service.removeAnimation(lazyRun.getClientPlayer(), layer) - ); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - public ApiBack inviteAnimation(ResourceLocation layer, ResourceLocation location, Collection targets) { - IAnimationService service = AnimationApi.getServiceGetterHelper(location).getService(); - if(service == null) return ApiBack.FAIL; - return lazyRun.testLoadedAndCall( - () -> { - AnimationData data = service.getAnimation(location); - if(data == null) return ApiBack.FAIL; - return service.invite(lazyRun.getServerPlayer(), layer, data, targets); - }, - () -> { - ClientLevel level = Minecraft.getInstance().level; - if(level == null) return ApiBack.FAIL; - List list = targets.stream().map(level::getPlayerByUUID) - .filter(Objects::nonNull).map(AbstractClientPlayer.class::cast).toList(); - if(list.isEmpty()) return ApiBack.FAIL; - return service.invite(layer, location, list.toArray(new AbstractClientPlayer[]{})); - } - ); - } - - public ApiBack applyAnimation(Player target) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall(() -> { - if(!(target instanceof ServerPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - return service.apply(lazyRun.getServerPlayer(), targetPlayer); - }, () -> { - if(!(target instanceof AbstractClientPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - return service.apply(targetPlayer); - }); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - public ApiBack requestAnimation(Player target, ResourceLocation layer, ResourceLocation location, boolean isRide) { - IAnimationService service = AnimationApi.getServiceGetterHelper(location).getService(); - if(service == null) return ApiBack.FAIL; - return lazyRun.testLoadedAndCall( - () -> { - AnimationData data = service.getAnimation(location); - if(data == null) return ApiBack.FAIL; - if(!(target instanceof ServerPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - return service.request(lazyRun.getServerPlayer(), targetPlayer, layer, data, isRide); - }, - () -> { - if(!(target instanceof AbstractClientPlayer targetPlayer)) return ApiBack.UNSUPPORTED; - return service.request(targetPlayer, layer, location); - } - ); - } - - public ApiBack acceptInvite(Player inviter) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall(() -> { - if(!(inviter instanceof ServerPlayer inviterPlayer)) return ApiBack.UNSUPPORTED; - return service.acceptInvite(lazyRun.getServerPlayer(), inviterPlayer); - }); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - public ApiBack acceptApply(Player applier) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall(() -> { - if(!(applier instanceof ServerPlayer applierPlayer)) return ApiBack.UNSUPPORTED; - return service.acceptApply(lazyRun.getServerPlayer(), applierPlayer); - }); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - public ApiBack acceptRequest(Player requestor) { - ApiBack result = ApiBack.FAIL; - for (IAnimationService service : AnimationApi.getServiceGetterHelper().getAllServices()) { - ApiBack apiBack = lazyRun.testLoadedAndCall(() -> { - if(!(requestor instanceof ServerPlayer requestorPlayer)) return ApiBack.UNSUPPORTED; - return service.acceptRequest(lazyRun.getServerPlayer(), requestorPlayer); - }); - if(apiBack == ApiBack.SUCCESS) return apiBack; - else result = apiBack; - } - return result; - } - - static class AnimationLazyHelper implements IModLazyRun { - private final Player player; - AnimationLazyHelper(Player player) { - this.player = player; - } - - @Override - public boolean testCondition() { - return player instanceof ServerPlayer; - } - - public ServerPlayer getServerPlayer() { - return (ServerPlayer) player; - } - - @OnlyIn(Dist.CLIENT) - public AbstractClientPlayer getClientPlayer() { - return (AbstractClientPlayer) player; - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationJsonHelper.java b/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationJsonHelper.java deleted file mode 100644 index 33dd49b..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationJsonHelper.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.helper; - -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.util.AnimJson; -import top.leisuretimedock.animationcore.animation.data.util.AnimLayerJson; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import net.minecraft.server.MinecraftServer; -import net.minecraft.world.level.storage.LevelResource; -import org.jetbrains.annotations.Nullable; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Comparator; - -public class AnimationJsonHelper { - private final MinecraftServer server; - AnimationJsonHelper(MinecraftServer server) { - this.server = server; - } - - public static AnimationJsonHelper getHelper(MinecraftServer server) { - return new AnimationJsonHelper(server); - } - - /** - * Get animation path - * @return path - */ - private Path getAnimationPath() { - Path dataPackPath = server.getWorldPath(LevelResource.DATAPACK_DIR); - return dataPackPath.resolve("animation"); - } - - /** - * Delete directories - * @throws IOException Exception - */ - public void clearPath() throws IOException { - Path animationPath = getAnimationPath(); - if (!Files.exists(animationPath)) return; - try (var pathStream = Files.walk(animationPath)) { - pathStream.sorted(Comparator.reverseOrder()).forEach(path -> { - try { - Files.delete(path); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } catch (RuntimeException ignored) {} - } - - /** - * Generate all json from server animation - * @param isLayer If layer - * @param isReset If reset - * @return Generate path - */ - @Nullable - public Path generateJson(boolean isLayer, boolean isReset) { - try { - Path animationPath = getAnimationPath(); - if (!Files.exists(animationPath)) { - try {Files.createDirectories(animationPath);} - catch (IOException e) { throw new RuntimeException(e); } - } - if(isReset) clearPath(); - - if(isLayer) { - return AnimLayerJson.Writer.syntaxImmediately(animationPath); - } else { - for (GenericAnimationData value : AnimationRegistry.getAnimations().values()) { - AnimJson.Writer.stream(animationPath, value).syntax(); - } - } - return animationPath; - } catch (Exception ignored){} - return null; - } - - /** - * Generate example json - * @return Example json path - */ - @Nullable - public Path generateExample() { - try { - Path animationPath = getAnimationPath(); - return AnimJson.Writer.syntaxExample(animationPath); - } catch (Exception ignored) {} - return null; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationServiceGetterHelper.java b/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationServiceGetterHelper.java deleted file mode 100644 index 3c52302..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/helper/AnimationServiceGetterHelper.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.helper; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Optional; -import java.util.Set; - -public class AnimationServiceGetterHelper implements IAnimationServiceGetter { - private final @Nullable ResourceLocation location; - private final @Nullable CompoundTag tag; - - public AnimationServiceGetterHelper(@NotNull ResourceLocation location) { - this.location = location; - this.tag = null; - } - - public AnimationServiceGetterHelper(@NotNull CompoundTag tag) { - this.tag = tag; - this.location = null; - } - - public AnimationServiceGetterHelper(){ - this.tag = null; - this.location = null; - } - - public static IAnimationServiceGetter create(ResourceLocation location) { - return new AnimationServiceGetterHelper(location); - } - - @Override - public boolean filter(IAnimationService helper) { - if(location != null && helper.isAnimationPresent(location)) return true; - return Optional.ofNullable(tag).map(helper::getAnimation).map(AnimationData::getKey) - .map(helper::isAnimationPresent).isPresent(); - } - - @Override - public @Nullable IAnimationService getService() { - return IAnimationServiceGetter.super.getService(); - } - - public Set> getAllServices() { - return IAnimationServiceGetter.HELPERS; - } - - @Nullable - public > T getService(Class tClass) { - IAnimationService service = getService(); - if(tClass.isInstance(service)) return tClass.cast(service); - return null; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/helper/IAnimationServiceGetter.java b/src/main/java/top/leisuretimedock/animationcore/animation/helper/IAnimationServiceGetter.java deleted file mode 100644 index 5acd336..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/helper/IAnimationServiceGetter.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.helper; - -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import top.leisuretimedock.animationcore.animation.service.RawAnimationService; -import org.jetbrains.annotations.Nullable; - -import java.util.LinkedHashSet; -import java.util.Set; - -public interface IAnimationServiceGetter { - /** - * Get helper - */ - Set> HELPERS = new LinkedHashSet<>(){{ - add(AnimationService.INSTANCE); - add(RawAnimationService.INSTANCE); - }}; - - /** - * @see IAnimationServiceGetter#filter - */ - @Nullable - default IAnimationService getService() { - for (IAnimationService helper : HELPERS) { - if (filter(helper)) { - return helper; - } - } - return null; - } - - boolean filter(IAnimationService helper); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/mixin/IMixinKeyframeAnimationPlayer.java b/src/main/java/top/leisuretimedock/animationcore/animation/mixin/IMixinKeyframeAnimationPlayer.java deleted file mode 100644 index 10fe6ea..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/mixin/IMixinKeyframeAnimationPlayer.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.mixin; - -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; - -@OnlyIn(Dist.CLIENT) -public interface IMixinKeyframeAnimationPlayer { - void animcore$setCurrentTick(int tick); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/mixin/IMixinPlayerAnimationFactoryHolder.java b/src/main/java/top/leisuretimedock/animationcore/animation/mixin/IMixinPlayerAnimationFactoryHolder.java deleted file mode 100644 index 84bd2da..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/mixin/IMixinPlayerAnimationFactoryHolder.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.mixin; - -import dev.kosmx.playerAnim.api.layered.IAnimation; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public interface IMixinPlayerAnimationFactoryHolder { - record DataHolder(@Nullable ResourceLocation id, int priority, @NotNull IAnimation animation) {} - - void animcore$clearAnimations(); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/ServiceGetterPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/ServiceGetterPacket.java deleted file mode 100644 index 1a5be54..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/ServiceGetterPacket.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network; - -import top.leisuretimedock.animationcore.animation.helper.IAnimationServiceGetter; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import top.leisuretimedock.animationcore.animation.service.RawAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import org.jetbrains.annotations.Nullable; - -public abstract class ServiceGetterPacket implements IAnimationServiceGetter { - /** - * Override it to filter helper in network packet - * @param helper helper - * @return Is right helper - */ - public boolean filter(IAnimationService helper) { - if(helper instanceof AnimationService service) { - ResourceLocation animation = getAnimation(); - if(animation != null) return service.isAnimationPresent(animation); - } else if (helper instanceof RawAnimationService service) { - CompoundTag tag = getAnimationTag(); - if(tag != null) return service.getAnimation(tag) != null; - } - return false; - } - - /** - * Selectable to override it - * @return Animation loacation - * @see ServiceGetterPacket#filter - */ - @Nullable - protected ResourceLocation getAnimation() { - return null; - } - - /** - * Selectable to override it - * @return Animation data - * @see ServiceGetterPacket#filter - */ - @Nullable - protected CompoundTag getAnimationTag() { - return null; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationCapabilityPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationCapabilityPacket.java deleted file mode 100644 index 34b1a8d..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationCapabilityPacket.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toclient; - -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.player.SimplePlayerCapabilitySync; -import top.leisuretimedock.animationcore.capability.network.SimpleCapabilityPacket; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.network.NetworkEvent; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -public class AnimationCapabilityPacket extends SimpleCapabilityPacket { - public AnimationCapabilityPacket(ICapabilitySync packet) { - super(packet); - } - - public AnimationCapabilityPacket(FriendlyByteBuf buf) { - super(buf); - } - - @Override - public void handler(NetworkEvent.Context context) { - context.setPacketHandled(true); - Minecraft instance = Minecraft.getInstance(); - ClientLevel level = instance.level; - if (level == null) return; - CompoundTag nbt = getData(); - Player player = level.getPlayerByUUID(nbt.getUUID(SimplePlayerCapabilitySync.OwnerUUID)); - if(player == null) return; - try { - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - testPlayAnimations((AbstractClientPlayer) player, nbt, data); - syncData(nbt, data); - }catch (Exception ignored) {} - } - - private void testPlayAnimations(AbstractClientPlayer player, CompoundTag tag, IAnimationCapability data) { - if(data == null) return; - ResourceLocation oldRiderAnimLayer = data.getRiderAnimLayer(); - String riderAnimLayerString = tag.getString(AnimationDataCapability.RideAnimLayer); - ResourceLocation newRiderAnimLayer = riderAnimLayerString.isEmpty() ? null : new ResourceLocation(riderAnimLayerString); - if(!Objects.equals(oldRiderAnimLayer, newRiderAnimLayer)) { - String riderAnimationString = tag.getString(AnimationDataCapability.RideAnimation); - ResourceLocation newRiderAnimation = riderAnimationString.isEmpty() ? null : new ResourceLocation(riderAnimationString); - if(oldRiderAnimLayer != null) AnimationUtils.playAnimation(player, oldRiderAnimLayer, null); - if(newRiderAnimLayer != null) AnimationUtils.playAnimation(player, newRiderAnimLayer, newRiderAnimation); - } - - Set oldLayerSet = new HashSet<>(data.getAnimations().keySet()); - CompoundTag animMap = tag.getCompound(AnimationDataCapability.AnimMap); - for (String newLayerString : animMap.getAllKeys()) { - ResourceLocation newLayerLocation = new ResourceLocation(newLayerString); - String newAnimString = animMap.getString(newLayerString); - ResourceLocation newAnimLocation = newAnimString.isEmpty() ? null : new ResourceLocation(newAnimString); - ResourceLocation oldAnimLocation = data.getAnimation(newLayerLocation); - if (!Objects.equals(newAnimLocation, oldAnimLocation)) { - AnimationUtils.playAnimation(player, newLayerLocation, newAnimLocation); - } - oldLayerSet.remove(newLayerLocation); - } - for (ResourceLocation oldLayerLocation : oldLayerSet) { - AnimationUtils.playAnimation(player, oldLayerLocation, null); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationClearPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationClearPacket.java deleted file mode 100644 index d046eeb..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationClearPacket.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toclient; - -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.fml.DistExecutor; -import net.minecraftforge.network.NetworkEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Supplier; - -public record AnimationClearPacket(@Nullable ResourceLocation layer) { - public AnimationClearPacket(FriendlyByteBuf buf) { - this(buf.readNullable(FriendlyByteBuf::readResourceLocation)); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeNullable(layer, FriendlyByteBuf::writeResourceLocation); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> this::handle); - }); - } - - @OnlyIn(Dist.CLIENT) - public void handle(){ - LocalPlayer player = Minecraft.getInstance().player; - if(player == null) return; - List layers = new ArrayList<>(); - if(layer != null) layers.add(layer); - else layers.addAll(AnimationRegistry.getLayers().keySet()); - layers.forEach(layer -> AnimationUtils.playAnimation(player, layer, null)); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationClientStatusPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationClientStatusPacket.java deleted file mode 100644 index b29dd80..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationClientStatusPacket.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toclient; - -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.function.Supplier; - -public record AnimationClientStatusPacket(int status) { - public enum Status { - ANIM_CACHE_CLEAR(0), - LAYER_CACHE_CLEAR(1), - ANIM_REGISTER(2), - LAYER_REGISTER(3),; - private final int value; - Status(final int value) { - this.value = value; - } - @Nullable - public static Status getStatus(final int value) { - for (Status status : values()) { - if (status.value == value) { - return status; - } - } - return null; - } - } - public AnimationClientStatusPacket(Status status) { - this(status.value); - } - public AnimationClientStatusPacket(FriendlyByteBuf buf) { - this(buf.readInt()); - } - public void encode(FriendlyByteBuf buf) { - buf.writeInt(status); - } - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - Status state = Status.getStatus(status); - if(state == null) return; - AnimationRegistry.ClientCache.animationStatusUpdate(state); - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationJsonPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationJsonPacket.java deleted file mode 100644 index 4898ab9..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/AnimationJsonPacket.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toclient; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.util.AnimJson; -import top.leisuretimedock.animationcore.animation.data.util.AnimLayerJson; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.network.NetworkEvent; - -import java.util.Map; -import java.util.function.Supplier; - -public record AnimationJsonPacket(String json, boolean isLayer) { - public AnimationJsonPacket(FriendlyByteBuf buf) { - this(buf.readUtf(), buf.readBoolean()); - } - public void encode(FriendlyByteBuf buf) { - buf.writeUtf(json); - buf.writeBoolean(isLayer); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - JsonElement element = JsonParser.parseString(json); - if(isLayer) { - Map parse = AnimLayerJson.Reader.stream(element).parse(); - parse.forEach(AnimationRegistry.ClientCache::cacheAddAnimationLayer); - } else { - GenericAnimationData animation = AnimJson.Reader.stream(element).parse(); - AnimationRegistry.ClientCache.cacheAddAnimation(animation.getKey(), animation); - } - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/RawAnimationCapabilityPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/RawAnimationCapabilityPacket.java deleted file mode 100644 index 1b3c049..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/RawAnimationCapabilityPacket.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toclient; - -import top.leisuretimedock.animationcore.animation.capability.RawAnimationDataCapability; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.player.SimplePlayerCapabilitySync; -import top.leisuretimedock.animationcore.capability.network.SimpleCapabilityPacket; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.network.NetworkEvent; - -import java.util.HashSet; -import java.util.Objects; -import java.util.Set; - -public class RawAnimationCapabilityPacket extends SimpleCapabilityPacket { - public RawAnimationCapabilityPacket(ICapabilitySync packet) { - super(packet); - } - - public RawAnimationCapabilityPacket(FriendlyByteBuf buf) { - super(buf); - } - - @Override - public void handler(NetworkEvent.Context context) { - context.setPacketHandled(true); - Minecraft instance = Minecraft.getInstance(); - ClientLevel level = instance.level; - if (level == null) return; - CompoundTag nbt = getData(); - Player player = level.getPlayerByUUID(nbt.getUUID(SimplePlayerCapabilitySync.OwnerUUID)); - if(player == null) return; - try { - RawAnimationDataCapability data = RawAnimationDataCapability.getCapability(player).orElse(null); - testPlayAnimations((AbstractClientPlayer) player, nbt, data); - syncData(nbt, data); - }catch (Exception ignored) {} - } - - private void testPlayAnimations(AbstractClientPlayer player, CompoundTag tag, RawAnimationDataCapability data) { - if(data == null) return; - Set oldLayerSet = new HashSet<>(data.getAnimations().keySet()); - CompoundTag animMap = tag.getCompound(RawAnimationDataCapability.AnimMap); - for (String newLayerString : animMap.getAllKeys()) { - ResourceLocation newLayerLocation = new ResourceLocation(newLayerString); - String newAnimString = animMap.getString(newLayerString); - ResourceLocation newAnimLocation = newAnimString.isEmpty() ? null : new ResourceLocation(newAnimString); - ResourceLocation oldAnimLocation = data.getAnimation(newLayerLocation); - if (!Objects.equals(newAnimLocation, oldAnimLocation)) { - AnimationUtils.playAnimation(player, newLayerLocation, newAnimLocation); - } - oldLayerSet.remove(newLayerLocation); - } - for (ResourceLocation oldLayerLocation : oldLayerSet) { - AnimationUtils.playAnimation(player, oldLayerLocation, null); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/SyncAnimationPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/SyncAnimationPacket.java deleted file mode 100644 index aff5cbe..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toclient/SyncAnimationPacket.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toclient; - -import top.leisuretimedock.animationcore.animation.event.client.ClientPlayerEvent; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkEvent; - -import java.util.AbstractMap; -import java.util.UUID; -import java.util.function.Supplier; - -public class SyncAnimationPacket { - private final UUID playerUUID; - private final UUID targetUUID; - public SyncAnimationPacket(UUID playerUUID, UUID targetUUID) { - this.playerUUID = playerUUID; - this.targetUUID = targetUUID; - } - - public SyncAnimationPacket(FriendlyByteBuf buf) { - this.playerUUID = buf.readUUID(); - this.targetUUID = buf.readUUID(); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeUUID(this.playerUUID); - buf.writeUUID(this.targetUUID); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - Minecraft instance = Minecraft.getInstance(); - ClientLevel level = instance.level; - if(level == null) return; - AbstractClientPlayer player = (AbstractClientPlayer) level.getPlayerByUUID(playerUUID); - AbstractClientPlayer target = (AbstractClientPlayer) level.getPlayerByUUID(targetUUID); - ClientPlayerEvent.runs.put( - () -> AnimationUtils.syncAnimation(player, target), - new AbstractMap.SimpleEntry<>(5, 0) - ); - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/ApplyAnimationPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/ApplyAnimationPacket.java deleted file mode 100644 index 29984bb..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/ApplyAnimationPacket.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toserver; - -import top.leisuretimedock.animationcore.animation.network.ServiceGetterPacket; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; - -import java.util.UUID; -import java.util.function.Supplier; - -public class ApplyAnimationPacket extends ServiceGetterPacket { - private final UUID targetUUID; - - public ApplyAnimationPacket(UUID targetUUID) { - this.targetUUID = targetUUID; - } - - public ApplyAnimationPacket(FriendlyByteBuf buf) { - this.targetUUID = buf.readUUID(); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeUUID(targetUUID); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - ServerPlayer target; - ServerPlayer sender = context.getSender(); - if(sender == null || sender.getServer() == null) return; - if(this.targetUUID == null) target = sender; - else target = sender.getServer().getPlayerList().getPlayer(this.targetUUID); - if(target == null) return; - IAnimationService service = getService(); - if(service == null) return; - if(target == sender) return; - service.apply(sender, target); - }); - } - - @Override - public boolean filter(IAnimationService helper) { - return true; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/InviteAnimationPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/InviteAnimationPacket.java deleted file mode 100644 index 6be4287..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/InviteAnimationPacket.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toserver; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.network.ServiceGetterPacket; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; -import java.util.UUID; -import java.util.function.Supplier; - -public class InviteAnimationPacket extends ServiceGetterPacket { - private final @Nullable CompoundTag animationTag; - private final ResourceLocation layer; - private final ResourceLocation animation; - private final Collection targets; - - public InviteAnimationPacket(AnimationData data, ResourceLocation layer, Collection targets) { - this.animationTag = data.serializeNBT(); - this.animation = data.getKey(); - this.layer = layer; - this.targets = targets; - } - - public InviteAnimationPacket(FriendlyByteBuf buf) { - this.animationTag = buf.readNullable(FriendlyByteBuf::readAnySizeNbt); - this.layer = buf.readResourceLocation(); - this.animation = buf.readResourceLocation(); - this.targets = buf.readList(FriendlyByteBuf::readUUID); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeNullable(animationTag, FriendlyByteBuf::writeNbt); - buf.writeResourceLocation(layer); - buf.writeResourceLocation(animation); - buf.writeCollection(targets, FriendlyByteBuf::writeUUID); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - ServerPlayer sender = context.getSender(); - if(sender == null) return; - IAnimationService service = getService(); - if(service == null) return; - AnimationData data = service.getAnimation(animationTag); - if(data == null) return; - if(!targets.isEmpty()) service.invite(sender, layer, data, targets); - else service.playAnimationWithRide(sender, layer, data, false); - }); - } - - @Override - public @Nullable CompoundTag getAnimationTag() { - return animationTag; - } - - @Override - public @Nullable ResourceLocation getAnimation() { - return animation; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/PlayAnimationPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/PlayAnimationPacket.java deleted file mode 100644 index 29eabb0..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/PlayAnimationPacket.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toserver; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.network.ServiceGetterPacket; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; -import java.util.function.Supplier; - -public class PlayAnimationPacket extends ServiceGetterPacket { - private final @Nullable CompoundTag animationTag; - private final ResourceLocation layer; - private final ResourceLocation animation; - private final @Nullable UUID uuid; - - public PlayAnimationPacket(AnimationData data, ResourceLocation layer, ResourceLocation animation, @Nullable UUID uuid) { - this.animationTag = data.serializeNBT(); - this.layer = layer; - this.animation = animation; - this.uuid = uuid; - } - - public PlayAnimationPacket(FriendlyByteBuf buf){ - this.animationTag = buf.readNullable(FriendlyByteBuf::readAnySizeNbt); - this.layer = buf.readResourceLocation(); - this.animation = buf.readResourceLocation(); - this.uuid = buf.readNullable(FriendlyByteBuf::readUUID); - } - - public void encode(FriendlyByteBuf buf){ - buf.writeNullable(animationTag, FriendlyByteBuf::writeNbt); - buf.writeResourceLocation(layer); - buf.writeResourceLocation(animation); - buf.writeNullable(uuid, FriendlyByteBuf::writeUUID); - } - - public void handle(Supplier supplier){ - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - ServerPlayer target; - ServerPlayer sender = context.getSender(); - if(sender == null || sender.getServer() == null) return; - if(this.uuid == null) target = sender; - else target = sender.getServer().getPlayerList().getPlayer(this.uuid); - if(target == null) return; - IAnimationService service = getService(); - if(service == null) return; - AnimationData data = service.getAnimation(animationTag); - if(data == null) return; - if(target == sender) service.playAnimation(target, layer, data); - else service.request(sender, target, layer, data, false); - }); - } - - @Override - public @Nullable CompoundTag getAnimationTag() { - return animationTag; - } - - @Override - public @Nullable ResourceLocation getAnimation() { - return animation; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/PlayAnimationRidePacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/PlayAnimationRidePacket.java deleted file mode 100644 index 581fceb..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/PlayAnimationRidePacket.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toserver; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.network.ServiceGetterPacket; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; -import java.util.function.Supplier; - -public class PlayAnimationRidePacket extends ServiceGetterPacket { - private final @Nullable CompoundTag animationTag; - private final ResourceLocation layer; - private final ResourceLocation animation; - private final @Nullable UUID uuid; - private final boolean force; - - public PlayAnimationRidePacket(@Nullable AnimationData data, ResourceLocation layer, ResourceLocation animation, @Nullable UUID uuid, boolean force) { - this.animationTag = data != null ? data.serializeNBT() : null; - this.layer = layer; - this.animation = animation; - this.uuid = uuid; - this.force = force; - } - - public PlayAnimationRidePacket(FriendlyByteBuf buf) { - this.animationTag = buf.readNullable(FriendlyByteBuf::readAnySizeNbt); - this.layer = buf.readResourceLocation(); - this.animation = buf.readResourceLocation(); - this.uuid = buf.readNullable(FriendlyByteBuf::readUUID); - this.force = buf.readBoolean(); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeNullable(animationTag, FriendlyByteBuf::writeNbt); - buf.writeResourceLocation(layer); - buf.writeResourceLocation(animation); - buf.writeNullable(uuid, FriendlyByteBuf::writeUUID); - buf.writeBoolean(force); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - ServerPlayer target; - ServerPlayer sender = context.getSender(); - if(sender == null || sender.getServer() == null) return; - if(this.uuid == null) target = sender; - else target = sender.getServer().getPlayerList().getPlayer(this.uuid); - if(target == null) return; - IAnimationService service = getService(); - if(service == null) return; - AnimationData data = service.getAnimation(animationTag); - if(data == null) return; - if(target == sender) service.playAnimationWithRide(target, layer, data, force); - else service.request(sender, target, layer, data, true); - }); - } - - @Override - public @Nullable CompoundTag getAnimationTag() { - return animationTag; - } - - @Override - public @Nullable ResourceLocation getAnimation() { - return animation; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/RequestAnimationPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/RequestAnimationPacket.java deleted file mode 100644 index 6452e3c..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/RequestAnimationPacket.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toserver; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.network.ServiceGetterPacket; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; -import org.jetbrains.annotations.Nullable; - -import java.util.UUID; -import java.util.function.Supplier; - -public class RequestAnimationPacket extends ServiceGetterPacket { - private final @Nullable CompoundTag animationTag; - private final ResourceLocation layer; - private final ResourceLocation animation; - private final UUID targetUUID; - - public RequestAnimationPacket(AnimationData data, ResourceLocation layer, UUID targetUUID) { - this.animationTag = data.serializeNBT(); - this.animation = data.getKey(); - this.layer = layer; - this.targetUUID = targetUUID; - } - - public RequestAnimationPacket(FriendlyByteBuf buf) { - this.animationTag = buf.readNullable(FriendlyByteBuf::readAnySizeNbt); - this.layer = buf.readResourceLocation(); - this.animation = buf.readResourceLocation(); - this.targetUUID = buf.readUUID(); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeNullable(animationTag, FriendlyByteBuf::writeNbt); - buf.writeResourceLocation(layer); - buf.writeResourceLocation(animation); - buf.writeUUID(targetUUID); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - ServerPlayer target; - ServerPlayer sender = context.getSender(); - if(sender == null || sender.getServer() == null) return; - if(this.targetUUID == null) target = sender; - else target = sender.getServer().getPlayerList().getPlayer(this.targetUUID); - if(target == null) return; - IAnimationService service = getService(); - if(service == null) return; - AnimationData data = service.getAnimation(animationTag); - if(data == null) return; - if(target == sender) return; - service.request(sender, target, layer, data, false); - }); - } - - @Override - public @Nullable CompoundTag getAnimationTag() { - return animationTag; - } - - @Override - public @Nullable ResourceLocation getAnimation() { - return animation; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/StopAnimationPacket.java b/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/StopAnimationPacket.java deleted file mode 100644 index cc81330..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/network/toserver/StopAnimationPacket.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.network.toserver; - -import top.leisuretimedock.animationcore.animation.AnimationApi; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.network.NetworkEvent; - -import java.util.function.Supplier; - -public record StopAnimationPacket(ResourceLocation layer) { - public StopAnimationPacket(FriendlyByteBuf buf) { - this(buf.readResourceLocation()); - } - - public void encode(FriendlyByteBuf buf) { - buf.writeResourceLocation(layer); - } - - public void handle(Supplier supplier) { - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> { - context.setPacketHandled(true); - ServerPlayer sender = context.getSender(); - if(sender == null) return; - AnimationApi.getHelper(sender).removeAnimation(layer); - }); - } - -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationCapabilities.java b/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationCapabilities.java deleted file mode 100644 index 50a9207..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationCapabilities.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.register; - -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.RawAnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationCapabilityPacket; -import top.leisuretimedock.animationcore.animation.network.toclient.RawAnimationCapabilityPacket; -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.player.PlayerCapabilityRegistry; -import top.leisuretimedock.animationcore.capability.network.CapabilityChannel; -import top.leisuretimedock.animationcore.core.ModChannel; -import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.common.capabilities.CapabilityToken; - -public class AnimationCapabilities { - public static void registerAnimationCapability() { - CapabilityChannel channel = CapabilityUtils.createChannel(); - CapabilityUtils.registerPlayerCapabilityWithNetwork( - AnimationDataCapability.key, - new PlayerCapabilityRegistry.CapabilityRecord<>( - AnimationDataCapability.class, - CapabilityManager.get(new CapabilityToken<>() {}), - IAnimationCapability.class - ), - channel, - ModChannel.getAndAddCid(), - AnimationCapabilityPacket.class, - AnimationCapabilityPacket::new, - AnimationCapabilityPacket::encode, - AnimationCapabilityPacket::handle - ); - CapabilityUtils.registerPlayerCapabilityWithNetwork( - RawAnimationDataCapability.key, - new PlayerCapabilityRegistry.CapabilityRecord<>( - RawAnimationDataCapability.class, - CapabilityManager.get(new CapabilityToken<>() {}), - RawAnimationDataCapability.class - ), - channel, - ModChannel.getAndAddCid(), - RawAnimationCapabilityPacket.class, - RawAnimationCapabilityPacket::new, - RawAnimationCapabilityPacket::encode, - RawAnimationCapabilityPacket::handle - ); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationChannels.java b/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationChannels.java deleted file mode 100644 index 7b13dfc..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationChannels.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.register; - -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationClearPacket; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationClientStatusPacket; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationJsonPacket; -import top.leisuretimedock.animationcore.animation.network.toclient.SyncAnimationPacket; -import top.leisuretimedock.animationcore.animation.network.toserver.*; -import top.leisuretimedock.animationcore.core.ModChannel; -import net.minecraftforge.network.NetworkDirection; - -public class AnimationChannels { - public static void registerChannel() { - ModChannel.INSTANCE.messageBuilder(SyncAnimationPacket.class, cid(), NetworkDirection.PLAY_TO_CLIENT) - .decoder(SyncAnimationPacket::new) - .encoder(SyncAnimationPacket::encode) - .consumerMainThread(SyncAnimationPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(AnimationJsonPacket.class, cid(), NetworkDirection.PLAY_TO_CLIENT) - .decoder(AnimationJsonPacket::new) - .encoder(AnimationJsonPacket::encode) - .consumerMainThread(AnimationJsonPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(AnimationClientStatusPacket.class, cid(), NetworkDirection.PLAY_TO_CLIENT) - .decoder(AnimationClientStatusPacket::new) - .encoder(AnimationClientStatusPacket::encode) - .consumerMainThread(AnimationClientStatusPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(AnimationClearPacket.class, cid(), NetworkDirection.PLAY_TO_CLIENT) - .decoder(AnimationClearPacket::new) - .encoder(AnimationClearPacket::encode) - .consumerMainThread(AnimationClearPacket::handle) - .add(); - - //To server - ModChannel.INSTANCE.messageBuilder(PlayAnimationPacket.class, cid(), NetworkDirection.PLAY_TO_SERVER) - .decoder(PlayAnimationPacket::new) - .encoder(PlayAnimationPacket::encode) - .consumerMainThread(PlayAnimationPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(PlayAnimationRidePacket.class, cid(), NetworkDirection.PLAY_TO_SERVER) - .decoder(PlayAnimationRidePacket::new) - .encoder(PlayAnimationRidePacket::encode) - .consumerMainThread(PlayAnimationRidePacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(ApplyAnimationPacket.class, cid(), NetworkDirection.PLAY_TO_SERVER) - .decoder(ApplyAnimationPacket::new) - .encoder(ApplyAnimationPacket::encode) - .consumerMainThread(ApplyAnimationPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(InviteAnimationPacket.class, cid(), NetworkDirection.PLAY_TO_SERVER) - .decoder(InviteAnimationPacket::new) - .encoder(InviteAnimationPacket::encode) - .consumerMainThread(InviteAnimationPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(RequestAnimationPacket.class, cid(), NetworkDirection.PLAY_TO_SERVER) - .decoder(RequestAnimationPacket::new) - .encoder(RequestAnimationPacket::encode) - .consumerMainThread(RequestAnimationPacket::handle) - .add(); - ModChannel.INSTANCE.messageBuilder(StopAnimationPacket.class, cid(), NetworkDirection.PLAY_TO_SERVER) - .decoder(StopAnimationPacket::new) - .encoder(StopAnimationPacket::encode) - .consumerMainThread(StopAnimationPacket::handle) - .add(); - } - - private static int cid() { - return ModChannel.getAndAddCid(); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationCommands.java b/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationCommands.java deleted file mode 100644 index a7991a3..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationCommands.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.register; - -import top.leisuretimedock.animationcore.animation.command.*; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationArgument; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationLayerArgument; -import top.leisuretimedock.animationcore.animation.command.client.ListClientCommand; -import top.leisuretimedock.animationcore.animation.command.client.RefreshCommand; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.synchronization.ArgumentTypeInfo; -import net.minecraft.commands.synchronization.ArgumentTypeInfos; -import net.minecraft.commands.synchronization.SingletonArgumentInfo; -import net.minecraftforge.registries.DeferredRegister; - -import static net.minecraft.commands.Commands.literal; - -public class AnimationCommands { - public static void commonCommandRegister(LiteralArgumentBuilder builder) { - if(IAnimationService.ANIMATION_RUNNER.testCondition()){ - LiteralArgumentBuilder anim = literal("anim"); - ApplyCommand.register(anim); - InviteCommand.register(anim); - JsonCommand.register(anim); - ListServerCommand.register(anim); - PlayCommand.register(anim); - RequestCommand.register(anim); - builder.then(anim); - } - } - - public static void clientCommandRegister(LiteralArgumentBuilder builder) { - if(IAnimationService.ANIMATION_RUNNER.testCondition()) { - LiteralArgumentBuilder anim = literal("anim"); - ListClientCommand.register(anim); - RefreshCommand.register(anim); - builder.then(anim); - } - } - - public static void registerArguments(DeferredRegister> register) { - register.register("animations", - () -> ArgumentTypeInfos.registerByClass( - AnimationArgument.class, - SingletonArgumentInfo.contextFree(AnimationArgument::animation) - ) - ); - register.register("layers", - () -> ArgumentTypeInfos.registerByClass( - AnimationLayerArgument.class, - SingletonArgumentInfo.contextFree(AnimationLayerArgument::layer) - ) - ); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationEntities.java b/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationEntities.java deleted file mode 100644 index 644453f..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationEntities.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.register; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.entity.AnimationRideEntity; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.MobCategory; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.registries.DeferredRegister; -import net.minecraftforge.registries.ForgeRegistries; -import net.minecraftforge.registries.RegistryObject; - - - -public class AnimationEntities { - public static final DeferredRegister> REGISTER = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, AnimationCore.MOD_ID); - - public static final RegistryObject> RIDE = register( - "animation_ride_entity", EntityType.Builder.of((type, world) -> new AnimationRideEntity(world), MobCategory.MISC) - .sized(0.0F, 0.0F) - .setCustomClientFactory((spawnEntity, world) -> - new AnimationRideEntity(world) - ) - ); - - private static RegistryObject> register(String name, EntityType.Builder builder) { - return REGISTER.register(name, () -> builder.build(name)); - } - - public static void register(IEventBus modBus){ - REGISTER.register(modBus); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationRegistry.java b/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationRegistry.java deleted file mode 100644 index 6007378..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/register/AnimationRegistry.java +++ /dev/null @@ -1,611 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.register; - -import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.RawAnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.RawAnimationData; -import top.leisuretimedock.animationcore.animation.data.util.AnimJson; -import top.leisuretimedock.animationcore.animation.data.util.AnimLayerJson; -import top.leisuretimedock.animationcore.animation.event.create.AnimationRegisterEvent; -import top.leisuretimedock.animationcore.animation.mixin.IMixinPlayerAnimationFactoryHolder; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationClientStatusPacket; -import top.leisuretimedock.animationcore.animation.network.toclient.AnimationJsonPacket; -import top.leisuretimedock.animationcore.animation.service.RawAnimationService; -import top.leisuretimedock.animationcore.animation.utils.FileUtils; -import top.leisuretimedock.animationcore.core.ModChannel; -import dev.kosmx.playerAnim.api.layered.AnimationStack; -import dev.kosmx.playerAnim.api.layered.IAnimation; -import dev.kosmx.playerAnim.api.layered.KeyframeAnimationPlayer; -import dev.kosmx.playerAnim.api.layered.ModifierLayer; -import dev.kosmx.playerAnim.api.layered.modifier.AbstractFadeModifier; -import dev.kosmx.playerAnim.core.data.KeyframeAnimation; -import dev.kosmx.playerAnim.core.util.Ease; -import dev.kosmx.playerAnim.core.util.Pair; -import dev.kosmx.playerAnim.impl.animation.AnimationApplier; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationFactory; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.MinecraftServer; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.packs.PackType; -import net.minecraft.server.packs.resources.ResourceManager; -import net.minecraft.server.packs.resources.SimpleJsonResourceReloadListener; -import net.minecraft.util.GsonHelper; -import net.minecraft.util.profiling.ProfilerFiller; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.level.storage.LevelResource; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.event.AddReloadListenerEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; -import net.minecraftforge.event.server.ServerStartedEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; - -import javax.annotation.Nonnull; -import java.io.IOException; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.*; - -public class AnimationRegistry { - private static final Map animations = new HashMap<>(); - private static final Map layers = new HashMap<>(); - - public static Map getAnimations() { - return Map.copyOf(animations); - } - - public static Map getLayers() { - return Map.copyOf(layers); - } - - @OnlyIn(Dist.CLIENT) - public static void registerAnimations(Map animationMap) { - animations.clear(); - animations.putAll(animationMap); - } - - @OnlyIn(Dist.CLIENT) - public static void registerLayers(Map layerMap) { - layers.clear(); - layers.putAll(layerMap); - } - - @SubscribeEvent - public static void onAddReloadListeners(AddReloadListenerEvent event) { - event.addListener(AnimationDataManager.INSTANCE); - event.addListener(LayerDataManager.INSTANCE); - } - - @SubscribeEvent - public static void onServerStarted(ServerStartedEvent event) { - // Load legacy animations from datapacks - loadLegacyDataPackAnimations(event.getServer()); - - // Load animations from registration events - loadFromRegistrationEvents(); - - AnimationCore.log.info("Animation loading completed. Total animations: {}, Total layers: {}", - animations.size(), layers.size()); - } - - /** - * Load legacy datapack animations from world/datapacks/animation directory - */ - private static void loadLegacyDataPackAnimations(MinecraftServer server) { - Path dataPackPath = server.getWorldPath(LevelResource.DATAPACK_DIR); - Path animationPath = dataPackPath.resolve("animation"); - - if (!Files.exists(animationPath)) { - try { - Files.createDirectories(animationPath); - } catch (IOException e) { - AnimationCore.log.error("Failed to create legacy animation directory", e); - return; - } - } - - try { - // Handle zip files - if (Files.exists(dataPackPath.resolve("animation.zip"))) { - FileUtils.safeUnzip(dataPackPath.resolve("animation.zip").toString(), - animationPath.toAbsolutePath().toString()); - } - - Set animZipPaths = FileUtils.getAllFile( - dataPackPath.resolve("animation"), - path -> path.toString().endsWith(".anim.zip") - ); - - Set layerZipPaths = FileUtils.getAllFile( - dataPackPath.resolve("animation"), - path -> path.toString().endsWith(".layer.zip") - ); - - for (Path zipPath : animZipPaths) { - FileUtils.safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString()); - } - - for (Path zipPath : layerZipPaths) { - FileUtils.safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString()); - } - - // Load animation JSON files - Set animPaths = FileUtils.getAllFile( - dataPackPath.resolve("animation"), - path -> path.toString().endsWith(".anim.json") - ); - - Set layerPaths = FileUtils.getAllFile( - dataPackPath.resolve("animation"), - path -> path.getFileName().toString().equals("animation.layer.json") - ); - - for (Path path : animPaths) { - try { - AnimJson.Reader reader = AnimJson.Reader.stream(path); - GenericAnimationData anim = reader.parse(); - animations.put(anim.getKey(), anim); - AnimationCore.log.info("Loaded legacy animation: {} -> {}", - anim.getKey(), anim.getName()); - } catch (Exception e) { - AnimationCore.log.error("Failed to parse legacy animation JSON: {}", path, e); - } - } - - for (Path path : layerPaths) { - try { - AnimLayerJson.Reader reader = AnimLayerJson.Reader.stream(path); - Map parse = reader.parse(); - layers.putAll(parse); - AnimationCore.log.info("Loaded {} legacy layer configurations from {}", - parse.size(), path); - } catch (Exception e) { - AnimationCore.log.error("Failed to parse legacy layer JSON: {}", path, e); - } - } - } catch (Exception e) { - AnimationCore.log.error("Error loading legacy animations", e); - } - } - - /** - * Load animations from registration events - */ - private static void loadFromRegistrationEvents() { - AnimationRegisterEvent.Animation animationRegisterEvent = new AnimationRegisterEvent.Animation(); - MinecraftForge.EVENT_BUS.post(animationRegisterEvent); - Map animationMap = animationRegisterEvent.getAnimations(); - animations.putAll(animationMap); - - AnimationRegisterEvent.Layer layerRegisterEvent = new AnimationRegisterEvent.Layer(); - MinecraftForge.EVENT_BUS.post(layerRegisterEvent); - Map layerMap = layerRegisterEvent.getLayers(); - layers.putAll(layerMap); - - AnimationCore.log.info("Loaded {} animations and {} layers from registration events", - animationMap.size(), layerMap.size()); - } - - /** - * Animation data manager using SimpleJsonResourceReloadListener - */ - public static class AnimationDataManager extends SimpleJsonResourceReloadListener { - public static final AnimationDataManager INSTANCE = new AnimationDataManager(); - - private AnimationDataManager() { - super(new GsonBuilder() - .setPrettyPrinting() - .disableHtmlEscaping() - .create(), "ac_animations"); - } - - @Override - protected void apply(@Nonnull Map resources, - @Nonnull ResourceManager resourceManager, - @Nonnull ProfilerFiller profiler) { - AnimationCore.log.info("Loading animations from data packs..."); - - Map sorted = new LinkedHashMap<>(); - - // Sort resources by priority - resourceManager.listPacks().forEach(packResources -> { - Set namespaces = packResources.getNamespaces(PackType.SERVER_DATA); - namespaces.forEach(namespace -> - packResources.listResources(PackType.SERVER_DATA, namespace, "ac_animations", - (resourceLocation, inputStreamIoSupplier) -> { - String path = resourceLocation.getPath(); - if (path.endsWith(".anim.json")) { - ResourceLocation rl = new ResourceLocation(namespace, - path.substring("ac_animations/".length(), path.length() - ".json".length())); - - JsonElement el = resources.get(rl); - if (el != null) { - rl = new ResourceLocation(namespace, - path.substring("ac_animations/".length(), path.length() - ".anim.json".length())); - sorted.put(rl, el); - } - } - } - ) - ); - }); - - int loadedCount = 0; - for (Map.Entry entry : sorted.entrySet()) { - ResourceLocation animKey = entry.getKey(); - - try { - JsonObject json = GsonHelper.convertToJsonObject(entry.getValue(), "animation"); - - // Parse animation using existing AnimJson.Reader - AnimJson.Reader animReader = AnimJson.Reader.stream(json); - GenericAnimationData anim = animReader.parse(); - - // Ensure the key matches - if (!anim.getKey().equals(animKey)) { - AnimationCore.log.warn("Animation key mismatch: file={}, expected={}, actual={}", - entry.getKey(), animKey, anim.getKey()); - anim = anim.withName(animKey.getPath()); // Create a copy with correct key if possible - } - - animations.put(animKey, anim); - loadedCount++; - AnimationCore.log.debug("Loaded animation: {} -> {}", animKey, anim.getName()); - - } catch (IllegalArgumentException | JsonParseException e) { - AnimationCore.log.error("Parsing error loading animation {}", animKey, e); - } - } - - AnimationCore.log.info("Loaded {} animations from data packs", loadedCount); - } - } - - /** - * Layer data manager using SimpleJsonResourceReloadListener - */ - public static class LayerDataManager extends SimpleJsonResourceReloadListener { - public static final LayerDataManager INSTANCE = new LayerDataManager(); - - - private LayerDataManager() { - super(new GsonBuilder() - .setPrettyPrinting() - .disableHtmlEscaping() - .create(), "ac_animations"); - } - - @Override - protected void apply(@Nonnull Map resources, - @Nonnull ResourceManager resourceManager, - @Nonnull ProfilerFiller profiler) { - AnimationCore.log.info("Loading layer configurations from data packs..."); - - Map sorted = new LinkedHashMap<>(); - - // Sort resources by priority - resourceManager.listPacks().forEach(packResources -> { - Set namespaces = packResources.getNamespaces(PackType.SERVER_DATA); - namespaces.forEach(namespace -> - packResources.listResources(PackType.SERVER_DATA, namespace, "ac_animations", - (resourceLocation, inputStreamIoSupplier) -> { - String path = resourceLocation.getPath(); - if (path.endsWith("animation.layer.json")) { - ResourceLocation rl = new ResourceLocation(namespace, "animation.layer"); - - JsonElement el = resources.get(rl); - if (el != null) { - rl = new ResourceLocation(namespace, "animation_layer"); - sorted.put(rl, el); - } - } - } - ) - ); - }); - - int loadedCount = 0; - for (Map.Entry entry : sorted.entrySet()) { - try { - JsonElement json = entry.getValue(); - AnimLayerJson.Reader layerReader = AnimLayerJson.Reader.stream(json); - Map parsedLayers = layerReader.parse(); - - // Merge layer configurations - parsedLayers.forEach((layerKey, priority) -> { - if (layers.containsKey(layerKey)) { - AnimationCore.log.debug("Overriding layer {} with priority {}", layerKey, priority); - } - layers.put(layerKey, priority); - }); - - loadedCount += parsedLayers.size(); - AnimationCore.log.debug("Loaded {} layer configurations from {}", - parsedLayers.size(), entry.getKey().getNamespace()); - - } catch (IllegalArgumentException | JsonParseException e) { - AnimationCore.log.error("Parsing error loading layer configuration", e); - } - } - - AnimationCore.log.info("Loaded {} layer configurations from data packs", loadedCount); - } - } - - @SubscribeEvent - public static void onPlayerLoggedIn(PlayerEvent.PlayerLoggedInEvent event) { - if (event.getEntity() instanceof ServerPlayer serverPlayer) { - MinecraftServer server = serverPlayer.getServer(); - if(server == null) return; - - // Send animations to client - sendAnimationsToClient(serverPlayer); - } - } - - /** - * Send all animations and layers to the client - */ - private static void sendAnimationsToClient(ServerPlayer player) { - AnimationCore.log.debug("Sending animations to player: {}", player.getName().getString()); - - // Clear client cache first - ModChannel.sendToPlayer(new AnimationClientStatusPacket( - AnimationClientStatusPacket.Status.ANIM_CACHE_CLEAR), player); - - // Send all animations - for (GenericAnimationData anim : animations.values()) { - JsonElement json = AnimJson.Writer.stream(anim).toJson(); - String jsonString = json.toString(); - ModChannel.sendToPlayer(new AnimationJsonPacket(jsonString, false), player); - } - - // Register animations on client - ModChannel.sendToPlayer(new AnimationClientStatusPacket( - AnimationClientStatusPacket.Status.ANIM_REGISTER), player); - - // Clear layer cache - ModChannel.sendToPlayer(new AnimationClientStatusPacket( - AnimationClientStatusPacket.Status.LAYER_CACHE_CLEAR), player); - - // Send layer configurations - JsonElement layerJson = convertLayersToJson(layers); - ModChannel.sendToPlayer(new AnimationJsonPacket(layerJson.toString(), true), player); - - // Register layers on client - ModChannel.sendToPlayer(new AnimationClientStatusPacket( - AnimationClientStatusPacket.Status.LAYER_REGISTER), player); - - AnimationCore.log.debug("Sent {} animations and {} layers to player {}", - animations.size(), layers.size(), player.getName().getString()); - } - - /** - * Convert layers map to JSON - */ - private static JsonElement convertLayersToJson(Map layers) { - JsonArray jsonArray = new JsonArray(); - - for (Map.Entry entry : layers.entrySet()) { - JsonObject jsonObject = new JsonObject(); - jsonObject.addProperty("key", entry.getKey().toString()); - jsonObject.addProperty("priority", entry.getValue()); - jsonArray.add(jsonObject); - } - - return jsonArray; - } - - @OnlyIn(Dist.CLIENT) - public static class ClientCache { - public static boolean isAnimationRegistered = false; - private static final Map animationsCache = new HashMap<>(); - private static final Map layersCache = new HashMap<>(); - private static final Map> modifierLayers = new HashMap<>(); - - public static void cacheAddAnimation(ResourceLocation location, GenericAnimationData animation) { - animationsCache.put(location, animation); - } - - public static void cacheAddAnimationLayer(ResourceLocation location, Integer priority) { - layersCache.put(location, priority); - } - - public static void animationStatusUpdate(AnimationClientStatusPacket.Status status) { - switch (status) { - case ANIM_CACHE_CLEAR -> animationsCache.clear(); - case LAYER_CACHE_CLEAR -> { - ((IMixinPlayerAnimationFactoryHolder)(PlayerAnimationFactory.ANIMATION_DATA_FACTORY)) - .animcore$clearAnimations(); - layersCache.clear(); - } - case ANIM_REGISTER -> { - isAnimationRegistered = true; - registerAnimations(animationsCache); - RawAnimationRegistry.triggerRegistry(); - } - case LAYER_REGISTER -> { - registerLayers(layersCache); - layersCache.forEach((key, value) -> PlayerAnimationFactory.ANIMATION_DATA_FACTORY.registerFactory( - key, value, player -> { - if (Minecraft.getInstance().player == null) { - return ClientCache.registerPlayerAnimation(player); - } - Map animationMap = - modifierLayers.getOrDefault(player.getUUID(), new HashMap<>()); - if (animationMap.containsKey(key)) { - return animationMap.get(key); - } - IAnimation iAnimation = ClientCache.registerPlayerAnimation(player); - animationMap.put(key, iAnimation); - modifierLayers.put(player.getUUID(), animationMap); - return iAnimation; - }) - ); - - // Update existing players' animation stacks - ClientLevel level = Minecraft.getInstance().level; - if (level == null) { - AnimationCore.log.error("Level is null, cannot update animation layers"); - return; - } - - try { - for (AbstractClientPlayer player : level.players()) { - updatePlayerAnimationStack(player); - } - } catch (Exception e) { - AnimationCore.log.error("Failed to update player animation layers", e); - } - } - } - } - - /** - * Update a player's animation stack with new layers - */ - @SuppressWarnings({"unchecked", "JavaReflectionMemberAccess"}) - private static void updatePlayerAnimationStack(AbstractClientPlayer player) { - try { - Class playerClass = Player.class; - Field animationStackField = playerClass.getDeclaredField("animationStack"); - animationStackField.setAccessible(true); - - Method createAnimationStack = playerClass.getDeclaredMethod("createAnimationStack"); - createAnimationStack.setAccessible(true); - - AnimationStack newAnimationStack = (AnimationStack) createAnimationStack.invoke(player); - AnimationStack oldAnimationStack = (AnimationStack) animationStackField.get(player); - - Field layersField = AnimationStack.class.getDeclaredField("layers"); - layersField.setAccessible(true); - - ArrayList> oldArrayList = - new ArrayList<>((ArrayList>) layersField.get(oldAnimationStack)); - ArrayList> newArrayList = - new ArrayList<>((ArrayList>) layersField.get(newAnimationStack)); - - // Merge layers, keeping unique ones - ArrayList> result = new ArrayList<>(); - - // Add old layers that aren't replaced by new ones - for (Pair oldPair : oldArrayList) { - boolean isReplaced = false; - for (Pair newPair : newArrayList) { - if (Objects.equals(oldPair.getLeft(), newPair.getLeft())) { - isReplaced = true; - break; - } - } - if (!isReplaced) { - result.add(oldPair); - } - } - - // Add all new layers - result.addAll(newArrayList); - - // Set the merged layers - layersField.set(newAnimationStack, result); - animationStackField.set(player, newAnimationStack); - - // Update animation applier - Field animationApplierField = playerClass.getDeclaredField("animationApplier"); - animationApplierField.setAccessible(true); - //noinspection UnstableApiUsage - animationApplierField.set(player, new AnimationApplier(newAnimationStack)); - - // Restore any playing animations - restorePlayingAnimations(player); - - } catch (Exception e) { - AnimationCore.log.error("Failed to update animation stack for player: {}", player, e); - } - } - - /** - * Restore animations that were playing before the update - */ - private static void restorePlayingAnimations(AbstractClientPlayer player) { - try { - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - if (data == null) return; - - RawAnimationDataCapability rawData = RawAnimationDataCapability.getCapability(player).orElse(null); - if (rawData == null) return; - - Map dataAnimations = new HashMap<>(); - dataAnimations.putAll(data.getAnimations()); - dataAnimations.putAll(rawData.getAnimations()); - - ResourceLocation riderAnimLayer = data.getRiderAnimLayer(); - if (riderAnimLayer != null && data.getRiderAnimation() != null) { - dataAnimations.put(riderAnimLayer, data.getRiderAnimation()); - } - - for (Map.Entry entry : dataAnimations.entrySet()) { - ResourceLocation layerKey = entry.getKey(); - ResourceLocation animKey = entry.getValue(); - - @SuppressWarnings("unchecked") - ModifierLayer modifierLayer = (ModifierLayer) - PlayerAnimationAccess.getPlayerAssociatedData(player).get(layerKey); - if (modifierLayer == null) continue; - - KeyframeAnimation keyframeAnimation; - GenericAnimationData anim = animations.get(animKey); - - if (anim == null) { - RawAnimationData rawAnim = RawAnimationService.INSTANCE.getAnimation(animKey); - if (rawAnim == null) continue; - keyframeAnimation = rawAnim.getAnimation(); - } else { - keyframeAnimation = anim.getAnimation(); - } - - if (keyframeAnimation == null) continue; - - modifierLayer.replaceAnimationWithFade( - AbstractFadeModifier.standardFadeIn(3, Ease.INOUTSINE), - new KeyframeAnimationPlayer(keyframeAnimation) - ); - } - } catch (Exception e) { - AnimationCore.log.error("Failed to restore playing animations for player: {}", player, e); - } - } - - private static IAnimation registerPlayerAnimation(AbstractClientPlayer player) { - return new ModifierLayer<>(); - } - } -} \ No newline at end of file diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/register/RawAnimationRegistry.java b/src/main/java/top/leisuretimedock/animationcore/animation/register/RawAnimationRegistry.java deleted file mode 100644 index 602ecb3..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/register/RawAnimationRegistry.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.register; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.command.argument.AnimationArgument; -import top.leisuretimedock.animationcore.animation.data.RawAnimationData; -import top.leisuretimedock.animationcore.animation.data.util.RawAnimJson; -import top.leisuretimedock.animationcore.animation.event.create.AnimationRegisterEvent; -import top.leisuretimedock.animationcore.animation.utils.FileUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -@OnlyIn(Dist.CLIENT) -public class RawAnimationRegistry { - private static final Map animations = new HashMap<>(); - - public static Map getAnimations() { - return Map.copyOf(animations); - } - - private static void registerAnimations(Map animationMap) { - animations.clear(); - Map.copyOf(animationMap).keySet().forEach(location -> { - if(!validateLocation(location)) animations.remove(location); - }); - animations.putAll(animationMap); - AnimationArgument.resetAnimationNames(); - } - - public static boolean register(ResourceLocation location, RawAnimationData rawAnimation) { - if (validateLocation(location)) { - animations.put(location, rawAnimation); - return true; - } - return false; - } - - public static void triggerRegistry() { - resetAnimations(); - AnimationRegisterEvent.RawAnimation event = new AnimationRegisterEvent.RawAnimation(); - MinecraftForge.EVENT_BUS.post(event); - Map animationDataMap = new HashMap<>(event.getAnimations()); - Minecraft instance = Minecraft.getInstance(); - Path dataPackPath = instance.getResourcePackDirectory(); - Path animationPath = dataPackPath.resolve("animation"); - if (!Files.exists(animationPath)) { - try { - Files.createDirectories(animationPath); - } catch (IOException e) { return; } - } - FileUtils.safeUnzip(dataPackPath.resolve("animation.zip").toString(), animationPath.toAbsolutePath().toString()); - Set animZipPaths = FileUtils.getAllFile( - dataPackPath.resolve("animation"), - path -> path.toString().endsWith(".anim.zip") - ); - for (Path zipPath : animZipPaths) { - FileUtils.safeUnzip(zipPath.toString(), animationPath.toAbsolutePath().toString()); - } - Set animPaths = FileUtils.getAllFile( - dataPackPath.resolve("animation"), - path -> path.toString().endsWith(".anim.json") - ); - - for (Path path : animPaths) { - try { - RawAnimJson.Reader reader = RawAnimJson.Reader.stream(path); - RawAnimationData anim = reader.parse(); - animationDataMap.put(anim.getKey(), anim); - } catch (Exception ignored) { - AnimationCore.log.error("Failed to parse raw animation JSON: {}", path.toString()); - } - } - registerAnimations(animationDataMap); - } - - private static void resetAnimations() { - animations.clear(); - } - - public static boolean validateLocation(ResourceLocation location) { - try { - if(!AnimationRegistry.ClientCache.isAnimationRegistered) - throw new RuntimeException("Server animation is not registered!"); - if(AnimationRegistry.getAnimations().containsKey(location)) - throw new RuntimeException("Duplicated animation on server: " + location); - return true; - } catch (RuntimeException e) { - AnimationCore.log.error(e.getMessage(), e); - return false; - } - } - -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/service/AnimationService.java b/src/main/java/top/leisuretimedock/animationcore/animation/service/AnimationService.java deleted file mode 100644 index 0d5c78e..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/service/AnimationService.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.service; - -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.util.FakePlayer; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; - -/** - * Animation Util. May be you can call it Api. - */ -public class AnimationService implements IAnimationService { - public static final AnimationService INSTANCE = new AnimationService(); - - /** - * Get the HeightModifier when there are animations which playing on player.
- * And It will return the first which be found. - * @param player Target player - * @return The first HeightModifier it find. - */ - public float getHeightModifier(Player player) { - Float result = ANIMATION_RUNNER.testLoadedAndCall(() -> { - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - if (data == null) return 1.0f; - float heightModifier = 1.0f; - for (ResourceLocation value : data.getAnimations().values()) { - GenericAnimationData animation = getAnimation(value); - if (animation == null) continue; - float animationHeightModifier = animation.getHeightModifier(); - heightModifier = Math.min(heightModifier, animationHeightModifier); - } - return heightModifier; - }); - return result == null ? 1.0f : result; - } - - - @Override - public @Nullable GenericAnimationData getAnimation(ResourceLocation location) { - return AnimationRegistry.getAnimations().getOrDefault(location, null); - } - - @Override - public @Nullable GenericAnimationData getAnimation(CompoundTag tag) { - return new GenericAnimationData(){{deserializeNBT(tag);}}; - } - - @Override - public @Nullable IAnimationCapability getCapability(Player player) { - return AnimationDataCapability.getCapability(player).orElse(null); - } - - @Override - public void clearAnimations(ServerPlayer serverPlayer) { - ANIMATION_RUNNER.testLoadedAndRun(() -> { - Optional.ofNullable(getCapability(serverPlayer)).ifPresent(IAnimationCapability::clearAnimations); - detachAnimation(serverPlayer); - }); - } - - @Override - public boolean isAnimationPresent(ResourceLocation location) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> AnimationRegistry.getAnimations().containsKey(location)); - } - - @Override - @OnlyIn(Dist.CLIENT) - public void refreshAnimation(AbstractClientPlayer clientPlayer) { - ANIMATION_RUNNER.testLoadedAndRun(() -> { - IAnimationCapability data = getCapability(clientPlayer); - if(data == null) return; - Set oldLayers = new HashSet<>(data.getAnimations().keySet()); - for (ResourceLocation layer : Set.copyOf(oldLayers)) { - if (AnimationUtils.isClientAnimationStop(clientPlayer, layer)) { - removeAnimation(clientPlayer, layer); - } - } - }); - } - - @Override - public @Nullable ResourceLocation getAnimationPlaying(Player player, @Nullable ResourceLocation layer) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - IAnimationCapability data = getCapability(player); - if(data == null) return null; - if(layer == null){ - for (ResourceLocation value : data.getAnimations().values()) { - if(value != null) return value; - } - } else if (isAnimationLayerPresent(layer)) { - if(data.isAnimationPresent(layer)){ - return data.getAnimation(layer); - } - } - return null; - }); - } - - @Override - public ApiBack removeAnimation(@NotNull ServerPlayer serverPlayer, ResourceLocation layer) { - boolean result = ANIMATION_RUNNER.testLoadedAndCall(() -> Optional.ofNullable(getCapability(serverPlayer)) - .map(data -> data.removeAnimation(layer)).orElse(false)); - return result ? ApiBack.SUCCESS : ApiBack.FAIL; - } - - @Override - public ApiBack playAnimationServer(@NotNull ServerPlayer player, ResourceLocation layer, AnimationData animation) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - ResourceLocation key = animation.getKey(); - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(key)) - return ApiBack.RESOURCE_NOT_FOUND; - if(player instanceof FakePlayer) - return ApiBack.UNSUPPORTED; - Boolean flag = Optional.ofNullable(getCapability(player)).map(data -> - data.mergeAnimation(layer, key)).orElse(false); - return flag ? ApiBack.SUCCESS : ApiBack.FAIL; - }); - } - - public ApiBack playAnimation(@NotNull ServerPlayer player, ResourceLocation layer, ResourceLocation animation) { - return playAnimation(player, layer, getAnimation(animation)); - } - public ApiBack playAnimationWithRide(@NotNull ServerPlayer player, ResourceLocation layer, ResourceLocation animation, boolean force) { - return playAnimationWithRide(player, layer, getAnimation(animation), force); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/service/IAnimationService.java b/src/main/java/top/leisuretimedock/animationcore/animation/service/IAnimationService.java deleted file mode 100644 index e3b392e..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/service/IAnimationService.java +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.service; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.entity.AnimationRideEntity; -import top.leisuretimedock.animationcore.animation.event.PlayerTickEvent; -import top.leisuretimedock.animationcore.animation.event.client.CameraModify; -import top.leisuretimedock.animationcore.animation.event.client.ClientPlayerEvent; -import top.leisuretimedock.animationcore.animation.event.client.EntityRendererRegisterEvent; -import top.leisuretimedock.animationcore.animation.event.create.AnimationEvent; -import top.leisuretimedock.animationcore.animation.network.toclient.SyncAnimationPacket; -import top.leisuretimedock.animationcore.animation.network.toserver.*; -import top.leisuretimedock.animationcore.animation.register.AnimationCapabilities; -import top.leisuretimedock.animationcore.animation.register.AnimationChannels; -import top.leisuretimedock.animationcore.animation.register.AnimationEntities; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.core.ModChannel; -import top.leisuretimedock.animationcore.core.ModCompatRun; -import top.leisuretimedock.animationcore.core.configs.ModConfigs; -import dev.kosmx.playerAnim.core.data.KeyframeAnimation; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationRegistry; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.MinecraftForge; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.eventbus.api.Event; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.LogicalSide; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * Animation helper interface - * @param Animation data - * @param Capability - */ -@SuppressWarnings({"UnusedReturnValue", "unused"}) -public interface IAnimationService>{ - String AnimModId = "playeranimator"; - /** - * Lazy runner - */ - ModCompatRun ANIMATION_RUNNER = new ModCompatRun(AnimModId) { - @Override - public void addCommonListener(IEventBus forgeBus, IEventBus modBus) { - AnimationEntities.register(modBus); - forgeBus.register(AnimationRegistry.class); - forgeBus.register(PlayerTickEvent.class); - } - - @Override - public void addClientListener(IEventBus forgeBus, IEventBus modBus) { - modBus.register(EntityRendererRegisterEvent.class); - forgeBus.register(CameraModify.class); - forgeBus.register(ClientPlayerEvent.class); - } - }; - - //Cache info record, not persistent - record ApplyAnimationRecord(UUID target, int expireTick) {} - record InviteAnimationRecord(ResourceLocation layer, AnimationData animation, int expireTick, List targets) {} - record RequestAnimationRecord(ResourceLocation layer, AnimationData animation, int expireTick, UUID target, boolean isRide) {} - - //Apply & invite & request history record - Map applyMap = new ConcurrentHashMap<>(); - Map inviteMap = new ConcurrentHashMap<>(); - Map requestMap = new ConcurrentHashMap<>(); - - //Last apply & invite & request tick map - Map lastApplyTickMap = new ConcurrentHashMap<>(); - Map lastInviteTickMap = new ConcurrentHashMap<>(); - Map lastRequestTickMap = new ConcurrentHashMap<>(); - - /** - * Equal to {@link AnimationRegistry#getLayers()} - * @return Resource location set - */ - default Set getLayers() { - return Set.copyOf(AnimationRegistry.getLayers().keySet()); - } - - /** - * Get animation by location - * @param location location - * @return Animation data - */ - @Nullable - D getAnimation(ResourceLocation location); - - /** - * Get animation by Tag (deserializeNBT) - * @param tag tag - * @return Animation data - */ - @Nullable - D getAnimation(CompoundTag tag); - - /** - * Get capability - * @param player player - * @return Capability - */ - @Nullable - C getCapability(Player player); - - /** - * To register handler - * @param forgeBus Forge event bus - * @param modBus Mod event bus - */ - static void register(IEventBus forgeBus, IEventBus modBus){ - ANIMATION_RUNNER.testLoadedAndRun(() -> { - AnimationCapabilities.registerAnimationCapability(); - AnimationChannels.registerChannel(); - }); - ANIMATION_RUNNER.testLoadedAndAddListener(forgeBus, modBus); - } - - default void clearAnimations(AbstractClientPlayer player){ - for (ResourceLocation layer : getLayers()) { - AnimationUtils.removeAnimation(player, layer); - } - } - - //clear animations - void clearAnimations(ServerPlayer serverPlayer); - //according to location, judge if animation is present - boolean isAnimationPresent(ResourceLocation location); - //stop riding - default ApiBack detachAnimation(ServerPlayer player){ - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(player.getVehicle() instanceof AnimationRideEntity) { - player.stopRiding(); - return ApiBack.SUCCESS; - } - return ApiBack.UNSUPPORTED; - }); - }; - //start ride - default ApiBack joinAnimationServer(ServerPlayer player, ServerPlayer target, boolean force){ - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - Entity vehicle = target.getVehicle(); - if(vehicle instanceof AnimationRideEntity) { - boolean result = player.startRiding(vehicle, force); - return result ? ApiBack.SUCCESS : ApiBack.FAIL; - } - return ApiBack.UNSUPPORTED; - }); - }; - - /** - * Trigger event and let implementation class handle - * @param player player - * @param target target - * @param force is force - * @return Api back - */ - default ApiBack joinAnimation(ServerPlayer player, ServerPlayer target, boolean force){ - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - AnimationEvent.Join playEvent = new AnimationEvent.Join(player, target, force); - boolean post = MinecraftForge.EVENT_BUS.post(playEvent); - Event.Result eventResult = playEvent.getResult(); - if(post || eventResult == Event.Result.DENY) return ApiBack.BE_CANCELLED; - return joinAnimationServer(player, target, playEvent.isForce()); - }); - } - - /** - * Sync animation tick to client - * @param player Player - * @param target Target player - */ - default void syncAnimation(ServerPlayer player, ServerPlayer target) { - ANIMATION_RUNNER.testLoadedAndRun(() -> { - ModChannel.sendToPlayer(new SyncAnimationPacket(player.getUUID(), target.getUUID()), player); - ModChannel.sendToPlayer(new SyncAnimationPacket(player.getUUID(), target.getUUID()), target); - }); - } - - /** - * Sync animation tick on client - * @param player Player - * @param target Target player - */ - @OnlyIn(Dist.CLIENT) - default void syncAnimation(AbstractClientPlayer player, AbstractClientPlayer target) { - ANIMATION_RUNNER.testLoadedAndRun(() -> AnimationUtils.syncAnimation(player, target)); - } - - /** - * Refresh animation throw capability - * @param clientPlayer player - */ - @OnlyIn(Dist.CLIENT) - void refreshAnimation(AbstractClientPlayer clientPlayer); - - /** - * Refresh animation on client, it will not sync to capability - * @param clientPlayer player - */ - @OnlyIn(Dist.CLIENT) - default void refreshAnimationUnsafe(AbstractClientPlayer clientPlayer) { - ANIMATION_RUNNER.testLoadedAndRun(() -> { - Set oldLayers = new HashSet<>(AnimationRegistry.getLayers().keySet()); - for (ResourceLocation layer : Set.copyOf(oldLayers)) { - if (AnimationUtils.isClientAnimationStop(clientPlayer, layer)) { - removeAnimation(clientPlayer, layer); - } - } - }); - } - - /** - * Test if layer exist and has been invite. - * @param layer Target layer - * @return If layer exist and has been invited - */ - default boolean isAnimationLayerPresent(ResourceLocation layer) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> getLayers().contains(layer)); - } - - /** - * Get animation which is playing now on player.
- * If layer is null, it will return the first playing animation which can be found. - * @param player Target player - * @param layer Target layer - * @return Playing animation resource location - */ - @Nullable - ResourceLocation getAnimationPlaying(Player player, @Nullable ResourceLocation layer); - - /** - * Remove animation. - * @param player Target player - * @param layer Target layer - * @return If success - */ - @OnlyIn(Dist.CLIENT) - default ApiBack removeAnimation(@Nullable AbstractClientPlayer player, ResourceLocation layer) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - AnimationUtils.removeAnimation(player, layer); - LocalPlayer self = Minecraft.getInstance().player; - if(self != null && player != null && Objects.equals(self.getUUID(), player.getUUID())) { - ModChannel.INSTANCE.sendToServer(new StopAnimationPacket(layer)); - } - return ApiBack.SUCCESS; - }); - } - ApiBack removeAnimation(@NotNull ServerPlayer serverPlayer, ResourceLocation layer); - - /** - *
-     * Play animation with ride. Player will ride an entity, then play animation.
-     * When player unride, animation will be remove.
-     * If player is riding and the "force" is false, it will return false
-     * 
- * @param player Target player - * @param layer Target layer - * @param animation Animation - * @param force If force to ride and play animation - * @return If success - */ - @OnlyIn(Dist.CLIENT) - default ApiBack playAnimationWithRide(@Nullable AbstractClientPlayer player, ResourceLocation layer, ResourceLocation animation, boolean force) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(isAnimationLayerPresent(layer) && isAnimationPresent(animation)) - return ApiBack.RESOURCE_NOT_FOUND; - UUID uuid = player == null ? null : player.getUUID(); - AnimationData anim = getAnimation(animation); - if(anim == null || anim.getRide() == null) return ApiBack.RESOURCE_NOT_FOUND; - ModChannel.sendToServer(new PlayAnimationRidePacket(anim, layer, animation, uuid, force)); - return ApiBack.SUCCESS; - }); - } - default ApiBack playAnimationWithRide(@NotNull ServerPlayer player, ResourceLocation layer, AnimationData animation, boolean force, Vec3 pos) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - ResourceLocation key = animation.getKey(); - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(key)) - return ApiBack.RESOURCE_NOT_FOUND; - if(animation.getRide() == null) - return ApiBack.RESOURCE_NOT_FOUND; - if(player instanceof FakePlayer) - return ApiBack.UNSUPPORTED; - boolean flag = player.getVehicle() != null; - if(flag && force) player.stopRiding(); - else if(flag) return ApiBack.UNSUPPORTED; - boolean result = AnimationRideEntity.create(player, layer, animation, force, pos) != null; - return result ? ApiBack.SUCCESS : ApiBack.FAIL; - }); - } - default ApiBack playAnimationWithRide(@NotNull ServerPlayer player, ResourceLocation layer, AnimationData animation, boolean force) { - return playAnimationWithRide(player, layer, animation, force, player.position()); - } - - /** - *
-     * Play animation.
-     * If run in Dist.CLIENT, player can be null, it will play animation only client.
-     * If animation be null, it will remove animation on layer.
-     * 
- * @param player Target player - * @param layer Target layer - * @param animation Animation - * @return If success - */ - @OnlyIn(Dist.CLIENT) - default ApiBack playAnimation(@Nullable AbstractClientPlayer player, ResourceLocation layer, ResourceLocation animation) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(isAnimationLayerPresent(layer) && isAnimationPresent(animation)) - return ApiBack.RESOURCE_NOT_FOUND; - UUID uuid = player == null ? null : player.getUUID(); - AnimationData anim = getAnimation(animation); - if(anim == null) return ApiBack.RESOURCE_NOT_FOUND; - - AnimationEvent.Play playEvent = new AnimationEvent.Play( - LogicalSide.CLIENT, - player, - layer, - anim - ); - boolean post = MinecraftForge.EVENT_BUS.post(playEvent); - Event.Result eventResult = playEvent.getResult(); - if(post || eventResult == Event.Result.DENY) return ApiBack.BE_CANCELLED; - ModChannel.sendToServer(new PlayAnimationPacket(anim, layer, animation, uuid)); - return ApiBack.SUCCESS; - }); - } - - /** - * Trigger event and let implementation class handle - * @param player player - * @param layer target layer - * @param animation animation - * @return Api back - */ - default ApiBack playAnimation(@NotNull ServerPlayer player, ResourceLocation layer, AnimationData animation){ - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - AnimationEvent.Play playEvent = new AnimationEvent.Play(LogicalSide.SERVER, player, layer, animation); - boolean post = MinecraftForge.EVENT_BUS.post(playEvent); - Event.Result eventResult = playEvent.getResult(); - if(post || eventResult == Event.Result.DENY) return ApiBack.BE_CANCELLED; - return playAnimationServer(player, layer, animation); - }); - } - ApiBack playAnimationServer(@NotNull ServerPlayer player, ResourceLocation layer, AnimationData animation); - - /** - * Request animation - */ - default ApiBack request(ServerPlayer player, ServerPlayer target, ResourceLocation layer, AnimationData animation, boolean isRide) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(animation.getKey())) - return ApiBack.RESOURCE_NOT_FOUND; - int tickCount = player.server.getTickCount(); - UUID playerUUID = player.getUUID(); - UUID targetUUID = target.getUUID(); - - int origin = ModConfigs.Server.requestValidTime.get() * 20; - int cooldown = ModConfigs.Server.requestCooldown.get() * 20; - AnimationEvent.Send sendEvent = new AnimationEvent.Send(LogicalSide.SERVER, origin, cooldown, AnimationEvent.Type.APPLY); - boolean post = MinecraftForge.EVENT_BUS.post(sendEvent); - if(post) return ApiBack.BE_CANCELLED; - Event.Result eventResult = sendEvent.getResult(); - switch (eventResult) { - case DENY : return ApiBack.BE_CANCELLED; - case DEFAULT : { - //Test if is not in cooldown - int lastTick = lastRequestTickMap.getOrDefault(playerUUID, 0); - if(Math.max(tickCount - sendEvent.getCooldownTick(), 0) >= lastTick) { - lastRequestTickMap.put(playerUUID, tickCount); - } else return ApiBack.COOLDOWN; - } - case ALLOW : { - //Add to cache, done - int expireTick = sendEvent.getValidTick() + tickCount; - requestMap.put(playerUUID, new RequestAnimationRecord(layer, animation, expireTick, targetUUID, isRide)); - return ApiBack.SUCCESS; - } - default: return ApiBack.UNSUPPORTED; - } - }); - } - - /** - * Client request - * @param target target - * @param layer layer - * @param animation animation - * @return Api back - */ - default ApiBack request(AbstractClientPlayer target, ResourceLocation layer, ResourceLocation animation) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(animation)) - return ApiBack.RESOURCE_NOT_FOUND; - KeyframeAnimation keyframeAnimation = PlayerAnimationRegistry.getAnimation(animation); - if(keyframeAnimation == null) return ApiBack.RESOURCE_NOT_FOUND; - D data = getAnimation(animation); - if(data == null) return ApiBack.RESOURCE_NOT_FOUND; - AnimationEvent.Send sendEvent = new AnimationEvent.Send( - LogicalSide.CLIENT, - 0, - 0, - AnimationEvent.Type.REQUEST - ); - boolean post = MinecraftForge.EVENT_BUS.post(sendEvent); - Event.Result eventResult = sendEvent.getResult(); - if(post || eventResult == Event.Result.DENY) return ApiBack.BE_CANCELLED; - ModChannel.sendToServer(new RequestAnimationPacket(data, layer, target.getUUID())); - return ApiBack.SUCCESS; - }); - } - - /** - * Accept Request - */ - default ApiBack acceptRequest(ServerPlayer player, ServerPlayer requestor) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - UUID requestorUUID = requestor.getUUID(); - RequestAnimationRecord record = requestMap.getOrDefault(requestorUUID, null); - if (record == null) return ApiBack.UNSUPPORTED; - UUID uuid = player.getUUID(); - if (!record.target().equals(uuid)) return ApiBack.UNSUPPORTED; - - AnimationEvent.Accept acceptEvent = new AnimationEvent.Accept(AnimationEvent.Type.REQUEST, 0); - boolean post = MinecraftForge.EVENT_BUS.post(acceptEvent); - if(post) return ApiBack.BE_CANCELLED; - Event.Result eventResult = acceptEvent.getResult(); - switch (eventResult) { - case DENY : return ApiBack.BE_CANCELLED; - case DEFAULT : { - //Test if is in valid time - int tickCount = requestor.server.getTickCount(); - if (tickCount >= record.expireTick()) { - requestMap.remove(requestorUUID); - return ApiBack.OPERATION_EXPIRE; - } - } - case ALLOW : { - //done - ApiBack back; - if(record.isRide()) back = playAnimationWithRide(player, record.layer(), record.animation(), false); - else back = playAnimation(player, record.layer(), record.animation()); - if(back == ApiBack.SUCCESS) requestMap.remove(requestorUUID); - return back; - } - default: return ApiBack.UNSUPPORTED; - } - }); - } - - /** - * Send apply to join animation on server side - */ - default ApiBack apply(ServerPlayer player, ServerPlayer target) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - int tickCount = player.server.getTickCount(); - - int origin = ModConfigs.Server.applyValidTime.get() * 20; - int cooldown = ModConfigs.Server.applyCooldown.get() * 20; - AnimationEvent.Send sendEvent = new AnimationEvent.Send( - LogicalSide.SERVER, - origin, - cooldown, - AnimationEvent.Type.APPLY - ); - boolean post = MinecraftForge.EVENT_BUS.post(sendEvent); - if(post) return ApiBack.BE_CANCELLED; - Event.Result eventResult = sendEvent.getResult(); - switch (eventResult) { - case DENY : return ApiBack.BE_CANCELLED; - case DEFAULT : { - //Test if is not in cooldown - int lastTick = lastApplyTickMap.getOrDefault(player.getUUID(), 0); - if(Math.max(tickCount - sendEvent.getCooldownTick(), 0) >= lastTick) { - lastApplyTickMap.put(player.getUUID(), tickCount); - } else return ApiBack.COOLDOWN; - } - case ALLOW : { - //Add to cache, done - int expireTick = sendEvent.getValidTick() + tickCount; - applyMap.put(player.getUUID(), new ApplyAnimationRecord(target.getUUID(), expireTick)); - return ApiBack.SUCCESS; - } - default: return ApiBack.UNSUPPORTED; - } - }); - } - - /** - * Send apply to join animation on client side.
- * It will send network packet and work on server side. - */ - @OnlyIn(Dist.CLIENT) - default ApiBack apply(AbstractClientPlayer target) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - AnimationEvent.Send sendEvent = new AnimationEvent.Send( - LogicalSide.CLIENT, - 0, - 0, - AnimationEvent.Type.APPLY - ); - boolean post = MinecraftForge.EVENT_BUS.post(sendEvent); - Event.Result eventResult = sendEvent.getResult(); - if(post || eventResult == Event.Result.DENY) return ApiBack.BE_CANCELLED; - ModChannel.sendToServer(new ApplyAnimationPacket(target.getUUID())); - return ApiBack.SUCCESS; - }); - } - - /** - * Player accept join apply. - * @param player Acceptor - * @param applier Applier - * @return If accept and riding success - */ - default ApiBack acceptApply(ServerPlayer player, ServerPlayer applier) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - ApplyAnimationRecord record = applyMap.getOrDefault(applier.getUUID(), null); - if (record == null) return ApiBack.UNSUPPORTED; - UUID uuid = player.getUUID(); - if (!record.target().equals(uuid)) return ApiBack.UNSUPPORTED; - - int maxDistance = ModConfigs.Server.applyValidDistance.get(); - AnimationEvent.Accept acceptEvent = new AnimationEvent.Accept(AnimationEvent.Type.APPLY, maxDistance); - boolean post = MinecraftForge.EVENT_BUS.post(acceptEvent); - if(post) return ApiBack.BE_CANCELLED; - Event.Result eventResult = acceptEvent.getResult(); - switch (eventResult) { - case DENY : return ApiBack.BE_CANCELLED; - case DEFAULT : { - //Test if is in valid distance - int validDistance = acceptEvent.getValidDistance(); - if(player.distanceToSqr(applier) > validDistance * validDistance) { - return ApiBack.OUT_RANGE; - } - int tickCount = applier.server.getTickCount(); - if (tickCount > record.expireTick()) { - applyMap.remove(applier.getUUID()); - return ApiBack.OPERATION_EXPIRE; - } - } - case ALLOW : { - //done - ApiBack back = joinAnimation(applier, player, false); - if(back == ApiBack.SUCCESS) applyMap.remove(applier.getUUID()); - return back; - } - default: return ApiBack.UNSUPPORTED; - } - }); - } - - /** - * Send invite on server side. - * @param player Sender - * @param animation Raw animation info - * @param layer Target layer - * @param targets Be invited players - */ - default ApiBack invite(ServerPlayer player, ResourceLocation layer, AnimationData animation, Collection targets) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(animation.getKey())) - return ApiBack.RESOURCE_NOT_FOUND; - int tickCount = player.server.getTickCount(); - - int origin = ModConfigs.Server.inviteValidTime.get() * 20; - int cooldown = ModConfigs.Server.inviteCooldown.get() * 20; - AnimationEvent.Send sendEvent = new AnimationEvent.Send( - LogicalSide.SERVER, - origin, - cooldown, - AnimationEvent.Type.INVITE - ); - boolean post = MinecraftForge.EVENT_BUS.post(sendEvent); - if(post) return ApiBack.BE_CANCELLED; - Event.Result eventResult = sendEvent.getResult(); - switch (eventResult) { - case DENY : return ApiBack.BE_CANCELLED; - case DEFAULT : { - //Test if is not in cooldown - int lastTick = lastInviteTickMap.getOrDefault(player.getUUID(), 0); - if(Math.max(tickCount - sendEvent.getCooldownTick(), 0) >= lastTick) { - lastInviteTickMap.put(player.getUUID(), tickCount); - } else return ApiBack.COOLDOWN; - } - case ALLOW : { - //Add to cache, done - int expireTick = sendEvent.getValidTick() + tickCount; - inviteMap.put(player.getUUID(), new InviteAnimationRecord(layer, animation, expireTick, new ArrayList<>(targets))); - return ApiBack.SUCCESS; - } - default: return ApiBack.UNSUPPORTED; - } - }); - } - - /** - * Send invite on client side.
- * It will send network packet and work on server side. - * @param animation Raw animation info - * @param layer Target layer - * @param targets Be invited players - * @return If send to server successfully. - */ - @OnlyIn(Dist.CLIENT) - default ApiBack invite(ResourceLocation layer, ResourceLocation animation, AbstractClientPlayer ... targets){ - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(animation)) - return ApiBack.RESOURCE_NOT_FOUND; - KeyframeAnimation keyframeAnimation = PlayerAnimationRegistry.getAnimation(animation); - if(keyframeAnimation == null) return ApiBack.RESOURCE_NOT_FOUND; - Set list = Arrays.stream(targets).map(AbstractClientPlayer::getUUID).collect(Collectors.toSet()); - D data = getAnimation(animation); - if(data == null) return ApiBack.RESOURCE_NOT_FOUND; - AnimationEvent.Send sendEvent = new AnimationEvent.Send( - LogicalSide.CLIENT, - 0, - 0, - AnimationEvent.Type.INVITE - ); - boolean post = MinecraftForge.EVENT_BUS.post(sendEvent); - Event.Result eventResult = sendEvent.getResult(); - if(post || eventResult == Event.Result.DENY) return ApiBack.BE_CANCELLED; - ModChannel.sendToServer(new InviteAnimationPacket(data, layer, list)); - return ApiBack.SUCCESS; - }); - } - - /** - * Player accept invite - * @param player Acceptor - * @param inviter Inviter - * @return If accept and riding success. - */ - default ApiBack acceptInvite(ServerPlayer player, ServerPlayer inviter) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - InviteAnimationRecord record = inviteMap.getOrDefault(inviter.getUUID(), null); - if(record == null) return ApiBack.UNSUPPORTED; - UUID uuid = player.getUUID(); - if (!record.targets().contains(uuid)) return ApiBack.UNSUPPORTED; - - int maxDistance = ModConfigs.Server.inviteValidDistance.get(); - AnimationEvent.Accept acceptEvent = new AnimationEvent.Accept(AnimationEvent.Type.INVITE, maxDistance); - boolean post = MinecraftForge.EVENT_BUS.post(acceptEvent); - if(post) return ApiBack.BE_CANCELLED; - Event.Result eventResult = acceptEvent.getResult(); - switch (eventResult) { - case DENY : return ApiBack.BE_CANCELLED; - case DEFAULT : { - //Test if is in valid distance - int validDistance = acceptEvent.getValidDistance(); - if(player.distanceToSqr(inviter) > validDistance * validDistance) { - return ApiBack.OUT_RANGE; - } - int tickCount = inviter.server.getTickCount(); - if(tickCount >= record.expireTick()) { - inviteMap.remove(inviter.getUUID()); - return ApiBack.OPERATION_EXPIRE; - } - } - case ALLOW : { - //done - ApiBack apiBack = playAnimationWithRide(inviter, record.layer(), record.animation(), false); - if(apiBack == ApiBack.SUCCESS) { - if(record.targets().isEmpty()) inviteMap.remove(inviter.getUUID()); - ApiBack back = joinAnimation(player, inviter, false); - if(back == ApiBack.SUCCESS) record.targets().remove(uuid); - return back; - } else return apiBack; - } - default: return ApiBack.UNSUPPORTED; - } - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/service/RawAnimationService.java b/src/main/java/top/leisuretimedock/animationcore/animation/service/RawAnimationService.java deleted file mode 100644 index d081176..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/service/RawAnimationService.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.service; - -import top.leisuretimedock.animationcore.animation.capability.RawAnimationDataCapability; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.RawAnimationData; -import top.leisuretimedock.animationcore.animation.event.create.AnimationRegisterEvent; -import top.leisuretimedock.animationcore.animation.register.RawAnimationRegistry; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import top.leisuretimedock.animationcore.animation.utils.ApiBack; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.common.util.FakePlayer; -import net.minecraftforge.fml.loading.FMLEnvironment; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.HashSet; -import java.util.Optional; -import java.util.Set; - -public class RawAnimationService implements IAnimationService { - public static final RawAnimationService INSTANCE = new RawAnimationService(); - - /** - * Trigger raw animation registry.
- * It will clear all have been registered raw animation, then trigger register event.
- * If you need dynamic register, see {@link RawAnimationRegistry#register}, but it will reset when registry call register event.
- * If you need static register, you can add listener to {@link AnimationRegisterEvent.RawAnimation} - */ - @OnlyIn(Dist.CLIENT) - public void triggerRegistry() { - ANIMATION_RUNNER.testLoadedAndRun(RawAnimationRegistry::triggerRegistry); - } - - @Override - public @Nullable RawAnimationData getAnimation(ResourceLocation location) { - if(FMLEnvironment.dist == Dist.CLIENT) { - return RawAnimationRegistry.getAnimations().getOrDefault(location, null); - } else { - return RawAnimationData.create(location); - } - } - - @Override - public @Nullable RawAnimationData getAnimation(CompoundTag tag) { - return new RawAnimationData(){{deserializeNBT(tag);}}; - } - - @Override - public @Nullable RawAnimationDataCapability getCapability(Player player) { - return RawAnimationDataCapability.getCapability(player).orElse(null); - } - - @Override - public void clearAnimations(ServerPlayer serverPlayer) { - ANIMATION_RUNNER.testLoadedAndRun(() -> { - Optional.ofNullable(getCapability(serverPlayer)).ifPresent(RawAnimationDataCapability::clearAnimations); - detachAnimation(serverPlayer); - }); - } - - @Override - public boolean isAnimationPresent(ResourceLocation location) { - return true; - } - - @Override - @OnlyIn(Dist.CLIENT) - public void refreshAnimation(AbstractClientPlayer clientPlayer) { - ANIMATION_RUNNER.testLoadedAndRun(() -> { - RawAnimationDataCapability data = getCapability(clientPlayer); - if(data == null) return; - Set oldLayers = new HashSet<>(data.getAnimations().keySet()); - for (ResourceLocation layer : Set.copyOf(oldLayers)) { - if (AnimationUtils.isClientAnimationStop(clientPlayer, layer)) { - removeAnimation(clientPlayer, layer); - } - } - }); - } - - @Override - public @Nullable ResourceLocation getAnimationPlaying(Player player, @Nullable ResourceLocation layer) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - RawAnimationDataCapability data = getCapability(player); - if(data == null) return null; - if(layer == null){ - for (ResourceLocation value : data.getAnimations().values()) { - if(value != null) return value; - } - } else if (isAnimationLayerPresent(layer)) { - if(data.isAnimationPresent(layer)){ - return data.getAnimation(layer); - } - } - return null; - }); - } - - @Override - public ApiBack removeAnimation(@NotNull ServerPlayer serverPlayer, ResourceLocation layer) { - boolean result = ANIMATION_RUNNER.testLoadedAndCall(() -> Optional.ofNullable(getCapability(serverPlayer)) - .map(data -> data.removeAnimation(layer)).orElse(false)); - return result ? ApiBack.SUCCESS : ApiBack.FAIL; - } - - @Override - public ApiBack playAnimationServer(@NotNull ServerPlayer player, ResourceLocation layer, AnimationData animation) { - return ANIMATION_RUNNER.testLoadedAndCall(() -> { - ResourceLocation key = animation.getKey(); - if(!isAnimationLayerPresent(layer) || !isAnimationPresent(key)) - return ApiBack.RESOURCE_NOT_FOUND; - if(player instanceof FakePlayer) return ApiBack.UNSUPPORTED; - Boolean flag = Optional.ofNullable(getCapability(player)).map(data -> - data.mergeAnimation(layer, key)).orElse(false); - return flag ? ApiBack.SUCCESS : ApiBack.FAIL; - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/utils/AnimationUtils.java b/src/main/java/top/leisuretimedock/animationcore/animation/utils/AnimationUtils.java deleted file mode 100644 index d91b3d6..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/utils/AnimationUtils.java +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.utils; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.AnimationApi; -import top.leisuretimedock.animationcore.animation.capability.AnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.RawAnimationDataCapability; -import top.leisuretimedock.animationcore.animation.capability.inter.IAnimationCapability; -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.mixin.IMixinKeyframeAnimationPlayer; -import top.leisuretimedock.animationcore.animation.register.AnimationRegistry; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.animation.service.IAnimationService; -import top.leisuretimedock.animationcore.animation.service.RawAnimationService; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import dev.kosmx.playerAnim.api.layered.IAnimation; -import dev.kosmx.playerAnim.api.layered.KeyframeAnimationPlayer; -import dev.kosmx.playerAnim.api.layered.ModifierLayer; -import dev.kosmx.playerAnim.api.layered.modifier.AbstractFadeModifier; -import dev.kosmx.playerAnim.core.data.KeyframeAnimation; -import dev.kosmx.playerAnim.core.util.Ease; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationAccess; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.chat.Component; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import org.jetbrains.annotations.Nullable; - -import java.util.*; -import java.util.function.Predicate; - -public class AnimationUtils { - /** - * Test if layer exist animation which is not end.
- * Only in dist client - * @param player Target player - * @param layer Target layer - * @return True when animation is loop, or currentTick not larger than endTick - */ - @SuppressWarnings("unchecked") - @OnlyIn(Dist.CLIENT) - public static boolean isClientAnimationNotEnd(AbstractClientPlayer player, @Nullable ResourceLocation layer) { - return IAnimationService.ANIMATION_RUNNER.testLoadedAndCall(() -> { - try { - Set resourceLocations = new HashSet<>(); - if(layer == null) resourceLocations.addAll(AnimationRegistry.getLayers().keySet()); - else resourceLocations.add(layer); - for (ResourceLocation location : resourceLocations) { - ModifierLayer animationModifierLayer = (ModifierLayer) PlayerAnimationAccess - .getPlayerAssociatedData(player).get(location); - if(animationModifierLayer == null) continue; - KeyframeAnimationPlayer animation = (KeyframeAnimationPlayer) animationModifierLayer.getAnimation(); - if(animation == null) return false; - int currentTick = animation.getCurrentTick(); - boolean isLoop = animation.getData().isInfinite; - int endTick = animation.getData().endTick; - return isLoop || currentTick <= endTick; - } - } catch (Exception ignored) {} - return false; - }); - } - - /** - * Test if layer exist animation which is not stop.
- * Only in dist client - * @param player Target player - * @param layer Target layer - * @return True when the currentTick not larger than stopTick - */ - @SuppressWarnings("unchecked") - @OnlyIn(Dist.CLIENT) - public static boolean isClientAnimationStop(AbstractClientPlayer player, @Nullable ResourceLocation layer) { - return IAnimationService.ANIMATION_RUNNER.testLoadedAndCall(() -> { - try { - Set resourceLocations = new HashSet<>(); - if(layer == null) resourceLocations.addAll(AnimationRegistry.getLayers().keySet()); - else resourceLocations.add(layer); - boolean isNoneAnimation = true; - for (ResourceLocation location : resourceLocations) { - ModifierLayer animationModifierLayer = (ModifierLayer) PlayerAnimationAccess - .getPlayerAssociatedData(player).get(location); - if(animationModifierLayer == null) continue; - KeyframeAnimationPlayer animation = (KeyframeAnimationPlayer) animationModifierLayer.getAnimation(); - if(animation == null) continue; - int currentTick = animation.getCurrentTick(); - int stopTick = animation.getStopTick(); - if(currentTick < stopTick) isNoneAnimation = false; - } - return isNoneAnimation; - } catch (Exception ignored) {} - return true; - }); - } - - /** - * Client sync animation - * @param clientPlayer player - * @param target target - */ - @SuppressWarnings("unchecked") - @OnlyIn(Dist.CLIENT) - public static void syncAnimation(AbstractClientPlayer clientPlayer, AbstractClientPlayer target) { - IAnimationCapability clientPlayerData = AnimationDataCapability.getCapability(clientPlayer).orElse(null); - IAnimationCapability targetData = AnimationDataCapability.getCapability(target).orElse(null); - if(clientPlayerData == null) return; - if(targetData == null) return; - ResourceLocation clientPlayerLayer = clientPlayerData.getRiderAnimLayer(); - ResourceLocation targetLayer = targetData.getRiderAnimLayer(); - try { - if(clientPlayerLayer == null || targetLayer == null) return; - ModifierLayer modifierLayer = (ModifierLayer) PlayerAnimationAccess - .getPlayerAssociatedData(clientPlayer).get(clientPlayerLayer); - ModifierLayer targetModifierLayer = (ModifierLayer) PlayerAnimationAccess - .getPlayerAssociatedData(target).get(targetLayer); - if(modifierLayer == null || targetModifierLayer == null) return; - IMixinKeyframeAnimationPlayer animation = (IMixinKeyframeAnimationPlayer) modifierLayer.getAnimation(); - KeyframeAnimationPlayer targetAnimation = (KeyframeAnimationPlayer) targetModifierLayer.getAnimation(); - if(animation == null || targetAnimation == null) return; - int currentTick = targetAnimation.getCurrentTick(); - animation.animcore$setCurrentTick(currentTick); - } catch (Exception ignored) {} - } - - /** - * client remove animation - * @param clientPlayer player - * @param layer layer - */ - @OnlyIn(Dist.CLIENT) - public static void removeAnimation(@Nullable AbstractClientPlayer clientPlayer, ResourceLocation layer) { - playAnimation(clientPlayer, layer, null); - } - - /** - * Client play animation - * @param clientPlayer player - * @param layer layer - * @param animation animation - */ - @SuppressWarnings("unchecked") - @OnlyIn(Dist.CLIENT) - public static void playAnimation(@Nullable AbstractClientPlayer clientPlayer, ResourceLocation layer, @Nullable ResourceLocation animation) { - try { - LocalPlayer localPlayer = Minecraft.getInstance().player; - if(clientPlayer == null) clientPlayer = localPlayer; - if(clientPlayer == null) return; - ModifierLayer modifierLayer = (ModifierLayer) PlayerAnimationAccess - .getPlayerAssociatedData(clientPlayer).get(layer); - if(animation == null) { - if(modifierLayer != null) { - modifierLayer.replaceAnimationWithFade( - AbstractFadeModifier.standardFadeIn(3, Ease.INOUTSINE), - null - ); - } - return; - } - if(modifierLayer == null) return; - AnimationData anim = AnimationService.INSTANCE.getAnimation(animation); - if(anim == null) { - if((anim = RawAnimationService.INSTANCE.getAnimation(animation)) == null) - return; - } - KeyframeAnimation keyframeAnimation = anim.getAnimation(); - if(keyframeAnimation == null) { - if(localPlayer == null) return; - localPlayer.sendSystemMessage(Component.translatable( - ModLang.TranslatableMessage.ANIMATION_RESOURCE_NOT_FOUND.getKey(), - animation.toString() - ).withStyle(ChatFormatting.RED)); - modifierLayer.replaceAnimationWithFade( - AbstractFadeModifier.standardFadeIn(3, Ease.INOUTSINE), - null - ); - IAnimationService service = AnimationApi.getServiceGetterHelper(anim.getKey()).getService(); - if(service != null) service.removeAnimation(clientPlayer, layer); - return; - } - modifierLayer.replaceAnimationWithFade( - AbstractFadeModifier.standardFadeIn(3, Ease.INOUTSINE), - new KeyframeAnimationPlayer(keyframeAnimation) - ); - }catch (Exception e) { - AnimationCore.log.error("Failed to play animation : {}", animation, e); - } - } - - /** - * Get the LyingType when there are animations which playing on player.
- * And It will return the first which be found. - * @param player Target player - * @return The first LyingType it find. - */ - @Nullable - public static GenericAnimationData.LyingType getSideView(Player player) { - return IAnimationService.ANIMATION_RUNNER.testLoadedAndCall(() -> { - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - RawAnimationDataCapability rawData = RawAnimationDataCapability.getCapability(player).orElse(null); - if(data == null) return null; - if(rawData == null) return null; - - Map.Entry animations = null; - ArrayList resourceLocations = new ArrayList<>(); - resourceLocations.addAll(data.getAnimations().values()); - resourceLocations.addAll(rawData.getAnimations().values()); - for (ResourceLocation value : resourceLocations) { - AnimationData animation = AnimationApi.getDataHelper().getAnimationData(value); - if(animation == null) return null; - AnimationData.LyingType type = animation.getLyingType(); - if(type == null) continue; - switch (type) { - case FRONT,BACK -> {} - case LEFT,RIGHT -> { - if(animations == null || animations.getKey() < animation.getCamComputePriority()) { - animations = new AbstractMap.SimpleEntry<>(animation.getCamComputePriority(), type); - } - } - } - } - return animations == null ? null : animations.getValue(); - }); - } - - @Nullable - @OnlyIn(Dist.CLIENT) - public static AnimationData getPredicateAnimationData(Predicate predicate) { - return IAnimationService.ANIMATION_RUNNER.testLoadedAndCall(() -> { - LocalPlayer player = Minecraft.getInstance().player; - if(player == null) return null; - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - RawAnimationDataCapability rawData = RawAnimationDataCapability.getCapability(player).orElse(null); - if(data == null) return null; - if(rawData == null) return null; - - Map.Entry animations = null; - ArrayList resourceLocations = new ArrayList<>(); - resourceLocations.addAll(data.getAnimations().values()); - resourceLocations.addAll(rawData.getAnimations().values()); - if(data.getRiderAnimation() != null) resourceLocations.add(data.getRiderAnimation()); - for (ResourceLocation value : resourceLocations) { - AnimationData animation = AnimationApi.getDataHelper().getAnimationData(value); - if(animation == null) continue; - if(!predicate.test(animation)) continue; - if(animations == null || animations.getKey() < animation.getCamComputePriority()) { - animations = new AbstractMap.SimpleEntry<>(animation.getCamComputePriority(), animation); - } - } - return animations == null ? null : animations.getValue(); - }); - } - - @Nullable - public static AnimationData getEyeModifierAnimationData(Player player) { - IAnimationCapability data = AnimationDataCapability.getCapability(player).orElse(null); - RawAnimationDataCapability rawData = RawAnimationDataCapability.getCapability(player).orElse(null); - if(data == null) return null; - if(rawData == null) return null; - Map.Entry entry = null; - List values = new ArrayList<>(); - if(data.getRiderAnimation() != null) values.add(data.getRiderAnimation()); - values.addAll(data.getAnimations().values()); - values.addAll(rawData.getAnimations().values()); - for (ResourceLocation value : values) { - AnimationData animation = AnimationApi.getDataHelper().getAnimationData(value); - if(animation == null) continue; - float animationCamY = (float) animation.getCamPosOffset().y; - int priority = animation.getCamComputePriority(); - if((entry == null && animationCamY != 0) - || (entry != null && priority > entry.getValue())) { - entry = new HashMap.SimpleEntry<>(animation, priority); - } - } - return entry == null ? null : entry.getKey(); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/utils/ApiBack.java b/src/main/java/top/leisuretimedock/animationcore/animation/utils/ApiBack.java deleted file mode 100644 index 56d1337..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/utils/ApiBack.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.utils; - -import org.jetbrains.annotations.Nullable; - -public enum ApiBack { - FAIL(0), - SUCCESS(1), - COOLDOWN(2), - RESOURCE_NOT_FOUND(3), - OUT_RANGE(4), - OPERATION_EXPIRE(5), - UNSUPPORTED(6), - BE_CANCELLED(7), - ; - public final int value; - ApiBack(int value) { - this.value = value; - } - - public boolean isValueOf(int value) { - return this.value == value; - } - - @Nullable - public static ApiBack valueOf(int value) { - ApiBack[] values = ApiBack.values(); - for (ApiBack v : values) { - if (v.isValueOf(value)) { - return v; - } - } - return null; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/animation/utils/FileUtils.java b/src/main/java/top/leisuretimedock/animationcore/animation/utils/FileUtils.java deleted file mode 100644 index 5fba7ae..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/animation/utils/FileUtils.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.animation.utils; - -import java.io.InputStream; -import java.io.OutputStream; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.nio.file.StandardOpenOption; -import java.util.Collections; -import java.util.Enumeration; -import java.util.Set; -import java.util.function.Predicate; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -public class FileUtils { - public static Set getAllFile(Path directory, Predicate filter) { - try (Stream walk = Files.walk(directory)) { - return walk.filter(Files::isRegularFile) - .filter(filter) - .collect(Collectors.toSet()); - } catch (Exception ignored) { - return Collections.emptySet(); - } - } - - public static void safeUnzip(String zipFile, String destDir) { - Path destPath = Paths.get(destDir).toAbsolutePath(); - - try (ZipFile zip = new ZipFile(zipFile)) { - Files.createDirectories(destPath); - Enumeration entries = zip.entries(); - - while (entries.hasMoreElements()) { - ZipEntry entry = entries.nextElement(); - Path entryPath = destPath.resolve(entry.getName()).normalize(); - - if (entry.isDirectory()) { - Files.createDirectories(entryPath); - } else { - Files.createDirectories(entryPath.getParent()); - try (InputStream in = zip.getInputStream(entry); - OutputStream out = Files.newOutputStream(entryPath, StandardOpenOption.CREATE)) { - byte[] buffer = new byte[8192]; - int bytesRead; - while ((bytesRead = in.read(buffer)) != -1) { - out.write(buffer, 0, bytesRead); - } - } - } - } - } catch (Exception ignored) {} - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/CapabilityUtils.java b/src/main/java/top/leisuretimedock/animationcore/capability/CapabilityUtils.java deleted file mode 100644 index 2350db2..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/CapabilityUtils.java +++ /dev/null @@ -1,212 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.entity.EntityCapabilityHandler; -import top.leisuretimedock.animationcore.capability.data.entity.EntityCapabilityRegistry; -import top.leisuretimedock.animationcore.capability.data.player.PlayerCapabilityHandler; -import top.leisuretimedock.animationcore.capability.data.player.PlayerCapabilityRegistry; -import top.leisuretimedock.animationcore.capability.network.CapabilityChannel; -import top.leisuretimedock.animationcore.capability.network.ICapabilityPacket; -import top.leisuretimedock.animationcore.core.ModChannel; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.network.NetworkEvent; -import net.minecraftforge.network.simple.SimpleChannel; -import org.jetbrains.annotations.Nullable; - -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - -public class CapabilityUtils { - - /** - * Simultaneously invite player capability and corresponding network packets - * @param key The unique name of capability - * @param capabilityRecord Registration data for capability - * @param channelRegister You should create an instance in advance to pass in, see: {@link CapabilityUtils#createChannel} - * @param cid Network Channel Index - * @param clazz Class of network packets - * @param decoder Decoding of network packets - * @param encoder Encoding of network packets - * @param handler Handle of network packets - * @param extend {@code ICapabilityPacket} - */ - public static > void registerPlayerCapabilityWithNetwork( - ResourceLocation key, PlayerCapabilityRegistry.CapabilityRecord> capabilityRecord, - CapabilityChannel channelRegister, - int cid, - Class clazz, - Function decoder, - BiConsumer encoder, - BiConsumer> handler - ) { - PlayerCapabilityRegistry.registerCapability(key, capabilityRecord); - channelRegister.register(clazz, cid, decoder, encoder, handler); - } - - /** - * Simultaneously invite entity capability and corresponding network packets - * @param key The unique name of capability - * @param capabilityRecord Registration data for capability - * @param channelRegister You should create an instance in advance to pass in, see: {@link CapabilityUtils#createChannel} - * @param cid Network Channel Index - * @param clazz Class of network packets - * @param decoder Decoding of network packets - * @param encoder Encoding of network packets - * @param handler Handle of network packets - * @param {@code ICapabilityPacket} - */ - public static > void registerEntityCapabilityWithNetwork( - ResourceLocation key, EntityCapabilityRegistry.CapabilityRecord> capabilityRecord, - CapabilityChannel channelRegister, - int cid, - Class clazz, - Function decoder, - BiConsumer encoder, - BiConsumer> handler - ) { - EntityCapabilityRegistry.registerCapability(key, capabilityRecord); - channelRegister.register(clazz, cid, decoder, encoder, handler); - } - - /** - * See {@link PlayerCapabilityRegistry#registerCapability(ResourceLocation, PlayerCapabilityRegistry.CapabilityRecord)} - * @param key The unique name of capability. - * @param capabilityRecord Record is used to store various data of the capabilities that should be registered, refer to: {@link PlayerCapabilityRegistry.CapabilityRecord} - * @param extends {@code ICapabilitySync} - */ - public static > void registerPlayerCapability(ResourceLocation key, PlayerCapabilityRegistry.CapabilityRecord capabilityRecord){ - PlayerCapabilityRegistry.registerCapability(key, capabilityRecord); - } - - /** - * See {@link EntityCapabilityRegistry#registerCapability(ResourceLocation, EntityCapabilityRegistry.CapabilityRecord)} - * @param key The unique name of capability. - * @param capabilityRecord Record is used to store various data of the capabilities that should be registered, refer to: {@link EntityCapabilityRegistry.CapabilityRecord} - * @param extends {@code ICapabilitySync} - */ - public static > void registerEntityCapability(ResourceLocation key, EntityCapabilityRegistry.CapabilityRecord capabilityRecord){ - EntityCapabilityRegistry.registerCapability(key, capabilityRecord); - } - - /** - * Return a new PlayerCapabilityChannel instance through this method
- * Generally, only network packets registered on different channels will be used - * @param channel Your own mod channel - * @return newInstances - */ - public static CapabilityChannel createChannel(SimpleChannel channel) { - return new CapabilityChannel(channel); - } - - /** - * Return the PlayerCapabilityChannel instance of the Channel in SCCore through this method - * @return newInstances - */ - public static CapabilityChannel createChannel() { - return new CapabilityChannel(ModChannel.INSTANCE); - } - - /** - * By using this method to listen for capability events, all functions will be enabled
- * Repeated calls will not cause anything - * @param forgeBus Forge event bus - */ - public static void registerHandler(IEventBus forgeBus){ - PlayerCapabilityHandler.register(forgeBus); - EntityCapabilityHandler.register(forgeBus); - } - - /** - * Please obtain capability through this method - * @param entity Target entity, type: {@code } - * @param key The unique name of capability - * @param clazz The capability type that should be returned. If it is null, will return: {@code ICapabilitySync} - * @param extend {@code Entity} - * @param extend {@code ICapabilitySync} - * @return Return the corresponding capability - */ - @SuppressWarnings("unchecked") - @Nullable - public static > T getEntityCapability(E entity, ResourceLocation key, @Nullable Class clazz) { - try { - ICapabilitySync capabilitySync = entity.getCapability( - EntityCapabilityRegistry.getCapabilityMap().get(key).capability() - ).resolve().orElse(null); - if(clazz == null) return (T) capabilitySync; - if(clazz.isInstance(capabilitySync)) - return clazz.cast(capabilitySync); - else return null; - }catch(Exception e){ - return null; - } - } - - /** - * Please obtain capability through this method - * @param entity Target entity, type: {@code } - * @param key The unique name of capability - * @param clazz The capability type that should be returned. If it is null, will return: {@code ICapabilitySync} - * @param extend {@code Player} - * @param extend {@code ICapabilitySync} - * @return Return the corresponding capability - */ - @SuppressWarnings("unchecked") - @Nullable - public static > T getPlayerCapability(E entity, ResourceLocation key, @Nullable Class clazz) { - try { - ICapabilitySync capabilitySync = entity.getCapability( - PlayerCapabilityRegistry.getCapabilityMap().get(key).capability() - ).resolve().orElse(null); - if(clazz == null) return (T) capabilitySync; - if(clazz.isInstance(capabilitySync)) - return clazz.cast(capabilitySync); - else return null; - }catch(Exception e){ - return null; - } - } - - /** - * Get a capability of an unconverted type - * @param entity Target - * @param key The unique name of capability - * @return An unconverted capability - */ - @Nullable - public static ICapabilitySync getCapability(Entity entity, ResourceLocation key) { - if(entity == null) return null; - try { - if(entity instanceof Player) { - return entity.getCapability( - PlayerCapabilityRegistry.getCapabilityMap().get(key).capability() - ).resolve().orElse(null); - } - return entity.getCapability( - EntityCapabilityRegistry.getCapabilityMap().get(key).capability() - ).resolve().orElse(null); - }catch(Exception e){ - return null; - } - - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/ICapabilitySync.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/ICapabilitySync.java deleted file mode 100644 index 81480c4..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/ICapabilitySync.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data; - -import top.leisuretimedock.animationcore.capability.network.SimpleCapabilityPacket; -import top.leisuretimedock.animationcore.core.ModChannel; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.common.util.INBTSerializable; - -public interface ICapabilitySync extends INBTSerializable { - /** - * You should call it to set it to true in the setter of each property to trigger automatic synchronization - * @param dirty dirty - */ - void setDirty(boolean dirty); - - boolean isDirty(); - - ResourceLocation getKey(); - - /** - * When this method is overridden, the super method should be called at the end - * @param oldData old data - * @param listenDone Whether to execute the completion method at the end: {@link ICapabilitySync#onCopyDone()} - */ - default void copyFrom(ICapabilitySync oldData, boolean listenDone) { - this.setDirty(oldData.isDirty()); - if(listenDone) onCopyDone(); - } - - /** - * After the copy is completed, if certain values need to be redefined, you should override this method
- * Commonly used for resetting data when players cross dimensions or die - */ - default void onCopyDone(){} - - /** - * In general, it is recommended to rewrite it, otherwise it will be sent as a Channel instance of SCCore
- * The server sends client synchronized data to all players - */ - default void sendToClient(){ - ModChannel.sendAllPlayer(getDefaultPacket()); - } - - /** - * In general, it is recommended to rewrite it, otherwise it will be sent as a Channel instance of SCCore
- * The server sends client synchronized data to a single player - * @param player Target player - */ - default void sendToClient(ServerPlayer player){ - ModChannel.sendToPlayer(getDefaultPacket(), player); - } - - /** - * Rewrite this method to set a network packet class for your Capability
- * When calling the sendToClient method, network packets will be obtained from here and sent directly
- * In general, you should extend SimpleCapacityPackage and then override the method to return your subclass - * @return SimpleCapacityPacket, a network packet class - */ - SimpleCapabilityPacket getDefaultPacket(); - - /** - * When players log in or entity join the world, the capability initialization will be called
- * Must be implemented, but can be an empty method - * @param entity Target - */ - void attachInit(T entity); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityHandler.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityHandler.java deleted file mode 100644 index b780650..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.entity; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; -import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Mod.EventBusSubscriber(modid = AnimationCore.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) -public class EntityCapabilityHandler { - private static final Logger log = LoggerFactory.getLogger(EntityCapabilityHandler.class); - private static boolean isRegistered = false; - - /** - * It should be called in the Forge mainline to listen to the capability registration
- * Suggest calling it in the Mod constructor method
- * Normally AnimCore will call it, so you should not call it - * @param forgeBus forge event bus - */ - public static void register(IEventBus forgeBus) { - if (isRegistered) return; - //remainder - forgeBus.addListener(EventPriority.HIGHEST, EntityCapabilityRemainder::capabilitySync); - forgeBus.addListener(EventPriority.HIGHEST, EntityCapabilityRemainder::onEntityBeTracked); - forgeBus.addListener(EventPriority.HIGHEST, EntityCapabilityRemainder::onEntityJoin); - isRegistered = true; - } - - /** - * Register capability - * @param event event - */ - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void registerCapability(RegisterCapabilitiesEvent event) { - EntityCapabilityRegistry.getCapabilityMap().values().forEach(record -> - event.register(record.interfaceClass()) - ); - } - - /** - * Attach capability to entity - * @param event event - */ - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void attachCapability(AttachCapabilitiesEvent event) { - if(event.getObject() instanceof Entity entity) { - EntityCapabilityRegistry.getCapabilityMap().forEach((key, record) -> - record.targets().forEach(target -> { - if(target.isInstance(entity)) { - try { - ICapabilitySync capabilitySync = (ICapabilitySync) record.aClass().getDeclaredConstructor().newInstance(); - event.addCapability(key, new EntityCapabilityProvider<>(key, capabilitySync)); - } catch (Exception e) { - log.error("Failed to instantiate capability sync class {}. Your capability invite is wrong.", record.aClass(), e); - } - } - })); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityProvider.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityProvider.java deleted file mode 100644 index 4fd1ee7..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityProvider.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.entity; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.common.capabilities.AutoRegisterCapability; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ICapabilitySerializable; -import net.minecraftforge.common.util.LazyOptional; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * The final serialization, deserialization, and retrieval methods of capability - * @param extends {@link ICapabilitySync} - */ -@AutoRegisterCapability -public class EntityCapabilityProvider> implements ICapabilitySerializable { - private final C instance; - private final ResourceLocation resourceLocation; - - /** - * Constructor - * @param resourceLocation key - * @param instance instance - */ - public EntityCapabilityProvider(ResourceLocation resourceLocation, C instance) { - this.resourceLocation = resourceLocation; - this.instance = instance; - } - - @SuppressWarnings("unchecked") - @Override - public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { - Capability iCapabilitySyncCapability = (Capability) EntityCapabilityRegistry.getCapabilityRecord(resourceLocation).capability(); - return iCapabilitySyncCapability.orEmpty(cap, LazyOptional.of(() -> instance)); - } - - @Override - public CompoundTag serializeNBT() { - return instance.serializeNBT(); - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - instance.deserializeNBT(nbt); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityRegistry.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityRegistry.java deleted file mode 100644 index 4765e9c..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityRegistry.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.entity; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.common.capabilities.Capability; - -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -public class EntityCapabilityRegistry { - public static final EntityCapabilityRegistry CAPABILITIES = new EntityCapabilityRegistry(); - private final Map> capabilityRecordMap = new HashMap<>(); - - /** - * Registering entity capabilities through this method only applies to {@link net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent}
- * @param key The unique name of capability. - * @param capabilityRecord Record is used to store various data of the capabilities that should be registered, refer to: {@link EntityCapabilityRegistry.CapabilityRecord} - */ - public static void registerCapability(ResourceLocation key, CapabilityRecord capabilityRecord) { - CAPABILITIES.capabilityRecordMap.put(key, capabilityRecord); - } - - /** - * Obtain corresponding capability data through this method - * @param key Obtain based on key - * @return capability - */ - public static CapabilityRecord getCapabilityRecord(ResourceLocation key){ - return CAPABILITIES.capabilityRecordMap.get(key); - } - - public static Map> getCapabilityMap(){ - return CAPABILITIES.capabilityRecordMap; - } - - /** - * Record the registration data of capability - * @param aClass The instance that will ultimately be attached to the entity. Should be an instance of ICapabilitySync - * @param capability In general, it is not necessary to initialize it, default: {@code CapabilityManager.get(new CapabilityToken<>(){})} - * @param interfaceClass The interface class corresponding to the instance, such as: ICapabilitySync.class. - * @param targets Targets types attached to capability - */ - public record CapabilityRecord>( - Class aClass, - Capability capability, - Class interfaceClass, - Set> targets - ) { - - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityRemainder.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityRemainder.java deleted file mode 100644 index 60ea3ca..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/EntityCapabilityRemainder.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.entity; - -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.player.PlayerCapabilityRegistry; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.LivingEntity; -import net.minecraftforge.event.entity.EntityJoinLevelEvent; -import net.minecraftforge.event.entity.living.LivingEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; - -public class EntityCapabilityRemainder { - /** - * Player start tracking an entity event
- * When other entities are loaded, the client requires the capabilities of the other party, and this event can be actively sent
- * Will call{@link ICapabilitySync#sendToClient(ServerPlayer)} - * @param event event - */ - public static void onEntityBeTracked(PlayerEvent.StartTracking event) { - if (event.getEntity() instanceof ServerPlayer attacker) { - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getCapability(event.getTarget(), key); - if(data == null) return; - data.sendToClient(attacker); - }); - } - } - - /** - * Entity Tick Event
- * If the capability is dirty, it will call {@link ICapabilitySync#sendToClient()}
- * For performance reasons, synchronization is only triggered once per second - * @param event event - */ - public static void capabilitySync(LivingEvent.LivingTickEvent event) { - LivingEntity entity = event.getEntity(); - if(!entity.level().isClientSide){ - if (entity.tickCount % 20 == 0) { - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getCapability(entity, key); - if(data == null) return; - if(data.isDirty()) { - data.setDirty(false); - data.sendToClient(); - } - }); - } - } - } - - /** - * Event of entity joining level, initialization - * @param event event - */ - public static void onEntityJoin(EntityJoinLevelEvent event) { - Entity entity = event.getEntity(); - if(entity.level().isClientSide) return; - EntityCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getEntityCapability(entity, key, null); - if(data == null) return; - if(data instanceof SimpleEntityCapabilitySync capabilitySync){ - capabilitySync.setId(entity.getId()); - } - data.attachInit(entity); - data.setDirty(false); - data.sendToClient(); - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/SimpleEntityCapabilitySync.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/SimpleEntityCapabilitySync.java deleted file mode 100644 index 819d772..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/entity/SimpleEntityCapabilitySync.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.entity; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.Entity; - -/** - * It is recommended to manually add it during implementation:
- * {@code key} ---- As the unique identifier of capability.
- * {@code getCapability(Entity entity)} ---- Simplified method for obtaining capability
- * 例: - *
- * {@code
- *     public static final ResourceLocation key =
- *          new ResourceLocation(MyMod.MOD_ID, "sheep_data");
- *     public static Optional getCapability(Sheep sheep){
- *         return Optional.ofNullable(CapabilityUtils.getEntityCapability(
- *             player, SheepDataCapability.key, SheepDataCapability.class
- *         ));
- *     }
- * }
- * 
- * - */ -public abstract class SimpleEntityCapabilitySync implements ICapabilitySync { - /** - * Id - */ - public static final String Id = "Id"; - - private boolean dirty; - private Integer id; - - @Override - public boolean isDirty() { - return dirty; - } - - /** - * You should call it to set it to true in the setter of each property to trigger automatic synchronization - * @param dirty dirty - */ - @Override - public void setDirty(boolean dirty) { - this.dirty = dirty; - } - - /** - * get id - * @return Id - */ - public Integer getId() { - return id; - } - - /** - * set id - * @param id id - */ - public void setId(Integer id) { - this.id = id; - setDirty(true); - } - - /** - * Copy data from parameter instance to current instance
- *You shouldn't rewrite it, you should implement: {@link SimpleEntityCapabilitySync#copyFrom(ICapabilitySync)} - * @param oldData old data - * @param listenDone Whether to execute the completion method at the end: {@link ICapabilitySync#onCopyDone()} - */ - @Override - public void copyFrom(ICapabilitySync oldData, boolean listenDone) { - SimpleEntityCapabilitySync data = (SimpleEntityCapabilitySync) oldData; - this.setId(data.getId()); - copyFrom(data); - ICapabilitySync.super.copyFrom(oldData, listenDone); - } - - /** - * The method that will be executed when triggering data replication - * @param oldData Copy from this data to the current instance - */ - public abstract void copyFrom(ICapabilitySync oldData); - - /** - * Serialize to tag
- * You shouldn't rewrite it, you should implement: {@link SimpleEntityCapabilitySync#toTag(CompoundTag)} - * @return tag - */ - @Override - public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - if(id != null) tag.putInt(Id, id); - tag = toTag(tag); - return tag; - } - - /** - * Deserialize to instance object
- * You don't need to rewrite it, you should implement: {@link SimpleEntityCapabilitySync#fromTag(CompoundTag)} - * @param nbt nbt - */ - @Override - public void deserializeNBT(CompoundTag nbt) { - this.id = null; - if(nbt.contains(Id)) this.id = nbt.getInt(Id); - fromTag(nbt); - } - - /** - * In the serializeNBT method of SimpleElementCapability Sync, it will be called
- * Actually equivalent to serializeNBT() - * @param tag data tag - * @return tag - */ - public abstract CompoundTag toTag(CompoundTag tag); - - /** - * In the deserializeNBT method of SimpleElementCapability Sync, it will be called
- * Actually equivalent to deserializeNBT() - * @param tag data tag - */ - public abstract void fromTag(CompoundTag tag); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityHandler.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityHandler.java deleted file mode 100644 index d838cda..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityHandler.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.player; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent; -import net.minecraftforge.event.AttachCapabilitiesEvent; -import net.minecraftforge.eventbus.api.EventPriority; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@Mod.EventBusSubscriber(modid = AnimationCore.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE) -public class PlayerCapabilityHandler { - private static final Logger log = LoggerFactory.getLogger(PlayerCapabilityHandler.class); - private static boolean isRegistered = false; - - /** - * It should be called in the Forge mainline to listen to the capability registration
- * Suggest calling it in the Mod constructor method
- * Normally SCCore will call it, so you should not call it - * @param forgeBus forge event bus - */ - public static void register(IEventBus forgeBus) { - if (isRegistered) return; - //remainder - forgeBus.addListener(EventPriority.HIGHEST, PlayerCapabilityRemainder::capabilitySync); - forgeBus.addListener(EventPriority.HIGHEST, PlayerCapabilityRemainder::onPlayerClone); - forgeBus.addListener(EventPriority.HIGHEST, PlayerCapabilityRemainder::onPlayerRespawn); - forgeBus.addListener(EventPriority.HIGHEST, PlayerCapabilityRemainder::onEntityBeTracked); - forgeBus.addListener(EventPriority.HIGHEST, PlayerCapabilityRemainder::onPlayerLogin); - isRegistered = true; - } - - /** - * Register capability - * @param event event - */ - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void registerCapability(RegisterCapabilitiesEvent event) { - PlayerCapabilityRegistry.getCapabilityMap().values().forEach(record -> - event.register(record.interfaceClass()) - ); - } - - /** - * Attach capability to entity - * @param event event - */ - @SubscribeEvent(priority = EventPriority.HIGHEST) - public static void attachCapability(AttachCapabilitiesEvent event) { - if(event.getObject() instanceof Player) { - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, record) -> { - try { - ICapabilitySync capabilitySync = (ICapabilitySync) record.aClass().getDeclaredConstructor().newInstance(); - event.addCapability(key, new PlayerCapabilityProvider<>(key, capabilitySync)); - } catch (Exception e) { - log.error("Failed to instantiate capability sync class {}. Your capability invite is wrong.", record.aClass(), e); - } - }); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityProvider.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityProvider.java deleted file mode 100644 index 215c644..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityProvider.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.player; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.core.Direction; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.resources.ResourceLocation; -import net.minecraftforge.common.capabilities.AutoRegisterCapability; -import net.minecraftforge.common.capabilities.Capability; -import net.minecraftforge.common.capabilities.ICapabilitySerializable; -import net.minecraftforge.common.util.LazyOptional; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * The final serialization, deserialization, and retrieval methods of capability - * @param extends {@link ICapabilitySync} - */ -@AutoRegisterCapability -public class PlayerCapabilityProvider> implements ICapabilitySerializable { - private final C instance; - private final ResourceLocation resourceLocation; - - /** - * Constructor - * @param resourceLocation key - * @param instance instance - */ - public PlayerCapabilityProvider(ResourceLocation resourceLocation, C instance) { - this.resourceLocation = resourceLocation; - this.instance = instance; - } - - @SuppressWarnings("unchecked") - @Override - public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { - Capability iCapabilitySyncCapability = (Capability) PlayerCapabilityRegistry.getCapabilityRecord(resourceLocation).capability(); - return iCapabilitySyncCapability.orEmpty(cap, LazyOptional.of(() -> instance)); - } - - @Override - public CompoundTag serializeNBT() { - return instance.serializeNBT(); - } - - @Override - public void deserializeNBT(CompoundTag nbt) { - instance.deserializeNBT(nbt); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityRegistry.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityRegistry.java deleted file mode 100644 index eb0833e..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityRegistry.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.player; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.common.capabilities.Capability; - -import java.util.HashMap; -import java.util.Map; - -public class PlayerCapabilityRegistry { - public static final PlayerCapabilityRegistry CAPABILITIES = new PlayerCapabilityRegistry(); - private final Map> capabilityRecordMap = new HashMap<>(); - - /** - * Registering player capabilities through this method only applies to {@link net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent}
- * @param key The unique name of capability. - * @param capabilityRecord Record is used to store various data of the capabilities that should be registered, refer to: {@link PlayerCapabilityRegistry.CapabilityRecord} - */ - public static void registerCapability(ResourceLocation key, CapabilityRecord capabilityRecord) { - CAPABILITIES.capabilityRecordMap.put(key, capabilityRecord); - } - - /** - * Obtain corresponding capability data through this method - * @param key Obtain based on key - * @return capability - */ - public static CapabilityRecord getCapabilityRecord(ResourceLocation key){ - return CAPABILITIES.capabilityRecordMap.get(key); - } - - public static Map> getCapabilityMap(){ - return CAPABILITIES.capabilityRecordMap; - } - - /** - * Record the registration data of capability - * @param aClass The instance that will ultimately be attached to the player. Should be an instance of ICapabilitySync - * @param capability In general, it is not necessary to initialize it, default: {@code CapabilityManager.get(new CapabilityToken<>(){})} - * @param interfaceClass The interface class corresponding to the instance, such as: ICapabilitySync.class. - */ - public record CapabilityRecord>(Class aClass, Capability capability, Class interfaceClass) { } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityRemainder.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityRemainder.java deleted file mode 100644 index abf87a9..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/PlayerCapabilityRemainder.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.player; - -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.event.TickEvent; -import net.minecraftforge.event.entity.player.PlayerEvent; - -public class PlayerCapabilityRemainder { - /** - * Players should transfer data to a new body when crossing dimensions or dying - * @param event event - */ - public static void onPlayerClone(PlayerEvent.Clone event) { - Player entity = event.getEntity(); - if(entity instanceof ServerPlayer newPlayer) { - Player original = event.getOriginal(); - original.reviveCaps(); - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync originData = CapabilityUtils.getCapability(original, key); - ICapabilitySync newData = CapabilityUtils.getCapability(newPlayer, key); - if(originData != null && newData != null) { - newData.copyFrom(originData, true); - newData.sendToClient(); - } - }); - original.invalidateCaps(); - } - } - - /** - * Players should update their capabilities when they are reborn - * @param event event - */ - public static void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) { - if(event.getEntity() instanceof ServerPlayer newPlayer){ - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getCapability(newPlayer, key); - if(data == null) return; - data.sendToClient(newPlayer); - }); - } - } - - /** - * Player start tracking an player event
- * When other entities are loaded, the client requires the capabilities of the other party, and this event can be actively sent
- * Will call{@link ICapabilitySync#sendToClient(ServerPlayer)} - * @param event event - */ - public static void onEntityBeTracked(PlayerEvent.StartTracking event) { - if (event.getTarget() instanceof Player target && event.getEntity() instanceof ServerPlayer attacker) { - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getCapability(target, key); - if(data == null) return; - data.sendToClient(attacker); - }); - } - } - - /** - * Player Tick Event
- * If the capability is dirty, it will call {@link ICapabilitySync#sendToClient()}
- * @param event event - */ - public static void capabilitySync(TickEvent.PlayerTickEvent event) { - if(!event.player.level().isClientSide){ - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getCapability(event.player, key); - if(data == null) return; - if(data.isDirty()) { - data.setDirty(false); - data.sendToClient(); - } - }); - } - } - - /** - * Player login event
- * Reinitialize the login player's capability
- * @param event event - */ - public static void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) { - Player player = event.getEntity(); - if(!(player instanceof ServerPlayer serverPlayer)) return; - PlayerCapabilityRegistry.getCapabilityMap().forEach((key, value) -> { - ICapabilitySync data = CapabilityUtils.getPlayerCapability(player, key, null); - if(data == null) return; - if(data instanceof SimplePlayerCapabilitySync capabilitySync) { - capabilitySync.setOwnerUUID(serverPlayer.getUUID()); - } - data.attachInit(serverPlayer); - data.setDirty(false); - data.sendToClient(); - }); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/SimplePlayerCapabilitySync.java b/src/main/java/top/leisuretimedock/animationcore/capability/data/player/SimplePlayerCapabilitySync.java deleted file mode 100644 index c3aa663..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/data/player/SimplePlayerCapabilitySync.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.data.player; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.entity.SimpleEntityCapabilitySync; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.player.Player; - -import java.util.UUID; - -/** - * It is recommended to manually add it during implementation:
- * {@code key} ---- As the unique identifier of capability.
- * {@code getCapability(Player player)} ---- Simplified method for obtaining capability
- * 例: - *
- * {@code
- *     public static final ResourceLocation key =
- *          new ResourceLocation(MyMod.MOD_ID, "my_data");
- *     public static Optional getCapability(Player player){
- *         return Optional.ofNullable(CapabilityUtils.getPlayerCapability(
- *             player, MyDataCapability.key, MyDataCapability.class
- *         ));
- *     }
- * }
- * 
- * - */ -public abstract class SimplePlayerCapabilitySync implements ICapabilitySync { - public static final String OwnerUUID = "OwnerUUID"; - - private boolean dirty; - private UUID ownerUUID; - - @Override - public boolean isDirty() { - return dirty; - } - - @Override - public void setDirty(boolean dirty) { - this.dirty = dirty; - } - - public UUID getOwnerUUID() { - return ownerUUID; - } - - public void setOwnerUUID(UUID ownerUUID) { - this.ownerUUID = ownerUUID; - setDirty(true); - } - - /** - * Copy data from parameter instance to current instance
- *You shouldn't rewrite it, you should implement: {@link SimpleEntityCapabilitySync#copyFrom(ICapabilitySync)} - * @param oldData old data - * @param listenDone Whether to execute the completion method at the end: {@link ICapabilitySync#onCopyDone()} - */ - @Override - public void copyFrom(ICapabilitySync oldData, boolean listenDone) { - SimplePlayerCapabilitySync data = (SimplePlayerCapabilitySync) oldData; - this.setOwnerUUID(data.getOwnerUUID()); - copyFrom(data); - ICapabilitySync.super.copyFrom(oldData, listenDone); - } - - /** - * The method that will be executed when triggering data replication - * @param oldData Copy from this data to the current instance - */ - public abstract void copyFrom(ICapabilitySync oldData); - - /** - * Serialize to tag
- * You shouldn't rewrite it, you should implement: {@link SimplePlayerCapabilitySync#toTag(CompoundTag)} - * @return tag - */ - @Override - public CompoundTag serializeNBT() { - CompoundTag tag = new CompoundTag(); - if(ownerUUID != null) tag.putUUID(OwnerUUID, ownerUUID); - tag = toTag(tag); - return tag; - } - - /** - * Deserialize to instance object
- * You don't need to rewrite it, you should implement: {@link SimplePlayerCapabilitySync#fromTag(CompoundTag)} - * @param nbt nbt - */ - @Override - public void deserializeNBT(CompoundTag nbt) { - this.ownerUUID = null; - if(nbt.contains(OwnerUUID)) this.ownerUUID = nbt.getUUID(OwnerUUID); - fromTag(nbt); - } - - /** - * In the serializeNBT method of SimpleElementCapability Sync, it will be called
- * Actually equivalent to serializeNBT() - * @param tag data tag - * @return tag - */ - public abstract CompoundTag toTag(CompoundTag tag); - - /** - * In the deserializeNBT method of SimpleElementCapability Sync, it will be called
- * Actually equivalent to deserializeNBT() - * @param tag data tag - */ - public abstract void fromTag(CompoundTag tag); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/network/CapabilityChannel.java b/src/main/java/top/leisuretimedock/animationcore/capability/network/CapabilityChannel.java deleted file mode 100644 index 90341e2..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/network/CapabilityChannel.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.network; - -import net.minecraft.network.FriendlyByteBuf; -import net.minecraftforge.network.NetworkDirection; -import net.minecraftforge.network.NetworkEvent; -import net.minecraftforge.network.simple.SimpleChannel; - -import java.util.function.BiConsumer; -import java.util.function.Function; -import java.util.function.Supplier; - -/** - * Call createChannel in the Mod main class construction method logic. There are two ways:
- *
- * 1. {@link top.leisuretimedock.animationcore.capability.CapabilityUtils#createChannel(SimpleChannel)}
- * If you do this, you must override all the sendToPlayer methods in the Capability class, and call your Channel in the override
- * 
- *
- * 2. {@link top.leisuretimedock.animationcore.capability.CapabilityUtils#createChannel()}
- * If this is done, the network package will be registered with SCCore's Channel
- * 
- * The added network packet must implement the ICapabilityPacket interface - */ -public class CapabilityChannel { - private final SimpleChannel channel; - - public CapabilityChannel(SimpleChannel channel) { - this.channel = channel; - } - - /** - * Add a network packet through this method and invite - * @param clazz Network packet class - * @param cid index - * @param decoder decoder - * @param encoder encoder - * @param handler handler - * @param extend {@code ICapabilityPacket} - */ - public > void register( - Class clazz, - int cid, - Function decoder, - BiConsumer encoder, - BiConsumer> handler - ) { - channel.messageBuilder(clazz, cid, NetworkDirection.PLAY_TO_CLIENT) - .decoder(decoder) - .encoder(encoder) - .consumerMainThread(handler) - .add(); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/network/ICapabilityPacket.java b/src/main/java/top/leisuretimedock/animationcore/capability/network/ICapabilityPacket.java deleted file mode 100644 index e2c1cc9..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/network/ICapabilityPacket.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.network; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.network.NetworkEvent; - -import java.util.function.Supplier; - -public interface ICapabilityPacket { - /** - * Decoding network packets - * @param buf FriendlyByteBuf - */ - void encode(FriendlyByteBuf buf); - - /** - * Network packet processing events generally do not need to be rewritten, and the default behavior is sufficient for use - * @param supplier supplier - */ - default void handle(Supplier supplier){ - NetworkEvent.Context context = supplier.get(); - context.enqueueWork(() -> handler(context)); - } - - /** - * Network packet processing events should be rewritten here - * @param context NetworkEvent.Context - */ - void handler(NetworkEvent.Context context); - - - /** - * Get tag - * @return tag - */ - CompoundTag getData(); - - /** - * Convert tags to capability data in network packets and deserialize them directly by default - * @param dataTag tag - * @param data The data that should be written into the data - */ - default void syncData(CompoundTag dataTag, ICapabilitySync data){ - if(data == null) return; - data.deserializeNBT(dataTag); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/capability/network/SimpleCapabilityPacket.java b/src/main/java/top/leisuretimedock/animationcore/capability/network/SimpleCapabilityPacket.java deleted file mode 100644 index dc9e272..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/capability/network/SimpleCapabilityPacket.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.capability.network; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.entity.SimpleEntityCapabilitySync; -import top.leisuretimedock.animationcore.capability.data.player.SimplePlayerCapabilitySync; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraftforge.network.NetworkEvent; - -public class SimpleCapabilityPacket implements ICapabilityPacket { - private final ResourceLocation key; - private final CompoundTag data; - - /** - * Constructor - * @param data data tag - */ - public SimpleCapabilityPacket(ResourceLocation key, CompoundTag data) { - this.key = key; - this.data = data; - } - - public SimpleCapabilityPacket(ICapabilitySync packet) { - this.key = packet.getKey(); - this.data = packet.serializeNBT(); - } - - /** - * decoder - * @param buf buf - */ - public SimpleCapabilityPacket(FriendlyByteBuf buf) { - this.key = buf.readResourceLocation(); - this.data = buf.readNbt(); - } - - /** - * encoder - * @param buf buf - */ - @Override - public void encode(FriendlyByteBuf buf) { - buf.writeResourceLocation(key); - buf.writeNbt(data); - } - - /** - * Default network packet handle, generally sufficient for use - * @param context NetworkEvent.Context - */ - @Override - public void handler(NetworkEvent.Context context) { - context.setPacketHandled(true); - Minecraft instance = Minecraft.getInstance(); - ClientLevel level = instance.level; - if (level == null) return; - CompoundTag nbt = getData(); - Entity entity = null; - if(nbt.contains(SimpleEntityCapabilitySync.Id)){ - entity = level.getEntity(nbt.getInt(SimpleEntityCapabilitySync.Id)); - } - if(nbt.contains(SimplePlayerCapabilitySync.OwnerUUID)){ - entity = level.getPlayerByUUID(nbt.getUUID(SimplePlayerCapabilitySync.OwnerUUID)); - } - if(entity == null) return; - try { - ICapabilitySync data = CapabilityUtils.getCapability(entity, key); - if(data == null) { - AnimationCore.log.error("key {} not found when sync capability on entity {}", key, entity); - return; - } - syncData(nbt, data); - }catch (Exception ignored) {} - } - - @Override - public CompoundTag getData() { - return data; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/IModLazyRun.java b/src/main/java/top/leisuretimedock/animationcore/core/IModLazyRun.java deleted file mode 100644 index 5939194..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/IModLazyRun.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core; - -import java.util.concurrent.Callable; - -@SuppressWarnings("UnusedReturnValue") -public interface IModLazyRun { - default boolean testLoadedAndRun(Runnable runnable){ - if(testCondition()) runnable.run(); - else return false; - return true; - } - - default void testLoadedAndRun(Runnable runnable, Runnable elseRun){ - if(testCondition()) runnable.run(); - else elseRun.run(); - } - - default T testLoadedAndCall(Callable callable) { - try { - if(testCondition()) return callable.call(); - } catch (Exception ignored) {} - return null; - } - - default T testLoadedAndCall(Callable callable, Callable elseCall) { - try { - if(testCondition()) return callable.call(); - else return elseCall.call(); - }catch(Exception ignored) { - return null; - } - } - - boolean testCondition(); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/ModChannel.java b/src/main/java/top/leisuretimedock/animationcore/core/ModChannel.java deleted file mode 100644 index ccf8214..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/ModChannel.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core; - -import top.leisuretimedock.animationcore.AnimationCore; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.network.NetworkRegistry; -import net.minecraftforge.network.PacketDistributor; -import net.minecraftforge.network.simple.SimpleChannel; - -public class ModChannel { - private static int cid = 0; - private static final String PROTOCOL_VERSION = ModList.get() - .getModContainerById(AnimationCore.MOD_ID) - .map(c -> c.getModInfo().getVersion().toString()) - .orElse("unknown"); - public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( - new ResourceLocation(AnimationCore.MOD_ID, AnimationCore.MOD_ID), - () -> PROTOCOL_VERSION, - PROTOCOL_VERSION::equals, - PROTOCOL_VERSION::equals - ); - - public static void register() { - - } - - public static int getAndAddCid() { - return cid++; - } - - public static void sendAllPlayer(MSG message){ - INSTANCE.send(PacketDistributor.ALL.noArg(), message); - } - - public static void sendToPlayer(MSG message, ServerPlayer player){ - INSTANCE.send(PacketDistributor.PLAYER.with(() -> player), message); - } - - public static void sendToServer(MSG message){ - INSTANCE.send(PacketDistributor.SERVER.noArg(), message); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/ModCommands.java b/src/main/java/top/leisuretimedock/animationcore/core/ModCommands.java deleted file mode 100644 index 7b8548a..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/ModCommands.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.register.AnimationCommands; -import com.mojang.brigadier.builder.LiteralArgumentBuilder; -import net.minecraft.commands.CommandBuildContext; -import net.minecraft.commands.CommandSourceStack; -import net.minecraft.commands.synchronization.ArgumentTypeInfo; -import net.minecraftforge.client.event.RegisterClientCommandsEvent; -import net.minecraftforge.event.RegisterCommandsEvent; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.registries.DeferredRegister; -import net.minecraftforge.registries.ForgeRegistries; - -import java.util.HashSet; -import java.util.Set; - -import static net.minecraft.commands.Commands.literal; - -public class ModCommands { - static final Set animationCommand = new HashSet<>(Set.of(AnimationCore.MOD_ID, "animationcore", "ac")); - public static void addCommandAlias(String alias) { - animationCommand.add(alias); - } - public static Set getAnimationCommand() { - return animationCommand; - } - - public static void registerCommands(IEventBus forgeBus, IEventBus modBus) { - forgeBus.addListener(ModCommands::commonCommandRegister); - forgeBus.addListener(ModCommands::clientCommandRegister); - Arguments.register(modBus); - } - - - public static void commonCommandRegister(RegisterCommandsEvent event) { - animationCommand.forEach(string -> { - LiteralArgumentBuilder builder = literal(string); - AnimationCommands.commonCommandRegister(builder); - - event.getDispatcher().register(builder); - }); - } - - public static void clientCommandRegister(RegisterClientCommandsEvent event) { - animationCommand.forEach(string -> { - LiteralArgumentBuilder builder = literal(string); - AnimationCommands.clientCommandRegister(builder); - - event.getDispatcher().register(builder); - }); - } - - public static class Arguments { - public static final DeferredRegister> REGISTRY = DeferredRegister.create( - ForgeRegistries.Keys.COMMAND_ARGUMENT_TYPES, AnimationCore.MOD_ID - ); - public static void register(IEventBus eventBus) { - AnimationCommands.registerArguments(REGISTRY); - REGISTRY.register(eventBus); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/ModCompatRun.java b/src/main/java/top/leisuretimedock/animationcore/core/ModCompatRun.java deleted file mode 100644 index 03bc264..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/ModCompatRun.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core; - -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.ModList; -import net.minecraftforge.fml.loading.FMLLoader; - -public abstract class ModCompatRun implements IModLazyRun{ - private final String modId; - public ModCompatRun(String modId) { - this.modId = modId; - } - - @Override - public boolean testCondition() { - return ModList.get().isLoaded(modId); - } - - public void addCommonListener(IEventBus forgeBus, IEventBus modBus){} - public void addClientListener(IEventBus forgeBus, IEventBus modBus){} - public void testLoadedAndAddListener(IEventBus forgeBus, IEventBus modBus) { - if(testCondition()){ - addCommonListener(forgeBus, modBus); - if(FMLLoader.getDist() == Dist.CLIENT){ - addClientListener(forgeBus, modBus); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/configs/ModConfigs.java b/src/main/java/top/leisuretimedock/animationcore/core/configs/ModConfigs.java deleted file mode 100644 index bd6a8c7..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/configs/ModConfigs.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core.configs; - -import net.minecraftforge.common.ForgeConfigSpec; - -public class ModConfigs { - public enum ConfigName { - inviteValidTime("inviteValidTime"), - inviteValidDistance("inviteValidDistance"), - inviteCooldown("inviteCooldown"), - - applyValidTime("applyValidTime"), - applyValidDistance("applyValidDistance"), - applyCooldown("applyCooldown"), - - requestValidTime("requestValidTime"), - requestCooldown("requestCooldown"), - ; - - private final String name; - ConfigName(String name){ - this.name = name; - } - - public String getName() { - return name; - } - } - public static class Server { - public static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder(); - public static final ForgeConfigSpec SPEC; - - //invite - public static final ForgeConfigSpec.ConfigValue inviteValidTime; - public static final ForgeConfigSpec.ConfigValue inviteValidDistance; - public static final ForgeConfigSpec.ConfigValue inviteCooldown; - //apply - public static final ForgeConfigSpec.ConfigValue applyValidTime; - public static final ForgeConfigSpec.ConfigValue applyValidDistance; - public static final ForgeConfigSpec.ConfigValue applyCooldown; - //request - public static final ForgeConfigSpec.ConfigValue requestValidTime; - public static final ForgeConfigSpec.ConfigValue requestCooldown; - - static { - BUILDER.push("Animation"); - //invite - inviteValidTime = BUILDER.comment("Animation invite valid time. Ignore when zero. (seconds)") - .defineInRange(ConfigName.inviteValidTime.name, 120, 0, Integer.MAX_VALUE); - inviteValidDistance = BUILDER.comment("Animation invite max distance. Ignore when zero. (blocks)") - .defineInRange(ConfigName.inviteValidDistance.name, 6, 0, Integer.MAX_VALUE); - inviteCooldown = BUILDER.comment("Animation invite cooldown. (seconds)") - .defineInRange(ConfigName.inviteCooldown.name, 60, 0, Integer.MAX_VALUE); - - //apply - applyValidTime = BUILDER.comment("Animation apply valid time. Ignore when zero. (seconds)") - .defineInRange(ConfigName.applyValidTime.name, 120, 0, Integer.MAX_VALUE); - applyValidDistance = BUILDER.comment("Animation apply max distance. Ignore when zero. (blocks)") - .defineInRange(ConfigName.applyValidDistance.name, 6, 0, Integer.MAX_VALUE); - applyCooldown = BUILDER.comment("Animation apply cooldown. (seconds)") - .defineInRange(ConfigName.applyCooldown.name, 60, 0, Integer.MAX_VALUE); - - //request - requestValidTime = BUILDER.comment("Animation request valid time. Ignore when zero (seconds)") - .defineInRange(ConfigName.requestValidTime.name, 120, 0, Integer.MAX_VALUE); - requestCooldown = BUILDER.comment("Animation request cooldown. (seconds)") - .defineInRange(ConfigName.requestCooldown.name, 60, 0, Integer.MAX_VALUE); - - BUILDER.pop(); - SPEC = BUILDER.build(); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/datagen/DataGenEvent.java b/src/main/java/top/leisuretimedock/animationcore/core/datagen/DataGenEvent.java deleted file mode 100644 index 0d85179..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/datagen/DataGenEvent.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core.datagen; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.core.datagen.provider.ModAnimationLayerProvider; -import top.leisuretimedock.animationcore.core.datagen.provider.ModAnimationProvider; -import top.leisuretimedock.animationcore.core.datagen.provider.ModLangProvider; -import net.minecraft.core.HolderLookup; -import net.minecraft.data.DataGenerator; -import net.minecraft.data.PackOutput; -import net.minecraftforge.common.data.ExistingFileHelper; -import net.minecraftforge.data.event.GatherDataEvent; -import net.minecraftforge.eventbus.api.SubscribeEvent; -import net.minecraftforge.fml.common.Mod; - -import java.util.concurrent.CompletableFuture; - -@Mod.EventBusSubscriber(modid = AnimationCore.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) -public class DataGenEvent { - - @SubscribeEvent - public static void gatherData(GatherDataEvent event) { - DataGenerator generator = event.getGenerator(); - PackOutput packOutput = generator.getPackOutput(); - CompletableFuture lookupProvider = event.getLookupProvider(); - ExistingFileHelper helper = event.getExistingFileHelper(); - - generator.addProvider(event.includeClient(), new ModLangProvider(packOutput, ModLangProvider.Lang.EN_US)); - generator.addProvider(event.includeClient(), new ModLangProvider(packOutput, ModLangProvider.Lang.ZH_CN)); - generator.addProvider(true, new ModAnimationProvider(generator)); - generator.addProvider(true, new ModAnimationLayerProvider(generator)); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/datagen/ModLang.java b/src/main/java/top/leisuretimedock/animationcore/core/datagen/ModLang.java deleted file mode 100644 index 5362bfc..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/datagen/ModLang.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core.datagen; - -import top.leisuretimedock.animationcore.AnimationCore; -import net.minecraft.sounds.SoundEvent; - -import java.util.ArrayList; -import java.util.List; - -public class ModLang { - public record LangEntity(T key, String zhCn, String enUs) { } - public static final List> langList = new ArrayList<>(); - private final static String translationString = "translation." + AnimationCore.MOD_ID; - private final static String command = ".command"; - private static final String animation = ".animation"; - public enum TranslatableMessage{ - COMMAND_RUN_FAIL(new LangEntity<>( - translationString + command + animation + ".command_run_fail", - "命令执行失败。", - "Command run fail." - )), - COMMAND_RUN_SUCCESS(new LangEntity<>( - translationString + command + animation + ".command_run_success", - "命令执行成功。", - "Command run success." - )), - PLAY_ANIMATION_FAIL(new LangEntity<>( - translationString + command + animation + ".play_animation_fail", - "在这些玩家上播放动画失败:%s", - "Fail to play animation with: %s" - )), - PLAY_ANIMATION_SUCCESS(new LangEntity<>( - translationString + command + animation + ".play_animation_success", - "在%s个玩家上播放动画成功。", - "Successfully played animation on %s player(s)." - )), - REMOVE_ANIMATION_FAIL(new LangEntity<>( - translationString + command + animation + ".remove_animation_fail", - "在这些玩家上移除动画失败:%s", - "Fail to remove animation with: %s" - )), - REMOVE_ANIMATION_SUCCESS(new LangEntity<>( - translationString + command + animation + ".remove_animation_success", - "在%s个玩家上移除动画成功。", - "Successfully removed animation on %s player(s)." - )), - CLEAR_ANIMATIONS(new LangEntity<>( - translationString + command + animation + ".clear_animations", - "动画已清除。", - "Animation cleared." - )), - REFRESH_ANIMATIONS(new LangEntity<>( - translationString + command + animation + ".refresh_animations", - "动画同步状态已刷新。", - "Animation refreshed." - )), - ACCEPT_MESSAGE_CLICK(new LangEntity<>( - translationString + command + animation + ".accept_message_click", - "单击此处同意。", - "Click here to accept." - )), - INVITE_MESSAGE(new LangEntity<>( - translationString + command + animation + ".invite_message", - "已发送邀请。", - "Invitation sent." - )), - INVITED_MESSAGE(new LangEntity<>( - translationString + command + animation + ".invited_message", - "%s§c§l 邀请§r你进行动画:%s。", - "%s§c§l invites§r you to animation: %s. " - )), - ACCEPT_INVITE_SUCCESS(new LangEntity<>( - translationString + command + animation + ".accept_invite_success", - "已接受邀请。", - "Invitation accepted." - )), - INVITE_SUCCESS(new LangEntity<>( - translationString + command + animation + ".invite_success", - "%s 接受了你的动画邀请。", - "%s has accepted your animation invitation." - )), - REQUEST_MESSAGE(new LangEntity<>( - translationString + command + animation + ".request_message", - "已发送请求。", - "Request sent." - )), - REQUESTED_MESSAGE(new LangEntity<>( - translationString + command + animation + ".requested_message", - "%s§d§l 请求§r你进行动画:%s。", - "%s§d§l requests§r you to animation: %s. " - )), - ACCEPT_REQUEST_SUCCESS(new LangEntity<>( - translationString + command + animation + ".accept_request_success", - "已接受请求。", - "Request accepted." - )), - REQUEST_SUCCESS(new LangEntity<>( - translationString + command + animation + ".request_success", - "%s 接受了你的动画请求。", - "%s has accepted your animation request." - )), - APPLY_JOIN_MESSAGE(new LangEntity<>( - translationString + command + animation + ".apply_join_message", - "已发送申请。", - "Application sent." - )), - APPLIED_JOIN_MESSAGE(new LangEntity<>( - translationString + command + animation + ".applied_join_message", - "%s§b§l 申请§r加入动画。", - "%S§b§l Apply for §r to join your animation. " - )), - ACCEPT_APPLY_SUCCESS(new LangEntity<>( - translationString + command + animation + ".accept_apply_success", - "%s 接受了 %s 的申请。", - "%s has accepted the application of %s." - )), - APPLY_SUCCESS(new LangEntity<>( - translationString + command + animation + ".apply_success", - "%s 接受了你的动画申请。", - "%s has accepted your animation application." - )), - ANIMATION_TO_JSON(new LangEntity<>( - translationString + command + animation + ".animation_to_json", - "动画%s已经存储到%s路径:", - "The animation %s has been stored in the path on %s:" - )), - ANIMATION_JSON_PATH(new LangEntity<>( - translationString + command + animation + ".animation_json_path", - "%s", - "%s" - )), - LIST_ANIMATION_RESOURCE(new LangEntity<>( - translationString + command + animation + ".list_animation_resource", - "%s侧的%s有:%s", - "The %2$s on %1$s has : %s" - )), - ANIMATION_EXPIRE(new LangEntity<>( - translationString + command + animation + ".animation_expire", - "你不能执行该操作: 已过期。", - "You cannot perform this operation: It has expired." - )), - ANIMATION_OUT_RANGE(new LangEntity<>( - translationString + command + animation + ".animation_out_range", - "你不能执行该操作: 距离不在%s格以内。", - "You cannot perform this operation: The distance is not within %s blocks." - )), - ANIMATION_OPERATION_UNSUPPORTED(new LangEntity<>( - translationString + command + animation + ".animation_operation_unsupported", - "错误: 不支持这样做。", - "Error: Unsupported operation." - )), - ANIMATION_COOLDOWN(new LangEntity<>( - translationString + command + animation + ".animation_cooldown", - "你不能执行该操作: 冷却中(%s秒)。", - "You cannot perform this operation: Cooling down (%s second(s))." - )), - ANIMATION_RESOURCE_NOT_FOUND(new LangEntity<>( - translationString + command + animation + ".animation_resource_not_found", - "错误: 资源未找到,请检查资源或操作是否有误: %s", - "Error: Resource not found, please check if there are any errors in the resource or operation : %s" - )), - ANIMATION_OPERATION_CANCELLED(new LangEntity<>( - translationString + command + animation + ".animation_operation_cancelled", - "异常: 操作被取消。", - "Exception: Operation cancelled." - )), - ; - - private final LangEntity langEntity; - TranslatableMessage(LangEntity lang){ - this.langEntity = lang; - } - - public String getKey() { - return langEntity.key; - } - } - - public static void initLang() { - langList.clear(); - - initLangMessage(); - } - - private static void initLangMessage() { - for (TranslatableMessage value : TranslatableMessage.values()) { - langList.add(value.langEntity); - } - } - - public static String getSoundKey(SoundEvent soundEvent){ - return "subtitle." + AnimationCore.MOD_ID + ".sound." + soundEvent.getLocation().getPath(); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModAnimationLayerProvider.java b/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModAnimationLayerProvider.java deleted file mode 100644 index 008a90a..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModAnimationLayerProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core.datagen.provider; - -import top.leisuretimedock.animationcore.AnimationCore; - -import top.leisuretimedock.animationcore.animation.data.util.ACAnimationLayerProvider; -import top.leisuretimedock.animationcore.example.animation.ModAnimation; -import net.minecraft.data.DataGenerator; - -public class ModAnimationLayerProvider extends ACAnimationLayerProvider { - public ModAnimationLayerProvider(DataGenerator generator) { - super(generator, AnimationCore.MOD_ID); - } - - - @Override - protected LayerBuilder createLayerData() { - return LayerBuilder.create() - .addCustomLayer(ModAnimation.normalLayers, 42); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModAnimationProvider.java b/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModAnimationProvider.java deleted file mode 100644 index b09a3d4..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModAnimationProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core.datagen.provider; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.data.AnimationDataBuilder; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.Ride; -import top.leisuretimedock.animationcore.animation.data.util.ACAnimationProvider; -import net.minecraft.data.DataGenerator; -import net.minecraft.world.phys.Vec3; - -import java.util.function.Consumer; - -import static top.leisuretimedock.animationcore.example.animation.ModAnimation.WaltzGentleman; -import static top.leisuretimedock.animationcore.example.animation.ModAnimation.WaltzLady; - -public class ModAnimationProvider extends ACAnimationProvider { - - public ModAnimationProvider(DataGenerator generator) { - super(generator, AnimationCore.MOD_ID); - } - - @Override - protected void registerAnimations(Consumer consumer) { - { - GenericAnimationData waltzGentleman = AnimationDataBuilder - .create(WaltzGentleman) - .withName("Waltz-Gentleman") - .addCamPosOffset(new Vec3(0.0, 0.0, 1.0)) - .withCamPosOffsetRelative(true) - .withRide(Ride.create().addComponentAnimation(WaltzLady)) - .buildGeneric(); - GenericAnimationData waltzLady = AnimationDataBuilder - .create(WaltzLady) - .withName("Waltz-Lady") - .withCamYaw(180) - .withRide(Ride.create().addComponentAnimation(WaltzGentleman)) - .buildGeneric(); - consumer.accept(waltzGentleman); - consumer.accept(waltzLady); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModLangProvider.java b/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModLangProvider.java deleted file mode 100644 index 10205e8..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/core/datagen/provider/ModLangProvider.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.core.datagen.provider; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.core.datagen.ModLang; -import net.minecraft.data.PackOutput; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.world.effect.MobEffect; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.Enchantment; -import net.minecraft.world.level.block.Block; -import net.minecraftforge.common.data.LanguageProvider; - - -public class ModLangProvider extends LanguageProvider { - - private final Lang lang; - - static { - ModLang.initLang(); - } - - public ModLangProvider(PackOutput output, Lang lang) { - super(output, AnimationCore.MOD_ID, lang.getLangName()); - this.lang = lang; - } - - @Override - protected void addTranslations() { - switch (lang){ - case EN_US -> ModLang.langList.forEach(langEntity -> addTranslation(langEntity.key(), langEntity.enUs())); - case ZH_CN -> ModLang.langList.forEach(langEntity -> addTranslation(langEntity.key(), langEntity.zhCn())); - } - } - - private void addTranslation(T o, String string) { - if(o instanceof Item object){ - add(object,string); - }else if(o instanceof Block object){ - add(object,string); - }else if(o instanceof String object){ - add(object,string); - }else if(o instanceof ItemStack object){ - add(object,string); - }else if(o instanceof Enchantment object){ - add(object,string); - }else if(o instanceof MobEffect object){ - add(object,string); - }else if(o instanceof EntityType object) { - add(object,string); - }else if(o instanceof SoundEvent object) { - add(ModLang.getSoundKey(object),string); - }else { - throw new RuntimeException("Unknown object type: " + o.getClass()); - } - } - - public enum Lang{ - - ZH_CN("zh_cn"), - EN_US("en_us"), - ; - - private final String langName; - Lang(String langName) { - this.langName = langName; - } - public String getLangName() { - return langName; - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/example/animation/ModAnimation.java b/src/main/java/top/leisuretimedock/animationcore/example/animation/ModAnimation.java deleted file mode 100644 index ff685f1..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/example/animation/ModAnimation.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.example.animation; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.data.Ride; -import top.leisuretimedock.animationcore.animation.event.create.AnimationRegisterEvent; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.example.animation.event.ExamplePlayerAttackEvent; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.phys.Vec3; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.eventbus.api.IEventBus; -import net.minecraftforge.fml.loading.FMLEnvironment; - -/** - * @see AnimationService - */ -public class ModAnimation { - /** - * This is an animation layer - */ - public static final ResourceLocation normalLayers = new ResourceLocation(AnimationCore.MOD_ID, "normal_layers"); - - /** - *
-     * They are animations
-     * {@code new ResourceLocation(MOD_ID, name)}
-     * Resource from "assets/{MOD_ID}/player_animation/{name}.json"
- */ - public static final ResourceLocation AmLyingToRightLying = new ResourceLocation(AnimationCore.MOD_ID, "am_lying_to_right_lying"); - public static final ResourceLocation AmStandToLying = new ResourceLocation(AnimationCore.MOD_ID, "am_stand_to_lying"); - public static final ResourceLocation WaltzGentleman = new ResourceLocation(AnimationCore.MOD_ID, "waltz_gentleman"); - public static final ResourceLocation WaltzLady = new ResourceLocation(AnimationCore.MOD_ID, "waltz_lady"); - - /** - * You can register animation layer by event or json
- * See wiki (If I'm done.) - * @param event event - */ - public static void onLayerRegister(AnimationRegisterEvent.Layer event) { -// event.registerLayer(normalLayers, 42); - } - - /** - * You can register animation by event or json
- * See wiki (If I'm done.) - * @param event event - */ - public static void onAnimationRegister(AnimationRegisterEvent.Animation event) { - //You must define corresponding Animation to invite -// GenericAnimationData amLTRL = GenericAnimationData.create(AmLyingToRightLying) -// .withLyingType(GenericAnimationData.LyingType.RIGHT) -// .withName("Lying-to-Right-Lying"); -// GenericAnimationData amSTL = GenericAnimationData.create(AmStandToLying) -// .withName("Stand-to-Lying") -// .withLyingType(GenericAnimationData.LyingType.FRONT); -// GenericAnimationData waltzGentleman = (GenericAnimationData) GenericAnimationData -// .create(WaltzGentleman) -// .withName("Waltz-Gentleman") -// .addCamPosOffset(new Vec3(0.0,0.0,1.0)) -// .withCamPosOffsetRelative(true) -// .withRide(Ride.create().addComponentAnimation(WaltzLady)); -// GenericAnimationData waltzLady = (GenericAnimationData) GenericAnimationData -// .create(WaltzLady) -// .withName("Waltz-Lady") -// .withCamYaw(180) -// .withRide(Ride.create().addComponentAnimation(WaltzGentleman)); - - //You can use it to invite an Animation -// event.registerAnimation(AmLyingToRightLying, amLTRL); -// event.registerAnimation(AmStandToLying, amSTL); -// event.registerAnimation(WaltzGentleman, waltzGentleman); -// event.registerAnimation(WaltzLady, waltzLady); - } - - public static void onRawAnimationRegister(AnimationRegisterEvent.RawAnimation event) { -// RawAnimationData amSTL = RawAnimationData.create(AmStandToLying).withRide(Ride.create().withExistTick(100)); -// RawAnimationData amLTRL = RawAnimationData.create(AmLyingToRightLying).withRide(Ride.create().withExistTick(100)); -// RawAnimationData waltzGentleman = RawAnimationData.create(WaltzGentleman).withRide(Ride.create().withExistTick(100).addComponentAnimation(WaltzLady)); -// RawAnimationData waltzLady = RawAnimationData.create(WaltzLady).withRide(Ride.create().withExistTick(100).addComponentAnimation(WaltzGentleman)); -// event.registerAnimation(AmLyingToRightLying, amLTRL); -// event.registerAnimation(AmStandToLying, amSTL); -// event.registerAnimation(WaltzGentleman, waltzGentleman); -// event.registerAnimation(WaltzLady, waltzLady); - } - - public static void register(IEventBus forgeBus, IEventBus modBus) { - //Register by event - //Or use AnimationUtils.registerAnimationLayer(ResourceLocation layer, int priority); - forgeBus.addListener(ModAnimation::onLayerRegister); - forgeBus.addListener(ModAnimation::onAnimationRegister); - - //Try to play animation -// forgeBus.addListener(ExamplePlayerAttackEvent::onPlayerAttack); - forgeBus.addListener(ExamplePlayerAttackEvent::rawAnimationAttack); - if(FMLEnvironment.dist == Dist.CLIENT){ -// forgeBus.addListener(ExamplePlayerAttackEvent::onInputEvent); - forgeBus.addListener(ModAnimation::onRawAnimationRegister); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/example/animation/event/ExamplePlayerAttackEvent.java b/src/main/java/top/leisuretimedock/animationcore/example/animation/event/ExamplePlayerAttackEvent.java deleted file mode 100644 index 1a7619d..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/example/animation/event/ExamplePlayerAttackEvent.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.example.animation.event; - -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.animation.service.RawAnimationService; -import top.leisuretimedock.animationcore.example.animation.ModAnimation; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.Sheep; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.api.distmarker.Dist; -import net.minecraftforge.api.distmarker.OnlyIn; -import net.minecraftforge.client.event.InputEvent; -import net.minecraftforge.event.entity.player.AttackEntityEvent; - -public class ExamplePlayerAttackEvent { - /** - * when attack sheep, will play stand to lying animation - * @param event event - */ - public static void onPlayerAttack(AttackEntityEvent event) { - Entity target = event.getTarget(); - Player entity = event.getEntity(); - if(entity instanceof ServerPlayer player) { - if(target instanceof Sheep){ - ResourceLocation playing = AnimationService.INSTANCE.getAnimationPlaying(player, ModAnimation.normalLayers); - if(playing == null) { - AnimationService.INSTANCE.playAnimation(player, ModAnimation.normalLayers, ModAnimation.AmStandToLying); - } else { - AnimationService.INSTANCE.removeAnimation(player, ModAnimation.normalLayers); - } - } - } - } - - public static void rawAnimationAttack(AttackEntityEvent event) { - Entity target = event.getTarget(); - Player entity = event.getEntity(); - if(entity instanceof AbstractClientPlayer player && target instanceof AbstractClientPlayer targetPlayer) { - if(player == Minecraft.getInstance().player){ - RawAnimationService.INSTANCE.invite( - ModAnimation.normalLayers, - ModAnimation.WaltzGentleman, - targetPlayer - ); - } - } - if(entity instanceof ServerPlayer player && target instanceof ServerPlayer targetPlayer) { - RawAnimationService.INSTANCE.acceptInvite(player, targetPlayer); - } - } - - /** - * when press "/", this will run - * @param event event - */ - @OnlyIn(Dist.CLIENT) - public static void onInputEvent(InputEvent.Key event) { - Minecraft instance = Minecraft.getInstance(); - LocalPlayer player = instance.player; - if (player == null) return; - if(instance.options.keyCommand.isDown()) { - ResourceLocation playing = AnimationService.INSTANCE.getAnimationPlaying(player, ModAnimation.normalLayers); - if(playing == null) { - AnimationService.INSTANCE.playAnimationWithRide((AbstractClientPlayer) null, ModAnimation.normalLayers, ModAnimation.AmLyingToRightLying, true); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/example/capability/ModCapability.java b/src/main/java/top/leisuretimedock/animationcore/example/capability/ModCapability.java deleted file mode 100644 index bc3f7bc..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/example/capability/ModCapability.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.example.capability; - -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.entity.EntityCapabilityRegistry; -import top.leisuretimedock.animationcore.capability.network.CapabilityChannel; -import top.leisuretimedock.animationcore.core.ModChannel; -import top.leisuretimedock.animationcore.example.capability.data.ISheepData; -import top.leisuretimedock.animationcore.example.capability.data.SheepDataCapability; -import top.leisuretimedock.animationcore.example.capability.event.PlayerAttackEvent; -import net.minecraft.world.entity.animal.Sheep; -import net.minecraftforge.common.capabilities.CapabilityManager; -import net.minecraftforge.common.capabilities.CapabilityToken; -import net.minecraftforge.eventbus.api.IEventBus; - -import java.util.Set; - -public class ModCapability { - /** - * Example of Registered Entity Capability
- * @see CapabilityUtils#registerEntityCapability - * @see CapabilityUtils#registerPlayerCapability - * @see CapabilityUtils#registerEntityCapabilityWithNetwork - * @see CapabilityUtils#registerPlayerCapabilityWithNetwork - */ - public static void register(){ - //If you want to invite network packets in your own mod, to use : createChannel(INSTANCE) - //And don't forget to rewrite all the sendToClient methods in the capability class - CapabilityChannel channel = CapabilityUtils.createChannel(); - //Register the entity capability and its network packet - //If you want invite about player, please use CapabilityUtils.registerPlayerCapabilityWithNetwork() - CapabilityUtils.registerEntityCapabilityWithNetwork( - //A resourceLocation, named arbitrarily without repetition - SheepDataCapability.key, - //Data that needs to be registered for capability - new EntityCapabilityRegistry.CapabilityRecord<>( - //Registry will create a new instance of this class - //And you can override the parameterless construct in this class to initialize it - SheepDataCapability.class, - //Fixed writing style, generally you don't need to modify it - CapabilityManager.get(new CapabilityToken<>() {}), - //The interface of the first parameter class can be an abstract class or not require an interface - //You can use it yourself: SheepDataCapability.class - ISheepData.class, - //What entities should the registered capability be attached to - Set.of(Sheep.class) - ), - channel, - //Index+1 after use to prevent subsequent network channel conflicts - ModChannel.getAndAddCid(), - //Class of network packet - SheepDataCapability.SheepCapabilityPacket.class, - //Decoder method for network packet - SheepDataCapability.SheepCapabilityPacket::new, - //Encoder method for network packet - SheepDataCapability.SheepCapabilityPacket::encode, - //Handler method for network packet - SheepDataCapability.SheepCapabilityPacket::handle - ); - } - - public static void addListenerToEvent(IEventBus forgeBus){ - forgeBus.addListener(PlayerAttackEvent::onPlayerAttack); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/example/capability/data/ISheepData.java b/src/main/java/top/leisuretimedock/animationcore/example/capability/data/ISheepData.java deleted file mode 100644 index 1dcf52a..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/example/capability/data/ISheepData.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.example.capability.data; - -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import net.minecraft.world.entity.animal.Sheep; - -/** - * The interface inheritance ICapabilitySync is required, but the interface is not necessary (you can directly use the cap class itself during registration)
- * Server methods for sharing caps that may be used. - */ -public interface ISheepData extends ICapabilitySync { - Integer getValue(); - void setValue(Integer value); -} diff --git a/src/main/java/top/leisuretimedock/animationcore/example/capability/data/SheepDataCapability.java b/src/main/java/top/leisuretimedock/animationcore/example/capability/data/SheepDataCapability.java deleted file mode 100644 index 07d97cb..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/example/capability/data/SheepDataCapability.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.example.capability.data; - -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.capability.CapabilityUtils; -import top.leisuretimedock.animationcore.capability.data.ICapabilitySync; -import top.leisuretimedock.animationcore.capability.data.entity.SimpleEntityCapabilitySync; -import top.leisuretimedock.animationcore.capability.network.SimpleCapabilityPacket; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.FriendlyByteBuf; -import net.minecraft.resources.ResourceLocation; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.Sheep; - -import java.util.Optional; - -/** - * The entity class of cap
- * Inheriting SimpleElementCapability Sync means automatically hosting synchronization of an ID
- * The IsheepData implemented only contains the property 'value' as a getter and setter
- * @see SimpleEntityCapabilitySync - */ -public class SheepDataCapability extends SimpleEntityCapabilitySync implements ISheepData { - public static final ResourceLocation key = new ResourceLocation(AnimationCore.MOD_ID, "sheep_data"); - - public static final String Value = "Value"; - - private Integer value; - - @Override - public Integer getValue() { - return value; - } - - @Override - public void setValue(Integer value) { - this.value = value; - setDirty(true); - } - - /** - * @param tag data tag - * @return tag - * @see SimpleEntityCapabilitySync#toTag(CompoundTag) - */ - @Override - public CompoundTag toTag(CompoundTag tag) { - if(value != null) tag.putInt(Value, value); - return tag; - } - - /** - * @see SimpleEntityCapabilitySync#fromTag(CompoundTag) - * @param tag data tag - */ - @Override - public void fromTag(CompoundTag tag) { - this.value = null; - if(tag.contains(Value)) this.value = tag.getInt(Value); - } - - /** - * @see SimpleEntityCapabilitySync#copyFrom(ICapabilitySync) - * @param oldData Copy from this data to the current instance - */ - @Override - public void copyFrom(ICapabilitySync oldData) { - SheepDataCapability data = (SheepDataCapability) oldData; - this.value = data.getValue(); - } - - /** - * Network packet, you can rewrite any method inside. For the function of methods, please refer to
- * {@link top.leisuretimedock.animationcore.capability.network.ICapabilityPacket}
- * It is not necessary to include it in the internal class. I feel that the content is too limited and writing it inside makes it more compact and beautiful - * @see SimpleCapabilityPacket - */ - public static class SheepCapabilityPacket extends SimpleCapabilityPacket { - /** - * You must override the constructor of FriendlyByteBuf - * @param buf FriendlyByteBuf - */ - public SheepCapabilityPacket(FriendlyByteBuf buf) { - super(buf); - } - - /** - * More, you must override a constructor to help you create an instance - * @param data Cap data - */ - public SheepCapabilityPacket(SheepDataCapability data) { - super(data); - } - } - - /** - * Return the capability key - * @return The capability key - */ - @Override - public ResourceLocation getKey() { - return new ResourceLocation(AnimationCore.MOD_ID, "sheep_data"); - } - - /** - * Get the default network packet, which will be called when sendToClient sends it - * @return network packet - * @see ICapabilitySync#getDefaultPacket() - */ - @Override - public SimpleCapabilityPacket getDefaultPacket() { - return new SheepCapabilityPacket(this); - } - - /** - * This method will be called during cap initialization, such as player login
- * In this example, when the sheep joins the level, this method will be called to initialize the capability - * @param entity Target - * @see ICapabilitySync#attachInit(Entity) - */ - @Override - public void attachInit(Sheep entity) { - - } - - /** - * It is not necessary.
- * Call this when capability is needed in other places
- * The purpose is to simplify the method of capability get - * @param sheep Target - * @return Optional capability - */ - public static Optional getCapability(Sheep sheep){ - return Optional.ofNullable(CapabilityUtils.getEntityCapability( - sheep, SheepDataCapability.key, SheepDataCapability.class - )); - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/example/capability/event/PlayerAttackEvent.java b/src/main/java/top/leisuretimedock/animationcore/example/capability/event/PlayerAttackEvent.java deleted file mode 100644 index 9741c4b..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/example/capability/event/PlayerAttackEvent.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.example.capability.event; - -import top.leisuretimedock.animationcore.example.capability.data.SheepDataCapability; -import net.minecraft.network.chat.Component; -import net.minecraft.server.level.ServerPlayer; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.animal.Sheep; -import net.minecraft.world.entity.player.Player; -import net.minecraftforge.event.entity.player.AttackEntityEvent; - -public class PlayerAttackEvent { - public static void onPlayerAttack(AttackEntityEvent event) { - Entity target = event.getTarget(); - Player entity = event.getEntity(); - if(entity instanceof ServerPlayer player) { - if(target instanceof Sheep sheep){ - SheepDataCapability.getCapability(sheep).ifPresent(data -> { - Integer value = data.getValue(); - if(value == null) value = 0; - value++; - data.setValue(value); - Integer id = data.getId(); - player.sendSystemMessage(Component.literal( - value + "th attack on sheep with ID " + id - )); - }); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/AnimCoreMixinPlugin.java b/src/main/java/top/leisuretimedock/animationcore/mixin/AnimCoreMixinPlugin.java index 5736e2d..b465fa6 100644 --- a/src/main/java/top/leisuretimedock/animationcore/mixin/AnimCoreMixinPlugin.java +++ b/src/main/java/top/leisuretimedock/animationcore/mixin/AnimCoreMixinPlugin.java @@ -15,10 +15,6 @@ package top.leisuretimedock.animationcore.mixin; -import top.leisuretimedock.animationcore.AnimationCore; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import net.minecraftforge.fml.loading.LoadingModList; -import net.minecraftforge.fml.loading.moddiscovery.ModInfo; import org.objectweb.asm.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; import org.spongepowered.asm.mixin.extensibility.IMixinInfo; @@ -28,7 +24,7 @@ import java.util.Set; public class AnimCoreMixinPlugin implements IMixinConfigPlugin { @Override - public void onLoad(String s) { + public void onLoad(String mixinPackage) { } @@ -39,19 +35,11 @@ public class AnimCoreMixinPlugin implements IMixinConfigPlugin { @Override public boolean shouldApplyMixin(String targetClassName, String mixinClassName) { - if (targetClassName.startsWith("runData.")) { - return "runData".equals(System.getProperty("gradle.task")); - } - if (mixinClassName.startsWith("top.leisuretimedock." + AnimationCore.MOD_ID + ".mixin.animation.")) { - return LoadingModList.get().getMods().stream().map(ModInfo::getModId).anyMatch( - s -> s.equals(AnimationService.AnimModId) - ); - } return true; } @Override - public void acceptTargets(Set set, Set set1) { + public void acceptTargets(Set myTargets, Set otherTargets) { } @@ -61,12 +49,12 @@ public class AnimCoreMixinPlugin implements IMixinConfigPlugin { } @Override - public void preApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) { + public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } @Override - public void postApply(String s, ClassNode classNode, String s1, IMixinInfo iMixinInfo) { + public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { } } diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/MixinAnimationRegistry.java b/src/main/java/top/leisuretimedock/animationcore/mixin/MixinAnimationRegistry.java new file mode 100644 index 0000000..3807030 --- /dev/null +++ b/src/main/java/top/leisuretimedock/animationcore/mixin/MixinAnimationRegistry.java @@ -0,0 +1,50 @@ +/* + * Anim Core mod + * Copyright (C) 2026 LeisureTimeDock + * 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.leisuretimedock.animationcore.mixin; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import io.zershyan.sccore.animation.data.GenericAnimationData; +import io.zershyan.sccore.animation.register.AnimationRegistry; +import net.minecraft.resources.ResourceLocation; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import top.leisuretimedock.animationcore.animation.AnimationDataManager; +import top.leisuretimedock.animationcore.animation.LayerDataManager; + +import java.util.LinkedHashMap; +import java.util.Map; + +@Mixin(value = AnimationRegistry.class, remap = false) +public class MixinAnimationRegistry { + @WrapMethod( + method = "getAnimations" + ) + private static @NotNull Map getAnimations(@NotNull Operation> original) { + Map wrap = new LinkedHashMap<>(original.call()); + wrap.putAll(AnimationDataManager.ANIMATIONS); + return wrap; + } + + @WrapMethod( + method = "getLayers" + ) + private static @NotNull Map getLayers(@NotNull Operation> original) { + Map wrap = new LinkedHashMap<>(original.call()); + wrap.putAll(LayerDataManager.LAYERS); + return wrap; + } +} diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/MixinEntity.java b/src/main/java/top/leisuretimedock/animationcore/mixin/animation/MixinEntity.java deleted file mode 100644 index 00542e2..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/MixinEntity.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.mixin.animation; - -import top.leisuretimedock.animationcore.animation.data.AnimationData; -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.service.AnimationService; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.Pose; -import net.minecraft.world.entity.player.Player; -import net.minecraft.world.phys.AABB; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(Entity.class) -public abstract class MixinEntity { - @Shadow private AABB bb; - - @Shadow public abstract void setPose(Pose pPose); - - @ModifyReturnValue( - method = "getEyeHeight()F", - at = @At("RETURN") - ) - private float redefinedEyeHeight(float original){ - Entity self = Entity.class.cast(this); - if(self instanceof Player player){ - AnimationData data = AnimationUtils.getEyeModifierAnimationData(player); - if(data instanceof GenericAnimationData){ - return player.getEyeHeight(Pose.STANDING) + (float) data.getCamPosOffset().y; - } - } - return original; - } - - @Inject( - method = "getBoundingBox", - at = @At(value = "RETURN"), - cancellable = true - ) - private void redefinedBoundingBox(CallbackInfoReturnable cir){ - Entity self = Entity.class.cast(this); - if(self instanceof Player player){ - float heightModifier = AnimationService.INSTANCE.getHeightModifier(player); - if(heightModifier == 1.0f) return; - double modifyHeight = 1.8f * heightModifier; - cir.setReturnValue(this.bb.setMaxY(modifyHeight + this.bb.minY)); - } - } - - @ModifyReturnValue( - method = "getBbHeight", - at = @At(value = "RETURN") - ) - private float redefinedBbHeight(float original){ - Entity self = Entity.class.cast(this); - if(self instanceof Player player){ - float heightModifier = AnimationService.INSTANCE.getHeightModifier(player); - if(heightModifier == 1.0f) return original; - return original * heightModifier; - } - return original; - } - - - - @Inject( - method = "getPose", - at = @At(value = "HEAD"), - cancellable = true - ) - private void redefinedPose(CallbackInfoReturnable cir){ - Entity self = Entity.class.cast(this); - if(self instanceof Player player){ - float heightModifier = AnimationService.INSTANCE.getHeightModifier(player); - if(heightModifier == 1.0f) return; - setPose(Pose.STANDING); - cir.setReturnValue(Pose.STANDING); - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinEntity.java b/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinEntity.java deleted file mode 100644 index 19eedf5..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinEntity.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.mixin.animation.client; - -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import net.minecraft.client.Minecraft; -import net.minecraft.util.Mth; -import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.player.Player; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(Entity.class) -public abstract class MixinEntity { - @Shadow public abstract void setXRot(float pXRot); - - @Shadow private float xRot; - - @Shadow public abstract void setYRot(float pYRot); - - @Shadow private float yRot; - - @Shadow public abstract float getXRot(); - - @Shadow public float xRotO; - - @Shadow public float yRotO; - - @Inject( - method = "turn", - at = {@At(value = "HEAD")}, - cancellable = true - ) - private void turnPosePlayer(double pYRot, double pXRot, CallbackInfo ci) { - Entity self = Entity.class.cast(this); - if(self instanceof Player player){ - GenericAnimationData.LyingType lyingType = AnimationUtils.getSideView(player); - if(lyingType != null && Minecraft.getInstance().options.getCameraType().isFirstPerson()) { - float f = (float)pXRot * 0.15F; - float f1 = (float)pYRot * 0.15F; - switch (lyingType) { - case LEFT -> { - this.setXRot(this.xRot + f1 * -1.0f); - this.setYRot(this.yRot + f); - } - case RIGHT -> { - this.setXRot(this.xRot + f1); - this.setYRot(this.yRot + f * -1.0f); - } - } - this.setXRot(Mth.clamp(this.getXRot(), 0.0f, 90.0f)); - this.xRotO = this.xRot; - this.yRotO = this.yRot; - ci.cancel(); - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinHumanoidModel.java b/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinHumanoidModel.java deleted file mode 100644 index ed70f3e..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinHumanoidModel.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.mixin.animation.client; - -import top.leisuretimedock.animationcore.animation.data.GenericAnimationData; -import top.leisuretimedock.animationcore.animation.utils.AnimationUtils; -import net.minecraft.client.model.AgeableListModel; -import net.minecraft.client.model.ArmedModel; -import net.minecraft.client.model.HeadedModel; -import net.minecraft.client.model.HumanoidModel; -import net.minecraft.client.model.geom.ModelPart; -import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.player.Player; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(HumanoidModel.class) -public abstract class MixinHumanoidModel extends AgeableListModel implements ArmedModel, HeadedModel { - @Shadow @Final public ModelPart head; - - @Inject( - method = "setupAnim(Lnet/minecraft/world/entity/LivingEntity;FFFFF)V", - at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/geom/ModelPart;copyFrom(Lnet/minecraft/client/model/geom/ModelPart;)V") - ) - private void modifyHeadRot(T pEntity, float pLimbSwing, float pLimbSwingAmount, float pAgeInTicks, float pNetHeadYaw, float pHeadPitch, CallbackInfo ci){ - if(pEntity instanceof Player player){ - GenericAnimationData.LyingType lyingType = AnimationUtils.getSideView(player); - if(lyingType != null) { - float pitch = pHeadPitch - 90.0f; - float yaw = pNetHeadYaw * -1.0f; - switch (lyingType) { - case LEFT: { - pitch *= -1.0f; - yaw *= -1.0f; - } - case RIGHT: { - this.head.yRot = pitch * 0.017453292F; - this.head.xRot = yaw * 0.017453292F; - } - } - } - } - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinKeyframeAnimationPlayer.java b/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinKeyframeAnimationPlayer.java deleted file mode 100644 index d9ee0b3..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinKeyframeAnimationPlayer.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.mixin.animation.client; - -import top.leisuretimedock.animationcore.animation.mixin.IMixinKeyframeAnimationPlayer; -import dev.kosmx.playerAnim.api.layered.KeyframeAnimationPlayer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; - -@Mixin(KeyframeAnimationPlayer.class) -public class MixinKeyframeAnimationPlayer implements IMixinKeyframeAnimationPlayer { - - @Shadow(remap = false) - private int currentTick; - - @Override - @Unique - public void animcore$setCurrentTick(int tick) { - this.currentTick = tick; - } -} diff --git a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinPlayerAnimationFactoryHolder.java b/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinPlayerAnimationFactoryHolder.java deleted file mode 100644 index 5fde80a..0000000 --- a/src/main/java/top/leisuretimedock/animationcore/mixin/animation/client/MixinPlayerAnimationFactoryHolder.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Anim Core mod - * Copyright (C) 2026 LeisureTimeDock - * 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.leisuretimedock.animationcore.mixin.animation.client; - -import top.leisuretimedock.animationcore.animation.mixin.IMixinPlayerAnimationFactoryHolder; -import dev.kosmx.playerAnim.api.layered.AnimationStack; -import dev.kosmx.playerAnim.api.layered.IAnimation; -import dev.kosmx.playerAnim.minecraftApi.PlayerAnimationFactory; -import net.minecraft.client.player.AbstractClientPlayer; -import net.minecraft.resources.ResourceLocation; -import org.spongepowered.asm.mixin.Final; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; - -@Mixin(PlayerAnimationFactory.FactoryHolder.class) -public class MixinPlayerAnimationFactoryHolder implements IMixinPlayerAnimationFactoryHolder { - @Unique - @Final - private static final List> animcore$factories = new ArrayList<>(); - - @Inject( - method = "prepareAnimations", - at = @At("HEAD"), - cancellable = true, - remap = false - ) - private void prepareAnimations(AbstractClientPlayer player, AnimationStack playerStack, Map animationMap, CallbackInfo ci) { - for (Function factory: animcore$factories) { - DataHolder dataHolder = factory.apply(player); - if (dataHolder != null) { - playerStack.addAnimLayer(dataHolder.priority(), dataHolder.animation()); - if (dataHolder.id() != null) { - animationMap.put(dataHolder.id(), dataHolder.animation()); - } - } - } - ci.cancel(); - } - - @Inject( - method = "registerFactory", - at = @At("HEAD"), - cancellable = true, - remap = false - ) - private void registerFactory(ResourceLocation id, int priority, PlayerAnimationFactory factory, CallbackInfo ci) { - animcore$factories.add(player -> Optional.ofNullable(factory.invoke(player)).map(animation -> new DataHolder(id, priority, animation)).orElse(null)); - ci.cancel(); - } - - @Unique - public void animcore$clearAnimations() { - animcore$factories.clear(); - } -} diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index a6d0e63..139597f 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1 +1,2 @@ -public net.minecraft.client.Camera f_90552_ # position \ No newline at end of file + + diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml index 20ff457..bca4749 100644 --- a/src/main/resources/META-INF/mods.toml +++ b/src/main/resources/META-INF/mods.toml @@ -39,4 +39,11 @@ modId = "bendylib" mandatory = false versionRange = "[4.0.0,)" ordering = "AFTER" +side = "BOTH" + +[[dependencies."${mod_id}"]] +modId = "sccore" +mandatory = false +versionRange = "[${sccore_verson},)" +ordering = "AFTER" side = "BOTH" \ No newline at end of file diff --git a/src/main/resources/animcore.mixins.json b/src/main/resources/animcore.mixins.json index a736174..2a075ac 100644 --- a/src/main/resources/animcore.mixins.json +++ b/src/main/resources/animcore.mixins.json @@ -1,21 +1,14 @@ { - "required": true, - "minVersion": "0.8", - "package": "top.leisuretimedock.animationcore.mixin", - "compatibilityLevel": "JAVA_17", - "refmap": "animcore.refmap.json", - "priority": -255, - "plugin": "top.leisuretimedock.animationcore.mixin.AnimCoreMixinPlugin", - "mixins": [ - "animation.MixinEntity", - "animation.client.MixinPlayerAnimationFactoryHolder" - ], - "client": [ - "animation.client.MixinEntity", - "animation.client.MixinHumanoidModel", - "animation.client.MixinKeyframeAnimationPlayer" - ], - "injectors": { - "defaultRequire": 1 + "required": true, + "minVersion": "0.8", + "package": "top.leisuretimedock.animationcore.mixin", + "compatibilityLevel": "JAVA_17", + "refmap": "animcore.refmap.json", + "plugin": "top.leisuretimedock.animationcore.mixin.AnimCoreMixinPlugin", + "mixins": [ + "MixinAnimationRegistry" + ], + "injectors": { + "defaultRequire": 1 } } diff --git a/src/main/resources/assets/animcore/player_animation/am_lying_to_right_lying.json b/src/main/resources/assets/animcore/player_animation/am_lying_to_right_lying.json deleted file mode 100644 index b3562b3..0000000 --- a/src/main/resources/assets/animcore/player_animation/am_lying_to_right_lying.json +++ /dev/null @@ -1,112 +0,0 @@ -{ - "name": "am_lying_to_right_lying", - "author": "LostInLinearPast", - "description": "fix in 1.20.1 from CreatorGalaxy", - "emote":{ - "isLoop": "false", - "returnTick": 2, - "beginTick":0, - "endTick":6, - "stopTick":2147483647, - "degrees":false, - "moves":[ - - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":-0.08066412806510925 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":-0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":-1.568853497505188 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":1.5707963705062866 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":1.5704461336135864 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.623153030872345 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.4366978108882904 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.0 - } - } - ] - } -} \ No newline at end of file diff --git a/src/main/resources/assets/animcore/player_animation/am_stand_to_lying.json b/src/main/resources/assets/animcore/player_animation/am_stand_to_lying.json deleted file mode 100644 index 5c753ec..0000000 --- a/src/main/resources/assets/animcore/player_animation/am_stand_to_lying.json +++ /dev/null @@ -1,64 +0,0 @@ -{ - "name": "am_stand_to_lying", - "author": "LostInLinearPast", - "description": "fix in 1.20.1 from CreatorGalaxy", - "emote":{ - "isLoop": "false", - "returnTick": 2, - "beginTick":0, - "endTick":5, - "stopTick":2147483647, - "degrees":false, - "moves":[ - - { - "tick":5, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":0.0 - } - }, - { - "tick":5, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":-0.0 - } - }, - { - "tick":5, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":1.5707963705062866 - } - }, - { - "tick":5, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.623153030872345 - } - }, - { - "tick":5, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":5, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.0 - } - } - ] - } -} \ No newline at end of file diff --git a/src/main/resources/assets/animcore/player_animation/waltz_gentleman.json b/src/main/resources/assets/animcore/player_animation/waltz_gentleman.json deleted file mode 100644 index 2ae3908..0000000 --- a/src/main/resources/assets/animcore/player_animation/waltz_gentleman.json +++ /dev/null @@ -1,1536 +0,0 @@ -{ - "name": "waltz_gentleman", - "author": "LostInLinearPast", - "description": "waltz gentleman", - "emote":{ - "isLoop": "true", - "returnTick": 2, - "beginTick":0, - "endTick":81, - "stopTick":2147483647, - "degrees":false, - "moves":[ - - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "y":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "y":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "z":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "z":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "x":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "x":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "yaw":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "yaw":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "roll":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "roll":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "pitch":-0.1944645792245865 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "pitch":-0.1944645792245865 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":-0.06981316953897476 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.03490658476948738 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":-0.03490658476948738 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.0625 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.027499999850988388 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.009999999776482582 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.02500000037252903 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.0625 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.027499999850988388 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.009999999776482582 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.02500000037252903 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.012500000186264515 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.05000000074505806 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.13750000298023224 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.3125 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.3125 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.30000001192092896 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.26249998807907104 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.17499999701976776 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.4124999940395355 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.6875 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.7950000166893005 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.925000011920929 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.925000011920929 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.512499988079071 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.23749999701976776 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.12999999523162842 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "yaw":-0.30647698044776917 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "yaw":-0.30647698044776917 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "roll":1.3770651817321777 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "roll":1.3770651817321777 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "y":3.5131139755249023 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "y":3.5131139755249023 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "z":-0.9560732841491699 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "z":-0.9560732841491699 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "x":-5.65712833404541 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "x":-5.65712833404541 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "pitch":-1.2955334186553955 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "pitch":-1.2955334186553955 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "bend":-0.46759316325187683 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "bend":-0.46759316325187683 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "roll":-0.5759586691856384 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "roll":-0.5759586691856384 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "yaw":-1.3089969158172607 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "yaw":-1.3089969158172607 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "pitch":-1.0646508932113647 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "pitch":-1.0646508932113647 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "y":2.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "z":-1.2999999523162842 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "z":-1.2999999523162842 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "x":5.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.09413255006074905 - } - }, - { - "tick":32, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.05712477117776871 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":0.006151077337563038 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":0.010275216773152351 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.032113973051309586 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.10115855187177658 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.23402659595012665 - } - }, - { - "tick":32, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.42213836312294006 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.0634104534983635 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.1390521377325058 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.2702104151248932 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.2626937925815582 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.7774391174316406 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.2324778437614441 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":0.2255288064479828 - } - }, - { - "tick":32, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":0.1099814623594284 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":44, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.19448231160640717 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.6989269852638245 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.176431804895401 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":0.11157336086034775 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":4.2785497367248126e-11 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":4.2785497367248126e-11 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.140909433364868 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":-0.8861581921577454 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.33404916524887085 - } - }, - { - "tick":12, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.2565633952617645 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.20696492493152618 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.042693521827459335 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.10096975415945053 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.07553856074810028 - } - }, - { - "tick":10, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.1206885427236557 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0923948809504509 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.10970524698495865 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.010996125638484955 - } - }, - { - "tick":72, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.04013187810778618 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.16261258721351624 - } - }, - { - "tick":10, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.23268601298332214 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.15703840553760529 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.246794655919075 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.14305073022842407 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.2745340168476105 - } - }, - { - "tick":72, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.4361734688282013 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":6, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.5139611959457397 - } - }, - { - "tick":10, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.22671326994895935 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.08939548581838608 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.13704152405261993 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.4427417814731598 - } - }, - { - "tick":50, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.28025344014167786 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.20064905285835266 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.04128774628043175 - } - }, - { - "tick":72, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.10648827999830246 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":50, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.10896075647324324 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":0.2722991406917572 - } - }, - { - "tick":18, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":0.15728268027305603 - } - }, - { - "tick":26, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":0.17915907502174377 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - } - ] - } -} \ No newline at end of file diff --git a/src/main/resources/assets/animcore/player_animation/waltz_lady.json b/src/main/resources/assets/animcore/player_animation/waltz_lady.json deleted file mode 100644 index 1003640..0000000 --- a/src/main/resources/assets/animcore/player_animation/waltz_lady.json +++ /dev/null @@ -1,1552 +0,0 @@ -{ - "name": "waltz_lady", - "author": "LostInLinearPast", - "description": "waltz lady", - "emote":{ - "isLoop": "true", - "returnTick": 2, - "beginTick":0, - "endTick":81, - "stopTick":2147483647, - "degrees":false, - "moves":[ - - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "y":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "z":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "x":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "yaw":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "roll":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "pitch":0.1185886561870575 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "head":{ - "pitch":0.1185886561870575 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":3.1415927410125732 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":3.1415927410125732 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "yaw":3.1415927410125732 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "roll":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.03490658476948738 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":-0.03490658476948738 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "pitch":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.027499999850988388 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.009999999776482582 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.02500000037252903 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.0625 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.027499999850988388 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.009999999776482582 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":-0.02500000037252903 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "y":0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.012500000186264515 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.05000000074505806 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.13750000298023224 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.3125 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.3125 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.30000001192092896 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.26249998807907104 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":-0.17499999701976776 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "x":0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.5 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.9125000238418579 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-1.1875 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-1.2949999570846558 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-1.4249999523162842 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-1.4249999523162842 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-1.0125000476837158 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.737500011920929 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.6299999952316284 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.5 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.5 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "torso":{ - "z":-0.5 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "yaw":1.3089969158172607 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "yaw":1.3089969158172607 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "roll":0.5759586691856384 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "roll":0.5759586691856384 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "y":2.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "z":-1.2999999523162842 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "z":-1.2999999523162842 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "x":-5.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "pitch":-1.0646508932113647 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightArm":{ - "pitch":-1.0646508932113647 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "roll":1.510741949081421 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "roll":1.510741949081421 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "yaw":0.24142970144748688 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "yaw":0.24142970144748688 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "pitch":-1.8961212635040283 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "pitch":-1.8961212635040283 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "y":1.3259220123291016 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "y":1.3259220123291016 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "z":-0.8563777208328247 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "z":-0.8563777208328247 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "x":5.7146406173706055 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "x":5.7146406173706055 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "bend":0.37502986192703247 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftArm":{ - "bend":0.37502986192703247 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.006303687114268541 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.007730656303465366 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":0.0030700149945914745 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.030118120834231377 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "yaw":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.21962174773216248 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.2617029547691345 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.08802766352891922 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.2535526156425476 - } - }, - { - "tick":72, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":0.40923434495925903 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "roll":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":2, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.2701720595359802 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.7349715828895569 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0006949927774257958 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.00104520411696285 - } - }, - { - "tick":35, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.6743449568748474 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.15383221209049225 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":0.12758493423461914 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "pitch":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":2, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.342857241630554 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.75428593158722 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.473965883255005 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "y":12.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":2, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":-0.17428531646728515 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":-0.6542854547500611 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":-0.25547447204589846 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "z":0.1 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":2, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.20577150583267212 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.5501528382301331 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.2617993950843811 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":0.35444632172584534 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "rightLeg":{ - "bend":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":0.008380268700420856 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":0.020489023998379707 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":0.03528726473450661 - } - }, - { - "tick":32, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":0.09650745987892151 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.06075865775346756 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.03179699555039406 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":0.01990862935781479 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "yaw":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":0.0 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.04884415119886398 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.10059066116809845 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.26200801134109497 - } - }, - { - "tick":32, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.4258441925048828 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.028214696794748306 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.20640932023525238 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.21954356133937836 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.24775296449661255 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "roll":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.4414220154285431 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.18329083919525146 - } - }, - { - "tick":20, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.052891556173563004 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.08107911050319672 - } - }, - { - "tick":32, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.06880011409521103 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.636621356010437 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.05537297576665878 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.16388186812400818 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":0.03859478235244751 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "pitch":-0.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.425536721944809 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":60, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":11.753142833709717 - } - }, - { - "tick":75, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "y":12.0 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":25, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.49681914448738096 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "z":-0.1 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "x":1.9 - } - }, - { - "tick":1, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":8, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":0.20332171022891998 - } - }, - { - "tick":15, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":41, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":48, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":0.2600111663341522 - } - }, - { - "tick":55, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":0.13962633907794952 - } - }, - { - "tick":65, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - }, - { - "tick":81, - "easing": "EASEINOUTQUAD", - "turn": 0, - "leftLeg":{ - "bend":-0.0 - } - } - ] - } -} \ No newline at end of file