From bf6b98c49fb0ce129ca95a2d27bd9864c8f75936 Mon Sep 17 00:00:00 2001 From: batchprogrammer314 Date: Mon, 19 Jul 2021 17:35:28 -0500 Subject: [PATCH] more epic stuff --- src/main/java/net/nuggetmc/ai/bot/Bot.java | 57 ++- .../java/net/nuggetmc/ai/bot/BotManager.java | 21 +- .../java/net/nuggetmc/ai/bot/agent/Agent.java | 21 +- .../ai/bot/agent/botagent/BotAgent.java | 6 +- .../bot/agent/legacyagent/EnumTargetGoal.java | 28 ++ .../ai/bot/agent/legacyagent/LegacyAgent.java | 331 ++++++++++++++++-- .../ai/bot/agent/legacyagent/LegacyMats.java | 19 +- .../ai/bot/agent/legacyagent/LegacyUtils.java | 1 + .../ai/bot/event/BotFallDamageEvent.java | 26 ++ .../ai/command/commands/MainCommand.java | 69 +++- .../java/net/nuggetmc/ai/utils/Debugger.java | 109 +++--- .../java/net/nuggetmc/ai/utils/MathUtils.java | 18 +- .../net/nuggetmc/ai/utils/PlayerUtils.java | 19 +- 13 files changed, 573 insertions(+), 152 deletions(-) create mode 100644 src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/EnumTargetGoal.java create mode 100644 src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java diff --git a/src/main/java/net/nuggetmc/ai/bot/Bot.java b/src/main/java/net/nuggetmc/ai/bot/Bot.java index b4efb88..05843e3 100644 --- a/src/main/java/net/nuggetmc/ai/bot/Bot.java +++ b/src/main/java/net/nuggetmc/ai/bot/Bot.java @@ -4,6 +4,7 @@ import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; import net.minecraft.server.v1_16_R3.*; import net.nuggetmc.ai.PlayerAI; +import net.nuggetmc.ai.bot.event.BotFallDamageEvent; import net.nuggetmc.ai.utils.BotUtils; import net.nuggetmc.ai.utils.MathUtils; import org.bukkit.Material; @@ -120,15 +121,13 @@ public class Bot extends EntityPlayer { this.velocity = vector; } - public void addVelocity(Vector vector) { // This can cause lag? - try { - velocity.checkFinite(); - } catch (IllegalArgumentException e) { + public void addVelocity(Vector vector) { // This can cause lag? (maybe i fixed it with the new static method) + if (MathUtils.isNotFinite(vector)) { velocity = vector; return; } - this.velocity.add(vector); + velocity.add(vector); } public boolean tickDelay(int i) { @@ -175,17 +174,24 @@ public class Bot extends EntityPlayer { setHealth(amount); fireDamageCheck(); - - if (!isAlive()) return; - fallDamageCheck(); oldVelocity = velocity.clone(); } private void fireDamageCheck() { + if (!isAlive()) { + return; // maybe also have packet reset thing + } + Material type = getLocation().getBlock().getType(); + if (type == Material.WATER) { + setOnFirePackets(false); // maybe also play extinguish noise? + fireTicks = 0; + return; + } + boolean lava = type == org.bukkit.Material.LAVA; if (lava || type == org.bukkit.Material.FIRE || type == Material.SOUL_FIRE) { @@ -217,17 +223,31 @@ public class Bot extends EntityPlayer { sendPacket(new PacketPlayOutEntityMetadata(getId(), datawatcher, false)); } - private void fallDamageCheck() { - if (groundTicks == 0 || noFallTicks != 0) return; - double y = oldVelocity.getY(); - if (y >= -0.8 || BotUtils.NO_FALL.contains(getLocation().getBlock().getType())) return; + public boolean isOnFire() { + return fireTicks != 0; + } - damageEntity(DamageSource.FALL, (float) Math.pow(3.6, -y)); + private void fallDamageCheck() { // TODO create a better bot event system in the future, also have bot.getAgent() + if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !BotUtils.NO_FALL.contains(getLocation().getBlock().getType())) { + BotFallDamageEvent event = new BotFallDamageEvent(this); + + PlayerAI.getInstance().getManager().getAgent().onFallDamage(event); + + if (!event.isCancelled()) { + damageEntity(DamageSource.FALL, (float) Math.pow(3.6, -oldVelocity.getY())); + } + } + } + + public boolean isFalling() { + return velocity.getY() < -0.8; } private void updateLocation() { double y; + MathUtils.clean(velocity); // TODO lag???? + if (isInWater()) { y = Math.min(velocity.getY() + 0.1, 0.1); addFriction(0.8); @@ -241,9 +261,8 @@ public class Bot extends EntityPlayer { y = 0; } else { y = velocity.getY(); + velocity.setY(Math.max(y - 0.1, -3.5)); } - - velocity.setY(Math.max(velocity.getY() - 0.1, -3.5)); } this.move(EnumMoveType.SELF, new Vec3D(velocity.getX(), y, velocity.getZ())); @@ -473,7 +492,13 @@ public class Bot extends EntityPlayer { setYawPitch(yaw, pitch); } - public void attemptBlockPlace(Location loc, Material type) { + public void attemptBlockPlace(Location loc, Material type, boolean down) { + if (down) { + look(BlockFace.DOWN); + } else { + faceLocation(loc); + } + setItem(new org.bukkit.inventory.ItemStack(Material.COBBLESTONE)); punch(); diff --git a/src/main/java/net/nuggetmc/ai/bot/BotManager.java b/src/main/java/net/nuggetmc/ai/bot/BotManager.java index 4555eb5..d061a17 100644 --- a/src/main/java/net/nuggetmc/ai/bot/BotManager.java +++ b/src/main/java/net/nuggetmc/ai/bot/BotManager.java @@ -26,7 +26,7 @@ public class BotManager implements Listener { private final Set bots; private final NumberFormat numberFormat; - private boolean removeOnDeath = true; + public boolean removeOnDeath = true; public BotManager() { this.agent = new LegacyAgent(this); @@ -42,6 +42,16 @@ public class BotManager implements Listener { bots.add(bot); } + public Bot getFirst(String name) { + for (Bot bot : bots) { + if (name.equals(bot.getName())) { + return bot; + } + } + + return null; + } + public Agent getAgent() { return agent; } @@ -68,9 +78,9 @@ public class BotManager implements Listener { String[] skin = MojangAPI.getSkin(skinName); - for (int i = 0; i < n; i++) { - Bot bot = Bot.createBot(loc, name, skin, removeOnDeath); - if (i > 0) bot.setVelocity(new Vector(Math.random() - 0.5, 0.5, Math.random() - 0.5).normalize().multiply(f)); + for (int i = 1; i <= n; i++) { + Bot bot = Bot.createBot(loc, name.replace("%", String.valueOf(i)), skin, removeOnDeath); + if (i > 1) bot.setVelocity(new Vector(Math.random() - 0.5, 0.5, Math.random() - 0.5).normalize().multiply(f)); } world.spawnParticle(Particle.CLOUD, loc, 100, 1, 1, 1, 0.5); @@ -85,11 +95,12 @@ public class BotManager implements Listener { public void reset() { bots.forEach(Bot::removeVisually); bots.clear(); // Not always necessary, but a good security measure + agent.stopAllTasks(); } @EventHandler public void onJoin(PlayerJoinEvent event) { PlayerConnection connection = ((CraftPlayer) event.getPlayer()).getHandle().playerConnection; - bots.forEach(b -> b.render(connection, true)); + bots.forEach(bot -> bot.render(connection, true)); } } diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/Agent.java b/src/main/java/net/nuggetmc/ai/bot/agent/Agent.java index b8fcc26..6968b1e 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/Agent.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/Agent.java @@ -1,7 +1,9 @@ package net.nuggetmc.ai.bot.agent; import net.nuggetmc.ai.PlayerAI; +import net.nuggetmc.ai.bot.Bot; import net.nuggetmc.ai.bot.BotManager; +import net.nuggetmc.ai.bot.event.BotFallDamageEvent; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.scheduler.BukkitScheduler; @@ -42,14 +44,21 @@ public abstract class Agent { taskID = scheduler.scheduleSyncRepeatingTask(plugin, this::tick, 0, 1); } else { scheduler.cancelTask(taskID); - taskList.forEach(t -> { - if (!t.isCancelled()) { - t.cancel(); - } - }); - taskList.clear(); + stopAllTasks(); } } + public void stopAllTasks() { + taskList.forEach(t -> { + if (!t.isCancelled()) { + t.cancel(); + } + }); + taskList.clear(); + } + protected abstract void tick(); + + public void onFallDamage(BotFallDamageEvent event) { + } } diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/botagent/BotAgent.java b/src/main/java/net/nuggetmc/ai/bot/agent/botagent/BotAgent.java index 1542222..58850a6 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/botagent/BotAgent.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/botagent/BotAgent.java @@ -85,7 +85,7 @@ public class BotAgent extends Agent { } private void attack(Bot bot, Player player, Location loc) { - if (!PlayerUtils.isVulnerableGameMode(player.getGameMode()) || player.getNoDamageTicks() >= 5 || loc.distance(player.getLocation()) >= 4) return; + if (PlayerUtils.isInvincible(player.getGameMode()) || player.getNoDamageTicks() >= 5 || loc.distance(player.getLocation()) >= 4) return; bot.attack(player); } @@ -102,7 +102,7 @@ public class BotAgent extends Agent { try { vel.add(bot.velocity); } catch (IllegalArgumentException e) { - if (!MathUtils.isFinite(vel)) { + if (MathUtils.isNotFinite(vel)) { MathUtils.clean(vel); } } @@ -124,7 +124,7 @@ public class BotAgent extends Agent { Player result = null; for (Player player : Bukkit.getOnlinePlayers()) { - if (!PlayerUtils.isTargetable(player.getGameMode()) || loc.getWorld() != player.getWorld()) continue; + if (PlayerUtils.isInvincible(player.getGameMode()) || loc.getWorld() != player.getWorld()) continue; if (result == null || loc.distance(player.getLocation()) < loc.distance(result.getLocation())) { result = player; diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/EnumTargetGoal.java b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/EnumTargetGoal.java new file mode 100644 index 0000000..e0567dc --- /dev/null +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/EnumTargetGoal.java @@ -0,0 +1,28 @@ +package net.nuggetmc.ai.bot.agent.legacyagent; + +public enum EnumTargetGoal { + CLOSEST_REAL_VULNERABLE_PLAYER, + CLOSEST_REAL_PLAYER, + CLOSEST_BOT_DIFFER, + CLOSEST_BOT, + NONE; + + public static EnumTargetGoal of(int n) { + switch (n) { + default: + return NONE; + + case 1: + return CLOSEST_REAL_VULNERABLE_PLAYER; + + case 2: + return CLOSEST_REAL_PLAYER; + + case 3: + return CLOSEST_BOT_DIFFER; + + case 4: + return CLOSEST_BOT; + } + } +} diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyAgent.java b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyAgent.java index cbfe350..f3f6003 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyAgent.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyAgent.java @@ -5,6 +5,7 @@ import net.minecraft.server.v1_16_R3.PacketPlayOutBlockBreakAnimation; import net.nuggetmc.ai.bot.Bot; import net.nuggetmc.ai.bot.BotManager; import net.nuggetmc.ai.bot.agent.Agent; +import net.nuggetmc.ai.bot.event.BotFallDamageEvent; import net.nuggetmc.ai.utils.MathUtils; import net.nuggetmc.ai.utils.PlayerUtils; import org.bukkit.*; @@ -12,6 +13,7 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.entity.Boat; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitRunnable; @@ -27,6 +29,7 @@ public class LegacyAgent extends Agent { public LegacyAgent(BotManager manager) { super(manager); + this.goal = EnumTargetGoal.CLOSEST_REAL_VULNERABLE_PLAYER; this.blockCheck = new LegacyBlockCheck(this); } @@ -102,6 +105,9 @@ public class LegacyAgent extends Agent { blockCheck.clutch(bot, player); + fallDamageCheck(bot); + miscellaneousChecks(bot, player); + Player playerBot = bot.getBukkitEntity(); Location target = player.getLocation().add(bot.getOffset()); @@ -179,6 +185,71 @@ public class LegacyAgent extends Agent { } } + private void fallDamageCheck(Bot bot) { + if (bot.isFalling()) { + bot.look(BlockFace.DOWN); + + Material itemType; + + if (bot.getBukkitEntity().getWorld().getName().equals("world_nether")) { + itemType = Material.TWISTING_VINES; + } else { + itemType = Material.WATER_BUCKET; + } + + bot.setItem(new ItemStack(itemType)); + } + } + + @Override + public void onFallDamage(BotFallDamageEvent event) { + Bot bot = event.getBot(); + World world = bot.getBukkitEntity().getWorld(); + + bot.look(BlockFace.DOWN); + + Material itemType; + Material placeType; + Sound sound; + + if (world.getName().equals("world_nether")) { + itemType = Material.TWISTING_VINES; + sound = Sound.BLOCK_WEEPING_VINES_PLACE; + placeType = itemType; + } else { + itemType = Material.WATER_BUCKET; + sound = Sound.ITEM_BUCKET_EMPTY; + placeType = Material.WATER; + } + + Location loc = bot.getLocation(); + + if (!loc.clone().add(0, -1, 0).getBlock().getType().isSolid()) return; + + event.cancel(); + + if (loc.getBlock().getType() != placeType) { + bot.punch(); + loc.getBlock().setType(placeType); + world.playSound(loc, sound, 1, 1); + + if (itemType == Material.WATER_BUCKET) { + bot.setItem(new ItemStack(Material.BUCKET)); + + scheduler.runTaskLater(plugin, () -> { + Block block = loc.getBlock(); + + if (block.getType() == Material.WATER) { + bot.look(BlockFace.DOWN); + bot.setItem(new ItemStack(Material.WATER_BUCKET)); + world.playSound(loc, Sound.ITEM_BUCKET_FILL, 1, 1); + block.setType(Material.AIR); + } + }, 5); + } + } + } + private void swim(Bot bot, Location loc, Player playerNPC, Player ply, boolean anim) { playerNPC.setSneaking(false); @@ -222,18 +293,6 @@ public class LegacyAgent extends Agent { } } - /*private void moveSmall(Bot bot, Location loc, Location target) { - Vector vel = target.toVector().subtract(loc.toVector()).setY(0).normalize(); - - bot.stand(); // eventually create a memory system so packets do not have to be sent every tick - - try { - Vector newVel = bot.velocity.clone().add(vel); - if (newVel.length() > 1) newVel.normalize(); - bot.addVelocity(newVel.multiply(0.01)); - } catch (IllegalArgumentException ignored) { } - }*/ - private void move(Bot bot, Player player, Location loc, Location target) { Vector vel = target.toVector().subtract(loc.toVector()).normalize(); @@ -246,7 +305,7 @@ public class LegacyAgent extends Agent { try { vel.add(bot.velocity); } catch (IllegalArgumentException e) { - if (!MathUtils.isFinite(vel)) { + if (MathUtils.isNotFinite(vel)) { MathUtils.clean(vel); } } @@ -265,6 +324,8 @@ public class LegacyAgent extends Agent { vel.setY(0.4); } + vel.setY(vel.getY() - Math.random() * 0.05); + bot.jump(vel); } @@ -354,7 +415,7 @@ public class LegacyAgent extends Agent { } private static boolean checkSideBreak(Material type) { - return !LegacyMats.BREAK.contains(type) && !LegacyMats.LEAVES.contains(type); + return !LegacyMats.BREAK.contains(type);// && !LegacyMats.LEAVES.contains(type); } private boolean checkUp(Bot npc, Player player, Player playerNPC, Location loc, boolean c) { @@ -412,13 +473,13 @@ public class LegacyAgent extends Agent { npc.look(BlockFace.DOWN); // maybe put this in lower if statement onGround() - Bukkit.getScheduler().runTaskLater(plugin, () -> { + scheduler.runTaskLater(plugin, () -> { npc.sneak(); npc.setItem(new ItemStack(Material.COBBLESTONE)); npc.punch(); npc.look(BlockFace.DOWN); - Bukkit.getScheduler().runTaskLater(plugin, () -> { + scheduler.runTaskLater(plugin, () -> { npc.look(BlockFace.DOWN); }, 1); @@ -435,7 +496,7 @@ public class LegacyAgent extends Agent { if (player.getLocation().distance(playerNPC.getLocation()) < 16) { if (noJump.contains(playerNPC)) { - Bukkit.getScheduler().runTaskLater(plugin, () -> { + scheduler.runTaskLater(plugin, () -> { npc.setVelocity(new Vector(0, 0.5, 0)); }, 1); @@ -462,7 +523,7 @@ public class LegacyAgent extends Agent { vector.multiply(0.1); vector.setY(0.5); - npc.setVelocity(npc.getVelocity().add(vector)); + npc.addVelocity(vector); return true; } } @@ -485,7 +546,7 @@ public class LegacyAgent extends Agent { vector.multiply(0.1); vector.setY(0); - npc.setVelocity(npc.getVelocity().add(vector)); + npc.addVelocity(vector); } return true; @@ -555,7 +616,7 @@ public class LegacyAgent extends Agent { if (!fallDamageCooldown.contains(npc)) { fallDamageCooldown.add(npc); - Bukkit.getScheduler().runTaskLater(plugin, () -> { + scheduler.runTaskLater(plugin, () -> { fallDamageCooldown.remove(npc); }, 10); } @@ -599,7 +660,7 @@ public class LegacyAgent extends Agent { if (level == LegacyLevel.EAST_D || level == LegacyLevel.NORTH_D || level == LegacyLevel.SOUTH_D || level == LegacyLevel.WEST_D) { bot.pitch = 69; - Bukkit.getScheduler().runTaskLater(plugin, () -> { + scheduler.runTaskLater(plugin, () -> { btCheck.put(player, true); }, 5); } else if (level == LegacyLevel.AT_D || level == LegacyLevel.AT) { @@ -722,7 +783,7 @@ public class LegacyAgent extends Agent { if (level == LegacyLevel.ABOVE) { noJump.add(player); - Bukkit.getScheduler().runTaskLater(plugin, () -> { + scheduler.runTaskLater(plugin, () -> { noJump.remove(player); }, 15); } @@ -754,6 +815,173 @@ public class LegacyAgent extends Agent { } } + private void placeWaterDown(Bot bot, World world, Location loc) { + if (loc.getBlock().getType() == Material.WATER) return; + + bot.look(BlockFace.DOWN); + bot.punch(); + loc.getBlock().setType(Material.WATER); + world.playSound(loc, Sound.ITEM_BUCKET_EMPTY, 1, 1); + bot.setItem(new org.bukkit.inventory.ItemStack(Material.BUCKET)); + + scheduler.runTaskLater(plugin, () -> { + Block block = loc.getBlock(); + + if (block.getType() == Material.WATER) { + bot.look(BlockFace.DOWN); + bot.setItem(new ItemStack(Material.WATER_BUCKET)); + world.playSound(loc, Sound.ITEM_BUCKET_FILL, 1, 1); + block.setType(Material.AIR); + } + }, 5); + } + + private void miscellaneousChecks(Bot bot, Player target) { + Player playerBot = bot.getBukkitEntity(); + World world = playerBot.getWorld(); + String worldName = world.getName(); + Location loc = bot.getLocation(); + + if (bot.isOnFire()) { + if (!worldName.equals("world_nether")) { + placeWaterDown(bot, world, loc); + } + } + + Material atType = loc.getBlock().getType(); + + if (atType == Material.FIRE || atType == Material.SOUL_FIRE) { + if (!worldName.equals("world_nether")) { + placeWaterDown(bot, world, loc); + world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); + } else { + bot.look(BlockFace.DOWN); + bot.punch(); + world.playSound(loc, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); + loc.getBlock().setType(Material.AIR); + } + } + + if (atType == Material.LAVA) { + if (worldName.equals("world_nether")) { + bot.attemptBlockPlace(loc, Material.COBBLESTONE, false); + } else { + placeWaterDown(bot, world, loc); + } + } + + Location head = loc.clone().add(0, 1, 0); + Material headType = head.getBlock().getType(); + + if (headType == Material.LAVA) { + if (worldName.equals("world_nether")) { + bot.attemptBlockPlace(head, Material.COBBLESTONE, false); + } else { + placeWaterDown(bot, world, head); + } + } + + if (headType == Material.FIRE || headType == Material.SOUL_FIRE) { + if (worldName.equals("world_nether")) { + bot.look(BlockFace.DOWN); + bot.punch(); + world.playSound(head, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); + head.getBlock().setType(Material.AIR); + } else { + placeWaterDown(bot, world, head); + } + } + + Location under = loc.clone().add(0, -1, 0); + Material underType = under.getBlock().getType(); + + if (underType == Material.FIRE || underType == Material.SOUL_FIRE) { + Block place = under.getBlock(); + bot.look(BlockFace.DOWN); + bot.punch(); + world.playSound(under, Sound.BLOCK_FIRE_EXTINGUISH, SoundCategory.BLOCKS, 1, 1); + place.setType(Material.AIR); + } + + Location under2 = loc.clone().add(0, -2, 0); + Material under2Type = under2.getBlock().getType(); + + if (under2Type == Material.MAGMA_BLOCK) { + if (LegacyMats.SPAWN.contains(under2Type)) { + bot.attemptBlockPlace(under2, Material.COBBLESTONE, true); + } + } + + if (playerBot.getLocation().getBlockY() <= target.getLocation().getBlockY() + 1) { + if (!miningAnim.containsKey(playerBot)) { + Vector vel = playerBot.getVelocity(); + double y = vel.getY(); + + if (y >= -0.6) { + if (loc.clone().add(0, -0.6, 0).getBlock().getType() == Material.WATER + && !LegacyMats.NO_CRACK.contains(under2Type) + && playerBot.getEyeLocation().getBlock().getType().isAir()) { + + Block place = loc.clone().add(0, -1, 0).getBlock(); + if (LegacyMats.WATER.contains(place.getType())) { + Location mlgLoc = place.getLocation(); + + bot.attemptBlockPlace(place.getLocation(), Material.COBBLESTONE, true); + } + } + } + } + } + + underType = loc.clone().add(0, -0.6, 0).getBlock().getType(); + + if (underType == Material.LAVA) { + if (!boatCooldown.contains(bot)) { + boatCooldown.add(bot); + + Location place = loc.clone().add(0, -0.1, 0); + + bot.setItem(new ItemStack(Material.OAK_BOAT)); + bot.look(BlockFace.DOWN); + bot.punch(); + + Boat boat = (Boat) world.spawnEntity(place, EntityType.BOAT); + + scheduler.runTaskLater(plugin, () -> { + if (!boat.isDead()) { + boats.remove(boat); + boat.remove(); + } + }, 20); + + scheduler.runTaskLater(plugin, () -> { + bot.look(BlockFace.DOWN); + }, 1); + + boats.add(boat); + + Location targetLoc = target.getLocation(); + + bot.stand(); + Vector vector = targetLoc.toVector().subtract(bot.getLocation().toVector()).normalize(); + vector.multiply(0.8); + + Vector move = bot.getVelocity().add(vector); + if (move.length() > 1) move = move.normalize(); + move.multiply(0.75); + move.setY(0.42); + bot.setVelocity(move); + + scheduler.runTaskLater(plugin, () -> { + boatCooldown.remove(bot); + if (bot.isAlive()) { + bot.faceLocation(target.getLocation()); + } + }, 5); + } + } + } + private void resetHand(Bot npc, Player player, Player playerNPC) { if (!noFace.contains(npc)) { // LESSLAG if there is no if statement here npc.faceLocation(player.getLocation()); @@ -797,20 +1025,55 @@ public class LegacyAgent extends Agent { } private void attack(Bot bot, Player player, Location loc) { - if (!PlayerUtils.isVulnerableGameMode(player.getGameMode()) || player.getNoDamageTicks() >= 5 || loc.distance(player.getLocation()) >= 4) return; + if (PlayerUtils.isInvincible(player.getGameMode()) || player.getNoDamageTicks() >= 5 || loc.distance(player.getLocation()) >= 4) return; bot.attack(player); } + private EnumTargetGoal goal; + + public void setTargetType(EnumTargetGoal goal) { + this.goal = goal; + } + private Player nearestPlayer(Bot bot, Location loc) { - return nearestBot(bot, loc); + switch (goal) { + case CLOSEST_REAL_VULNERABLE_PLAYER: + return nearestRealVulnerablePlayer(loc); + + case CLOSEST_REAL_PLAYER: + return nearestRealPlayer(loc); + + case CLOSEST_BOT_DIFFER: + return nearestBotDiffer(bot, loc); + + case CLOSEST_BOT: + return nearestBot(bot, loc); + + default: + return null; + } } private Player nearestRealPlayer(Location loc) { Player result = null; for (Player player : Bukkit.getOnlinePlayers()) { - if (!PlayerUtils.isTargetable(player.getGameMode()) || loc.getWorld() != player.getWorld()) continue; + if (loc.getWorld() != player.getWorld()) continue; + + if (result == null || loc.distance(player.getLocation()) < loc.distance(result.getLocation())) { + result = player; + } + } + + return result; + } + + private Player nearestRealVulnerablePlayer(Location loc) { + Player result = null; + + for (Player player : Bukkit.getOnlinePlayers()) { + if (PlayerUtils.isInvincible(player.getGameMode()) || loc.getWorld() != player.getWorld()) continue; if (result == null || loc.distance(player.getLocation()) < loc.distance(result.getLocation())) { result = player; @@ -823,6 +1086,24 @@ public class LegacyAgent extends Agent { private Player nearestBot(Bot bot, Location loc) { Player result = null; + for (Bot otherBot : manager.fetch()) { + if (bot == otherBot) continue; + + Player player = otherBot.getBukkitEntity(); + + if (loc.getWorld() != player.getWorld()) continue; + + if (result == null || loc.distance(player.getLocation()) < loc.distance(result.getLocation())) { + result = player; + } + } + + return result; + } + + private Player nearestBotDiffer(Bot bot, Location loc) { + Player result = null; + for (Bot otherBot : manager.fetch()) { if (bot == otherBot) continue; diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyMats.java b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyMats.java index 9824976..f4fc665 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyMats.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyMats.java @@ -24,15 +24,19 @@ public class LegacyMats { Material.TALL_SEAGRASS, Material.KELP, Material.KELP_PLANT, + Material.SUNFLOWER, Material.AIR, - Material.VOID_AIR + Material.VOID_AIR, + Material.FIRE, + Material.SOUL_FIRE )); public static final Set NO_CRACK = new HashSet<>(Arrays.asList( Material.WATER, Material.FIRE, Material.LAVA, - Material.CAVE_AIR + Material.CAVE_AIR, + Material.SOUL_FIRE )); public static final Set SHOVEL = new HashSet<>(Arrays.asList( @@ -78,7 +82,10 @@ public class LegacyMats { Material.SEAGRASS, Material.TALL_SEAGRASS, Material.KELP, - Material.KELP_PLANT + Material.KELP_PLANT, + Material.SUNFLOWER, + Material.FIRE, + Material.SOUL_FIRE )); public static final Set WATER = new HashSet<>(Arrays.asList( @@ -103,7 +110,10 @@ public class LegacyMats { Material.SEAGRASS, Material.TALL_SEAGRASS, Material.KELP, - Material.KELP_PLANT + Material.KELP_PLANT, + Material.SUNFLOWER, + Material.FIRE, + Material.SOUL_FIRE )); public static final Set FALL = new HashSet<>(Arrays.asList( @@ -121,6 +131,7 @@ public class LegacyMats { Material.TALL_SEAGRASS, Material.KELP, Material.KELP_PLANT, + Material.SUNFLOWER, Material.WATER )); diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyUtils.java b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyUtils.java index 7b17be4..655c4e1 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyUtils.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyUtils.java @@ -36,6 +36,7 @@ public class LegacyUtils { try { World nmsWorld = ((CraftWorld) block.getWorld()).getHandle(); net.minecraft.server.v1_16_R3.Block nmsBlock = nmsWorld.getType(new BlockPosition(block.getX(), block.getY(), block.getZ())).getBlock(); + SoundEffectType soundEffectType = nmsBlock.getStepSound(nmsBlock.getBlockData()); Field breakSound = SoundEffectType.class.getDeclaredField("stepSound"); diff --git a/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java b/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java new file mode 100644 index 0000000..ad6c389 --- /dev/null +++ b/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java @@ -0,0 +1,26 @@ +package net.nuggetmc.ai.bot.event; + +import net.nuggetmc.ai.bot.Bot; + +public class BotFallDamageEvent { + + private final Bot bot; + + private boolean isCancelled; + + public BotFallDamageEvent(Bot bot) { + this.bot = bot; + } + + public Bot getBot() { + return bot; + } + + public void cancel() { + isCancelled = true; + } + + public boolean isCancelled() { + return isCancelled; + } +} diff --git a/src/main/java/net/nuggetmc/ai/command/commands/MainCommand.java b/src/main/java/net/nuggetmc/ai/command/commands/MainCommand.java index 3c6b751..8d74080 100644 --- a/src/main/java/net/nuggetmc/ai/command/commands/MainCommand.java +++ b/src/main/java/net/nuggetmc/ai/command/commands/MainCommand.java @@ -6,25 +6,38 @@ import com.jonahseguin.drink.annotation.Sender; import com.jonahseguin.drink.annotation.Text; import com.jonahseguin.drink.utils.ChatUtils; import net.nuggetmc.ai.PlayerAI; +import net.nuggetmc.ai.bot.Bot; import net.nuggetmc.ai.bot.BotManager; import net.nuggetmc.ai.command.CommandHandler; import net.nuggetmc.ai.command.CommandInstance; import net.nuggetmc.ai.utils.Debugger; +import org.bukkit.Bukkit; import org.bukkit.ChatColor; +import org.bukkit.Location; import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitScheduler; +import org.bukkit.util.Vector; +import java.text.DecimalFormat; import java.text.NumberFormat; import java.util.Locale; public class MainCommand extends CommandInstance { + private final PlayerAI plugin; private final BotManager manager; + private final BukkitScheduler scheduler; + private final DecimalFormat formatter; public MainCommand(CommandHandler commandHandler) { super(commandHandler); - this.manager = PlayerAI.getInstance().getManager(); + this.plugin = PlayerAI.getInstance(); + this.manager = plugin.getManager(); + this.scheduler = Bukkit.getScheduler(); + this.formatter = new DecimalFormat("0.##"); } @Command( @@ -66,10 +79,57 @@ public class MainCommand extends CommandInstance { @Command( name = "info", - desc = "Information about loaded bots." + desc = "Information about loaded bots.", + usage = "[name]" ) - public void info(@Sender Player sender) { - sender.sendMessage(ChatColor.YELLOW + "Bot GUI coming soon!"); + public void info(@Sender CommandSender sender, @OptArg String name) { + if (name == null) { + sender.sendMessage(ChatColor.YELLOW + "Bot GUI coming soon!"); + return; + } + + sender.sendMessage("Processing request..."); + + scheduler.runTaskAsynchronously(plugin, () -> { + try { + Bot bot = manager.getFirst(name); + + if (bot == null) { + sender.sendMessage("Could not find bot " + ChatColor.GREEN + name + ChatColor.RESET + "!"); + return; + } + + /* + * health + * inventory + * current target + * current kills + * skin + * neural network values + */ + + sender.sendMessage(ChatUtils.LINE); + String botName = bot.getName(); + sender.sendMessage(ChatColor.GREEN + botName); + //String created = ChatColor.YELLOW + ""; + //sender.sendMessage(ChatUtils.BULLET_FORMATTED + "Created: " + created); + String world = ChatColor.YELLOW + bot.getBukkitEntity().getWorld().getName(); + sender.sendMessage(ChatUtils.BULLET_FORMATTED + "World: " + world); + Location loc = bot.getLocation(); + String strLoc = ChatColor.YELLOW + formatter.format(loc.getBlockX()) + ", " + formatter.format(loc.getBlockY()) + ", " + formatter.format(loc.getBlockZ()); + sender.sendMessage(ChatUtils.BULLET_FORMATTED + "Position: " + strLoc); + Vector vel = bot.getVelocity(); + sender.sendMessage(ChatUtils.BULLET_FORMATTED + "Velocity: " + vel); + String strVel = ChatColor.AQUA + formatter.format(vel.getX()) + ", " + formatter.format(vel.getY()) + ", " + formatter.format(vel.getZ()); + sender.sendMessage(ChatUtils.BULLET_FORMATTED + "Velocity: " + strVel); + + sender.sendMessage(ChatUtils.LINE); + } + + catch (Exception e) { + sender.sendMessage(ChatColor.RED + "An exception has occured. Please try again."); + } + }); } @Command( @@ -79,7 +139,6 @@ public class MainCommand extends CommandInstance { public void reset(@Sender CommandSender sender) { sender.sendMessage("Removing every bot..."); - BotManager manager = PlayerAI.getInstance().getManager(); int size = manager.fetch().size(); manager.reset(); diff --git a/src/main/java/net/nuggetmc/ai/utils/Debugger.java b/src/main/java/net/nuggetmc/ai/utils/Debugger.java index 65d3fa5..cf2a291 100644 --- a/src/main/java/net/nuggetmc/ai/utils/Debugger.java +++ b/src/main/java/net/nuggetmc/ai/utils/Debugger.java @@ -1,15 +1,15 @@ package net.nuggetmc.ai.utils; -import net.minecraft.server.v1_16_R3.*; import net.nuggetmc.ai.PlayerAI; import net.nuggetmc.ai.bot.Bot; import net.nuggetmc.ai.bot.agent.Agent; +import net.nuggetmc.ai.bot.agent.legacyagent.EnumTargetGoal; +import net.nuggetmc.ai.bot.agent.legacyagent.LegacyAgent; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.command.CommandSender; -import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.entity.ArmorStand; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; @@ -52,7 +52,9 @@ public class Debugger { String name = cmd.substring(0, pts[0]); String content = cmd.substring(pts[0] + 1, pts[1]); - Statement statement = new Statement(this, name, content.isEmpty() ? null : new Object[]{content}); + Object[] args = content.isEmpty() ? null : buildObjects(content); + + Statement statement = new Statement(this, name, args); print("Running the expression \"" + ChatColor.AQUA + cmd + ChatColor.RESET + "\"..."); statement.execute(); } @@ -70,55 +72,65 @@ public class Debugger { String[] values = content.split(","); for (String str : values) { - list.add(str.startsWith(" ") ? str.substring(1) : str); + String value = str.startsWith(" ") ? str.substring(1) : str; + Object obj = value; + + try { + obj = Double.parseDouble(value); + } catch (NumberFormatException ignored) { } + + try { + obj = Integer.parseInt(value); + } catch (NumberFormatException ignored) { } + + if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("false")) { + obj = Boolean.parseBoolean(value); + } + + list.add(obj); } } return list.toArray(); } - public void fire(String content) { - Object[] obj = buildObjects(content); + /* + * DEBUGGER METHODS + */ - if (obj.length != 1) { - print("Invalid arguments!"); + public void tp() { + Bot bot = MathUtils.getRandomSetElement(PlayerAI.getInstance().getManager().fetch()); + + if (bot == null) { + print("Failed to locate a bot."); return; } - boolean b = Boolean.parseBoolean((String) obj[0]); + print("Located bot", ChatColor.GREEN + bot.getName() + ChatColor.RESET + "."); - PlayerAI.getInstance().getManager().fetch().forEach(bot -> bot.setOnFirePackets(b)); + if (sender instanceof Player) { + print("Teleporting..."); + ((Player) sender).teleport(bot.getLocation()); + } } - public void sendPackets(String content) { - Object[] obj = buildObjects(content); - - if (obj.length != 1) { - print("Invalid arguments!"); + public void setTarget(int n) { + Agent agent = PlayerAI.getInstance().getManager().getAgent(); + if (!(agent instanceof LegacyAgent)) { + print("This method currently only supports " + ChatColor.AQUA + "LegacyAgent" + ChatColor.RESET + "."); return; } - byte b; + LegacyAgent legacyAgent = (LegacyAgent) agent; + EnumTargetGoal goal = EnumTargetGoal.of(n); - try { - b = Byte.parseByte((String) obj[0]); - } catch (NumberFormatException e) { - print("Invalid arguments!"); - return; - } + legacyAgent.setTargetType(goal); - PlayerAI.getInstance().getManager().fetch().forEach(bot -> { - /*DataWatcher datawatcher = bot.getDataWatcher(); - datawatcher.set(DataWatcherRegistry.s.a(6), EntityPose.DYING); - PacketPlayOutEntityMetadata metadata = new PacketPlayOutEntityMetadata(bot.getId(), datawatcher, false); - Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().playerConnection.sendPacket(metadata)); + print("The goal has been set to " + ChatColor.BLUE + goal.name() + ChatColor.RESET + "."); + } - PacketPlayOutEntityStatus packet = new PacketPlayOutEntityStatus(bot, b); - Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet));*/ - bot.setHealth(0); - }); - - Debugger.log("PACKETS_SENT"); + public void fire(boolean b) { + PlayerAI.getInstance().getManager().fetch().forEach(bot -> bot.setOnFirePackets(b)); } public void trackYVel() { @@ -131,28 +143,6 @@ public class Debugger { }, 0, 1); } - public void t() { - Bukkit.dispatchCommand(sender, "bot debug t(" + !PlayerUtils.getAllTargetable() + ")"); - } - - public void t(String content) { - Object[] obj = buildObjects(content); - - if (obj.length != 1) { - print("Invalid arguments!"); - return; - } - - PlayerUtils.setAllTargetable(Boolean.parseBoolean((String) obj[0])); - String var = "PlayerUtils.allTargetable"; - - if (PlayerUtils.getAllTargetable()) { - print(var + " is now " + ChatColor.GREEN + "TRUE" + ChatColor.RESET + "."); - } else { - print(var + " is now " + ChatColor.RED + "FALSE" + ChatColor.RESET + "."); - } - } - public void hideNametags() { // this works for some reason Set bots = PlayerAI.getInstance().getManager().fetch(); @@ -213,15 +203,6 @@ public class Debugger { } } - public void printObj(String content) { - if (content.isEmpty()) { - print("null"); - return; - } - - Arrays.stream(buildObjects(content)).forEach(this::print); - } - public void toggleAgent() { Agent agent = PlayerAI.getInstance().getManager().getAgent(); diff --git a/src/main/java/net/nuggetmc/ai/utils/MathUtils.java b/src/main/java/net/nuggetmc/ai/utils/MathUtils.java index aff233a..8f3ab98 100644 --- a/src/main/java/net/nuggetmc/ai/utils/MathUtils.java +++ b/src/main/java/net/nuggetmc/ai/utils/MathUtils.java @@ -3,8 +3,13 @@ package net.nuggetmc.ai.utils; import org.bukkit.util.NumberConversions; import org.bukkit.util.Vector; +import java.util.Random; +import java.util.Set; + public class MathUtils { + public static final Random RANDOM = new Random(); + public static float[] fetchYawPitch(Vector dir) { double x = dir.getX(); double z = dir.getZ(); @@ -57,13 +62,8 @@ public class MathUtils { return new Vector(x, 0, z); } - public static boolean isFinite(Vector vector) { - try { - vector.checkFinite(); - return true; - } catch (IllegalArgumentException e) { - return false; - } + public static boolean isNotFinite(Vector vector) { + return !NumberConversions.isFinite(vector.getX()) || !NumberConversions.isFinite(vector.getY()) || !NumberConversions.isFinite(vector.getZ()); } public static void clean(Vector vector) { @@ -71,4 +71,8 @@ public class MathUtils { if (!NumberConversions.isFinite(vector.getY())) vector.setY(0); if (!NumberConversions.isFinite(vector.getZ())) vector.setZ(0); } + + public static E getRandomSetElement(Set set) { + return set.isEmpty() ? null : set.stream().skip(RANDOM.nextInt(set.size())).findFirst().orElse(null); + } } diff --git a/src/main/java/net/nuggetmc/ai/utils/PlayerUtils.java b/src/main/java/net/nuggetmc/ai/utils/PlayerUtils.java index 8e2bce0..fac6b69 100644 --- a/src/main/java/net/nuggetmc/ai/utils/PlayerUtils.java +++ b/src/main/java/net/nuggetmc/ai/utils/PlayerUtils.java @@ -3,22 +3,7 @@ package net.nuggetmc.ai.utils; import org.bukkit.GameMode; public class PlayerUtils { - - public static boolean allTargetable; - - public static boolean isTargetable(GameMode mode) { - return allTargetable || isVulnerableGameMode(mode); - } - - public static boolean isVulnerableGameMode(GameMode mode) { - return mode == GameMode.SURVIVAL || mode == GameMode.ADVENTURE || mode == null; - } - - public static void setAllTargetable(boolean b) { - allTargetable = b; - } - - public static boolean getAllTargetable() { - return allTargetable; + public static boolean isInvincible(GameMode mode) { + return mode != GameMode.SURVIVAL && mode != GameMode.ADVENTURE && mode != null; } }