动画待完善,搁置

This commit is contained in:
xypp
2025-04-29 01:27:15 +08:00
parent 9423ca840e
commit 154a44bfab
10 changed files with 276 additions and 1 deletions

View File

@@ -168,6 +168,10 @@ dependencies {
compileOnly fg.deobf("curse.maven:touhou-little-maid-355044:6440955")
runtimeOnly fg.deobf("curse.maven:touhou-little-maid-355044:6440955")
runtimeOnly fg.deobf("curse.maven:maid-storage-manager-1210244:6455832")
compileOnly(annotationProcessor("io.github.llamalad7:mixinextras-common:0.4.1"))
implementation(jarJar("io.github.llamalad7:mixinextras-forge:0.4.1")) {
jarJar.ranged(it, "[0.4.1,)")
}
}
// This block of code expands all declared replace properties in the specified resource targets.

View File

@@ -3,10 +3,13 @@ package studio.fantasyit.maid_useful_task;
import com.github.tartaricacid.touhoulittlemaid.api.ILittleMaid;
import com.github.tartaricacid.touhoulittlemaid.api.LittleMaidExtension;
import com.github.tartaricacid.touhoulittlemaid.api.entity.ai.IExtraMaidBrain;
import com.github.tartaricacid.touhoulittlemaid.client.animation.HardcodedAnimationManger;
import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.ExtraMaidBrainManager;
import com.github.tartaricacid.touhoulittlemaid.entity.task.TaskManager;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import studio.fantasyit.maid_useful_task.animation.FlyAnimation;
import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry;
import studio.fantasyit.maid_useful_task.task.MaidEndEyeTask;
import studio.fantasyit.maid_useful_task.task.MaidTreeTask;
import java.util.List;
@@ -17,6 +20,7 @@ public class UsefulTaskExtension implements ILittleMaid {
public void addMaidTask(TaskManager manager) {
ILittleMaid.super.addMaidTask(manager);
manager.add(new MaidTreeTask());
manager.add(new MaidEndEyeTask());
}
@Override
@@ -29,9 +33,15 @@ public class UsefulTaskExtension implements ILittleMaid {
MemoryModuleRegistry.PLACE_TARGET.get(),
MemoryModuleRegistry.BLOCK_UP_TARGET.get(),
MemoryModuleRegistry.BLOCK_VALIDATION.get(),
MemoryModuleRegistry.CURRENT_WORK.get()
MemoryModuleRegistry.CURRENT_WORK.get(),
MemoryModuleRegistry.COMMON_BLOCK_CACHE.get()
);
}
});
}
@Override
public void addHardcodeAnimation(HardcodedAnimationManger manger) {
manger.addMaidAnimation(new FlyAnimation());
}
}

View File

@@ -0,0 +1,32 @@
package studio.fantasyit.maid_useful_task.animation;
import com.github.tartaricacid.touhoulittlemaid.api.animation.ICustomAnimation;
import com.github.tartaricacid.touhoulittlemaid.api.animation.IModelRenderer;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.geckolib3.geo.animated.AnimatedGeoModel;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.world.entity.Mob;
import java.util.HashMap;
public class FlyAnimation implements ICustomAnimation<Mob> {
@Override
public void setupRotations(Mob entity, PoseStack poseStack, float ageInTicks, float rotationYaw, float partialTicks) {
ICustomAnimation.super.setupRotations(entity, poseStack, ageInTicks, rotationYaw, partialTicks);
}
@Override
public void setRotationAngles(Mob entity, HashMap<String, ? extends IModelRenderer> models, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
ICustomAnimation.super.setRotationAngles(entity, models, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch);
}
@Override
public void setupGeckoRotations(Mob entity, PoseStack poseStack, float ageInTicks, float rotationYaw, float partialTicks) {
ICustomAnimation.super.setupGeckoRotations(entity, poseStack, ageInTicks, rotationYaw, partialTicks);
}
@Override
public void setGeckoRotationAngles(Mob entity, AnimatedGeoModel model, float limbSwing, float limbSwingAmount, float ageInTicks, float netHeadYaw, float headPitch) {
ICustomAnimation.super.setGeckoRotationAngles(entity, model, limbSwing, limbSwingAmount, ageInTicks, netHeadYaw, headPitch);
}
}

View File

