diff --git a/src/main/java/net/nuggetmc/ai/bot/Bot.java b/src/main/java/net/nuggetmc/ai/bot/Bot.java index 71614a6..b5a3871 100644 --- a/src/main/java/net/nuggetmc/ai/bot/Bot.java +++ b/src/main/java/net/nuggetmc/ai/bot/Bot.java @@ -6,11 +6,9 @@ import net.minecraft.server.v1_16_R3.Chunk; import net.minecraft.server.v1_16_R3.*; import net.nuggetmc.ai.TerminatorPlus; import net.nuggetmc.ai.bot.agent.legacyagent.ai.NeuralNetwork; +import net.nuggetmc.ai.bot.event.BotDamageByPlayerEvent; import net.nuggetmc.ai.bot.event.BotFallDamageEvent; -import net.nuggetmc.ai.utils.BotUtils; -import net.nuggetmc.ai.utils.MathUtils; -import net.nuggetmc.ai.utils.MojangAPI; -import net.nuggetmc.ai.utils.StringUtilities; +import net.nuggetmc.ai.utils.*; import org.bukkit.Material; import org.bukkit.SoundCategory; import org.bukkit.World; @@ -19,11 +17,11 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.craftbukkit.v1_16_R3.CraftServer; import org.bukkit.craftbukkit.v1_16_R3.CraftWorld; -import org.bukkit.craftbukkit.v1_16_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack; import org.bukkit.entity.Damageable; import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.util.Vector; import java.util.ArrayList; @@ -33,6 +31,9 @@ import java.util.UUID; public class Bot extends EntityPlayer { + private final TerminatorPlus plugin; + private final BukkitScheduler scheduler; + private NeuralNetwork network; public NeuralNetwork getNeuralNetwork() { @@ -48,7 +49,10 @@ public class Bot extends EntityPlayer { } public boolean item; // eventually make this not garbage lol - public boolean shield; + + private boolean shield; + private boolean blocking; + private boolean blockUse; private Vector velocity; private Vector oldVelocity; @@ -59,7 +63,6 @@ public class Bot extends EntityPlayer { private byte fireTicks; private byte groundTicks; private byte jumpTicks; - private byte kbTicks; private byte noFallTicks; private final Vector offset; @@ -67,6 +70,8 @@ public class Bot extends EntityPlayer { private Bot(MinecraftServer minecraftServer, WorldServer worldServer, GameProfile profile, PlayerInteractManager manager) { super(minecraftServer, worldServer, profile, manager); + this.plugin = TerminatorPlus.getInstance(); + this.scheduler = Bukkit.getScheduler(); this.velocity = new Vector(0, 0, 0); this.oldVelocity = velocity.clone(); this.noFallTicks = 60; @@ -115,7 +120,7 @@ public class Bot extends EntityPlayer { connection.sendPacket(packets[2]); if (login) { - Bukkit.getScheduler().runTaskLater(TerminatorPlus.getInstance(), () -> connection.sendPacket(packets[3]), 10); + scheduler.runTaskLater(plugin, () -> connection.sendPacket(packets[3]), 10); } else { connection.sendPacket(packets[3]); } @@ -176,7 +181,6 @@ public class Bot extends EntityPlayer { if (fireTicks > 0) --fireTicks; if (noDamageTicks > 0) --noDamageTicks; if (jumpTicks > 0) --jumpTicks; - if (kbTicks > 0) --kbTicks; if (noFallTicks > 0) --noFallTicks; if (checkGround()) { @@ -272,7 +276,7 @@ public class Bot extends EntityPlayer { if (groundTicks != 0 && noFallTicks == 0 && !(oldVelocity.getY() >= -0.8) && !BotUtils.NO_FALL.contains(getLocation().getBlock().getType())) { BotFallDamageEvent event = new BotFallDamageEvent(this); - TerminatorPlus.getInstance().getManager().getAgent().onFallDamage(event); + plugin.getManager().getAgent().onFallDamage(event); if (!event.isCancelled()) { damageEntity(DamageSource.FALL, (float) Math.pow(3.6, -oldVelocity.getY())); @@ -284,8 +288,34 @@ public class Bot extends EntityPlayer { return velocity.getY() < -0.8; } - public void block() { - // block for 10 ticks, cooldown for 10 extra ticks (20 total) + public void block(int blockLength, int cooldown) { + if (!shield || blockUse) return; + startBlocking(); + scheduler.runTaskLater(plugin, () -> stopBlocking(cooldown), blockLength); + } + + private void startBlocking() { + this.blocking = true; + this.blockUse = true; + c(EnumHand.OFF_HAND); + sendPacket(new PacketPlayOutEntityMetadata(getId(), datawatcher, true)); + } + + private void stopBlocking(int cooldown) { + this.blocking = false; + clearActiveItem(); + scheduler.runTaskLater(plugin, () -> this.blockUse = false, cooldown); + sendPacket(new PacketPlayOutEntityMetadata(getId(), datawatcher, true)); + } + + public boolean isBlocking() { + return blocking; + } + + public void setShield(boolean enabled) { + this.shield = enabled; + + setItemOffhand(new org.bukkit.inventory.ItemStack(enabled ? Material.SHIELD : Material.AIR)); } private void updateLocation() { @@ -355,7 +385,7 @@ public class Bot extends EntityPlayer { punch(); if (entity instanceof Damageable) { - ((Damageable) entity).damage(item ? 6 : 0.25, getBukkitEntity()); // fist damage is 0.25 + ((Damageable) entity).damage(item ? 2.5 : 0.25, getBukkitEntity()); // fist damage is 0.25 } } @@ -435,10 +465,8 @@ public class Bot extends EntityPlayer { private void dieCheck() { if (removeOnDeath) { - TerminatorPlus plugin = TerminatorPlus.getInstance(); - - Bukkit.getScheduler().runTask(plugin, () -> plugin.getManager().remove(this)); - Bukkit.getScheduler().runTaskLater(plugin, this::setDead, 30); + scheduler.runTask(plugin, () -> plugin.getManager().remove(this)); + scheduler.runTaskLater(plugin, this::setDead, 30); this.removeTab(); } @@ -491,17 +519,33 @@ public class Bot extends EntityPlayer { @Override public boolean damageEntity(DamageSource damagesource, float f) { - boolean damaged = super.damageEntity(damagesource, f); - net.minecraft.server.v1_16_R3.Entity attacker = damagesource.getEntity(); - if (damaged && kbTicks == 0 && attacker != null) { - Player player = getBukkitEntity(); - CraftEntity entity = attacker.getBukkitEntity(); - Location loc1 = player.getLocation(); - Location loc2 = entity.getLocation(); + float damage; - kb(loc1, loc2); + if (attacker instanceof EntityPlayer) { + + BotDamageByPlayerEvent event = new BotDamageByPlayerEvent(this, ((EntityPlayer) attacker).getBukkitEntity(), f); + + plugin.getManager().getAgent().onPlayerDamage(event); + + if (event.isCancelled()) { + return false; + } + + damage = event.getDamage(); + } else { + damage = f; + } + + boolean damaged = super.damageEntity(damagesource, damage); + + if (!damaged && blocking) { + getBukkitEntity().getWorld().playSound(getLocation(), Sound.ITEM_SHIELD_BLOCK, 1, 1); + } + + if (damaged && attacker != null) { + kb(getLocation(), attacker.getBukkitEntity().getLocation()); } return damaged; @@ -513,7 +557,6 @@ public class Bot extends EntityPlayer { if (isOnGround()) vel.multiply(0.8).setY(0.4); velocity = vel; - kbTicks = 10; } public Location getLocation() { @@ -565,12 +608,24 @@ public class Bot extends EntityPlayer { } public void setItem(org.bukkit.inventory.ItemStack item) { - if (item == null) item = new org.bukkit.inventory.ItemStack(this.item ? Material.IRON_SWORD : Material.AIR); + setItem(item, EnumItemSlot.MAINHAND); + } - getBukkitEntity().getInventory().setItemInMainHand(item); + public void setItemOffhand(org.bukkit.inventory.ItemStack item) { + setItem(item, EnumItemSlot.OFFHAND); + } + + public void setItem(org.bukkit.inventory.ItemStack item, EnumItemSlot slot) { + if (item == null) item = new org.bukkit.inventory.ItemStack(this.item ? Material.WOODEN_SHOVEL : Material.AIR); + + if (slot == EnumItemSlot.MAINHAND) { + getBukkitEntity().getInventory().setItemInMainHand(item); + } else if (slot == EnumItemSlot.OFFHAND) { + getBukkitEntity().getInventory().setItemInOffHand(item); + } sendPacket(new PacketPlayOutEntityEquipment(getId(), new ArrayList<>(Collections.singletonList( - new Pair<>(EnumItemSlot.MAINHAND, CraftItemStack.asNMSCopy(item)) + new Pair<>(slot, CraftItemStack.asNMSCopy(item)) )))); } diff --git a/src/main/java/net/nuggetmc/ai/bot/BotManager.java b/src/main/java/net/nuggetmc/ai/bot/BotManager.java index 3200e39..27313c1 100644 --- a/src/main/java/net/nuggetmc/ai/bot/BotManager.java +++ b/src/main/java/net/nuggetmc/ai/bot/BotManager.java @@ -11,6 +11,7 @@ import org.bukkit.craftbukkit.v1_16_R3.entity.CraftPlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityDamageByEntityEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.util.Vector; @@ -92,6 +93,8 @@ public class BotManager implements Listener { if (type == NetworkType.RANDOM) { bot.setNeuralNetwork(NeuralNetwork.generateRandomNetwork()); + bot.setShield(true); + bot.item = true; } } @@ -115,4 +118,13 @@ public class BotManager implements Listener { PlayerConnection connection = ((CraftPlayer) event.getPlayer()).getHandle().playerConnection; bots.forEach(bot -> bot.render(connection, true)); } + + @EventHandler + public void onEntityDamage(EntityDamageByEntityEvent event) { + if (!(event.getEntity() instanceof Player)) return; + if (!(event.getDamager() instanceof Player)) return; + + Player player = (Player) event.getEntity(); + Player damager = (Player) event.getDamager(); + } } 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 65ea948..067c43c 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/Agent.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/Agent.java @@ -2,6 +2,7 @@ package net.nuggetmc.ai.bot.agent; import net.nuggetmc.ai.TerminatorPlus; import net.nuggetmc.ai.bot.BotManager; +import net.nuggetmc.ai.bot.event.BotDamageByPlayerEvent; import net.nuggetmc.ai.bot.event.BotFallDamageEvent; import org.bukkit.Bukkit; import org.bukkit.scheduler.BukkitRunnable; @@ -55,4 +56,6 @@ public abstract class Agent { protected abstract void tick(); public void onFallDamage(BotFallDamageEvent event) { } + + public void onPlayerDamage(BotDamageByPlayerEvent event) { } } 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 index 8990733..b352605 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/EnumTargetGoal.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/EnumTargetGoal.java @@ -1,6 +1,6 @@ package net.nuggetmc.ai.bot.agent.legacyagent; -public enum EnumTargetGoal { +public enum EnumTargetGoal { // TODO USE ORDINAL!!!!! NEAREST_REAL_VULNERABLE_PLAYER, NEAREST_REAL_PLAYER, NEAREST_BOT_DIFFER, 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 a5ef3cb..5c7ac73 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 @@ -8,6 +8,7 @@ import net.nuggetmc.ai.bot.agent.Agent; import net.nuggetmc.ai.bot.agent.legacyagent.ai.BotData; import net.nuggetmc.ai.bot.agent.legacyagent.ai.BotNode; import net.nuggetmc.ai.bot.agent.legacyagent.ai.NeuralNetwork; +import net.nuggetmc.ai.bot.event.BotDamageByPlayerEvent; import net.nuggetmc.ai.bot.event.BotFallDamageEvent; import net.nuggetmc.ai.utils.MathUtils; import net.nuggetmc.ai.utils.PlayerUtils; @@ -133,7 +134,7 @@ public class LegacyAgent extends Agent { if (ai) { // force unable to block if they are more than 6/7 blocks away if (network.check(BotNode.BLOCK) && loc.distance(player.getLocation()) < 6) { - bot.block(); + bot.block(10, 10); } } @@ -236,13 +237,17 @@ public class LegacyAgent extends Agent { boolean left = network.check(BotNode.LEFT); boolean right = network.check(BotNode.RIGHT); + if (bot.isBlocking()) { + vel.multiply(0.6); + } + if (left != right && distance <= 6) { if (left) { - vel.rotateAroundY(Math.PI / 3); + vel.rotateAroundY(Math.PI / 4); } if (right) { - vel.rotateAroundY(-Math.PI / 3); + vel.rotateAroundY(-Math.PI / 4); } if (network.check(BotNode.JUMP)) { @@ -275,6 +280,20 @@ public class LegacyAgent extends Agent { } } + @Override + public void onPlayerDamage(BotDamageByPlayerEvent event) { + Bot bot = event.getBot(); + Location loc = bot.getLocation(); + Player player = event.getPlayer(); + + double dot = loc.toVector().subtract(player.getLocation().toVector()).normalize().dot(loc.getDirection()); + + if (bot.isBlocking() && dot >= -0.1) { + player.getWorld().playSound(bot.getLocation(), Sound.ITEM_SHIELD_BLOCK, 1, 1); + event.setCancelled(true); + } + } + @Override public void onFallDamage(BotFallDamageEvent event) { Bot bot = event.getBot(); @@ -300,7 +319,7 @@ public class LegacyAgent extends Agent { if (!loc.clone().add(0, -1, 0).getBlock().getType().isSolid()) return; - event.cancel(); + event.setCancelled(true); if (loc.getBlock().getType() != placeType) { bot.punch(); diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyWorldManager.java b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyWorldManager.java index 36dd5ea..1888be7 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyWorldManager.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/LegacyWorldManager.java @@ -7,13 +7,15 @@ public class LegacyWorldManager { public static boolean aboveGround(Location loc) { int y = 1; - int y0 = loc.getBlockY(); - while (y + y0 < y0 + 25) { + + while (y < 25) { if (loc.clone().add(0, y, 0).getBlock().getType() != Material.AIR) { return false; } + y++; } + return true; } } diff --git a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/ai/NeuralNetwork.java b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/ai/NeuralNetwork.java index 3e99c2b..c6302e3 100644 --- a/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/ai/NeuralNetwork.java +++ b/src/main/java/net/nuggetmc/ai/bot/agent/legacyagent/ai/NeuralNetwork.java @@ -11,6 +11,8 @@ public class NeuralNetwork { // thinking about making an enum called BotNode, and have a map here, .check(Node.L) or fetch // also randomize activation point between 0 and 0.5 + // randomize the blocking length and cooldown + // also the XZ offset randomizers!! (or maybe just turn them off entirely, that works too) private final Map nodes; diff --git a/src/main/java/net/nuggetmc/ai/bot/event/BotDamageByPlayerEvent.java b/src/main/java/net/nuggetmc/ai/bot/event/BotDamageByPlayerEvent.java new file mode 100644 index 0000000..e962834 --- /dev/null +++ b/src/main/java/net/nuggetmc/ai/bot/event/BotDamageByPlayerEvent.java @@ -0,0 +1,44 @@ +package net.nuggetmc.ai.bot.event; + +import net.nuggetmc.ai.bot.Bot; +import org.bukkit.entity.Player; + +public class BotDamageByPlayerEvent { + + private final Bot bot; + private final Player player; + + private float damage; + + private boolean cancelled; + + public BotDamageByPlayerEvent(Bot bot, Player player, float damage) { + this.bot = bot; + this.player = player; + this.damage = damage; + } + + public Bot getBot() { + return bot; + } + + public Player getPlayer() { + return player; + } + + public float getDamage() { + return damage; + } + + public void setDamage(float damage) { + this.damage = damage; + } + + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; + } + + public boolean isCancelled() { + return cancelled; + } +} diff --git a/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java b/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java index ad6c389..3340b85 100644 --- a/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java +++ b/src/main/java/net/nuggetmc/ai/bot/event/BotFallDamageEvent.java @@ -6,7 +6,7 @@ public class BotFallDamageEvent { private final Bot bot; - private boolean isCancelled; + private boolean cancelled; public BotFallDamageEvent(Bot bot) { this.bot = bot; @@ -16,11 +16,11 @@ public class BotFallDamageEvent { return bot; } - public void cancel() { - isCancelled = true; + public void setCancelled(boolean cancelled) { + this.cancelled = cancelled; } public boolean isCancelled() { - return isCancelled; + return cancelled; } } diff --git a/src/main/java/net/nuggetmc/ai/utils/Debugger.java b/src/main/java/net/nuggetmc/ai/utils/Debugger.java index 678c6bb..b704a48 100644 --- a/src/main/java/net/nuggetmc/ai/utils/Debugger.java +++ b/src/main/java/net/nuggetmc/ai/utils/Debugger.java @@ -14,10 +14,7 @@ import org.bukkit.permissions.ServerOperator; import org.bukkit.util.Vector; import java.beans.Statement; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Set; +import java.util.*; public class Debugger { @@ -96,6 +93,10 @@ public class Debugger { * DEBUGGER METHODS */ + public void block() { + TerminatorPlus.getInstance().getManager().fetch().forEach(bot -> bot.block(10, 10)); + } + public void offsets(boolean b) { Agent agent = TerminatorPlus.getInstance().getManager().getAgent(); if (!(agent instanceof LegacyAgent)) { @@ -131,27 +132,62 @@ public class Debugger { } public void dreamsmp() { - if (!(sender instanceof Player)) return; - - Player player = (Player) sender; - Location loc = player.getLocation(); - - String[] players = new String[] { + spawnBots(Arrays.asList( "Dream", "GeorgeNotFound", "Callahan", "Sapnap", "awesamdude", "Ponk", "BadBoyHalo", "TommyInnit", "Tubbo_", "ItsFundy", "Punz", "Purpled", "WilburSoot", "Jschlatt", "Skeppy", "The_Eret", "JackManifoldTV", "Nihachu", "Quackity", "KarlJacobs", "HBomb94", "Technoblade", "Antfrost", "Ph1LzA", "ConnorEatsPants", "CaptainPuffy", "Vikkstar123", "LazarCodeLazar", "Ranboo", "FoolishG", "hannahxxrose", "Slimecicle", "Michaelmcchill" - }; + )); + } - double f = .004 * players.length; + private void spawnBots(List players) { + if (!(sender instanceof Player)) return; - for (String name : players) { - Bot bot = Bot.createBot(loc, name); - bot.setVelocity(new Vector(Math.random() - 0.5, 0.5, Math.random() - 0.5).normalize().multiply(f)); - bot.faceLocation(bot.getLocation().add(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5)); - } + print("Processing request asynchronously..."); - player.getWorld().spawnParticle(Particle.CLOUD, loc, 100, 1, 1, 1, 0.5); + Bukkit.getScheduler().runTaskAsynchronously(TerminatorPlus.getInstance(), () -> { + try { + print("Fetching skin data from the Mojang API for:"); + + Player player = (Player) sender; + Location loc = player.getLocation(); + + Collections.shuffle(players); + + Map skinCache = new HashMap<>(); + + int size = players.size(); + int i = 1; + + for (String name : players) { + print(name, ChatColor.GRAY + "(" + ChatColor.GREEN + i + ChatColor.GRAY + "/" + size + ")"); + String[] skin = MojangAPI.getSkin(name); + skinCache.put(name, skin); + + i++; + } + + print("Creating bots..."); + + double f = .004 * players.size(); + + Bukkit.getScheduler().runTask(TerminatorPlus.getInstance(), () -> { + skinCache.forEach((name, skin) -> { + Bot bot = Bot.createBot(loc, name, skin); + bot.setVelocity(new Vector(Math.random() - 0.5, 0.5, Math.random() - 0.5).normalize().multiply(f)); + bot.faceLocation(bot.getLocation().add(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5)); + }); + + player.getWorld().spawnParticle(Particle.CLOUD, loc, 100, 1, 1, 1, 0.5); + + print("Done."); + }); + } + + catch (Exception e) { + print(e); + } + }); } public void item() { @@ -165,19 +201,17 @@ public class Debugger { public void epic(int n) { if (!(sender instanceof Player)) return; - Player player = (Player) sender; - Location loc = player.getLocation(); + print("Fetching names asynchronously..."); - double f = n < 100 ? .004 * n : .4; + List players = new ArrayList<>(); for (int i = 0; i < n; i++) { String name = PlayerUtils.randomName(); - Bot bot = Bot.createBot(loc, name); - bot.setVelocity(new Vector(Math.random() - 0.5, 0.5, Math.random() - 0.5).normalize().multiply(f)); - bot.faceLocation(bot.getLocation().add(Math.random() - 0.5, Math.random() - 0.5, Math.random() - 0.5)); + players.add(name); + print(name); } - player.getWorld().spawnParticle(Particle.CLOUD, loc, 100, 1, 1, 1, 0.5); + spawnBots(players); } public void tp() {