修正Mixin命名

添加新的AnimationDataBuilder,避免之前的冲突
This commit is contained in:
叁玖领域 2026-01-13 11:44:59 +08:00
parent 592becac22
commit 4344568628
14 changed files with 483 additions and 25 deletions

View File

@ -12,7 +12,7 @@ mapping_version=2023.09.03-1.20.1
mod_id=animcore
mod_name=AnimationCore
mod_license=GPL 3.0
mod_version=1.20.1-26H2
mod_version=1.20.1-26H3
mod_group_id=top.leisuiretimedock.animationcore
mod_authors=LostInLinearPast, R3944Realms
mod_description=A lib about player animator(modified by R3944Realms).

View File

@ -69,7 +69,7 @@ public class ApplyCommand {
//click event
Style pStyle = Style.EMPTY.withBold(true).withColor(ChatFormatting.GREEN).withClickEvent(
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animationcore anim apply accept " + player.getName().getString())
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animcore anim apply accept " + player.getName().getString())
).withUnderlined(true);
//send message to all participants

View File

@ -82,7 +82,7 @@ public class InviteCommand {
//click event
Style pStyle = Style.EMPTY.withBold(true).withColor(ChatFormatting.GREEN).withClickEvent(
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animationcore anim invite accept " + player.getName().getString())
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animcore anim invite accept " + player.getName().getString())
).withUnderlined(true);
//send message
for (ServerPlayer target : players) {

View File

@ -83,7 +83,7 @@ public class RequestCommand {
//click event
Style pStyle = Style.EMPTY.withBold(true).withColor(ChatFormatting.GREEN).withClickEvent(
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animationcore anim request acceptRequest " + player.getName().getString())
new ClickEvent(ClickEvent.Action.RUN_COMMAND, "/animcore anim request acceptRequest " + player.getName().getString())
).withUnderlined(true);
//send message

View File

@ -32,12 +32,12 @@ import java.util.List;
public class AnimationData implements INBTSerializable<CompoundTag> {
protected ResourceLocation key;
private float camYaw;
private float camPitch;
private float camRoll;
private int camComputePriority;
float camYaw;
float camPitch;
float camRoll;
int camComputePriority;
private Vec3 camPosOffset = new Vec3(0.0F, 0.0F, 0.0F);
private boolean camPosOffsetRelative;
boolean camPosOffsetRelative;
private @Nullable GenericAnimationData.LyingType lyingType;
protected @Nullable Ride ride;

View File

@ -0,0 +1,454 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package top.leisuretimedock.animationcore.animation.data;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* Builder for creating {@link AnimationData} instances.
* Supports building both {@link GenericAnimationData} and {@link RawAnimationData}.
*/
public class AnimationDataBuilder {
private final ResourceLocation key;
private boolean isGeneric = false;
private float camYaw = 0.0f;
private float camPitch = 0.0f;
private float camRoll = 0.0f;
private int camComputePriority = 0;
private Vec3 camPosOffset = new Vec3(0.0F, 0.0F, 0.0F);
private boolean camPosOffsetRelative = false;
private @Nullable GenericAnimationData.LyingType lyingType = null;
private @Nullable Ride ride = null;
private @Nullable String genericName = null;
private float heightModifier = 1.0f;
private final List<Consumer<AnimationData>> postBuildActions = new ArrayList<>();
/**
* Private constructor. Use {@link #create(ResourceLocation)} to create a builder.
*/
private AnimationDataBuilder(ResourceLocation key) {
this.key = key;
}
/**
* Creates a new builder for the given animation key.
*
* @param key The resource location identifying the animation
* @return A new builder instance
*/
public static AnimationDataBuilder create(ResourceLocation key) {
return new AnimationDataBuilder(key);
}
/**
* Creates a new builder for the given animation key from a string.
*
* @param key The string representation of the resource location
* @return A new builder instance
*/
public static AnimationDataBuilder create(String key) {
return new AnimationDataBuilder(new ResourceLocation(key));
}
/**
* Configures this builder to create a {@link GenericAnimationData} instead of a raw one.
*
* @return This builder for chaining
*/
public AnimationDataBuilder asGeneric() {
this.isGeneric = true;
return this;
}
/**
* Sets the name for generic animation data.
*
* @param name The animation name (must match regex: ^[a-zA-Z0-9_-]+$)
* @return This builder for chaining
* @throws IllegalArgumentException if the name doesn't match the required pattern
*/
public AnimationDataBuilder withName(String name) {
this.genericName = name;
this.isGeneric = true; // Implicitly set as generic when name is provided
return this;
}
/**
* Sets the height modifier for generic animation data.
*
* @param heightModifier The height modifier value
* @return This builder for chaining
*/
public AnimationDataBuilder withHeightModifier(float heightModifier) {
this.heightModifier = heightModifier;
this.isGeneric = true; // Implicitly set as generic when height modifier is provided
return this;
}
/**
* Sets the lying type for the animation.
* When set, automatically configures camera position and rotation for lying animations.
*
* @param lyingType The lying type
* @return This builder for chaining
*/
public AnimationDataBuilder withLyingType(@Nullable GenericAnimationData.LyingType lyingType) {
this.lyingType = lyingType;
if (lyingType != null) {
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;
}
// For generic animations, set height modifier when lying
if (this.isGeneric) {
this.heightModifier = 0.3f;
}
}
return this;
}
/**
* Sets the ride configuration for the animation.
*
* @param ride The ride configuration
* @return This builder for chaining
*/
public AnimationDataBuilder withRide(Ride ride) {
this.ride = ride;
return this;
}
/**
* Sets the ride configuration using a ride builder.
*
* @param rideBuilderConsumer Consumer that configures a {@link RideBuilder}
* @return This builder for chaining
*/
public AnimationDataBuilder withRide(Consumer<RideBuilder> rideBuilderConsumer) {
RideBuilder rideBuilder = RideBuilder.create();
rideBuilderConsumer.accept(rideBuilder);
this.ride = rideBuilder.build();
return this;
}
/**
* Sets the camera yaw rotation.
*
* @param camYaw The camera yaw in degrees
* @return This builder for chaining
*/
public AnimationDataBuilder withCamYaw(float camYaw) {
this.camYaw = camYaw;
return this;
}
/**
* Sets the camera pitch rotation.
*
* @param camPitch The camera pitch in degrees
* @return This builder for chaining
*/
public AnimationDataBuilder withCamPitch(float camPitch) {
this.camPitch = camPitch;
return this;
}
/**
* Sets the camera roll rotation.
*
* @param camRoll The camera roll in degrees
* @return This builder for chaining
*/
public AnimationDataBuilder withCamRoll(float camRoll) {
this.camRoll = camRoll;
return this;
}
/**
* Sets the camera computation priority.
*
* @param camComputePriority The priority value
* @return This builder for chaining
*/
public AnimationDataBuilder withCamComputePriority(int camComputePriority) {
this.camComputePriority = camComputePriority;
return this;
}
/**
* Sets the camera position offset.
*
* @param camPosOffset The position offset vector
* @return This builder for chaining
*/
public AnimationDataBuilder withCamPosOffset(Vec3 camPosOffset) {
this.camPosOffset = camPosOffset;
return this;
}
/**
* Adds to the camera position offset.
*
* @param camPosOffset The position offset to add
* @return This builder for chaining
*/
public AnimationDataBuilder addCamPosOffset(Vec3 camPosOffset) {
this.camPosOffset = this.camPosOffset.add(camPosOffset);
return this;
}
/**
* Sets whether the camera position offset is relative.
*
* @param camPosOffsetRelative True if offset is relative, false if absolute
* @return This builder for chaining
*/
public AnimationDataBuilder withCamPosOffsetRelative(boolean camPosOffsetRelative) {
this.camPosOffsetRelative = camPosOffsetRelative;
return this;
}
/**
* Adds a post-build action that will be executed after the animation data is created.
* Useful for additional customizations.
*
* @param action The action to perform on the created animation data
* @return This builder for chaining
*/
public AnimationDataBuilder withPostBuildAction(Consumer<AnimationData> action) {
this.postBuildActions.add(action);
return this;
}
/**
* Builds the animation data.
*
* @return The constructed {@link AnimationData}
*/
public AnimationData build() {
AnimationData animationData;
if (isGeneric) {
GenericAnimationData genericData = new GenericAnimationData(key);
genericData.heightModifier = heightModifier;
genericData.name = genericName;
animationData = genericData;
} else {
animationData = new RawAnimationData(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;
// Apply post-build actions
for (Consumer<AnimationData> action : postBuildActions) {
action.accept(animationData);
}
return animationData;
}
/**
* Builds the animation data and casts it to the specified type.
* Useful when you know the exact type you want.
*
* @param <T> The expected animation data type
* @param type The class of the expected type
* @return The constructed animation data cast to the specified type
* @throws ClassCastException if the built animation data is not of the expected type
*/
@SuppressWarnings("unchecked")
public <T extends AnimationData> T buildAs(Class<T> type) {
AnimationData data = build();
if (!type.isInstance(data)) {
throw new ClassCastException("Cannot cast " + data.getClass().getSimpleName() +
" to " + type.getSimpleName());
}
return (T) data;
}
/**
* Builds a {@link GenericAnimationData}.
* This method ensures the builder is configured for generic animations.
*
* @return The constructed {@link GenericAnimationData}
*/
public GenericAnimationData buildGeneric() {
this.isGeneric = true;
return buildAs(GenericAnimationData.class);
}
/**
* Builds a {@link RawAnimationData}.
* This method ensures the builder is configured for raw animations.
*
* @return The constructed {@link RawAnimationData}
*/
public RawAnimationData buildRaw() {
this.isGeneric = false;
return buildAs(RawAnimationData.class);
}
}
/**
* Builder for creating {@link Ride} instances.
*/
class RideBuilder {
private Vec3 offset = new Vec3(0.0F, 0.0F, 0.0F);
private int existTick = 0;
private float xRot = 0.0f;
private float yRot = 0.0f;
private List<ResourceLocation> componentAnimations = new ArrayList<>();
private RideBuilder() {}
/**
* Creates a new ride builder.
*
* @return A new ride builder instance
*/
public static RideBuilder create() {
return new RideBuilder();
}
/**
* Sets the offset for the ride.
*
* @param offset The offset vector
* @return This builder for chaining
*/
public RideBuilder withOffset(Vec3 offset) {
this.offset = offset;
return this;
}
/**
* Sets the offset for the ride using coordinates.
*
* @param x X coordinate
* @param y Y coordinate
* @param z Z coordinate
* @return This builder for chaining
*/
public RideBuilder withOffset(double x, double y, double z) {
this.offset = new Vec3(x, y, z);
return this;
}
/**
* Sets the existence tick count for the ride.
*
* @param existTick The number of ticks the ride exists
* @return This builder for chaining
*/
public RideBuilder withExistTick(int existTick) {
this.existTick = existTick;
return this;
}
/**
* Sets the X rotation for the ride.
*
* @param xRot The X rotation in degrees
* @return This builder for chaining
*/
public RideBuilder withXRot(float xRot) {
this.xRot = xRot;
return this;
}
/**
* Sets the Y rotation for the ride.
*
* @param yRot The Y rotation in degrees
* @return This builder for chaining
*/
public RideBuilder withYRot(float yRot) {
this.yRot = yRot;
return this;
}
/**
* Adds a component animation to the ride.
*
* @param animation The resource location of the component animation
* @return This builder for chaining
*/
public RideBuilder addComponentAnimation(ResourceLocation animation) {
this.componentAnimations.add(animation);
return this;
}
/**
* Adds a component animation to the ride from a string.
*
* @param animation The string representation of the resource location
* @return This builder for chaining
*/
public RideBuilder addComponentAnimation(String animation) {
this.componentAnimations.add(new ResourceLocation(animation));
return this;
}
/**
* Sets all component animations for the ride.
*
* @param componentAnimations List of component animation resource locations
* @return This builder for chaining
*/
public RideBuilder setComponentAnimations(List<ResourceLocation> componentAnimations) {
this.componentAnimations = new ArrayList<>(componentAnimations);
return this;
}
/**
* Builds the ride configuration.
*
* @return The constructed {@link Ride}
*/
public Ride build() {
return Ride.create()
.withOffset(offset)
.withExistTick(existTick)
.withXRot(xRot)
.withYRot(yRot)
.setComponentAnimations(componentAnimations);
}
}

View File

@ -21,8 +21,9 @@ import org.jetbrains.annotations.Nullable;
import java.util.regex.Pattern;
public class GenericAnimationData extends AnimationData {
private @Nullable String name;
private float heightModifier = 1.0f;
@Nullable
String name;
float heightModifier = 1.0f;
GenericAnimationData(ResourceLocation key) {
this.key = key;

View File

@ -20,5 +20,5 @@ import net.minecraftforge.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public interface IMixinKeyframeAnimationPlayer {
void sccore$setCurrentTick(int tick);
void animcore$setCurrentTick(int tick);
}

View File

@ -23,5 +23,5 @@ import org.jetbrains.annotations.Nullable;
public interface IMixinPlayerAnimationFactoryHolder {
record DataHolder(@Nullable ResourceLocation id, int priority, @NotNull IAnimation animation) {}
void sccore$clearAnimations();
void animcore$clearAnimations();
}

View File

@ -445,7 +445,7 @@ public class AnimationRegistry {
case ANIM_CACHE_CLEAR -> animationsCache.clear();
case LAYER_CACHE_CLEAR -> {
((IMixinPlayerAnimationFactoryHolder)(PlayerAnimationFactory.ANIMATION_DATA_FACTORY))
.sccore$clearAnimations();
.animcore$clearAnimations();
layersCache.clear();
}
case ANIM_REGISTER -> {

View File

@ -138,7 +138,7 @@ public class AnimationUtils {
KeyframeAnimationPlayer targetAnimation = (KeyframeAnimationPlayer) targetModifierLayer.getAnimation();
if(animation == null || targetAnimation == null) return;
int currentTick = targetAnimation.getCurrentTick();
animation.sccore$setCurrentTick(currentTick);
animation.animcore$setCurrentTick(currentTick);
} catch (Exception ignored) {}
}

View File

@ -16,6 +16,7 @@
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;
@ -36,17 +37,19 @@ public class ModAnimationProvider extends ACAnimationProvider {
@Override
protected void registerAnimations(Consumer<GenericAnimationData> consumer) {
{
GenericAnimationData waltzGentleman = (GenericAnimationData) GenericAnimationData
GenericAnimationData waltzGentleman = AnimationDataBuilder
.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
.withRide(Ride.create().addComponentAnimation(WaltzLady))
.buildGeneric();
GenericAnimationData waltzLady = AnimationDataBuilder
.create(WaltzLady)
.withName("Waltz-Lady")
.withCamYaw(180)
.withRide(Ride.create().addComponentAnimation(WaltzGentleman));
.withRide(Ride.create().addComponentAnimation(WaltzGentleman))
.buildGeneric();
consumer.accept(waltzGentleman);
consumer.accept(waltzLady);
}

View File

@ -29,7 +29,7 @@ public class MixinKeyframeAnimationPlayer implements IMixinKeyframeAnimationPlay
@Override
@Unique
public void sccore$setCurrentTick(int tick) {
public void animcore$setCurrentTick(int tick) {
this.currentTick = tick;
}
}

View File

@ -38,7 +38,7 @@ import java.util.function.Function;
public class MixinPlayerAnimationFactoryHolder implements IMixinPlayerAnimationFactoryHolder {
@Unique
@Final
private static List<Function<AbstractClientPlayer, DataHolder>> sccore$factories = new ArrayList<>();
private static final List<Function<AbstractClientPlayer, DataHolder>> animcore$factories = new ArrayList<>();
@Inject(
method = "prepareAnimations",
@ -47,7 +47,7 @@ public class MixinPlayerAnimationFactoryHolder implements IMixinPlayerAnimationF
remap = false
)
private void prepareAnimations(AbstractClientPlayer player, AnimationStack playerStack, Map<ResourceLocation, IAnimation> animationMap, CallbackInfo ci) {
for (Function<AbstractClientPlayer, DataHolder> factory: sccore$factories) {
for (Function<AbstractClientPlayer, DataHolder> factory: animcore$factories) {
DataHolder dataHolder = factory.apply(player);
if (dataHolder != null) {
playerStack.addAnimLayer(dataHolder.priority(), dataHolder.animation());
@ -66,12 +66,12 @@ public class MixinPlayerAnimationFactoryHolder implements IMixinPlayerAnimationF
remap = false
)
private void registerFactory(ResourceLocation id, int priority, PlayerAnimationFactory factory, CallbackInfo ci) {
sccore$factories.add(player -> Optional.ofNullable(factory.invoke(player)).map(animation -> new DataHolder(id, priority, animation)).orElse(null));
animcore$factories.add(player -> Optional.ofNullable(factory.invoke(player)).map(animation -> new DataHolder(id, priority, animation)).orElse(null));
ci.cancel();
}
@Unique
public void sccore$clearAnimations() {
sccore$factories.clear();
public void animcore$clearAnimations() {
animcore$factories.clear();
}
}