Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2dbeacf777 | ||
|
|
fa72af9bc3 | ||
|
|
01ec9c0b63 | ||
|
|
6a639a4483 | ||
|
|
b2db97e8f6 |
13
build.gradle
13
build.gradle
@@ -133,9 +133,9 @@ repositories {
|
||||
|
||||
// If you have mod jar dependencies in ./libs, you can declare them as a repository like so.
|
||||
// See https://docs.gradle.org/current/userguide/declaring_repositories.html#sub:flat_dir_resolver
|
||||
// flatDir {
|
||||
// dir 'libs'
|
||||
// }
|
||||
flatDir {
|
||||
dir 'libs'
|
||||
}
|
||||
maven {
|
||||
url "https://cursemaven.com"
|
||||
}
|
||||
@@ -165,13 +165,14 @@ dependencies {
|
||||
// http://www.gradle.org/docs/current/userguide/dependency_management.html
|
||||
|
||||
annotationProcessor 'org.spongepowered:mixin:0.8.5:processor'
|
||||
compileOnly fg.deobf("curse.maven:touhou-little-maid-355044:6596061")
|
||||
compileOnly fg.deobf("curse.maven:touhou-little-maid-355044:6911704")
|
||||
runtimeOnly fg.deobf("curse.maven:touhou-little-maid-355044:6911704")
|
||||
// compileOnly fg.deobf("libs:touhoulittlemaid-${minecraft_version}-release:1.3.7")
|
||||
// runtimeOnly fg.deobf("libs:touhoulittlemaid-${minecraft_version}-release:1.3.7")
|
||||
compileOnly fg.deobf("curse.maven:playerrevive-266890:6048921")
|
||||
compileOnly fg.deobf("curse.maven:creativecore-257814:6383884")
|
||||
compileOnly fg.deobf("curse.maven:natures-compass-252848:4712189")
|
||||
compileOnly fg.deobf("curse.maven:explorers-compass-491794:4712194")
|
||||
runtimeOnly fg.deobf("curse.maven:touhou-little-maid-355044:6596061")
|
||||
runtimeOnly fg.deobf("curse.maven:maid-storage-manager-1210244:6455832")
|
||||
runtimeOnly fg.deobf("curse.maven:playerrevive-266890:6048921")
|
||||
runtimeOnly fg.deobf("curse.maven:creativecore-257814:6383884")
|
||||
// runtimeOnly fg.deobf("curse.maven:natures-compass-252848:4712189")
|
||||
|
||||
@@ -38,7 +38,7 @@ mod_name=maid useful task
|
||||
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
|
||||
mod_license=MIT
|
||||
# The mod version. See https://semver.org/
|
||||
mod_version=1.3.5
|
||||
mod_version=1.3.7
|
||||
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
|
||||
# This should match the base package used for the mod sources.
|
||||
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html
|
||||
|
||||
@@ -11,6 +11,9 @@ import net.minecraftforge.fml.event.config.ModConfigEvent;
|
||||
public class Config {
|
||||
private static final ForgeConfigSpec.Builder BUILDER = new ForgeConfigSpec.Builder();
|
||||
|
||||
private static final ForgeConfigSpec.BooleanValue SELF_RESCUE = BUILDER
|
||||
.define("misc.self_rescue", true);
|
||||
|
||||
private static final ForgeConfigSpec.BooleanValue ENABLE_LOGGING = BUILDER
|
||||
.define("functions.logging", true);
|
||||
private static final ForgeConfigSpec.BooleanValue ENABLE_REVIVE = BUILDER
|
||||
@@ -33,6 +36,8 @@ public class Config {
|
||||
|
||||
static final ForgeConfigSpec SPEC = BUILDER.build();
|
||||
|
||||
public static boolean enableSelfRescue = false;
|
||||
|
||||
public static boolean enableLoggingTask = false;
|
||||
public static boolean enableReviveTask = false;
|
||||
public static boolean enableLocateTask = false;
|
||||
@@ -47,6 +52,7 @@ public class Config {
|
||||
|
||||
@SubscribeEvent
|
||||
static void onLoad(final ModConfigEvent event) {
|
||||
enableSelfRescue = SELF_RESCUE.get();
|
||||
enableLoggingTask = ENABLE_LOGGING.get();
|
||||
enableReviveTask = ENABLE_REVIVE.get();
|
||||
enableLocateTask = ENABLE_LOCATE.get();
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.github.tartaricacid.touhoulittlemaid.api.LittleMaidExtension;
|
||||
import com.github.tartaricacid.touhoulittlemaid.api.entity.ai.IExtraMaidBrain;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.ai.brain.ExtraMaidBrainManager;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.data.TaskDataRegister;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.item.control.BroomControlManager;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.task.TaskManager;
|
||||
import net.minecraft.world.entity.ai.memory.MemoryModuleType;
|
||||
import studio.fantasyit.maid_useful_task.compat.PlayerRevive;
|
||||
@@ -15,6 +16,7 @@ import studio.fantasyit.maid_useful_task.registry.MemoryModuleRegistry;
|
||||
import studio.fantasyit.maid_useful_task.task.MaidLocateTask;
|
||||
import studio.fantasyit.maid_useful_task.task.MaidRevivePlayerTask;
|
||||
import studio.fantasyit.maid_useful_task.task.MaidTreeTask;
|
||||
import studio.fantasyit.maid_useful_task.vehicle.broom.BroomController;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -60,4 +62,9 @@ public class UsefulTaskExtension implements ILittleMaid {
|
||||
MaidReviveConfig.KEY = register.register(new MaidReviveConfig()),
|
||||
MaidReviveConfig.Data::getDefault);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerBroomControl(BroomControlManager register) {
|
||||
register.register(BroomController::new);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package studio.fantasyit.maid_useful_task.api;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
|
||||
@Cancelable
|
||||
public class ItemLocateEvent extends Event {
|
||||
public final ItemStack itemStack;
|
||||
public final EntityMaid maid;
|
||||
public final BlockPos cache;
|
||||
public BlockPos target = null;
|
||||
|
||||
public ItemLocateEvent(ItemStack itemStack, EntityMaid maid, BlockPos cache) {
|
||||
this.itemStack = itemStack;
|
||||
this.maid = maid;
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public BlockPos getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public void setTarget(BlockPos target) {
|
||||
this.target = target;
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ public class DestoryBlockBehavior extends Behavior<EntityMaid> {
|
||||
BlockTargetMemory blockTargetMemory = MemoryUtil.getDestroyTargetMemory(maid);
|
||||
if (blockTargetMemory != null) {
|
||||
blockPosSet = new ArrayList<>(blockTargetMemory.getBlockPosSet());
|
||||
blockPosSet.sort((o1, o2) -> (int) (o1.distSqr(maid.blockPosition()) - o2.distSqr(maid.blockPosition())));
|
||||
blockPosSet.sort((o1, o2) -> (int) (o1.distSqr(maid.blockPosition().above()) - o2.distSqr(maid.blockPosition().above())));
|
||||
}
|
||||
index = 0;
|
||||
task = (IMaidBlockDestroyTask) maid.getTask();
|
||||
@@ -65,6 +65,8 @@ public class DestoryBlockBehavior extends Behavior<EntityMaid> {
|
||||
|
||||
@Override
|
||||
protected boolean canStillUse(ServerLevel p_22545_, EntityMaid p_22546_, long p_22547_) {
|
||||
if (MemoryUtil.getCurrent(p_22546_) != CurrentWork.DESTROY && MemoryUtil.getCurrent(p_22546_) != CurrentWork.BLOCKUP_DESTROY)
|
||||
return false;
|
||||
return (blockPosSet != null && index < blockPosSet.size()) || targetPos != null;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
|
||||
protected boolean shouldMoveTo(@NotNull ServerLevel serverLevel, @NotNull EntityMaid entityMaid, @NotNull BlockPos blockPos) {
|
||||
if (!task.shouldDestroyBlock(entityMaid, blockPos.immutable())) return false;
|
||||
targetPos = blockPos.immutable();
|
||||
BlockPos startPos = entityMaid.blockPosition();
|
||||
if (blockPos instanceof BlockPos.MutableBlockPos mb) {
|
||||
for (int dx = 0; dx < task.reachDistance(); dx = dx <= 0 ? 1 - dx : -dx) {
|
||||
for (int dy = 0; dy < task.reachDistance(); dy = dy <= 0 ? 1 - dy : -dy) {
|
||||
@@ -61,6 +62,9 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
|
||||
if (!PosUtils.isSafePos(serverLevel, pos)) continue;
|
||||
if (!Conditions.isGlobalValidTarget(entityMaid, pos, targetPos)) continue;
|
||||
if (pos.distSqr(targetPos) > task.reachDistance() * task.reachDistance()) continue;
|
||||
if (Math.abs(startPos.getY() - pos.getY()) >= task.reachDistance()) continue;
|
||||
if (Math.abs(startPos.getX() - pos.getX()) >= task.reachDistance()) continue;
|
||||
if (Math.abs(startPos.getZ() - pos.getZ()) >= task.reachDistance()) continue;
|
||||
if (pos.equals(entityMaid.blockPosition()) || (entityMaid.isWithinRestriction(pos) && pathfindingBFS.canPathReach(pos))) {
|
||||
blockPosSet = task.toDestroyFromStanding(entityMaid, targetPos, pos);
|
||||
if (blockPosSet != null) {
|
||||
@@ -81,9 +85,9 @@ public class DestoryBlockMoveBehavior extends MaidCenterMoveToBlockTask {
|
||||
protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) {
|
||||
if (this.pathfindingBFS == null)
|
||||
if (maid.hasRestriction())
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14, (int) maid.getRestrictRadius());
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, (int) maid.getRestrictRadius() + 1, task.reachDistance() + 2);
|
||||
else
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14);
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, task.reachDistance() + 1, task.reachDistance() + 2);
|
||||
return this.pathfindingBFS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
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;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.MaidPathFindingBFS;
|
||||
import com.github.tartaricacid.touhoulittlemaid.init.InitEntities;
|
||||
@@ -41,9 +40,11 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior<EntityMaid> {
|
||||
this.verticalSearchRange = verticalSearchRange;
|
||||
this.searchRange = defaultSearchRange;
|
||||
}
|
||||
|
||||
public void setSearchRange(int searchRange) {
|
||||
this.searchRange = searchRange;
|
||||
}
|
||||
|
||||
protected final void searchForDestination(ServerLevel worldIn, EntityMaid maid) {
|
||||
MaidPathFindingBFS pathFinding = this.getOrCreateArrivalMap(worldIn, maid);
|
||||
BlockPos centrePos = this.getWorkSearchPos(maid);
|
||||
@@ -73,7 +74,7 @@ abstract public class MaidCenterMoveToBlockTask extends Behavior<EntityMaid> {
|
||||
}
|
||||
|
||||
protected MaidPathFindingBFS getOrCreateArrivalMap(ServerLevel worldIn, EntityMaid maid) {
|
||||
return new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid);
|
||||
return new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, maid.searchRadius(), 9);
|
||||
}
|
||||
|
||||
private BlockPos getWorkSearchPos(EntityMaid maid) {
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
package studio.fantasyit.maid_useful_task.behavior.common;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import studio.fantasyit.maid_useful_task.Config;
|
||||
import studio.fantasyit.maid_useful_task.memory.CurrentWork;
|
||||
import studio.fantasyit.maid_useful_task.task.IMaidBlockDestroyTask;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class MaidSelfRescueBehavior extends Behavior<EntityMaid> {
|
||||
public MaidSelfRescueBehavior() {
|
||||
super(Map.of(), 600);
|
||||
}
|
||||
|
||||
boolean started = false;
|
||||
|
||||
private static boolean isNotSafeAndCanTryToDestroy(ServerLevel level, EntityMaid maid, BlockPos pos, IMaidBlockDestroyTask task) {
|
||||
BlockState bs = level.getBlockState(pos);
|
||||
if (bs.isAir()) return false;
|
||||
VoxelShape collision = bs.getCollisionShape(level, pos);
|
||||
if (collision.isEmpty()) return false;
|
||||
return maid.getBoundingBox().intersects(collision.bounds().move(pos)) && bs.isSuffocating(level, pos) && task.mayDestroy(maid, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean checkExtraStartConditions(ServerLevel level, EntityMaid maid) {
|
||||
if (!Config.enableSelfRescue) return false;
|
||||
if (!(maid.getTask() instanceof IMaidBlockDestroyTask ibdt)) return false;
|
||||
if (isNotSafeAndCanTryToDestroy(level, maid, maid.blockPosition(), ibdt) || isNotSafeAndCanTryToDestroy(level, maid, maid.blockPosition().above(), ibdt))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean canStillUse(ServerLevel p_22545_, EntityMaid p_22546_, long p_22547_) {
|
||||
return started && checkExtraStartConditions(p_22545_, p_22546_);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void start(ServerLevel p_22540_, EntityMaid maid, long p_22542_) {
|
||||
started = false;
|
||||
if (MemoryUtil.getCurrent(maid) == CurrentWork.DESTROY) {
|
||||
//如果执行中破坏任务,则立刻停止。用以清空相关状态
|
||||
MemoryUtil.setCurrent(maid, CurrentWork.IDLE);
|
||||
return;
|
||||
}
|
||||
//等待上一个任务结束
|
||||
if (MemoryUtil.getDestroyTargetMemory(maid) != null)
|
||||
return;
|
||||
if (!(maid.getTask() instanceof IMaidBlockDestroyTask task))
|
||||
return;
|
||||
|
||||
started = true;
|
||||
|
||||
List<BlockPos> list = new ArrayList<>();
|
||||
if (isNotSafeAndCanTryToDestroy(p_22540_, maid, maid.blockPosition(), task)) {
|
||||
list.add(maid.blockPosition());
|
||||
}
|
||||
if (isNotSafeAndCanTryToDestroy(p_22540_, maid, maid.blockPosition().above(), task)) {
|
||||
list.add(maid.blockPosition().above());
|
||||
}
|
||||
MemoryUtil.setDestroyTargetMemory(maid, list);
|
||||
MemoryUtil.setTarget(maid, maid.blockPosition(), 0.5f);
|
||||
MemoryUtil.setCurrent(maid, CurrentWork.DESTROY);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stop(ServerLevel p_22548_, EntityMaid p_22549_, long p_22550_) {
|
||||
MemoryUtil.clearTarget(p_22549_);
|
||||
MemoryUtil.setCurrent(p_22549_, CurrentWork.IDLE);
|
||||
}
|
||||
}
|
||||
@@ -89,9 +89,9 @@ public class PlaceBlockMoveBehavior extends MaidCenterMoveToBlockTask {
|
||||
protected @NotNull MaidPathFindingBFS getOrCreateArrivalMap(@NotNull ServerLevel worldIn, @NotNull EntityMaid maid) {
|
||||
if (this.pathfindingBFS == null)
|
||||
if (maid.hasRestriction())
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14, (int) maid.getRestrictRadius());
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, (int) maid.getRestrictRadius(), 9);
|
||||
else
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 14);
|
||||
this.pathfindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), worldIn, maid, 7, 9);
|
||||
return this.pathfindingBFS;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
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 = "TAIL"))
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public interface IMaidBlockUpTask {
|
||||
}
|
||||
};
|
||||
CenterOffsetBlockPosSet notAvailable = new CenterOffsetBlockPosSet(scanRange, scanRange + maxHeight / 2 + 1, scanRange, center.getX(), center.getY() + maxHeight / 2, center.getZ());
|
||||
MaidPathFindingBFS pathFindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), level, maid, 7, scanRange);
|
||||
MaidPathFindingBFS pathFindingBFS = new MaidPathFindingBFS(maid.getNavigation().getNodeEvaluator(), level, maid, 7, scanRange+2);
|
||||
for (int dx = 0; dx < scanRange; dx = dx <= 0 ? 1 - dx : -dx) {
|
||||
for (int dz = 0; dz < scanRange; dz = dz <= 0 ? 1 - dz : -dz) {
|
||||
//计算地面的位置
|
||||
|
||||
@@ -20,13 +20,14 @@ import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.MapItem;
|
||||
import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import studio.fantasyit.maid_useful_task.Config;
|
||||
import studio.fantasyit.maid_useful_task.MaidUsefulTask;
|
||||
import studio.fantasyit.maid_useful_task.api.ItemLocateEvent;
|
||||
import studio.fantasyit.maid_useful_task.behavior.common.FindTargetMoveBehavior;
|
||||
import studio.fantasyit.maid_useful_task.behavior.common.FindTargetWaitBehavior;
|
||||
import studio.fantasyit.maid_useful_task.compat.CompatEntry;
|
||||
import studio.fantasyit.maid_useful_task.compat.ExplorerCompass;
|
||||
import studio.fantasyit.maid_useful_task.util.MemoryUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -78,7 +79,10 @@ public class MaidLocateTask implements IMaidTask, IMaidFindTargetTask {
|
||||
MemoryUtil.setLocateItem(maid, itemStack);
|
||||
MemoryUtil.clearCommonBlockCache(maid);
|
||||
}
|
||||
if (maid.getMainHandItem().is(Items.ENDER_EYE)) {
|
||||
ItemLocateEvent event = new ItemLocateEvent(itemStack, maid, MemoryUtil.getCommonBlockCache(maid));
|
||||
if (MinecraftForge.EVENT_BUS.post(event)) {
|
||||
target = event.getTarget();
|
||||
} else 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);
|
||||
|
||||
@@ -184,11 +184,22 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
|
||||
|
||||
|
||||
protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos) {
|
||||
return isValidNatureTree(maid, startPos, new HashSet<>(), 0);
|
||||
HashSet<BlockPos> vis = new HashSet<>();
|
||||
BlockValidationMemory validationMemory = MemoryUtil.getBlockValidationMemory(maid);
|
||||
boolean validNatureTree = isValidNatureTree(maid, startPos, vis, 0, validationMemory);
|
||||
for (BlockPos pos : vis) {
|
||||
BlockState blockState = maid.level().getBlockState(pos);
|
||||
if (!blockState.is(BlockTags.LEAVES) && !blockState.is(BlockTags.LOGS))
|
||||
continue;
|
||||
if (validNatureTree)
|
||||
validationMemory.setValid(pos);
|
||||
else
|
||||
validationMemory.setInvalid(pos);
|
||||
}
|
||||
return validNatureTree;
|
||||
}
|
||||
|
||||
protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos, Set<BlockPos> visited, int depth) {
|
||||
BlockValidationMemory validationMemory = MemoryUtil.getBlockValidationMemory(maid);
|
||||
protected boolean isValidNatureTree(EntityMaid maid, BlockPos startPos, Set<BlockPos> visited, int depth, BlockValidationMemory validationMemory) {
|
||||
if (validationMemory.hasRecord(startPos))
|
||||
return validationMemory.isValid(startPos, false);
|
||||
if (visited.contains(startPos))
|
||||
@@ -205,7 +216,7 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
|
||||
if (blockState.is(BlockTags.LEAVES) && blockState.hasProperty(LeavesBlock.PERSISTENT) && !blockState.getValue(LeavesBlock.PERSISTENT)) {
|
||||
valid = true;
|
||||
}
|
||||
if (blockState.is(BlockTags.LOGS) && isValidNatureTree(maid, offset, visited, depth + 1)) {
|
||||
if (blockState.is(BlockTags.LOGS) && isValidNatureTree(maid, offset, visited, depth + 1, validationMemory)) {
|
||||
valid = true;
|
||||
}
|
||||
}
|
||||
@@ -221,6 +232,7 @@ public class MaidTreeTask implements IMaidTask, IMaidBlockPlaceTask, IMaidBlockD
|
||||
@Override
|
||||
public List<Pair<Integer, BehaviorControl<? super EntityMaid>>> createBrainTasks(EntityMaid entityMaid) {
|
||||
ArrayList<Pair<Integer, BehaviorControl<? super EntityMaid>>> list = new ArrayList<>();
|
||||
list.add(Pair.of(0, new MaidSelfRescueBehavior()));
|
||||
|
||||
list.add(Pair.of(1, new DestoryBlockBehavior()));
|
||||
list.add(Pair.of(1, new DestoryBlockMoveBehavior()));
|
||||
|
||||
@@ -3,8 +3,11 @@ 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$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);
|
||||
}
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
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 studio.fantasyit.maid_useful_task.vehicle.broom.VehicleBroom;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package studio.fantasyit.maid_useful_task.vehicle.broom;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
public class BroomControlParamStore {
|
||||
public record BroomControlParam(float xRot, float yRot, float vertical, float forward,
|
||||
MaidVehicleControlType type) {
|
||||
public static BroomControlParam fromNbt(CompoundTag tag) {
|
||||
return new BroomControlParam(
|
||||
tag.getFloat("xRot"),
|
||||
tag.getFloat("yRot"),
|
||||
tag.getFloat("vertical"),
|
||||
tag.getFloat("forward"),
|
||||
MaidVehicleControlType.valueOf(tag.getString("type"))
|
||||
);
|
||||
}
|
||||
|
||||
public CompoundTag toNbt() {
|
||||
CompoundTag tag = new CompoundTag();
|
||||
tag.putFloat("xRot", xRot);
|
||||
tag.putFloat("yRot", yRot);
|
||||
tag.putFloat("vertical", vertical);
|
||||
tag.putFloat("forward", forward);
|
||||
tag.putString("type", type.name());
|
||||
return tag;
|
||||
}
|
||||
}
|
||||
|
||||
private static final BroomControlParam NONE = new BroomControlParam(0, 0, 0, 0, MaidVehicleControlType.NONE);
|
||||
|
||||
private static final Map<UUID, BroomControlParam> store = new HashMap<>();
|
||||
|
||||
public static void setControlParam(EntityMaid maid, BroomControlParam param) {
|
||||
store.put(maid.getUUID(), param);
|
||||
}
|
||||
|
||||
public static BroomControlParam getControlParam(EntityMaid maid) {
|
||||
if (!store.containsKey(maid.getUUID()))
|
||||
return NONE;
|
||||
return store.get(maid.getUUID());
|
||||
}
|
||||
|
||||
public static void removeControlParam(EntityMaid maid) {
|
||||
store.remove(maid.getUUID());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package studio.fantasyit.maid_useful_task.vehicle.broom;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.api.entity.IBroomControl;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.item.EntityBroom;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
|
||||
|
||||
public class BroomController implements IBroomControl {
|
||||
private final EntityBroom broom;
|
||||
|
||||
public BroomController(EntityBroom broom) {
|
||||
this.broom = broom;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getPriority() {
|
||||
return 10;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inControl(Player player, EntityMaid entityMaid) {
|
||||
return BroomControlParamStore.getControlParam(entityMaid).type() != MaidVehicleControlType.NONE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void travel(Player player, EntityMaid entityMaid) {
|
||||
BroomControlParamStore.BroomControlParam param = BroomControlParamStore.getControlParam(entityMaid);
|
||||
|
||||
float forward = 0;
|
||||
float strafe = 0;
|
||||
float vertical = param.vertical();
|
||||
if (param.type() == MaidVehicleControlType.FULL) {
|
||||
forward = param.forward() / 15.0f;
|
||||
} else {
|
||||
boolean keyForward = player.zza > 0;
|
||||
boolean keyBack = player.zza < 0;
|
||||
boolean keyLeft = player.xxa > 0;
|
||||
boolean keyRight = player.xxa < 0;
|
||||
|
||||
if (keyForward || keyBack || keyLeft || keyRight) {
|
||||
strafe = keyLeft ? 0.2f : (keyRight ? -0.2f : 0);
|
||||
forward = keyForward ? 0.375f : (keyBack ? -0.2f : 0);
|
||||
} else {
|
||||
vertical = 0;
|
||||
}
|
||||
}
|
||||
//来自PlayerBroomControl
|
||||
double playerSpeed = player.getAttributeValue(Attributes.MOVEMENT_SPEED);
|
||||
double speed = Math.max(playerSpeed - 0.1, 0) * 2.5 + 0.1;
|
||||
Vec3 targetMotion = new Vec3(strafe, vertical, forward).scale(speed * 20);
|
||||
targetMotion = targetMotion.yRot((float) (-broom.getYRot() * Math.PI / 180.0));
|
||||
|
||||
// 插值到目标速度,而不是直接累加
|
||||
Vec3 currentMotion = broom.getDeltaMovement();
|
||||
Vec3 newMotion = currentMotion.lerp(targetMotion, 0.25f);
|
||||
broom.setDeltaMovement(newMotion);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void tickRot(Player player, EntityMaid entityMaid) {
|
||||
BroomControlParamStore.BroomControlParam param = BroomControlParamStore.getControlParam(entityMaid);
|
||||
|
||||
broom.yRotO = broom.yBodyRot = broom.yHeadRot = broom.getYRot();
|
||||
broom.setRot(param.yRot(), param.xRot());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
package studio.fantasyit.maid_useful_task.vehicle.broom;
|
||||
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.item.EntityBroom;
|
||||
import com.github.tartaricacid.touhoulittlemaid.entity.passive.EntityMaid;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import studio.fantasyit.maid_useful_task.util.RotUtil;
|
||||
import studio.fantasyit.maid_useful_task.vehicle.AbstractMaidControllableVehicle;
|
||||
import studio.fantasyit.maid_useful_task.vehicle.MaidVehicleControlType;
|
||||
|
||||
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) {
|
||||
BroomControlParamStore.removeControlParam(maid);
|
||||
return;
|
||||
}
|
||||
double xzDistance = maid.distanceToSqr(target.getX(), maid.getY(), target.getZ());
|
||||
double finalXRot = vehicle.getXRot();
|
||||
double finalYRot = vehicle.getYRot();
|
||||
double finalVertical = 0;
|
||||
double finalForward;
|
||||
if (vehicle.isInWater()) {
|
||||
finalXRot = 0;
|
||||
finalVertical = 0.1;
|
||||
} else if (xzDistance < Math.pow(maid.getY() - maid.level().getSeaLevel(), 2)) {
|
||||
finalXRot = 0;
|
||||
if (maid.getY() - maid.level().getSeaLevel() < 50 || vehicle.onGround()) {
|
||||
finalXRot = 5;
|
||||
finalVertical = -0.2;
|
||||
} else {
|
||||
finalXRot = 50;
|
||||
finalVertical = -0.35;
|
||||
}
|
||||
} else if (maid.getY() < 100) {
|
||||
finalXRot = -50;
|
||||
finalVertical = 0.2;
|
||||
} else if (maid.getY() > 160) {
|
||||
finalXRot = 0;
|
||||
finalVertical = -0.1;
|
||||
} else {
|
||||
finalXRot = 0;
|
||||
finalVertical = 0.05;
|
||||
}
|
||||
|
||||
finalYRot = RotUtil.getYRot(maid.position(), target.getCenter());
|
||||
|
||||
finalForward = type == MaidVehicleControlType.FULL ? 3.0 : 0;
|
||||
if (xzDistance < 5 * 5)
|
||||
finalForward = 0;
|
||||
|
||||
BroomControlParamStore.setControlParam(maid, new BroomControlParamStore.BroomControlParam((float) finalXRot, (float) finalYRot, (float) finalVertical, (float) finalForward, type));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void maidStopControlVehicle(EntityMaid maid) {
|
||||
BroomControlParamStore.removeControlParam(maid);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void syncVehicleParameter(EntityMaid maid, CompoundTag tag) {
|
||||
BroomControlParamStore.BroomControlParam broomControlParam = BroomControlParamStore.BroomControlParam.fromNbt(tag);
|
||||
BroomControlParamStore.setControlParam(maid, broomControlParam);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable CompoundTag getSyncVehicleParameter(EntityMaid maid) {
|
||||
return BroomControlParamStore.getControlParam(maid).toNbt();
|
||||
}
|
||||
}
|
||||
@@ -67,7 +67,7 @@ description='''${mod_description}'''
|
||||
[[dependencies."${mod_id}"]]
|
||||
modId="touhou_little_maid"
|
||||
mandatory=true
|
||||
versionRange="[1.2.2,)"
|
||||
versionRange="[1.3.7,)"
|
||||
ordering="AFTER"
|
||||
side="BOTH"
|
||||
[[dependencies."${mod_id}"]]
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
"FollowMaidMixin",
|
||||
"MaidCheckPickupItem",
|
||||
"MaidMoveControlMixin",
|
||||
"MaidRunOneMixin",
|
||||
"VehicleBroomMixin"
|
||||
"MaidRunOneMixin"
|
||||
],
|
||||
"client": [
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user