支持了移动目标类任务
支持了定位任务
This commit is contained in:
xypp
2025-04-29 23:28:55 +08:00
parent 154a44bfab
commit 5423bf54fd
42 changed files with 821 additions and 168 deletions

View File

@@ -29,6 +29,7 @@ import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
import org.slf4j.Logger;
import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleManager;
// The value here should match an entry in the META-INF/mods.toml file
@Mod(MaidUsefulTask.MODID)
@@ -41,5 +42,6 @@ public class MaidUsefulTask {
public MaidUsefulTask() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
MemoryModuleRegistry.register(modEventBus);
MaidVehicleManager.register();
}
}

View File

@@ -3,13 +3,11 @@ 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.MaidLocateTask;
import studio.fantasyit.maid_useful_task.task.MaidTreeTask;
import java.util.List;
@@ -20,7 +18,7 @@ public class UsefulTaskExtension implements ILittleMaid {
public void addMaidTask(TaskManager manager) {
ILittleMaid.super.addMaidTask(manager);
manager.add(new MaidTreeTask());
manager.add(new MaidEndEyeTask());
manager.add(new MaidLocateTask());
}
@Override
@@ -34,14 +32,11 @@ public class UsefulTaskExtension implements ILittleMaid {
MemoryModuleRegistry.BLOCK_UP_TARGET.get(),
MemoryModuleRegistry.BLOCK_VALIDATION.get(),
MemoryModuleRegistry.CURRENT_WORK.get(),
MemoryModuleRegistry.COMMON_BLOCK_CACHE.get()
MemoryModuleRegistry.COMMON_BLOCK_CACHE.get(),
MemoryModuleRegistry.IS_ALLOW_HANDLE_VEHICLE.get(),
MemoryModuleRegistry.LOCATE_ITEM.get()
);
}
});
}
@Override
public void addHardcodeAnimation(HardcodedAnimationManger manger) {
manger.addMaidAnimation(new FlyAnimation());
}
}

View File

@@ -1,32 +0,0 @@
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

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS;

View File

