Начинающий
Начинающий
- Статус
- Оффлайн
- Регистрация
- 26 Янв 2026
- Сообщения
- 12
- Реакции
- 1
Всем привет, хотел бы спросить экспертов как можно улучшить этот криперфарм.
package rich.modules.impl.player;
import antidaunleak.api.annotation.Native;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.CactusBlock;
import net.minecraft.block.FireBlock;
import net.minecraft.block.MagmaBlock;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.CreeperEntity;
import net.minecraft.item.Items;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import rich.events.api.EventHandler;
import rich.events.impl.InputEvent;
import rich.events.impl.TickEvent;
import rich.modules.impl.combat.aura.Angle;
import rich.modules.impl.combat.aura.AngleConfig;
import rich.modules.impl.combat.aura.AngleConnection;
import rich.modules.module.ModuleStructure;
import rich.modules.module.category.ModuleCategory;
import rich.modules.module.setting.implement.BooleanSetting;
import rich.modules.module.setting.implement.SliderSettings;
import rich.util.math.MathUtils;
import rich.util.math.TaskPriority;
import rich.util.string.chat.ChatMessage;
import rich.util.timer.StopWatch;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@FieldDefaults(level = AccessLevel.PRIVATE)
public class CreeperFarm extends ModuleStructure {
private final BooleanSetting useZone;
private final SliderSettings attackRange;
private final SliderSettings retreatDuration;
private final SliderSettings lootRange;
private final BooleanSetting autoJump;
private final BooleanSetting alwaysSprint;
private final BooleanSetting collectGunpowder;
private final BooleanSetting avoidIgnited;
private static BlockPos pos1 = null;
private static BlockPos pos2 = null;
private static final String CONFIG_FILE = "rich/config/creeperfarm.txt";
private enum State { IDLE, APPROACH, ATTACK, RETREAT, COLLECT, PATROL }
private State currentState = State.PATROL;
private LivingEntity target;
private Vec3d moveTarget;
private ItemEntity lootTarget;
private BlockPos[] patrolPoints;
private int patrolIndex = 0;
private int stuckTicks = 0;
private Vec3d lastPos;
private float stuckOffset = 0f;
private int collectTicks = 0;
private final StopWatch attackTimer = new StopWatch();
private final StopWatch jumpTimer = new StopWatch();
public CreeperFarm() {
super("CreeperFarm", "Imba Creeper Farm (Celestial-like)", ModuleCategory.MISC);
useZone = new BooleanSetting("Использовать зону", "Only farm creepers in defined zone");
useZone.setValue(true);
attackRange = new SliderSettings("Дистанция атаки", "Attack range");
attackRange.range(2.5f, 4.5f).setValue(3.3f);
retreatDuration = new SliderSettings("Время отхода (тики)", "How many ticks to retreat");
retreatDuration.range(15, 50).setValue(25);
lootRange = new SliderSettings("Дист. лута", "Gunpowder collect range");
lootRange.range(10f, 50f).setValue(32f);
autoJump = new BooleanSetting("Авто-прыжок", "Constantly jump for speed");
autoJump.setValue(true);
alwaysSprint = new BooleanSetting("Всегда спринт", "Always sprint");
alwaysSprint.setValue(true);
collectGunpowder = new BooleanSetting("Собирать порох", "Collect gunpowder");
collectGunpowder.setValue(true);
avoidIgnited = new BooleanSetting("Избегать горящих", "Run away from ignited creepers");
avoidIgnited.setValue(true);
settings(useZone, attackRange, retreatDuration, lootRange, autoJump, alwaysSprint, collectGunpowder, avoidIgnited);
loadZone();
}
public static void setPos1() {
if (mc.player != null) {
pos1 = mc.player.getBlockPos();
saveZone();
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Первая точка установлена").formatted(Formatting.GREEN), false);
}
}
public static void setPos2() {
if (mc.player != null) {
pos2 = mc.player.getBlockPos();
saveZone();
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Вторая точка установлена").formatted(Formatting.GREEN), false);
}
}
public static void clearZone() {
pos1 = null;
pos2 = null;
saveZone();
if (mc.player != null)
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Зона очищена").formatted(Formatting.GREEN), false);
}
public static void showZone() {
if (pos1 == null || pos2 == null) {
if (mc.player != null)
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Зона не полностью определена").formatted(Formatting.RED), false);
return;
}
if (mc.player != null)
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" §6Зона: §f" + pos1.toShortString() + " §8-> §f" + pos2.toShortString()).formatted(Formatting.RESET), false);
}
private static void saveZone() {
try {
Path path = Paths.get(CONFIG_FILE);
Files.createDirectories(path.getParent());
String content = (pos1 == null ? "null" : pos1.getX() + "," + pos1.getY() + "," + pos1.getZ()) + "\n" +
(pos2 == null ? "null" : pos2.getX() + "," + pos2.getY() + "," + pos2.getZ());
Files.writeString(path, content);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void loadZone() {
try {
Path path = Paths.get(CONFIG_FILE);
if (Files.exists(path)) {
List<String> lines = Files.readAllLines(path);
if (lines.size() >= 2) {
String line1 = lines.get(0);
String line2 = lines.get(1);
if (!"null".equals(line1)) {
String[] parts = line1.split(",");
pos1 = new BlockPos(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
}
if (!"null".equals(line2)) {
String[] parts = line2.split(",");
pos2 = new BlockPos(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isInZone(Entity entity) {
if (!useZone.isValue() || pos1 == null || pos2 == null) return true;
int minX = Math.min(pos1.getX(), pos2.getX());
int minY = Math.min(pos1.getY(), pos2.getY());
int minZ = Math.min(pos1.getZ(), pos2.getZ());
int maxX = Math.max(pos1.getX(), pos2.getX());
int maxY = Math.max(pos1.getY(), pos2.getY());
int maxZ = Math.max(pos1.getZ(), pos2.getZ());
return entity.getX() >= minX && entity.getX() <= maxX &&
entity.getY() >= minY && entity.getY() <= maxY &&
entity.getZ() >= minZ && entity.getZ() <= maxZ;
}
private void buildPatrolPoints() {
if (pos1 == null || pos2 == null) return;
int minX = Math.min(pos1.getX(), pos2.getX());
int maxX = Math.max(pos1.getX(), pos2.getX());
int minZ = Math.min(pos1.getZ(), pos2.getZ());
int maxZ = Math.max(pos1.getZ(), pos2.getZ());
int minY = Math.min(pos1.getY(), pos2.getY());
int maxY = Math.max(pos1.getY(), pos2.getY());
int playerY = mc.player.getBlockPos().getY();
patrolPoints = new BlockPos[]{
new BlockPos(minX, playerY, minZ),
new BlockPos(maxX, playerY, minZ),
new BlockPos(maxX, playerY, maxZ),
new BlockPos(minX, playerY, maxZ),
new BlockPos(minX, minY, minZ),
new BlockPos(maxX, maxY, maxZ)
};
}
private boolean isWalkableBlock(BlockPos pos) {
if (mc.world == null) return false;
BlockState state = mc.world.getBlockState(pos);
if (state.isAir()) return true;
Block block = state.getBlock();
return block instanceof SlabBlock || block instanceof StairsBlock;
}
private boolean isDangerousBlock(Vec3d pos) {
if (mc.world == null) return true;
BlockPos footPos = BlockPos.ofFloored(pos.x, pos.y, pos.z);
if (!isWalkableBlock(footPos)) return true;
BlockPos headPos = footPos.up();
if (!mc.world.getBlockState(headPos).isAir()) return true;
Block footBlock = mc.world.getBlockState(footPos).getBlock();
return footBlock instanceof CactusBlock || footBlock instanceof MagmaBlock || footBlock instanceof FireBlock;
}
private float findBestYaw(Vec3d playerPos, float desiredYaw) {
float bestYaw = desiredYaw;
float bestScore = Float.NEGATIVE_INFINITY;
for (int offset = -180; offset <= 180; offset += 10) {
float testYaw = wrapDegrees(desiredYaw + offset);
double rad = Math.toRadians(testYaw + 90);
Vec3d dir = new Vec3d(Math.cos(rad), 0, Math.sin(rad)).normalize();
boolean blocked = false;
int danger = 0;
for (double d = 0.5; d <= 8.0; d += 0.5) {
if (isDangerousBlock(playerPos.add(dir.multiply(d)))) {
blocked = true;
danger++;
if (danger > 3) break;
}
}
float diff = Math.abs(wrapDegrees(testYaw - desiredYaw));
float score = 1000 - diff * 1.2f - danger * 150f - (diff > 90 ? 400 : 0);
if (blocked) score -= 800;
if (score > bestScore) {
bestScore = score;
bestYaw = testYaw;
}
}
return bestYaw;
}
@EventHandler
@Native(type = Native.Type.VMProtectBeginUltra)
public void onTick(TickEvent event) {
if (mc.player == null || mc.world == null) return;
if (useZone.isValue() && (pos1 == null || pos2 == null)) return;
Vec3d cur = mc.player.getEntityPos();
if (lastPos != null) {
double moved = cur.distanceTo(lastPos);
if (moved < 0.05 && currentState != State.ATTACK && currentState != State.COLLECT) {
stuckTicks++;
if (stuckTicks > 15) {
stuckOffset = MathUtils.getRandom(-70f, 70f);
mc.options.jumpKey.setPressed(true);
}
if (stuckTicks > 30) {
stuckOffset += 180f;
mc.options.jumpKey.setPressed(true);
}
} else {
stuckTicks = 0;
stuckOffset = 0f;
}
}
lastPos = cur;
CreeperEntity exploding = findExplodingCreeper();
if (exploding != null && avoidIgnited.isValue()) {
Vec3d away = cur.subtract(exploding.getEntityPos()).normalize().multiply(15.0);
moveTarget = cur.add(away);
currentState = State.RETREAT;
lookAt(moveTarget);
return;
}
lootTarget = findSafeLoot();
if (lootTarget != null && collectGunpowder.isValue() && currentState != State.COLLECT) {
moveTarget = lootTarget.getEntityPos();
currentState = State.COLLECT;
collectTicks = 0;
lookAt(moveTarget);
return;
}
if (currentState == State.COLLECT) {
collectTicks++;
if (collectTicks > 40 || !lootTarget.isAlive() || mc.player.distanceTo(lootTarget) < 1.5) {
lootTarget = null;
currentState = State.PATROL;
}
lookAt(moveTarget);
return;
}
target = findClosestCreeper();
if (target != null) {
double dist = mc.player.distanceTo(target);
if (((CreeperEntity) target).isIgnited()) {
Vec3d away = cur.subtract(target.getEntityPos()).normalize().multiply(12.0);
moveTarget = cur.add(away);
currentState = State.RETREAT;
return;
}
Angle rot = calculateRotation(target);
AngleConnection.INSTANCE.rotateTo(rot, AngleConfig.DEFAULT, TaskPriority.HIGH_IMPORTANCE_1, this);
if (dist <= attackRange.getValue()) {
currentState = State.ATTACK;
moveTarget = null;
if (attackTimer.finished(400)) {
mc.interactionManager.attackEntity(mc.player, target);
mc.player.swingHand(Hand.MAIN_HAND);
attackTimer.reset();
Vec3d away = cur.subtract(target.getEntityPos()).normalize().multiply(10.0);
moveTarget = cur.add(away);
currentState = State.RETREAT;
}
} else {
currentState = State.APPROACH;
moveTarget = target.getEntityPos();
}
return;
}
if (patrolPoints == null) buildPatrolPoints();
if (patrolPoints != null) {
currentState = State.PATROL;
BlockPos pt = patrolPoints[patrolIndex];
Vec3d ptVec = new Vec3d(pt.getX() + 0.5, pt.getY(), pt.getZ() + 0.5);
double dist = cur.distanceTo(ptVec);
if (dist < 2.0) {
patrolIndex = (patrolIndex + 1) % patrolPoints.length;
}
moveTarget = ptVec;
lookAt(moveTarget);
} else {
currentState = State.IDLE;
}
}
@EventHandler
@Native(type = Native.Type.VMProtectBeginUltra)
public void onInput(InputEvent event) {
if (mc.player == null) return;
if (useZone.isValue() && (pos1 == null || pos2 == null)) return;
boolean jump = event.getInput().jump();
if (autoJump.isValue() && jumpTimer.finished(800)) {
jump = true;
jumpTimer.reset();
}
if (alwaysSprint.isValue()) event.setSprinting(true);
if (currentState == State.ATTACK) {
event.setDirectional(false, false, false, false, false, false, jump);
return;
}
if (moveTarget == null) {
event.setJumping(jump);
return;
}
Vec3d p = mc.player.getEntityPos();
double dx = moveTarget.x - p.x, dz = moveTarget.z - p.z;
double dist = Math.sqrt(dx * dx + dz * dz);
if (dist < 1.5) {
event.setDirectional(false, false, false, false, false, false, jump);
return;
}
float desired = (float) (Math.toDegrees(Math.atan2(dz, dx)) - 90f);
float bestYaw = findBestYaw(p, desired);
float diff = wrapDegrees(bestYaw - mc.player.getYaw() + stuckOffset);
boolean forward = Math.abs(diff) < 67.5f;
boolean backward = Math.abs(diff) > 112.5f;
boolean left = diff < -22.5f && diff > -157.5f;
boolean right = diff > 22.5f && diff < 157.5f;
event.setDirectional(forward, backward, left, right, false, true, jump);
}
private CreeperEntity findExplodingCreeper() {
Vec3d p = mc.player.getEntityPos();
double r = 10.0;
Box b = new Box(p.x - r, p.y - r, p.z - r, p.x + r, p.y + r, p.z + r);
for (Entity e : mc.world.getEntities()) {
if (e instanceof CreeperEntity c && c.isAlive() && c.isIgnited() && isInZone(c)) {
return c;
}
}
return null;
}
private ItemEntity findSafeLoot() {
Vec3d p = mc.player.getEntityPos();
double r = lootRange.getValue();
Box b = new Box(p.x - r, p.y - r, p.z - r, p.x + r, p.y + r, p.z + r);
ItemEntity best = null;
double bd = Double.MAX_VALUE;
for (Entity e : mc.world.getEntities()) {
if (!(e instanceof ItemEntity ie) || !ie.isAlive() || ie.getStack().getItem() != Items.GUNPOWDER || !isInZone(ie)) continue;
boolean safe = mc.world.getEntitiesByClass(CreeperEntity.class,
new Box(ie.getX() - 5, ie.getY() - 5, ie.getZ() - 5, ie.getX() + 5, ie.getY() + 5, ie.getZ() + 5),
ent -> ent.isAlive()).isEmpty();
if (!safe) continue;
double d = mc.player.distanceTo(ie);
if (d < bd) {
bd = d;
best = ie;
}
}
return best;
}
private LivingEntity findClosestCreeper() {
Vec3d p = mc.player.getEntityPos();
double r = 50.0;
Box b = new Box(p.x - r, p.y - 10, p.z - r, p.x + r, p.y + 10, p.z + r);
LivingEntity best = null;
double bd = Double.MAX_VALUE;
for (Entity e : mc.world.getEntities()) {
if (!(e instanceof CreeperEntity c) || !c.isAlive() || c.isIgnited() || !isInZone(c)) continue;
double d = mc.player.distanceTo(c);
if (d < bd) {
bd = d;
best = c;
}
}
return best;
}
private Angle calculateRotation(LivingEntity t) {
Vec3d eyes = mc.player.getEntityPos().add(0, mc.player.getEyeHeight(mc.player.getPose()), 0);
double dist = mc.player.distanceTo(t);
double ty = t.getY() + (dist < 2 ? 0.5 : t.getEyeHeight(t.getPose()));
double dx = t.getX() - eyes.x, dy = ty - eyes.y, dz = t.getZ() - eyes.z;
double h = Math.sqrt(dx*dx + dz*dz);
float yaw = (float)(Math.toDegrees(Math.atan2(dz, dx)) - 90) + MathUtils.getRandom(-2f, 2f);
float pitch = (float)(-Math.toDegrees(Math.atan2(dy, h))) + MathUtils.getRandom(-1f, 1f);
return new Angle(yaw, pitch);
}
private void lookAt(Vec3d t) {
if (t == null) return;
Vec3d eyes = mc.player.getEntityPos().add(0, mc.player.getEyeHeight(mc.player.getPose()), 0);
double dx = t.x - eyes.x, dy = t.y - eyes.y, dz = t.z - eyes.z;
double h = Math.sqrt(dx*dx + dz*dz);
float yaw = (float)(Math.toDegrees(Math.atan2(dz, dx)) - 90) + MathUtils.getRandom(-2f, 2f);
float pitch = (float)(-Math.toDegrees(Math.atan2(dy, h))) + MathUtils.getRandom(-1f, 1f);
AngleConnection.INSTANCE.rotateTo(new Angle(yaw, pitch), AngleConfig.DEFAULT, TaskPriority.HIGH_IMPORTANCE_1, this);
}
private float wrapDegrees(float deg) {
deg %= 360;
if (deg >= 180) deg -= 360;
if (deg < -180) deg += 360;
return deg;
}
@override
public void activate() {
buildPatrolPoints();
patrolIndex = 0;
currentState = State.PATROL;
target = null;
lootTarget = null;
moveTarget = null;
lastPos = null;
stuckTicks = 0;
stuckOffset = 0f;
attackTimer.reset();
jumpTimer.reset();
if (useZone.isValue() && (pos1 == null || pos2 == null)) {
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" §cЗона не задана!").formatted(Formatting.RED), false);
}
super.activate();
}
@override
public void deactivate() {
target = null;
lootTarget = null;
moveTarget = null;
if (mc.options != null) mc.options.jumpKey.setPressed(false);
super.deactivate();
}
}
package rich.modules.impl.player;
import antidaunleak.api.annotation.Native;
import lombok.AccessLevel;
import lombok.experimental.FieldDefaults;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.CactusBlock;
import net.minecraft.block.FireBlock;
import net.minecraft.block.MagmaBlock;
import net.minecraft.block.SlabBlock;
import net.minecraft.block.StairsBlock;
import net.minecraft.entity.Entity;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.mob.CreeperEntity;
import net.minecraft.item.Items;
import net.minecraft.util.Formatting;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Box;
import net.minecraft.util.math.Vec3d;
import rich.events.api.EventHandler;
import rich.events.impl.InputEvent;
import rich.events.impl.TickEvent;
import rich.modules.impl.combat.aura.Angle;
import rich.modules.impl.combat.aura.AngleConfig;
import rich.modules.impl.combat.aura.AngleConnection;
import rich.modules.module.ModuleStructure;
import rich.modules.module.category.ModuleCategory;
import rich.modules.module.setting.implement.BooleanSetting;
import rich.modules.module.setting.implement.SliderSettings;
import rich.util.math.MathUtils;
import rich.util.math.TaskPriority;
import rich.util.string.chat.ChatMessage;
import rich.util.timer.StopWatch;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@FieldDefaults(level = AccessLevel.PRIVATE)
public class CreeperFarm extends ModuleStructure {
private final BooleanSetting useZone;
private final SliderSettings attackRange;
private final SliderSettings retreatDuration;
private final SliderSettings lootRange;
private final BooleanSetting autoJump;
private final BooleanSetting alwaysSprint;
private final BooleanSetting collectGunpowder;
private final BooleanSetting avoidIgnited;
private static BlockPos pos1 = null;
private static BlockPos pos2 = null;
private static final String CONFIG_FILE = "rich/config/creeperfarm.txt";
private enum State { IDLE, APPROACH, ATTACK, RETREAT, COLLECT, PATROL }
private State currentState = State.PATROL;
private LivingEntity target;
private Vec3d moveTarget;
private ItemEntity lootTarget;
private BlockPos[] patrolPoints;
private int patrolIndex = 0;
private int stuckTicks = 0;
private Vec3d lastPos;
private float stuckOffset = 0f;
private int collectTicks = 0;
private final StopWatch attackTimer = new StopWatch();
private final StopWatch jumpTimer = new StopWatch();
public CreeperFarm() {
super("CreeperFarm", "Imba Creeper Farm (Celestial-like)", ModuleCategory.MISC);
useZone = new BooleanSetting("Использовать зону", "Only farm creepers in defined zone");
useZone.setValue(true);
attackRange = new SliderSettings("Дистанция атаки", "Attack range");
attackRange.range(2.5f, 4.5f).setValue(3.3f);
retreatDuration = new SliderSettings("Время отхода (тики)", "How many ticks to retreat");
retreatDuration.range(15, 50).setValue(25);
lootRange = new SliderSettings("Дист. лута", "Gunpowder collect range");
lootRange.range(10f, 50f).setValue(32f);
autoJump = new BooleanSetting("Авто-прыжок", "Constantly jump for speed");
autoJump.setValue(true);
alwaysSprint = new BooleanSetting("Всегда спринт", "Always sprint");
alwaysSprint.setValue(true);
collectGunpowder = new BooleanSetting("Собирать порох", "Collect gunpowder");
collectGunpowder.setValue(true);
avoidIgnited = new BooleanSetting("Избегать горящих", "Run away from ignited creepers");
avoidIgnited.setValue(true);
settings(useZone, attackRange, retreatDuration, lootRange, autoJump, alwaysSprint, collectGunpowder, avoidIgnited);
loadZone();
}
public static void setPos1() {
if (mc.player != null) {
pos1 = mc.player.getBlockPos();
saveZone();
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Первая точка установлена").formatted(Formatting.GREEN), false);
}
}
public static void setPos2() {
if (mc.player != null) {
pos2 = mc.player.getBlockPos();
saveZone();
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Вторая точка установлена").formatted(Formatting.GREEN), false);
}
}
public static void clearZone() {
pos1 = null;
pos2 = null;
saveZone();
if (mc.player != null)
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Зона очищена").formatted(Formatting.GREEN), false);
}
public static void showZone() {
if (pos1 == null || pos2 == null) {
if (mc.player != null)
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" -> Зона не полностью определена").formatted(Formatting.RED), false);
return;
}
if (mc.player != null)
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" §6Зона: §f" + pos1.toShortString() + " §8-> §f" + pos2.toShortString()).formatted(Formatting.RESET), false);
}
private static void saveZone() {
try {
Path path = Paths.get(CONFIG_FILE);
Files.createDirectories(path.getParent());
String content = (pos1 == null ? "null" : pos1.getX() + "," + pos1.getY() + "," + pos1.getZ()) + "\n" +
(pos2 == null ? "null" : pos2.getX() + "," + pos2.getY() + "," + pos2.getZ());
Files.writeString(path, content);
} catch (Exception e) {
e.printStackTrace();
}
}
private static void loadZone() {
try {
Path path = Paths.get(CONFIG_FILE);
if (Files.exists(path)) {
List<String> lines = Files.readAllLines(path);
if (lines.size() >= 2) {
String line1 = lines.get(0);
String line2 = lines.get(1);
if (!"null".equals(line1)) {
String[] parts = line1.split(",");
pos1 = new BlockPos(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
}
if (!"null".equals(line2)) {
String[] parts = line2.split(",");
pos2 = new BlockPos(Integer.parseInt(parts[0]), Integer.parseInt(parts[1]), Integer.parseInt(parts[2]));
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean isInZone(Entity entity) {
if (!useZone.isValue() || pos1 == null || pos2 == null) return true;
int minX = Math.min(pos1.getX(), pos2.getX());
int minY = Math.min(pos1.getY(), pos2.getY());
int minZ = Math.min(pos1.getZ(), pos2.getZ());
int maxX = Math.max(pos1.getX(), pos2.getX());
int maxY = Math.max(pos1.getY(), pos2.getY());
int maxZ = Math.max(pos1.getZ(), pos2.getZ());
return entity.getX() >= minX && entity.getX() <= maxX &&
entity.getY() >= minY && entity.getY() <= maxY &&
entity.getZ() >= minZ && entity.getZ() <= maxZ;
}
private void buildPatrolPoints() {
if (pos1 == null || pos2 == null) return;
int minX = Math.min(pos1.getX(), pos2.getX());
int maxX = Math.max(pos1.getX(), pos2.getX());
int minZ = Math.min(pos1.getZ(), pos2.getZ());
int maxZ = Math.max(pos1.getZ(), pos2.getZ());
int minY = Math.min(pos1.getY(), pos2.getY());
int maxY = Math.max(pos1.getY(), pos2.getY());
int playerY = mc.player.getBlockPos().getY();
patrolPoints = new BlockPos[]{
new BlockPos(minX, playerY, minZ),
new BlockPos(maxX, playerY, minZ),
new BlockPos(maxX, playerY, maxZ),
new BlockPos(minX, playerY, maxZ),
new BlockPos(minX, minY, minZ),
new BlockPos(maxX, maxY, maxZ)
};
}
private boolean isWalkableBlock(BlockPos pos) {
if (mc.world == null) return false;
BlockState state = mc.world.getBlockState(pos);
if (state.isAir()) return true;
Block block = state.getBlock();
return block instanceof SlabBlock || block instanceof StairsBlock;
}
private boolean isDangerousBlock(Vec3d pos) {
if (mc.world == null) return true;
BlockPos footPos = BlockPos.ofFloored(pos.x, pos.y, pos.z);
if (!isWalkableBlock(footPos)) return true;
BlockPos headPos = footPos.up();
if (!mc.world.getBlockState(headPos).isAir()) return true;
Block footBlock = mc.world.getBlockState(footPos).getBlock();
return footBlock instanceof CactusBlock || footBlock instanceof MagmaBlock || footBlock instanceof FireBlock;
}
private float findBestYaw(Vec3d playerPos, float desiredYaw) {
float bestYaw = desiredYaw;
float bestScore = Float.NEGATIVE_INFINITY;
for (int offset = -180; offset <= 180; offset += 10) {
float testYaw = wrapDegrees(desiredYaw + offset);
double rad = Math.toRadians(testYaw + 90);
Vec3d dir = new Vec3d(Math.cos(rad), 0, Math.sin(rad)).normalize();
boolean blocked = false;
int danger = 0;
for (double d = 0.5; d <= 8.0; d += 0.5) {
if (isDangerousBlock(playerPos.add(dir.multiply(d)))) {
blocked = true;
danger++;
if (danger > 3) break;
}
}
float diff = Math.abs(wrapDegrees(testYaw - desiredYaw));
float score = 1000 - diff * 1.2f - danger * 150f - (diff > 90 ? 400 : 0);
if (blocked) score -= 800;
if (score > bestScore) {
bestScore = score;
bestYaw = testYaw;
}
}
return bestYaw;
}
@EventHandler
@Native(type = Native.Type.VMProtectBeginUltra)
public void onTick(TickEvent event) {
if (mc.player == null || mc.world == null) return;
if (useZone.isValue() && (pos1 == null || pos2 == null)) return;
Vec3d cur = mc.player.getEntityPos();
if (lastPos != null) {
double moved = cur.distanceTo(lastPos);
if (moved < 0.05 && currentState != State.ATTACK && currentState != State.COLLECT) {
stuckTicks++;
if (stuckTicks > 15) {
stuckOffset = MathUtils.getRandom(-70f, 70f);
mc.options.jumpKey.setPressed(true);
}
if (stuckTicks > 30) {
stuckOffset += 180f;
mc.options.jumpKey.setPressed(true);
}
} else {
stuckTicks = 0;
stuckOffset = 0f;
}
}
lastPos = cur;
CreeperEntity exploding = findExplodingCreeper();
if (exploding != null && avoidIgnited.isValue()) {
Vec3d away = cur.subtract(exploding.getEntityPos()).normalize().multiply(15.0);
moveTarget = cur.add(away);
currentState = State.RETREAT;
lookAt(moveTarget);
return;
}
lootTarget = findSafeLoot();
if (lootTarget != null && collectGunpowder.isValue() && currentState != State.COLLECT) {
moveTarget = lootTarget.getEntityPos();
currentState = State.COLLECT;
collectTicks = 0;
lookAt(moveTarget);
return;
}
if (currentState == State.COLLECT) {
collectTicks++;
if (collectTicks > 40 || !lootTarget.isAlive() || mc.player.distanceTo(lootTarget) < 1.5) {
lootTarget = null;
currentState = State.PATROL;
}
lookAt(moveTarget);
return;
}
target = findClosestCreeper();
if (target != null) {
double dist = mc.player.distanceTo(target);
if (((CreeperEntity) target).isIgnited()) {
Vec3d away = cur.subtract(target.getEntityPos()).normalize().multiply(12.0);
moveTarget = cur.add(away);
currentState = State.RETREAT;
return;
}
Angle rot = calculateRotation(target);
AngleConnection.INSTANCE.rotateTo(rot, AngleConfig.DEFAULT, TaskPriority.HIGH_IMPORTANCE_1, this);
if (dist <= attackRange.getValue()) {
currentState = State.ATTACK;
moveTarget = null;
if (attackTimer.finished(400)) {
mc.interactionManager.attackEntity(mc.player, target);
mc.player.swingHand(Hand.MAIN_HAND);
attackTimer.reset();
Vec3d away = cur.subtract(target.getEntityPos()).normalize().multiply(10.0);
moveTarget = cur.add(away);
currentState = State.RETREAT;
}
} else {
currentState = State.APPROACH;
moveTarget = target.getEntityPos();
}
return;
}
if (patrolPoints == null) buildPatrolPoints();
if (patrolPoints != null) {
currentState = State.PATROL;
BlockPos pt = patrolPoints[patrolIndex];
Vec3d ptVec = new Vec3d(pt.getX() + 0.5, pt.getY(), pt.getZ() + 0.5);
double dist = cur.distanceTo(ptVec);
if (dist < 2.0) {
patrolIndex = (patrolIndex + 1) % patrolPoints.length;
}
moveTarget = ptVec;
lookAt(moveTarget);
} else {
currentState = State.IDLE;
}
}
@EventHandler
@Native(type = Native.Type.VMProtectBeginUltra)
public void onInput(InputEvent event) {
if (mc.player == null) return;
if (useZone.isValue() && (pos1 == null || pos2 == null)) return;
boolean jump = event.getInput().jump();
if (autoJump.isValue() && jumpTimer.finished(800)) {
jump = true;
jumpTimer.reset();
}
if (alwaysSprint.isValue()) event.setSprinting(true);
if (currentState == State.ATTACK) {
event.setDirectional(false, false, false, false, false, false, jump);
return;
}
if (moveTarget == null) {
event.setJumping(jump);
return;
}
Vec3d p = mc.player.getEntityPos();
double dx = moveTarget.x - p.x, dz = moveTarget.z - p.z;
double dist = Math.sqrt(dx * dx + dz * dz);
if (dist < 1.5) {
event.setDirectional(false, false, false, false, false, false, jump);
return;
}
float desired = (float) (Math.toDegrees(Math.atan2(dz, dx)) - 90f);
float bestYaw = findBestYaw(p, desired);
float diff = wrapDegrees(bestYaw - mc.player.getYaw() + stuckOffset);
boolean forward = Math.abs(diff) < 67.5f;
boolean backward = Math.abs(diff) > 112.5f;
boolean left = diff < -22.5f && diff > -157.5f;
boolean right = diff > 22.5f && diff < 157.5f;
event.setDirectional(forward, backward, left, right, false, true, jump);
}
private CreeperEntity findExplodingCreeper() {
Vec3d p = mc.player.getEntityPos();
double r = 10.0;
Box b = new Box(p.x - r, p.y - r, p.z - r, p.x + r, p.y + r, p.z + r);
for (Entity e : mc.world.getEntities()) {
if (e instanceof CreeperEntity c && c.isAlive() && c.isIgnited() && isInZone(c)) {
return c;
}
}
return null;
}
private ItemEntity findSafeLoot() {
Vec3d p = mc.player.getEntityPos();
double r = lootRange.getValue();
Box b = new Box(p.x - r, p.y - r, p.z - r, p.x + r, p.y + r, p.z + r);
ItemEntity best = null;
double bd = Double.MAX_VALUE;
for (Entity e : mc.world.getEntities()) {
if (!(e instanceof ItemEntity ie) || !ie.isAlive() || ie.getStack().getItem() != Items.GUNPOWDER || !isInZone(ie)) continue;
boolean safe = mc.world.getEntitiesByClass(CreeperEntity.class,
new Box(ie.getX() - 5, ie.getY() - 5, ie.getZ() - 5, ie.getX() + 5, ie.getY() + 5, ie.getZ() + 5),
ent -> ent.isAlive()).isEmpty();
if (!safe) continue;
double d = mc.player.distanceTo(ie);
if (d < bd) {
bd = d;
best = ie;
}
}
return best;
}
private LivingEntity findClosestCreeper() {
Vec3d p = mc.player.getEntityPos();
double r = 50.0;
Box b = new Box(p.x - r, p.y - 10, p.z - r, p.x + r, p.y + 10, p.z + r);
LivingEntity best = null;
double bd = Double.MAX_VALUE;
for (Entity e : mc.world.getEntities()) {
if (!(e instanceof CreeperEntity c) || !c.isAlive() || c.isIgnited() || !isInZone(c)) continue;
double d = mc.player.distanceTo(c);
if (d < bd) {
bd = d;
best = c;
}
}
return best;
}
private Angle calculateRotation(LivingEntity t) {
Vec3d eyes = mc.player.getEntityPos().add(0, mc.player.getEyeHeight(mc.player.getPose()), 0);
double dist = mc.player.distanceTo(t);
double ty = t.getY() + (dist < 2 ? 0.5 : t.getEyeHeight(t.getPose()));
double dx = t.getX() - eyes.x, dy = ty - eyes.y, dz = t.getZ() - eyes.z;
double h = Math.sqrt(dx*dx + dz*dz);
float yaw = (float)(Math.toDegrees(Math.atan2(dz, dx)) - 90) + MathUtils.getRandom(-2f, 2f);
float pitch = (float)(-Math.toDegrees(Math.atan2(dy, h))) + MathUtils.getRandom(-1f, 1f);
return new Angle(yaw, pitch);
}
private void lookAt(Vec3d t) {
if (t == null) return;
Vec3d eyes = mc.player.getEntityPos().add(0, mc.player.getEyeHeight(mc.player.getPose()), 0);
double dx = t.x - eyes.x, dy = t.y - eyes.y, dz = t.z - eyes.z;
double h = Math.sqrt(dx*dx + dz*dz);
float yaw = (float)(Math.toDegrees(Math.atan2(dz, dx)) - 90) + MathUtils.getRandom(-2f, 2f);
float pitch = (float)(-Math.toDegrees(Math.atan2(dy, h))) + MathUtils.getRandom(-1f, 1f);
AngleConnection.INSTANCE.rotateTo(new Angle(yaw, pitch), AngleConfig.DEFAULT, TaskPriority.HIGH_IMPORTANCE_1, this);
}
private float wrapDegrees(float deg) {
deg %= 360;
if (deg >= 180) deg -= 360;
if (deg < -180) deg += 360;
return deg;
}
@override
public void activate() {
buildPatrolPoints();
patrolIndex = 0;
currentState = State.PATROL;
target = null;
lootTarget = null;
moveTarget = null;
lastPos = null;
stuckTicks = 0;
stuckOffset = 0f;
attackTimer.reset();
jumpTimer.reset();
if (useZone.isValue() && (pos1 == null || pos2 == null)) {
mc.player.sendMessage(ChatMessage.brandmessage().copy().append(" §cЗона не задана!").formatted(Formatting.RED), false);
}
super.activate();
}
@override
public void deactivate() {
target = null;
lootTarget = null;
moveTarget = null;
if (mc.options != null) mc.options.jumpKey.setPressed(false);
super.deactivate();
}
}