首次提交 AutoDig Mod
这个提交包含在:
@@ -0,0 +1,95 @@
|
||||
package autodig.client.service;
|
||||
|
||||
import autodig.client.config.DigConfig;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.LivingEntity;
|
||||
import net.minecraft.entity.mob.Monster;
|
||||
import net.minecraft.util.math.Box;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
* 杀戮光环服务。
|
||||
*
|
||||
* <p>在开关开启时,自动攻击以玩家为中心、指定半径内最近的敌对生物
|
||||
* ({@link Monster})。攻击前会转向目标方向;"安全模式"开启时,
|
||||
* 玩家生命过低则停止攻击、保命优先。</p>
|
||||
*/
|
||||
public final class KillAura {
|
||||
|
||||
/** 攻击节流:每 N tick 才允许挥一刀,避免疯狂连点 */
|
||||
private int attackCooldownTicks;
|
||||
|
||||
/**
|
||||
* 每帧调用。执行杀戮光环逻辑(开关关闭时直接返回)。
|
||||
*
|
||||
* @param config 挖矿配置
|
||||
*/
|
||||
public void tick(DigConfig config) {
|
||||
MinecraftClient client = MinecraftClient.getInstance();
|
||||
if (client.player == null || client.world == null || client.interactionManager == null) {
|
||||
return;
|
||||
}
|
||||
if (!config.killAura) {
|
||||
return;
|
||||
}
|
||||
net.minecraft.entity.player.PlayerEntity player = client.player;
|
||||
if (player.isDead()) {
|
||||
return;
|
||||
}
|
||||
// 安全模式:血线过低不出击
|
||||
if (config.killAuraSafe) {
|
||||
double health = player.getHealth() / Math.max(player.getMaxHealth(), 1.0) * 100.0;
|
||||
if (health < config.healthFleeThreshold) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 挥刀节流
|
||||
if (this.attackCooldownTicks > 0) {
|
||||
this.attackCooldownTicks--;
|
||||
return;
|
||||
}
|
||||
// 攻击冷却未转好则等待
|
||||
if (player.getAttackCooldownProgress(0.5f) < 1.0f) {
|
||||
return;
|
||||
}
|
||||
Entity target = this.findNearestHostile(client, player, config.killRange);
|
||||
if (target == null) {
|
||||
return;
|
||||
}
|
||||
// 转向目标
|
||||
this.faceEntity(player, target);
|
||||
client.interactionManager.attackEntity(player, target);
|
||||
this.attackCooldownTicks = 4; // 约 4 tick 一刀
|
||||
}
|
||||
|
||||
/** 在玩家周围范围内找最近的敌对生物。 */
|
||||
private Entity findNearestHostile(MinecraftClient client, LivingEntity player, double range) {
|
||||
range = Math.max(2.0, range);
|
||||
Box box = player.getBoundingBox().expand(range);
|
||||
Entity best = null;
|
||||
double bestDist = Double.MAX_VALUE;
|
||||
for (Entity e : client.world.getEntitiesByClass(Entity.class, box, e -> e instanceof Monster && e.isAlive())) {
|
||||
double d = e.squaredDistanceTo(player);
|
||||
if (d < bestDist) {
|
||||
bestDist = d;
|
||||
best = e;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/** 让玩家面朝向实体。 */
|
||||
private void faceEntity(LivingEntity player, Entity target) {
|
||||
Vec3d p = player.getEyePos();
|
||||
Vec3d t = target.getEyePos();
|
||||
double dx = t.x - p.x;
|
||||
double dy = t.y - p.y;
|
||||
double dz = t.z - p.z;
|
||||
double d = Math.sqrt(dx * dx + dz * dz);
|
||||
float yaw = (float) (Math.toDegrees(Math.atan2(dz, dx)) - 90.0);
|
||||
float pitch = (float) (-Math.toDegrees(Math.atan2(dy, Math.max(d, 0.0001))));
|
||||
player.setYaw(yaw);
|
||||
player.setPitch(pitch);
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户