@@ -0,0 +1,81 @@
package studio.fantasyit.maid_useful_task.behavior;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
import com.google.common.collect.ImmutableMap;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.StructureTags;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.behavior.Behavior;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.item.Items;
import net.minecraft.world.phys.Vec3;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
public class EnderEyeMoveBehavior extends Behavior<EntityMaid> {
public EnderEyeMoveBehavior() {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, InitEntities.TARGET_POS.get(), MemoryStatus.VALUE_ABSENT));
}
@Override
protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid maid) {
if (!maid.getMainHandItem().is(Items.ENDER_EYE)) return false;
if (maid.hasRestriction()) return false;
LivingEntity owner = maid.getOwner();
return (owner != null && maid.distanceTo(owner) < 5);
}
@Override
protected void start(ServerLevel serverlevel, EntityMaid maid, long p_22542_) {
BlockPos target = MemoryUtil.getCommonBlockCache(maid);
LivingEntity owner = maid.getOwner();
if (owner == null) return;
if (target == null) {
BlockPos blockpos = serverlevel.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, maid.blockPosition(), 100, false);
if (blockpos != null) {
MemoryUtil.setCommonBlockCache(maid, blockpos);
target = blockpos;
}
}
if (target != null) {
if (maid.distanceToSqr(target.getCenter()) < 9) {
maid.getJumpControl().jump();
}
BlockPos finalTarget = target;
BlockPos ownerPos = owner.blockPosition();
BlockPos maidPos = maid.blockPosition();
if (finalTarget.distSqr(ownerPos) > 10 * 10) {
Vec3 dVec = target.getCenter().subtract(owner.position());
dVec = dVec.normalize().scale(7);
BlockPos fTarget = maidPos.offset((int) dVec.x, (int) dVec.y, (int) dVec.z);
for (int x = 0; x < 3; x = x <= 0 ? 1 - x : -x) {
for (int z = 0; z < 3; z = z <= 0 ? 1 - z : -z) {
int y = 0;
while (!serverlevel.getBlockState(fTarget.offset(x, y, z)).isAir()) y++;
while (!serverlevel.getBlockState(fTarget.offset(x, y, z)).isAir()) y--;
if (fTarget.offset(x, y, z).distSqr(ownerPos) < 10 * 10) {
finalTarget = fTarget.offset(x, y, z);
}
}
}
}
if (finalTarget.distSqr(maidPos) < 10 * 10) {
double distanceToOwner = maidPos.distSqr(ownerPos);
double speed = 0.4;
if (distanceToOwner < 4 * 4) {
speed = 0.5;
}
if (distanceToOwner < 3 * 3) {
speed = 0.64;
}
MemoryUtil.setTarget(maid, finalTarget, (float) speed);
}
}
}
}

View File

@@ -0,0 +1,39 @@
package studio.fantasyit.maid_useful_task.behavior;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
import com.google.common.collect.ImmutableMap;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.StructureTags;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.behavior.Behavior;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.entity.ai.memory.MemoryStatus;
import net.minecraft.world.item.Items;
import net.minecraft.world.phys.Vec3;
import studio.fantasyit.maid_useful_task.util.Conditions;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
public class EnderEyeWaitBehavior extends Behavior<EntityMaid> {
public EnderEyeWaitBehavior() {
super(ImmutableMap.of(InitEntities.TARGET_POS.get(), MemoryStatus.VALUE_PRESENT));
}
@Override
protected boolean checkExtraStartConditions(ServerLevel p_22538_, EntityMaid maid) {
if (!maid.getMainHandItem().is(Items.ENDER_EYE)) return false;
if (maid.hasRestriction()) return false;
LivingEntity owner = maid.getOwner();
if (owner != null && maid.distanceTo(owner) > 6) {
return true;
}
return Conditions.hasReachedValidTargetOrReset(maid, 4);
}
@Override
protected void start(ServerLevel serverlevel, EntityMaid maid, long p_22542_) {
MemoryUtil.clearTarget(maid);
}
}

View File