@@ -1,5 +1,6 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.item.EntityBroom;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
import com.google.common.collect.ImmutableMap;
@@ -10,47 +11,50 @@ 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.entity.vehicle.Boat;
import net.minecraft.world.item.Items;
import net.minecraft.world.phys.Vec3;
import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry;
import studio.fantasyit.maid_useful_task.task.IMaidFindTargetTask;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleManager;
public class EnderEyeMoveBehavior extends Behavior<EntityMaid> {
public class FindTargetMoveBehavior extends Behavior<EntityMaid> {
public EnderEyeMoveBehavior() {
super(ImmutableMap.of(MemoryModuleType.WALK_TARGET, MemoryStatus.VALUE_ABSENT, InitEntities.TARGET_POS.get(), MemoryStatus.VALUE_ABSENT));
public FindTargetMoveBehavior() {
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;
IMaidFindTargetTask task = (IMaidFindTargetTask) maid.getTask();
if (task.findTarget(p_22538_, maid) == null) return false;
if (maid.hasRestriction()) return false;
LivingEntity owner = maid.getOwner();
return (owner != null && maid.distanceTo(owner) < 5);
return (owner != null && maid.distanceTo(owner) < task.minReScheduleDistance());
}
@Override
protected void start(ServerLevel serverlevel, EntityMaid maid, long p_22542_) {
BlockPos target = MemoryUtil.getCommonBlockCache(maid);
IMaidFindTargetTask task = (IMaidFindTargetTask) maid.getTask();
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;
}
}
BlockPos target = task.findTarget(serverlevel, maid);
if (target != null) {
if (maid.distanceToSqr(target.getCenter()) < 9) {
maid.getJumpControl().jump();
return;
}
BlockPos finalTarget = target;
BlockPos ownerPos = owner.blockPosition();
BlockPos maidPos = maid.blockPosition();
if (finalTarget.distSqr(ownerPos) > 10 * 10) {
if (finalTarget.distSqr(ownerPos) > task.maxOutDistance() * task.maxOutDistance()) {
Vec3 dVec = target.getCenter().subtract(owner.position());
dVec = dVec.normalize().scale(7);
dVec = dVec.normalize().scale(task.maxOutDistance() - (double) (task.maxOutDistance() - task.minReScheduleDistance()) / 2);
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) {
@@ -59,13 +63,13 @@ public class EnderEyeMoveBehavior extends Behavior<EntityMaid> {
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) {
if (fTarget.offset(x, y, z).distSqr(ownerPos) < task.maxOutDistance() * task.maxOutDistance()) {
finalTarget = fTarget.offset(x, y, z);
}
}
}
}
if (finalTarget.distSqr(maidPos) < 10 * 10) {
if (finalTarget.distSqr(maidPos) < task.maxOutDistance() * task.maxOutDistance()) {
double distanceToOwner = maidPos.distSqr(ownerPos);
double speed = 0.4;
if (distanceToOwner < 4 * 4) {

View File

@@ -1,39 +1,42 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
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 org.jetbrains.annotations.NotNull;
import studio.fantasyit.maid_useful_task.task.IMaidFindTargetTask;
import studio.fantasyit.maid_useful_task.util.Conditions;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
public class EnderEyeWaitBehavior extends Behavior<EntityMaid> {
public class FindTargetWaitBehavior extends Behavior<EntityMaid> {
public EnderEyeWaitBehavior() {
public FindTargetWaitBehavior() {
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;
protected boolean checkExtraStartConditions(ServerLevel serverLevel, EntityMaid maid) {
IMaidFindTargetTask task = (IMaidFindTargetTask) maid.getTask();
if (task.findTarget(serverLevel, maid) == null) return true;
if (maid.hasRestriction()) return false;
LivingEntity owner = maid.getOwner();
if (owner != null && maid.distanceTo(owner) > 6) {
if (owner != null && maid.distanceTo(owner) > task.maxOutDistance()) {
return true;
}
return Conditions.hasReachedValidTargetOrReset(maid, 4);
}
@Override
protected void start(ServerLevel serverlevel, EntityMaid maid, long p_22542_) {
protected void start(@NotNull ServerLevel serverLevel, EntityMaid maid, long p_22542_) {
IMaidFindTargetTask task = (IMaidFindTargetTask) maid.getTask();
if (task.findTarget(serverLevel, maid) == null) {
task.clearCache(maid);
}
MemoryUtil.clearTarget(maid);
}
}

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidCheckRateTask;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS;

View File

@@ -1,4 +1,4 @@
package studio.fantasyit.maid_useful_task.behavior;
package studio.fantasyit.maid_useful_task.behavior.common;
import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.task.MaidCheckRateTask;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;

View File

@@ -0,0 +1,38 @@
package studio.fantasyit.maid_useful_task.client;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.client.Minecraft;
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.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
import studio.fantasyit.maid_useful_task.network.MaidAllowHandleVehicle;
import studio.fantasyit.maid_useful_task.network.Network;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import static studio.fantasyit.maid_useful_task.client.KeyMapping.KEY_SWITCH_VEHICLE_CONTROL;
@Mod.EventBusSubscriber(modid = MaidUsefulTask.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE, value = Dist.CLIENT)
public class KeyEvents {
@SubscribeEvent
@OnlyIn(Dist.CLIENT)
public static void keyInput(InputEvent.Key event) {
while (KEY_SWITCH_VEHICLE_CONTROL.get().consumeClick()) {
Player player = Minecraft.getInstance().player;
if (!player.isPassenger()) return;
EntityMaid maid = player
.getVehicle()
.getPassengers()
.stream()
.filter(entity -> entity instanceof EntityMaid)
.map(entity -> (EntityMaid) entity)
.findAny()
.orElse(null);
if (maid == null) return;
Network.INSTANCE.sendToServer(new MaidAllowHandleVehicle(maid));
}
}
}

View File

@@ -0,0 +1,26 @@
package studio.fantasyit.maid_useful_task.client;
import com.mojang.blaze3d.platform.InputConstants;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RegisterKeyMappingsEvent;
import net.minecraftforge.common.util.Lazy;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import org.lwjgl.glfw.GLFW;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
@Mod.EventBusSubscriber(modid = MaidUsefulTask.MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public class KeyMapping {
public static final Lazy<net.minecraft.client.KeyMapping> KEY_SWITCH_VEHICLE_CONTROL = Lazy.of(() -> new net.minecraft.client.KeyMapping(
"key.maid_useful_tasks.switch_vehicle_control",
InputConstants.Type.KEYSYM,
GLFW.GLFW_KEY_V,
"key.maid_useful_tasks.categories.main"
));
@SubscribeEvent
public static void registerKeyMappings(final RegisterKeyMappingsEvent event) {
event.register(KEY_SWITCH_VEHICLE_CONTROL.get());
}
}

View File

@@ -0,0 +1,20 @@
package studio.fantasyit.maid_useful_task.event;
import net.minecraft.server.level.ServerLevel;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
import studio.fantasyit.maid_useful_task.task.IMaidVehicleControlTask;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleManager;
@Mod.EventBusSubscriber(modid = MaidUsefulTask.MODID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public class MaidTickEvent {
@SubscribeEvent
public static void onTick(com.github.tartaricacid.touhoulittlemaid.api.event.MaidTickEvent event) {
if (event.getMaid().level() instanceof ServerLevel sl)
if (event.getMaid().getTask() instanceof IMaidVehicleControlTask imvc && event.getMaid().getVehicle() != null) {
imvc.tick(sl, event.getMaid());
MaidVehicleManager.syncVehicleParameter(event.getMaid());
}
}
}

View File

@@ -13,7 +13,7 @@ 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;
import studio.fantasyit.maid_useful_task.task.MaidLocateTask;
@Mixin(MaidFollowOwnerTask.class)
abstract public class FollowMaidMixin {
@@ -23,7 +23,7 @@ abstract public class FollowMaidMixin {
@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)) {
if (maid.getTask().getUid().equals(MaidLocateTask.UID)) {
LivingEntity owner = maid.getOwner();
if (owner != null && maid.distanceTo(owner) < 6) {
cir.setReturnValue(false);
@@ -33,7 +33,7 @@ abstract public class FollowMaidMixin {
@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)) {
if (maid.getTask().getUid().equals(MaidLocateTask.UID)) {
return 10;
}
return startDistance;
@@ -41,7 +41,7 @@ abstract public class FollowMaidMixin {
@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)) {
if (maid.getTask().getUid().equals(MaidLocateTask.UID)) {
return 10;
}
return stopDistance;

View File

@@ -0,0 +1,103 @@
package studio.fantasyit.maid_useful_task.mixin;
import com.github.tartaricacid.touhoulittlemaid.entity.item.AbstractEntityFromItem;
import com.github.tartaricacid.touhoulittlemaid.entity.item.EntityBroom;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import studio.fantasyit.maid_useful_task.vehicle.IVirtualControl;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
@Mixin(EntityBroom.class)
abstract public class VehicleBroomMixin extends AbstractEntityFromItem implements IVirtualControl {
public VehicleBroomMixin(EntityType<? extends LivingEntity> type, Level worldIn) {
super(type, worldIn);
}
@Unique
public MaidVehicleControlType maid_useful_tasks$vc_type = MaidVehicleControlType.NONE;
@Unique
public float maid_useful_tasks$vc_xRot;
@Unique
public float maid_useful_tasks$vc_yRot;
@Unique
public float maid_useful_tasks$vc_speed;
@Override
public void maid_useful_tasks$setControlParam(float xRot, float yRot, float speed, MaidVehicleControlType type) {
this.maid_useful_tasks$vc_xRot = xRot;
this.maid_useful_tasks$vc_yRot = yRot;
this.maid_useful_tasks$vc_speed = speed;
this.maid_useful_tasks$vc_type = type;
}
@Override
public CompoundTag maid_useful_tasks$getControlParam() {
CompoundTag result = new CompoundTag();
result.putFloat("xRot", maid_useful_tasks$vc_xRot);
result.putFloat("yRot", maid_useful_tasks$vc_yRot);
result.putFloat("speed", maid_useful_tasks$vc_speed);
result.putString("type", maid_useful_tasks$vc_type.name());
return result;
}
@Override
public void maid_useful_tasks$setControlParam(CompoundTag target) {
if (target.contains("type")) {
this.maid_useful_tasks$vc_type = MaidVehicleControlType.valueOf(target.getString("type"));
}
if (target.contains("xRot")) {
this.maid_useful_tasks$vc_xRot = target.getFloat("xRot");
}
if (target.contains("yRot")) {
this.maid_useful_tasks$vc_yRot = target.getFloat("yRot");
}
if (target.contains("speed")) {
this.maid_useful_tasks$vc_speed = target.getFloat("speed");
}
}
@Override
public void maid_useful_tasks$stopControl() {
this.maid_useful_tasks$vc_type = MaidVehicleControlType.NONE;
}
@Inject(method = "tickRidden", at = @At(value = "INVOKE", target = "Lcom/github/tartaricacid/touhoulittlemaid/entity/item/AbstractEntityFromItem;tickRidden(Lnet/minecraft/world/entity/player/Player;Lnet/minecraft/world/phys/Vec3;)V"))
public void maid_useful_tasks$tickRidden(CallbackInfo ci) {
if (maid_useful_tasks$vc_type == MaidVehicleControlType.NONE) {
return;
}
this.setRot(maid_useful_tasks$vc_yRot, maid_useful_tasks$vc_xRot);
}
@ModifyVariable(method = "travel", at = @At(value = "STORE"), name = "strafe")
float maid_useful_tasks$travel_s(float strafe) {
if (maid_useful_tasks$vc_type != MaidVehicleControlType.FULL) {
return strafe;
}
return 0;
}
@ModifyVariable(method = "travel", at = @At(value = "STORE"), name = "vertical")
float maid_useful_tasks$travel_v(float vertical) {
if (maid_useful_tasks$vc_type != MaidVehicleControlType.FULL) {
return vertical;
}
return -(maid_useful_tasks$vc_xRot - 10.0F) / 22.5F;
}
@ModifyVariable(method = "travel", at = @At(value = "STORE"), name = "forward")
float maid_useful_tasks$travel_f(float forward) {
if (maid_useful_tasks$vc_type != MaidVehicleControlType.FULL) {
return forward;
}
return maid_useful_tasks$vc_speed;
}
}

View File

@@ -0,0 +1,46 @@
package studio.fantasyit.maid_useful_task.network;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.network.NetworkEvent;
import org.jetbrains.annotations.Nullable;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
import java.util.function.Supplier;
public class MaidAllowHandleVehicle {
final int maidId;
public MaidAllowHandleVehicle(EntityMaid maid) {
this.maidId = maid.getId();
}
public MaidAllowHandleVehicle(FriendlyByteBuf buffer) {
maidId = buffer.readInt();
}
public void toBytes(FriendlyByteBuf buffer) {
buffer.writeInt(maidId);
}
public static void handle(MaidAllowHandleVehicle msg, Supplier<NetworkEvent.Context> contextSupplier) {
NetworkEvent.Context context = contextSupplier.get();
ServerPlayer sender = context.getSender();
Entity entity = sender.level().getEntity(msg.maidId);
if (entity instanceof EntityMaid maid) {
MaidVehicleControlType[] values = MaidVehicleControlType.values();
MaidVehicleControlType allowMode = values[(MemoryUtil.getAllowHandleVehicle(maid).ordinal() + 1) % values.length];
MemoryUtil.setAllowHandleVehicle(maid, allowMode);
Component component = switch (allowMode) {
case NONE -> Component.translatable("maid_useful_task.allow_handle_vehicle.none");
case ROT_ONLY -> Component.translatable("maid_useful_task.allow_handle_vehicle.rot_only");
case FULL -> Component.translatable("maid_useful_task.allow_handle_vehicle.full");
};
sender.sendSystemMessage(component);
}
}
}

View File

@@ -0,0 +1,30 @@
package studio.fantasyit.maid_useful_task.network;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraftforge.network.NetworkEvent;
import java.util.function.Supplier;
public class MaidConfigurePacket {
public String name;
public String value;
public MaidConfigurePacket(String name, String value) {
this.name = name;
this.value = value;
}
public MaidConfigurePacket(FriendlyByteBuf buffer) {
this.name = buffer.readUtf();
this.value = buffer.readUtf();
}
public void toBytes(FriendlyByteBuf buffer) {
buffer.writeUtf(name);
buffer.writeUtf(value);
}
public static void handle(MaidConfigurePacket msg, Supplier<NetworkEvent.Context> context) {
}
}

View File

@@ -0,0 +1,44 @@
package studio.fantasyit.maid_useful_task.network;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraftforge.network.NetworkEvent;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleManager;
import java.util.function.Supplier;
public class MaidSyncVehiclePacket {
final CompoundTag tag;
final int maidId;
public MaidSyncVehiclePacket(int maidId, CompoundTag tag) {
this.maidId = maidId;
this.tag = tag;
}
public MaidSyncVehiclePacket(FriendlyByteBuf buffer) {
this.maidId = buffer.readInt();
this.tag = buffer.readNbt();
}
public void toBytes(FriendlyByteBuf buffer) {
buffer.writeInt(maidId);
buffer.writeNbt(tag);
}
public static void handle(MaidSyncVehiclePacket msg, Supplier<NetworkEvent.Context> contextSupplier) {
NetworkEvent.Context context = contextSupplier.get();
Entity entity = Network.getLocalPlayer().level().getEntity(msg.maidId);
if (entity instanceof EntityMaid maid) {
MaidVehicleManager.getControllableVehicle(maid).ifPresent(vehicle -> {
vehicle.syncVehicleParameter(maid, msg.tag);
});
}
}
}

View File

@@ -0,0 +1,76 @@
package studio.fantasyit.maid_useful_task.network;
import net.minecraft.client.Minecraft;
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 net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import net.minecraftforge.fml.event.lifecycle.FMLDedicatedServerSetupEvent;
import net.minecraftforge.network.NetworkRegistry;
import net.minecraftforge.network.simple.SimpleChannel;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
public class Network {
private static final String PROTOCOL_VERSION = "1";
public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel(
new ResourceLocation(MaidUsefulTask.MODID, "mut_packets"),
() -> PROTOCOL_VERSION,
(v) -> true,
(v) -> true
);
private static void registerMessage() {
Network.INSTANCE.registerMessage(0,
MaidConfigurePacket.class,
MaidConfigurePacket::toBytes,
MaidConfigurePacket::new,
(msg, context) -> {
context.get().enqueueWork(() -> MaidConfigurePacket.handle(msg, context));
context.get().setPacketHandled(true);
}
);
Network.INSTANCE.registerMessage(1,
MaidAllowHandleVehicle.class,
MaidAllowHandleVehicle::toBytes,
MaidAllowHandleVehicle::new,
(msg, context) -> {
context.get().enqueueWork(() -> MaidAllowHandleVehicle.handle(msg, context));
context.get().setPacketHandled(true);
}
);
Network.INSTANCE.registerMessage(2,
MaidSyncVehiclePacket.class,
MaidSyncVehiclePacket::toBytes,
MaidSyncVehiclePacket::new,
(msg, context) -> {
context.get().enqueueWork(() -> MaidSyncVehiclePacket.handle(msg, context));
context.get().setPacketHandled(true);
}
);
}
@OnlyIn(Dist.CLIENT)
public static Player getLocalPlayer() {
return Minecraft.getInstance().player;
}
@Mod.EventBusSubscriber(modid = MaidUsefulTask.MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.DEDICATED_SERVER)
public static class Server {
@SubscribeEvent
public static void FMLClientSetupEvent(FMLDedicatedServerSetupEvent event) {
registerMessage();
}
}
@Mod.EventBusSubscriber(modid = MaidUsefulTask.MODID, bus = Mod.EventBusSubscriber.Bus.MOD, value = Dist.CLIENT)
public static class Client {
@SubscribeEvent
public static void FMLClientSetupEvent(FMLClientSetupEvent event) {
registerMessage();
}
}
}

View File

@@ -3,12 +3,14 @@ package studio.fantasyit.maid_useful_task.registry;
import net.minecraft.core.BlockPos;
import net.minecraft.core.registries.Registries;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.eventbus.api.IEventBus;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
import studio.fantasyit.maid_useful_task.memory.*;
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
import java.util.Optional;
@@ -25,8 +27,9 @@ public class MemoryModuleRegistry {
= 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<ItemStack>> LOCATE_ITEM = REGISTER.register("locate_item", () -> new MemoryModuleType<>(Optional.empty()));
public static final RegistryObject<MemoryModuleType<CurrentWork>> CURRENT_WORK = REGISTER.register("current_work", () -> new MemoryModuleType<>(Optional.empty()));
public static final RegistryObject<MemoryModuleType<MaidVehicleControlType>> IS_ALLOW_HANDLE_VEHICLE = REGISTER.register("is_allow_handle_vehicle", () -> new MemoryModuleType<>(Optional.empty()));
public static void register(IEventBus eventBus) {
REGISTER.register(eventBus);
}

View File

@@ -3,21 +3,14 @@ package studio.fantasyit.maid_useful_task.task;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.block.BaseFireBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockBehavior;
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockMoveBehavior;
import studio.fantasyit.maid_useful_task.behavior.common.DestoryBlockBehavior;
import studio.fantasyit.maid_useful_task.behavior.common.DestoryBlockMoveBehavior;
import studio.fantasyit.maid_useful_task.util.MaidUtils;
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;

View File

@@ -3,19 +3,12 @@ package studio.fantasyit.maid_useful_task.task;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import com.mojang.datafixers.util.Pair;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.BlockHitResult;
import org.jetbrains.annotations.NotNull;
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockBehavior;
import studio.fantasyit.maid_useful_task.behavior.DestoryBlockMoveBehavior;
import studio.fantasyit.maid_useful_task.behavior.common.DestoryBlockBehavior;
import studio.fantasyit.maid_useful_task.behavior.common.DestoryBlockMoveBehavior;
import studio.fantasyit.maid_useful_task.util.MaidUtils;
import studio.fantasyit.maid_useful_task.util.WrappedMaidFakePlayer;
import java.util.List;

View File

@@ -0,0 +1,24 @@
package studio.fantasyit.maid_useful_task.task;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import org.jetbrains.annotations.Nullable;
public interface IMaidFindTargetTask extends IMaidVehicleControlTask {
@Nullable BlockPos findTarget(ServerLevel level, EntityMaid maid);
void clearCache(EntityMaid maid);
default int maxOutDistance() {
return 10;
}
default int minReScheduleDistance() {
return 3;
}
default int moveDistance() {
return 10;
}
}

View File

@@ -0,0 +1,25 @@
package studio.fantasyit.maid_useful_task.task;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleManager;
public interface IMaidVehicleControlTask {
BlockPos findTarget(ServerLevel level, EntityMaid maid);
default void tick(ServerLevel level, EntityMaid maid) {
MaidVehicleControlType allowHandleVehicle = MemoryUtil.getAllowHandleVehicle(maid);
BlockPos targetPos = findTarget(level, maid);
MaidVehicleManager.getControllableVehicle(maid).ifPresent(vehicle -> {
if (targetPos == null) {
vehicle.maidStopControlVehicle(maid);
} else {
vehicle.maidControlVehicle(maid, allowHandleVehicle, targetPos);
}
});
}
}

View File

@@ -1,50 +0,0 @@
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

@@ -0,0 +1,92 @@
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.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.tags.StructureTags;
import net.minecraft.world.entity.LivingEntity;
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.common.FindTargetMoveBehavior;
import studio.fantasyit.maid_useful_task.behavior.common.FindTargetWaitBehavior;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import java.util.ArrayList;
import java.util.List;
public class MaidLocateTask implements IMaidTask, IMaidFindTargetTask {
public static final ResourceLocation UID = new ResourceLocation(MaidUsefulTask.MODID, "locate");
@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 FindTargetMoveBehavior()));
list.add(Pair.of(2, new FindTargetWaitBehavior()));
return list;
}
@Override
public boolean enableLookAndRandomWalk(EntityMaid maid) {
return false;
}
@Override
public @Nullable BlockPos findTarget(ServerLevel level, EntityMaid maid) {
BlockPos target = null;
ItemStack itemStack = maid.getMainHandItem();
ItemStack last = MemoryUtil.getLocateItem(maid);
if (!last.isEmpty() && !itemStack.isEmpty() && ItemStack.isSameItem(last, itemStack)) {
MemoryUtil.setLocateItem(maid, itemStack);
MemoryUtil.clearCommonBlockCache(maid);
}
if (maid.getMainHandItem().is(Items.ENDER_EYE)) {
target = MemoryUtil.getCommonBlockCache(maid);
if (target == null) {
BlockPos blockpos = level.findNearestMapStructure(StructureTags.EYE_OF_ENDER_LOCATED, maid.blockPosition(), 100, false);
if (blockpos != null) {
MemoryUtil.setCommonBlockCache(maid, blockpos);
target = blockpos;
}
}
} else if (maid.getMainHandItem().is(Items.COMPASS)) {
target = MemoryUtil.getCommonBlockCache(maid);
if (target == null) {
LivingEntity owner = maid.getOwner();
if (owner != null) {
target = owner.getSleepingPos().orElse(maid.level().getSharedSpawnPos());
}
}
} else {
MemoryUtil.clearCommonBlockCache(maid);
}
return target;
}
@Override
public void clearCache(EntityMaid maid) {
MemoryUtil.clearCommonBlockCache(maid);
}
}

View File

@@ -19,7 +19,7 @@ import net.minecraftforge.items.wrapper.CombinedInvWrapper;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
import studio.fantasyit.maid_useful_task.behavior.*;
import studio.fantasyit.maid_useful_task.behavior.common.*;
import studio.fantasyit.maid_useful_task.memory.BlockValidationMemory;
import studio.fantasyit.maid_useful_task.util.MaidUtils;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;

View File

@@ -9,9 +9,11 @@ import net.minecraft.world.entity.ai.behavior.BehaviorUtils;
import net.minecraft.world.entity.ai.behavior.BlockPosTracker;
import net.minecraft.world.entity.ai.behavior.PositionTracker;
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
import studio.fantasyit.maid_useful_task.memory.*;
import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry;
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
import java.util.List;
import java.util.Optional;
@@ -21,6 +23,7 @@ public class MemoryUtil {
Optional<BlockTargetMemory> memory = maid.getBrain().getMemory(MemoryModuleRegistry.DESTROY_TARGET.get());
return memory.orElse(null);
}
public static void setDestroyTargetMemory(EntityMaid maid, List<BlockPos> blockPosSet) {
maid.getBrain().setMemory(MemoryModuleRegistry.DESTROY_TARGET.get(), new BlockTargetMemory(blockPosSet));
}
@@ -43,9 +46,11 @@ public class MemoryUtil {
Optional<BlockPos> memory = maid.getBrain().getMemory(MemoryModuleRegistry.PLACE_TARGET.get());
return memory.orElse(null);
}
public static void setPlaceTarget(EntityMaid maid, BlockPos blockPos) {
maid.getBrain().setMemory(MemoryModuleRegistry.PLACE_TARGET.get(), blockPos);
}
public static void clearPlaceTarget(EntityMaid maid) {
maid.getBrain().eraseMemory(MemoryModuleRegistry.PLACE_TARGET.get());
}
@@ -54,37 +59,59 @@ public class MemoryUtil {
maid.getBrain().setMemory(MemoryModuleType.LOOK_TARGET, new BlockPosTracker(pos));
}
public static BlockUpContext getBlockUpContext(EntityMaid maid){
public static BlockUpContext getBlockUpContext(EntityMaid maid) {
Brain<EntityMaid> brain = maid.getBrain();
if(!brain.hasMemoryValue(MemoryModuleRegistry.BLOCK_UP_TARGET.get())){
if (!brain.hasMemoryValue(MemoryModuleRegistry.BLOCK_UP_TARGET.get())) {
brain.setMemory(MemoryModuleRegistry.BLOCK_UP_TARGET.get(), new BlockUpContext());
}
return brain.getMemory(MemoryModuleRegistry.BLOCK_UP_TARGET.get()).get();
}
public static BlockValidationMemory getBlockValidationMemory(EntityMaid maid){
public static BlockValidationMemory getBlockValidationMemory(EntityMaid maid) {
Brain<EntityMaid> brain = maid.getBrain();
if(!brain.hasMemoryValue(MemoryModuleRegistry.BLOCK_VALIDATION.get())){
if (!brain.hasMemoryValue(MemoryModuleRegistry.BLOCK_VALIDATION.get())) {
brain.setMemory(MemoryModuleRegistry.BLOCK_VALIDATION.get(), new BlockValidationMemory());
}
return brain.getMemory(MemoryModuleRegistry.BLOCK_VALIDATION.get()).get();
}
public static void setTarget(EntityMaid maid, BlockPos targetPos,float speed) {
public static void setTarget(EntityMaid maid, BlockPos targetPos, float speed) {
maid.getBrain().setMemory(InitEntities.TARGET_POS.get(), new BlockPosTracker(targetPos));
BehaviorUtils.setWalkAndLookTargetMemories(maid, targetPos, speed, 0);
}
public static CurrentWork getCurrent(EntityMaid maid){
public static CurrentWork getCurrent(EntityMaid maid) {
return maid.getBrain().getMemory(MemoryModuleRegistry.CURRENT_WORK.get()).orElse(CurrentWork.IDLE);
}
public static void setCurrent(EntityMaid maid, CurrentWork currentWork){
public static void setCurrent(EntityMaid maid, CurrentWork currentWork) {
maid.getBrain().setMemory(MemoryModuleRegistry.CURRENT_WORK.get(), currentWork);
}
public static void setCommonBlockCache(EntityMaid maid, BlockPos pos){
public static void setCommonBlockCache(EntityMaid maid, BlockPos pos) {
maid.getBrain().setMemory(MemoryModuleRegistry.COMMON_BLOCK_CACHE.get(), pos);
}
public static BlockPos getCommonBlockCache(EntityMaid maid){
public static BlockPos getCommonBlockCache(EntityMaid maid) {
return maid.getBrain().getMemory(MemoryModuleRegistry.COMMON_BLOCK_CACHE.get()).orElse(null);
}
public static void setAllowHandleVehicle(EntityMaid maid, MaidVehicleControlType allow) {
maid.getBrain().setMemory(MemoryModuleRegistry.IS_ALLOW_HANDLE_VEHICLE.get(), allow);
}
public static MaidVehicleControlType getAllowHandleVehicle(EntityMaid maid) {
return maid.getBrain().getMemory(MemoryModuleRegistry.IS_ALLOW_HANDLE_VEHICLE.get()).orElse(MaidVehicleControlType.NONE);
}
public static void clearCommonBlockCache(EntityMaid maid) {
maid.getBrain().eraseMemory(MemoryModuleRegistry.COMMON_BLOCK_CACHE.get());
}
public static void setLocateItem(EntityMaid maid, ItemStack item) {
maid.getBrain().setMemory(MemoryModuleRegistry.LOCATE_ITEM.get(), item);
}
public static ItemStack getLocateItem(EntityMaid maid) {
return maid.getBrain().getMemory(MemoryModuleRegistry.LOCATE_ITEM.get()).orElse(ItemStack.EMPTY);
}
}

View File

@@ -0,0 +1,26 @@
package studio.fantasyit.maid_useful_task.util;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Unique;
import java.util.function.Supplier;
public class RotUtil {
public static float getXRot(Vec3 from, Vec3 to) {
double d0 = to.x() - from.x();
double d1 = to.y() - from.y();
double d2 = to.z() - from.z();
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
return Mth.wrapDegrees((float) (-(Mth.atan2(d1, d3) * (double) (180F / (float) Math.PI))));
}
public static float getYRot(Vec3 from, Vec3 to) {
double d0 = to.x() - from.x();
double d1 = to.y() - from.y();
double d2 = to.z() - from.z();
double d3 = Math.sqrt(d0 * d0 + d2 * d2);
return Mth.wrapDegrees((float) (-(Mth.atan2(d0, d2) * (double) (180F / (float) Math.PI))));
}
}

View File

@@ -0,0 +1,26 @@
package studio.fantasyit.maid_useful_task.vehicle;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.Nullable;
abstract public class AbstractMaidControllableVehicle {
abstract public boolean isMaidOnThisVehicle(EntityMaid maid);
abstract public void maidStopControlVehicle(EntityMaid maid);
abstract public void maidControlVehicle(EntityMaid maid, MaidVehicleControlType type, BlockPos target);
public void syncVehicleParameter(EntityMaid maid, CompoundTag tag){
if(maid.getVehicle() instanceof IVirtualControl vehicle){
vehicle.maid_useful_tasks$setControlParam(tag);
}
}
public @Nullable CompoundTag getSyncVehicleParameter(EntityMaid maid) {
if (maid.getVehicle() instanceof IVirtualControl vehicle) {
return vehicle.maid_useful_tasks$getControlParam();
}
return null;
}
}

View File

@@ -0,0 +1,10 @@
package studio.fantasyit.maid_useful_task.vehicle;
import net.minecraft.nbt.CompoundTag;
public interface IVirtualControl {
void maid_useful_tasks$setControlParam(float xRot, float yRot, float speed,MaidVehicleControlType type);
void maid_useful_tasks$stopControl();
CompoundTag maid_useful_tasks$getControlParam();
void maid_useful_tasks$setControlParam(CompoundTag target);
}

View File

@@ -0,0 +1,7 @@
package studio.fantasyit.maid_useful_task.vehicle;
public enum MaidVehicleControlType {
NONE,
ROT_ONLY,
FULL
}

View File

@@ -0,0 +1,44 @@
package studio.fantasyit.maid_useful_task.vehicle;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.network.PacketDistributor;
import studio.fantasyit.maid_useful_task.network.MaidSyncVehiclePacket;
import studio.fantasyit.maid_useful_task.network.Network;
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
public class MaidVehicleManager {
public static List<AbstractMaidControllableVehicle> controllableVehicles = new ArrayList<>();
public static void register() {
controllableVehicles.add(new VehicleBroom());
}
public static void addControllableVehicle(AbstractMaidControllableVehicle vehicle) {
controllableVehicles.add(vehicle);
}
public static Optional<AbstractMaidControllableVehicle> getControllableVehicle(EntityMaid maid) {
for (AbstractMaidControllableVehicle vehicle : controllableVehicles) {
if (vehicle.isMaidOnThisVehicle(maid)) return Optional.of(vehicle);
}
return Optional.empty();
}
public static void syncVehicleParameter(EntityMaid maid) {
getControllableVehicle(maid).ifPresent(vehicle -> {
CompoundTag syncVehicleParameter = vehicle.getSyncVehicleParameter(maid);
if (syncVehicleParameter != null) {
Network.INSTANCE.send(
PacketDistributor.TRACKING_ENTITY_AND_SELF.with(() -> maid),
new MaidSyncVehiclePacket(maid.getId(), syncVehicleParameter)
);
}
});
}
}

View File

@@ -0,0 +1,60 @@
package studio.fantasyit.maid_useful_task.vehicle;
import com.github.tartaricacid.touhoulittlemaid.entity.item.EntityBroom;
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Rotations;
import net.minecraft.nbt.CompoundTag;
import org.jetbrains.annotations.Nullable;
import studio.fantasyit.maid_useful_task.util.RotUtil;
public class VehicleBroom extends AbstractMaidControllableVehicle {
@Override
public boolean isMaidOnThisVehicle(EntityMaid maid) {
return maid.getVehicle() instanceof EntityBroom;
}
@Override
public void maidControlVehicle(EntityMaid maid, MaidVehicleControlType type, BlockPos target) {
if (maid.level().isClientSide) return;
if (maid.getVehicle() instanceof EntityBroom vehicle) {
if (type == MaidVehicleControlType.NONE) {
((IVirtualControl) vehicle).maid_useful_tasks$setControlParam(0, 0, 0, type);
return;
}
double xzDistance = maid.distanceToSqr(target.getX(), maid.getY(), target.getZ());
double finalXRot = vehicle.getXRot();
double finalYRot = vehicle.getYRot();
double finalSpeed = 0;
if (vehicle.isInWater()) {
finalXRot = -10;
} else if (xzDistance < Math.pow(maid.getY() - maid.level().getSeaLevel(), 2)) {
if (maid.getY() - maid.level().getSeaLevel() < 50 || vehicle.onGround())
finalXRot = 15;
else
finalXRot = 60;
} else if (maid.getY() < 100) {
finalXRot = -50;
} else if (maid.getY() > 160) {
finalXRot = 15;
} else {
finalXRot = 0;
}
finalYRot = RotUtil.getYRot(maid.position(), target.getCenter());
finalSpeed = type == MaidVehicleControlType.FULL ? 3.0 : 0;
if (xzDistance < 5 * 5 && (vehicle.onGround() || vehicle.isInWater()))
finalSpeed = 0;
((IVirtualControl) vehicle).maid_useful_tasks$setControlParam((float) finalXRot, (float) finalYRot, (float) finalSpeed, type);
}
}
@Override
public void maidStopControlVehicle(EntityMaid maid) {
EntityBroom vehicle = (EntityBroom) maid.getVehicle();
if (vehicle instanceof IVirtualControl ivc)
ivc.maid_useful_tasks$stopControl();
}
}

View File

@@ -1,2 +1,3 @@
public net.minecraft.world.level.BlockGetter m_151361_(Lnet/minecraft/world/phys/Vec3;Lnet/minecraft/world/phys/Vec3;Ljava/lang/Object;Ljava/util/function/BiFunction;Ljava/util/function/Function;)Ljava/lang/Object;
public-f net.minecraft.world.entity.player.Player f_36093_
public-f net.minecraft.world.entity.player.Player f_36093_
public net.minecraft.world.entity.Entity m_19915_(FF)V

View File

@@ -1,3 +1,11 @@
{
"task.maid_useful_task.maid_tree": "Logging"
"task.maid_useful_task.maid_tree": "Logging",
"task.maid_useful_task.maid_tree.description": "The maid will cut down the logs around her and plant saplings.",
"task.maid_useful_task.locate": "Locate",
"task.maid_useful_task.locate.description": "The maid can locate the some structure or your home with specific items.",
"key.maid_useful_tasks.switch_vehicle_control": "Switch Vehicle Control Mode",
"maid_useful_task.allow_handle_vehicle.none": "Not allowing maid control vehicle",
"maid_useful_task.allow_handle_vehicle.rot_only": "Allow maid control rotation only",
"maid_useful_task.allow_handle_vehicle.full": "Allow maid control vehicle",
"key.maid_useful_tasks.categories.main": "Maid Useful Tasks"
}

View File

@@ -1,3 +1,11 @@
{
"task.maid_useful_task.maid_tree": "伐木"
"key.maid_useful_tasks.categories.main": "女仆实用任务",
"key.maid_useful_tasks.switch_vehicle_control": "切换载具控制模式",
"maid_useful_task.allow_handle_vehicle.full": "允许女仆控制载具",
"maid_useful_task.allow_handle_vehicle.none": "不允许女仆控制载具",
"maid_useful_task.allow_handle_vehicle.rot_only": "只允许女仆控制旋转",
"task.maid_useful_task.locate": "定位",
"task.maid_useful_task.locate.description": "女仆会根据手持物品定位指定的结构或你的出生点",
"task.maid_useful_task.maid_tree": "伐木",
"task.maid_useful_task.maid_tree.description": "女仆会砍伐身边的原木并种下树苗"
}

View File

@@ -8,7 +8,8 @@
"FollowMaidMixin",
"MaidCheckPickupItem",
"MaidMoveControlMixin",
"MaidRunOneMixin"
"MaidRunOneMixin",
"VehicleBroomMixin"
],
"client": [
],