9
0
mirror of https://github.com/LeavesMC/Leaves.git synced 2025-12-28 11:29:12 +00:00

Bot Improvements (#661)

* refactor: redesign bot use action

* fix: fix happy ghost and horse control

* fix: fix bot control boat

* fix: fix bot control vehicle

* fix: fix bot boat falling

* fix: fix comment and inline some vars

* fix: fix format and migrate use action nbt data
This commit is contained in:
MC_XiaoHei
2025-08-08 19:45:23 +08:00
committed by GitHub
parent e05f3f7c6a
commit 0c8662816d
14 changed files with 423 additions and 639 deletions

View File

@@ -32,8 +32,10 @@ import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.PositionMoveRotation;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.entity.player.Input;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.projectile.ProjectileUtil;
import net.minecraft.world.entity.vehicle.AbstractBoat;
import net.minecraft.world.inventory.ChestMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.GameRules;
@@ -83,6 +85,7 @@ public class ServerBot extends ServerPlayer {
public boolean resume = false;
public BotCreateState createState;
public UUID createPlayer;
public boolean handsBusy = false;
private final int tracingRange;
private final BotStatsCounter stats;
@@ -152,6 +155,19 @@ public class ServerBot extends ServerPlayer {
if (this.getConfigValue(Configs.TICK_TYPE) == TickType.ENTITY_LIST) {
this.doTick();
}
Input input = this.getLastClientInput();
this.setLastClientInput(
new Input(
this.zza > 0,
this.zza < 0,
this.xxa > 0,
this.xxa < 0,
input.jump(),
input.shift(),
input.sprint()
)
);
}
@Override
@@ -229,6 +245,23 @@ public class ServerBot extends ServerPlayer {
return true;
}
@Override
public void removeVehicle() {
super.removeVehicle();
this.handsBusy = false;
}
@Override
public void rideTick() {
super.rideTick();
this.handsBusy = false;
if (this.getControlledVehicle() instanceof AbstractBoat abstractBoat) {
Input input = this.getLastClientInput();
abstractBoat.setInput(input.left(), input.right(), input.forward(), input.backward());
this.handsBusy = this.handsBusy | (input.left() || input.right() || input.forward() || input.backward());
}
}
@Override
public @Nullable ServerBot teleport(@NotNull TeleportTransition teleportTransition) {
if (this.isSleeping() || this.isRemoved()) {

View File

@@ -76,13 +76,13 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
event.callEvent();
if (event.getResult() == BotActionExecuteEvent.Result.SOFT_CANCEL) {
this.tickToNext = this.getDoIntervalTick() - 1;
this.tickToNext = this.getDoIntervalTick();
return;
} else if (event.getResult() == BotActionExecuteEvent.Result.HARD_CANCEL) {
if (this.numberRemaining > 0) {
this.numberRemaining--;
}
this.tickToNext = this.getDoIntervalTick() - 1;
this.tickToNext = this.getDoIntervalTick();
return;
}
@@ -90,7 +90,7 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
if (this.numberRemaining > 0) {
this.numberRemaining--;
}
this.tickToNext = this.getDoIntervalTick() - 1;
this.tickToNext = this.getDoIntervalTick();
if (this.onSuccess != null) {
this.onSuccess.accept((E) this);
}
@@ -178,7 +178,7 @@ public abstract class ServerBotAction<E extends ServerBotAction<E>> {
}
public void setDoIntervalTick(int initialTickInterval) {
this.initialTickInterval = Math.max(1, initialTickInterval);
this.initialTickInterval = Math.max(0, initialTickInterval);
}
public int getDoIntervalTick() {

View File

@@ -22,7 +22,7 @@ public class ServerFishAction extends ServerTimerBotAction<ServerFishAction> {
@Override
public void setDoIntervalTick(int initialTickInterval) {
super.setDoIntervalTick(1);
super.setDoIntervalTick(0);
this.initialFishInterval = initialTickInterval;
}

View File

@@ -2,6 +2,7 @@ package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.world.entity.Entity;
import org.bukkit.Location;
import org.bukkit.craftbukkit.entity.CraftEntity;
import org.bukkit.craftbukkit.entity.CraftVehicle;
import org.bukkit.entity.Vehicle;
import org.jetbrains.annotations.NotNull;
@@ -24,13 +25,13 @@ public class ServerMountAction extends ServerBotAction<ServerMountAction> {
List<Vehicle> vehicles = center.getNearbyEntitiesByType(
Vehicle.class,
3,
vehicle -> manhattanDistance(bot, ((CraftVehicle) vehicle).getHandle()) <= 2
vehicle -> manhattanDistance(bot, ((CraftEntity) vehicle).getHandle()) <= 2
).stream().sorted(Comparator.comparingDouble(
(vehicle) -> center.distanceSquared(vehicle.getLocation())
)).toList();
for (Vehicle vehicle : vehicles) {
if (bot.startRiding(((CraftVehicle) vehicle).getHandle(), false)) {
if (bot.startRiding(((CraftEntity) vehicle).getHandle(), false)) {
return true;
}
}

View File

@@ -0,0 +1,127 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionResult;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
import java.util.function.Supplier;
public abstract class ServerUseBotAction<T extends ServerUseBotAction<T>> extends ServerTimerBotAction<T> {
private int useTick = -1;
private int alreadyUsedTick = 0;
private int useItemRemainingTicks = 0;
public ServerUseBotAction(String name, Supplier<T> supplier) {
super(name, CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), supplier);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
if (shouldStartUseItem()) {
boolean isSuccess = interact(bot);
syncUseItemRemainingTicks(bot);
if (alreadyUseOver()) {
resetAlreadyUsedTick();
return isSuccess;
}
} else {
syncUseItemRemainingTicks(bot);
}
if (alreadyUseOver()) {
resetAlreadyUsedTick();
bot.completeUsingItem();
return true;
} else {
increaseAlreadyUsedTick();
if (isUseTickLimitExceeded()) {
resetAlreadyUsedTick();
shouldStartUseItemNextTick();
return bot.releaseUsingItemWithResult();
}
return false;
}
}
protected abstract boolean interact(ServerBot bot);
public static boolean shouldSwing(InteractionResult result) {
return result instanceof InteractionResult.Success success && success.swingSource() != InteractionResult.SwingSource.NONE;
}
private boolean shouldStartUseItem() {
return useItemRemainingTicks == 0;
}
private boolean alreadyUseOver() {
return useItemRemainingTicks == 0;
}
private boolean isUseTickLimitExceeded() {
int useTickLimit = useTick == -1 ? Integer.MAX_VALUE : useTick;
return alreadyUsedTick > useTickLimit;
}
private void shouldStartUseItemNextTick() {
this.useItemRemainingTicks = 0;
}
private void resetAlreadyUsedTick() {
this.alreadyUsedTick = 0;
}
private void syncUseItemRemainingTicks(@NotNull ServerBot bot) {
this.useItemRemainingTicks = bot.getUseItemRemainingTicks();
}
private void increaseAlreadyUsedTick() {
this.alreadyUsedTick++;
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
super.save(nbt);
nbt.putInt("useTick", this.useTick);
nbt.putInt("alreadyUsedTick", this.alreadyUsedTick);
return nbt;
}
@Override
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);
this.useTick = nbt.getInt("useTick").orElseThrow();
this.alreadyUsedTick = nbt.getInt("alreadyUsedTick").orElseGet(
() -> this.useTick - nbt.getInt("tickToRelease").orElseThrow()
);
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.releaseUsingItem();
}
}

View File

@@ -1,106 +1,28 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.world.InteractionResult;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
public class ServerUseItemAction extends ServerTimerBotAction<ServerUseItemAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemAction extends ServerUseBotAction<ServerUseItemAction> {
public ServerUseItemAction() {
super("use", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use", ServerUseItemAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
protected boolean interact(@NotNull ServerBot bot) {
return useItem(bot, InteractionHand.MAIN_HAND).consumesAction();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
boolean result = execute(bot);
if (useTick >= 0) {
return false;
} else {
return result;
}
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
public static @NotNull InteractionResult useItem(@NotNull ServerBot bot, InteractionHand hand) {
InteractionResult result = bot.gameMode.useItem(bot, bot.level(), bot.getItemInHand(hand), hand);
if (shouldSwing(result)) {
bot.swing(hand);
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
super.save(nbt);
nbt.putInt("useTick", this.useTick);
nbt.putInt("tickToRelease", this.tickToRelease);
return nbt;
}
@Override
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);
this.useTick = nbt.getInt("useTick").orElseThrow();
this.tickToRelease = nbt.getInt("tickToRelease").orElseThrow();
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public static boolean execute(@NotNull ServerBot bot) {
if (bot.isUsingItem()) {
return false;
}
boolean flag = bot.gameMode.useItem(bot, bot.level(), bot.getItemInHand(InteractionHand.MAIN_HAND), InteractionHand.MAIN_HAND).consumesAction();
if (flag) {
bot.swing(InteractionHand.MAIN_HAND);
bot.updateItemInHand(InteractionHand.MAIN_HAND);
}
return flag;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
return result;
}
@Override

View File

@@ -1,110 +1,86 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.EntityHitResult;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemAutoAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.getBlockHitResult;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.getEntityHitResult;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo;
public class ServerUseItemAutoAction extends ServerTimerBotAction<ServerUseItemAutoAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemAutoAction extends ServerUseBotAction<ServerUseItemAutoAction> {
public ServerUseItemAutoAction() {
super("use_auto", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemAutoAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use_auto", ServerUseItemAutoAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
boolean result = execute(bot);
if (useTick >= 0) {
protected boolean interact(ServerBot bot) {
HitResult hitResult = getHitResult(bot);
for (InteractionHand hand : InteractionHand.values()) {
ItemStack itemStack = bot.getItemInHand(hand);
if (!itemStack.isItemEnabled(bot.level().enabledFeatures())) {
return false;
} else {
return result;
}
if (hitResult != null) {
switch (hitResult.getType()) {
case ENTITY -> {
EntityHitResult entityHitResult = (EntityHitResult) hitResult;
InteractionResult entityResult = useItemTo(bot, entityHitResult, hand);
if (entityResult instanceof InteractionResult.Success) {
return true;
} else if (entityResult instanceof InteractionResult.Pass && entityHitResult.getEntity() instanceof ArmorStand) {
return false;
}
}
case BLOCK -> {
InteractionResult blockResult = useItemOn(bot, (BlockHitResult) hitResult, hand);
if (blockResult instanceof InteractionResult.Success) {
return true;
} else if (blockResult instanceof InteractionResult.Fail) {
return false;
}
}
}
}
if (!itemStack.isEmpty() && useItem(bot, hand) instanceof InteractionResult.Success) {
return true;
}
}
return false;
}
private static @Nullable HitResult getHitResult(@NotNull ServerBot bot) {
Vec3 eyePos = bot.getEyePosition();
EntityHitResult entityHitResult = getEntityHitResult(bot);
double entityDistance = entityHitResult != null ? entityHitResult.getLocation().distanceToSqr(eyePos) : Double.MAX_VALUE;
BlockHitResult blockHitResult = getBlockHitResult(bot);
double blockDistance = blockHitResult != null ? blockHitResult.getLocation().distanceToSqr(eyePos) : Double.MAX_VALUE;
if (entityDistance == Double.MAX_VALUE && blockDistance == Double.MAX_VALUE) {
return null;
} else if (entityDistance < blockDistance) {
return entityHitResult;
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
return blockHitResult;
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public boolean execute(@NotNull ServerBot bot) {
if (bot.isUsingItem()) {
return false;
}
EntityHitResult entityHitResult = bot.getEntityHitResult(3, null);
BlockHitResult blockHitResult = (BlockHitResult) bot.getRayTrace(5, ClipContext.Fluid.NONE);
boolean mainSuccess, useTo = entityHitResult != null, useOn = !bot.level().getBlockState(blockHitResult.getBlockPos()).isAir();
if (useTo) {
InteractionResult result = ServerUseItemToAction.execute(bot, entityHitResult);
mainSuccess = result.consumesAction() || (result == InteractionResult.PASS && ServerUseItemAction.execute(bot));
} else if (useOn) {
mainSuccess = ServerUseItemOnAction.execute(bot, blockHitResult) || ServerUseItemAction.execute(bot);
} else {
mainSuccess = ServerUseItemAction.execute(bot);
}
if (mainSuccess) {
return true;
}
if (useTo) {
InteractionResult result = ServerUseItemToOffhandAction.execute(bot, entityHitResult);
return result.consumesAction() || (result == InteractionResult.PASS && ServerUseItemOffhandAction.execute(bot));
} else if (useOn) {
return ServerUseItemOnOffhandAction.execute(bot, blockHitResult) || ServerUseItemOffhandAction.execute(bot);
} else {
return ServerUseItemOffhandAction.execute(bot);
}
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
}
@Override
public Object asCraft() {
return new CraftUseItemAutoAction(this);

View File

@@ -1,106 +1,21 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOffhandAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemAction.useItem;
public class ServerUseItemOffhandAction extends ServerTimerBotAction<ServerUseItemOffhandAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemOffhandAction extends ServerUseBotAction<ServerUseItemOffhandAction> {
public ServerUseItemOffhandAction() {
super("use_offhand", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemOffhandAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use_offhand", ServerUseItemOffhandAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
boolean result = execute(bot);
if (useTick >= 0) {
return false;
} else {
return result;
}
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
super.save(nbt);
nbt.putInt("useTick", this.useTick);
nbt.putInt("tickToRelease", this.tickToRelease);
return nbt;
}
@Override
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);
this.useTick = nbt.getInt("useTick").orElseThrow();
this.tickToRelease = nbt.getInt("tickToRelease").orElseThrow();
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public static boolean execute(@NotNull ServerBot bot) {
if (bot.isUsingItem()) {
return false;
}
boolean flag = bot.gameMode.useItem(bot, bot.level(), bot.getItemInHand(InteractionHand.OFF_HAND), InteractionHand.OFF_HAND).consumesAction();
if (flag) {
bot.swing(InteractionHand.OFF_HAND);
bot.updateItemInHand(InteractionHand.OFF_HAND);
}
return flag;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
protected boolean interact(@NotNull ServerBot bot) {
return useItem(bot, InteractionHand.OFF_HAND).consumesAction();
}
@Override

View File

@@ -1,132 +1,57 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.TrappedChestBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
import java.util.List;
public class ServerUseItemOnAction extends ServerTimerBotAction<ServerUseItemOnAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemOnAction extends ServerUseBotAction<ServerUseItemOnAction> {
public ServerUseItemOnAction() {
super("use_on", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemOnAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use_on", ServerUseItemOnAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
protected boolean interact(@NotNull ServerBot bot) {
BlockHitResult hitResult = getBlockHitResult(bot);
return useItemOn(bot, hitResult, InteractionHand.MAIN_HAND).consumesAction();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
HitResult hitResult = bot.getRayTrace(5, ClipContext.Fluid.NONE);
boolean result = execute(bot, hitResult);
if (useTick >= 0) {
return false;
} else {
return result;
}
public static @Nullable BlockHitResult getBlockHitResult(@NotNull ServerBot bot) {
HitResult result = bot.getRayTrace((int) bot.blockInteractionRange(), ClipContext.Fluid.NONE);
if (result instanceof BlockHitResult blockHitResult) {
return blockHitResult;
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
return null;
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
super.save(nbt);
nbt.putInt("useTick", this.useTick);
nbt.putInt("tickToRelease", this.tickToRelease);
return nbt;
}
@Override
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);
this.useTick = nbt.getInt("useTick").orElseThrow();
this.tickToRelease = nbt.getInt("tickToRelease").orElseThrow();
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public static boolean execute(@NotNull ServerBot bot, HitResult result) {
if (!(result instanceof BlockHitResult blockHitResult)) {
return false;
}
BlockState state = bot.level().getBlockState(blockHitResult.getBlockPos());
if (state.isAir()) {
return false;
public static InteractionResult useItemOn(ServerBot bot, BlockHitResult hitResult, InteractionHand hand) {
if (hitResult == null) {
return InteractionResult.FAIL;
}
boolean success;
if (state.getBlock() == Blocks.TRAPPED_CHEST &&
bot.level().getBlockEntity(blockHitResult.getBlockPos()) instanceof TrappedChestBlockEntity chestBlockEntity
) {
chestBlockEntity.startOpen(bot);
Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> chestBlockEntity.stopOpen(bot), 1);
success = true;
} else {
bot.updateItemInHand(InteractionHand.MAIN_HAND);
success = bot.gameMode.useItemOn(bot, bot.level(), bot.getItemInHand(InteractionHand.MAIN_HAND), InteractionHand.MAIN_HAND, blockHitResult).consumesAction();
BlockPos blockPos = hitResult.getBlockPos();
if (!bot.level().getWorldBorder().isWithinBounds(blockPos)) {
return InteractionResult.FAIL;
}
if (success) {
bot.swing(InteractionHand.MAIN_HAND);
}
return success;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
InteractionResult interactionResult = bot.gameMode.useItemOn(bot, bot.level(), bot.getItemInHand(hand), hand, hitResult);
if (shouldSwing(interactionResult)) {
bot.swing(hand);
}
return interactionResult;
}
@Override
public Object asCraft() {
return new CraftUseItemOnAction(this);
}
}
}

View File

@@ -1,128 +1,24 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.TrappedChestBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
import org.apache.commons.lang3.tuple.Pair;
import org.bukkit.Bukkit;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemOnOffhandAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import org.leavesmc.leaves.plugin.MinecraftInternalPlugin;
import java.util.List;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.getBlockHitResult;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemOnAction.useItemOn;
public class ServerUseItemOnOffhandAction extends ServerTimerBotAction<ServerUseItemOnOffhandAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemOnOffhandAction extends ServerUseBotAction<ServerUseItemOnOffhandAction> {
public ServerUseItemOnOffhandAction() {
super("use_on_offhand", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemOnOffhandAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use_on_offhand", ServerUseItemOnOffhandAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
HitResult hitResult = bot.getRayTrace(5, ClipContext.Fluid.NONE);
boolean result = execute(bot, hitResult);
if (useTick >= 0) {
return false;
} else {
return result;
}
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
@Override
@NotNull
public CompoundTag save(@NotNull CompoundTag nbt) {
super.save(nbt);
nbt.putInt("useTick", this.useTick);
nbt.putInt("tickToRelease", this.tickToRelease);
return nbt;
}
@Override
public void load(@NotNull CompoundTag nbt) {
super.load(nbt);
this.useTick = nbt.getInt("useTick").orElseThrow();
this.tickToRelease = nbt.getInt("tickToRelease").orElseThrow();
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public static boolean execute(@NotNull ServerBot bot, HitResult result) {
if (!(result instanceof BlockHitResult blockHitResult)) {
return false;
}
BlockState state = bot.level().getBlockState(blockHitResult.getBlockPos());
if (state.isAir()) {
return false;
}
boolean success;
if (state.getBlock() == Blocks.TRAPPED_CHEST &&
bot.level().getBlockEntity(blockHitResult.getBlockPos()) instanceof TrappedChestBlockEntity chestBlockEntity
) {
chestBlockEntity.startOpen(bot);
Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> chestBlockEntity.stopOpen(bot), 1);
success = true;
} else {
bot.updateItemInHand(InteractionHand.OFF_HAND);
success = bot.gameMode.useItemOn(bot, bot.level(), bot.getItemInHand(InteractionHand.OFF_HAND), InteractionHand.OFF_HAND, blockHitResult).consumesAction();
}
if (success) {
bot.swing(InteractionHand.OFF_HAND);
}
return success;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
protected boolean interact(@NotNull ServerBot bot) {
BlockHitResult hitResult = getBlockHitResult(bot);
return useItemOn(bot, hitResult, InteractionHand.OFF_HAND).consumesAction();
}
@Override

View File

@@ -1,98 +1,51 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.phys.EntityHitResult;
import org.apache.commons.lang3.tuple.Pair;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
public class ServerUseItemToAction extends ServerTimerBotAction<ServerUseItemToAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemToAction extends ServerUseBotAction<ServerUseItemToAction> {
public ServerUseItemToAction() {
super("use_to", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemToAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use_to", ServerUseItemToAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
protected boolean interact(@NotNull ServerBot bot) {
EntityHitResult hitResult = getEntityHitResult(bot);
return useItemTo(bot, hitResult, InteractionHand.MAIN_HAND).consumesAction();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
public static EntityHitResult getEntityHitResult(@NotNull ServerBot bot) {
return bot.getEntityHitResult((int) bot.entityInteractionRange(), null);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
EntityHitResult hitResult = bot.getEntityHitResult(3, null);
boolean result = execute(bot, hitResult).consumesAction();
if (useTick >= 0) {
return false;
} else {
return result;
}
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public static InteractionResult execute(ServerBot bot, EntityHitResult hitResult) {
public static InteractionResult useItemTo(ServerBot bot, EntityHitResult hitResult, InteractionHand hand) {
if (hitResult == null) {
return InteractionResult.FAIL;
}
InteractionResult result;
if (hitResult.getEntity() instanceof ArmorStand armorStand) {
result = armorStand.interactAt(bot, hitResult.getLocation().subtract(armorStand.position()), InteractionHand.MAIN_HAND);
} else {
result = bot.interactOn(hitResult.getEntity(), InteractionHand.MAIN_HAND);
Entity entity = hitResult.getEntity();
if (!bot.level().getWorldBorder().isWithinBounds(entity.blockPosition())) {
return InteractionResult.FAIL;
}
if (result.consumesAction()) {
bot.swing(InteractionHand.MAIN_HAND);
bot.updateItemInHand(InteractionHand.MAIN_HAND);
}
return result;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
Vec3 vec3 = hitResult.getLocation().subtract(entity.getX(), entity.getY(), entity.getZ());
InteractionResult interactionResult = entity.interactAt(bot, vec3, hand);
if (!interactionResult.consumesAction()) {
interactionResult = bot.interactOn(hitResult.getEntity(), hand);
}
if (shouldSwing(interactionResult)) {
bot.swing(hand);
}
return interactionResult;
}
@Override

View File

@@ -1,98 +1,24 @@
package org.leavesmc.leaves.bot.agent.actions;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.decoration.ArmorStand;
import net.minecraft.world.phys.EntityHitResult;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.command.CommandArgument;
import org.leavesmc.leaves.command.CommandArgumentResult;
import org.leavesmc.leaves.command.CommandArgumentType;
import org.leavesmc.leaves.entity.bot.actions.CraftUseItemToOffhandAction;
import org.leavesmc.leaves.event.bot.BotActionStopEvent;
import java.util.List;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.getEntityHitResult;
import static org.leavesmc.leaves.bot.agent.actions.ServerUseItemToAction.useItemTo;
public class ServerUseItemToOffhandAction extends ServerTimerBotAction<ServerUseItemToOffhandAction> {
private int useTick = -1;
private int tickToRelease = -1;
public class ServerUseItemToOffhandAction extends ServerUseBotAction<ServerUseItemToOffhandAction> {
public ServerUseItemToOffhandAction() {
super("use_to_offhand", CommandArgument.of(CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER, CommandArgumentType.INTEGER), ServerUseItemToOffhandAction::new);
this.setSuggestion(3, Pair.of(List.of("-1"), "[UseTick]"));
super("use_to_offhand", ServerUseItemToOffhandAction::new);
}
@Override
public void init() {
super.init();
syncTickToRelease();
}
@Override
public void loadCommand(ServerPlayer player, @NotNull CommandArgumentResult result) {
super.loadCommand(player, result);
this.useTick = result.readInt(-1);
}
@Override
public boolean doTick(@NotNull ServerBot bot) {
tickToRelease--;
if (tickToRelease >= 0) {
EntityHitResult hitResult = bot.getEntityHitResult(3, null);
boolean result = execute(bot, hitResult).consumesAction();
if (useTick >= 0) {
return false;
} else {
return result;
}
} else {
syncTickToRelease();
bot.releaseUsingItem();
return true;
}
}
private void syncTickToRelease() {
if (this.useTick >= 0) {
this.tickToRelease = this.useTick;
} else {
this.tickToRelease = Integer.MAX_VALUE;
}
}
public int getUseTick() {
return useTick;
}
public void setUseTick(int useTick) {
this.useTick = useTick;
}
public static InteractionResult execute(ServerBot bot, EntityHitResult hitResult) {
if (hitResult == null) {
return InteractionResult.FAIL;
}
InteractionResult result;
if (hitResult.getEntity() instanceof ArmorStand armorStand) {
result = armorStand.interactAt(bot, hitResult.getLocation().subtract(armorStand.position()), InteractionHand.OFF_HAND);
} else {
result = bot.interactOn(hitResult.getEntity(), InteractionHand.OFF_HAND);
}
if (result.consumesAction()) {
bot.swing(InteractionHand.OFF_HAND);
bot.updateItemInHand(InteractionHand.OFF_HAND);
}
return result;
}
@Override
public void stop(@NotNull ServerBot bot, BotActionStopEvent.Reason reason) {
super.stop(bot, reason);
bot.completeUsingItem();
protected boolean interact(@NotNull ServerBot bot) {
EntityHitResult hitResult = getEntityHitResult(bot);
return useItemTo(bot, hitResult, InteractionHand.OFF_HAND).consumesAction();
}
@Override