@@ -0,0 +1,49 @@
package studio.fantasyit.maid_useful_task.mixin;
import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidFollowOwnerTask;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.llamalad7.mixinextras.sugar.Local;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LivingEntity;
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.ModifyArg;
import org.spongepowered.asm.mixin.injection.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import studio.fantasyit.maid_useful_task.task.MaidEndEyeTask;
@Mixin(MaidFollowOwnerTask.class)
abstract public class FollowMaidMixin {
@Shadow(remap = false)
@Final
private int stopDistance;
@Inject(method = "Lcom/github/tartaricacid/touhoulittlemaid/entity/ai/brain/task/MaidFollowOwnerTask;checkExtraStartConditions(Lnet/minecraft/server/level/ServerLevel;Lcom/github/tartaricacid/touhoulittlemaid/entity/passive/EntityMaid;)Z", at = @At("HEAD"),remap = false, cancellable = true)
public void checkExtraStartConditions(ServerLevel level, EntityMaid maid, CallbackInfoReturnable<Boolean> cir) {
if (maid.getTask().getUid().equals(MaidEndEyeTask.UID)) {
LivingEntity owner = maid.getOwner();
if (owner != null && maid.distanceTo(owner) < 6) {
cir.setReturnValue(false);
}
}
}
@ModifyVariable(method = "start(Lnet/minecraft/server/level/ServerLevel;Lcom/github/tartaricacid/touhoulittlemaid/entity/passive/EntityMaid;J)V", at = @At(value = "STORE"),remap = false)
public int start(int startDistance, @Local(argsOnly = true) EntityMaid maid) {
if (maid.getTask().getUid().equals(MaidEndEyeTask.UID)) {
return 10;
}
return startDistance;
}
@ModifyArg(method = "start(Lnet/minecraft/server/level/ServerLevel;Lcom/github/tartaricacid/touhoulittlemaid/entity/passive/EntityMaid;J)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/ai/behavior/BehaviorUtils;setWalkAndLookTargetMemories(Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/Entity;FI)V"))
public int maid_useful_task$stop_distance(int stopDistance, @Local(argsOnly = true) EntityMaid maid) {
if (maid.getTask().getUid().equals(MaidEndEyeTask.UID)) {
return 10;
}
return stopDistance;
}
}

View File

@@ -23,6 +23,8 @@ public class MemoryModuleRegistry {
= REGISTER.register("block_up", () -> new MemoryModuleType<>(Optional.of(BlockUpContext.CODEC)));
public static final RegistryObject<MemoryModuleType<BlockValidationMemory>> BLOCK_VALIDATION
= REGISTER.register("block_validation", () -> new MemoryModuleType<>(Optional.of(BlockValidationMemory.CODEC)));
public static final RegistryObject<MemoryModuleType<BlockPos>> COMMON_BLOCK_CACHE
= REGISTER.register("common_block_cache", () -> new MemoryModuleType<>(Optional.empty()));
public static final RegistryObject<MemoryModuleType<CurrentWork>> CURRENT_WORK = REGISTER.register("current_work", () -> new MemoryModuleType<>(Optional.empty()));
public static void register(IEventBus eventBus) {

View File

@@ -0,0 +1,50 @@
package studio.fantasyit.maid_useful_task.task;
import com.github.tartaricacid.touhoulittlemaid.api.task.IMaidTask;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.mojang.datafixers.util.Pair;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import org.jetbrains.annotations.Nullable;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
import studio.fantasyit.maid_useful_task.behavior.EnderEyeMoveBehavior;
import studio.fantasyit.maid_useful_task.behavior.EnderEyeWaitBehavior;
import java.util.ArrayList;
import java.util.List;
public class MaidEndEyeTask implements IMaidTask {
public static final ResourceLocation UID = new ResourceLocation(MaidUsefulTask.MODID, "end_eye");
@Override
public ResourceLocation getUid() {
return UID;
}
@Override
public ItemStack getIcon() {
return Items.ENDER_EYE.getDefaultInstance();
}
@Nullable
@Override
public SoundEvent getAmbientSound(EntityMaid entityMaid) {
return null;
}
@Override
public List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(EntityMaid entityMaid) {
List<Pair<Integer, BehaviorControl<? super EntityMaid>> > list = new ArrayList<>();
list.add(Pair.of(1, new EnderEyeMoveBehavior()));
list.add(Pair.of(2, new EnderEyeWaitBehavior()));
return list;
}
@Override
public boolean enableLookAndRandomWalk(EntityMaid maid) {
return false;
}
}

View File

@@ -80,4 +80,11 @@ public class MemoryUtil {
public static void setCurrent(EntityMaid maid, CurrentWork currentWork){
maid.getBrain().setMemory(MemoryModuleRegistry.CURRENT_WORK.get(), currentWork);
}
public static void setCommonBlockCache(EntityMaid maid, BlockPos pos){
maid.getBrain().setMemory(MemoryModuleRegistry.COMMON_BLOCK_CACHE.get(), pos);
}
public static BlockPos getCommonBlockCache(EntityMaid maid){
return maid.getBrain().getMemory(MemoryModuleRegistry.COMMON_BLOCK_CACHE.get()).orElse(null);
}
}

View File

@@ -5,6 +5,7 @@
"compatibilityLevel": "JAVA_8",
"refmap": "maid_useful_task.refmap.json",
"mixins": [
"FollowMaidMixin",
"MaidCheckPickupItem",
"MaidMoveControlMixin",
"MaidRunOneMixin"