Added basic following agent.
This commit is contained in:
@@ -24,9 +24,13 @@ public class Bot extends EntityPlayer {
|
|||||||
public Vector velocity;
|
public Vector velocity;
|
||||||
|
|
||||||
private byte kbTicks;
|
private byte kbTicks;
|
||||||
|
private byte jumpTicks;
|
||||||
|
private byte groundTicks;
|
||||||
|
|
||||||
private final double regenAmount = 0.05;
|
private final double regenAmount = 0.05;
|
||||||
private final double bbOffset = 0.05;
|
private final double bbOffset = 0.05;
|
||||||
|
private final double frictionMin = 0.01;
|
||||||
|
private final double kbUp = 0.3;
|
||||||
|
|
||||||
public Bot(MinecraftServer minecraftServer, WorldServer worldServer, GameProfile profile, PlayerInteractManager manager) {
|
public Bot(MinecraftServer minecraftServer, WorldServer worldServer, GameProfile profile, PlayerInteractManager manager) {
|
||||||
super(minecraftServer, worldServer, profile, manager);
|
super(minecraftServer, worldServer, profile, manager);
|
||||||
@@ -92,11 +96,22 @@ public class Bot extends EntityPlayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Vector getVelocity() {
|
||||||
|
return velocity.clone();
|
||||||
|
}
|
||||||
|
|
||||||
public void setVelocity(Vector vector) {
|
public void setVelocity(Vector vector) {
|
||||||
this.velocity = vector;
|
this.velocity = vector;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addVelocity(Vector vector) {
|
public void addVelocity(Vector vector) {
|
||||||
|
try {
|
||||||
|
velocity.checkFinite();
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
velocity = vector;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.velocity.add(vector);
|
this.velocity.add(vector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -106,6 +121,13 @@ public class Bot extends EntityPlayer {
|
|||||||
|
|
||||||
if (noDamageTicks > 0) --noDamageTicks;
|
if (noDamageTicks > 0) --noDamageTicks;
|
||||||
if (kbTicks > 0) --kbTicks;
|
if (kbTicks > 0) --kbTicks;
|
||||||
|
if (jumpTicks > 0) --jumpTicks;
|
||||||
|
|
||||||
|
if (predictGround()) {
|
||||||
|
groundTicks++;
|
||||||
|
} else {
|
||||||
|
groundTicks = 0;
|
||||||
|
}
|
||||||
|
|
||||||
Player botPlayer = this.getBukkitEntity();
|
Player botPlayer = this.getBukkitEntity();
|
||||||
if (botPlayer.isDead()) return;
|
if (botPlayer.isDead()) return;
|
||||||
@@ -128,11 +150,9 @@ public class Bot extends EntityPlayer {
|
|||||||
private void updateLocation() {
|
private void updateLocation() {
|
||||||
// Eventually there will be a whole algorithm here to slow a player down to a certain velocity depending on the liquid a player is in
|
// Eventually there will be a whole algorithm here to slow a player down to a certain velocity depending on the liquid a player is in
|
||||||
|
|
||||||
velocity.setY(velocity.getY() - 0.1);
|
|
||||||
|
|
||||||
double y;
|
double y;
|
||||||
|
|
||||||
if (predictGround()) {
|
if (groundTicks > 0) {
|
||||||
velocity.setY(0);
|
velocity.setY(0);
|
||||||
addFriction();
|
addFriction();
|
||||||
y = 0;
|
y = 0;
|
||||||
@@ -140,9 +160,18 @@ public class Bot extends EntityPlayer {
|
|||||||
y = velocity.getY();
|
y = velocity.getY();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
velocity.setY(velocity.getY() - 0.1);
|
||||||
|
|
||||||
this.move(EnumMoveType.SELF, new Vec3D(velocity.getX(), y, velocity.getZ()));
|
this.move(EnumMoveType.SELF, new Vec3D(velocity.getX(), y, velocity.getZ()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void jump(Vector vel) {
|
||||||
|
if (jumpTicks == 0 && groundTicks > 1) {
|
||||||
|
jumpTicks = 4;
|
||||||
|
velocity = vel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public boolean predictGround() {
|
public boolean predictGround() {
|
||||||
double vy = velocity.getY();
|
double vy = velocity.getY();
|
||||||
|
|
||||||
@@ -165,13 +194,7 @@ public class Bot extends EntityPlayer {
|
|||||||
|
|
||||||
for (double x : xVals) {
|
for (double x : xVals) {
|
||||||
for (double z : zVals) {
|
for (double z : zVals) {
|
||||||
double i = locY();
|
return world.getBlockAt(new Location(world, x, locY() - 0.01, z)).getType().isSolid();
|
||||||
|
|
||||||
Location test = new Location(world, x, i - 0.05, z);
|
|
||||||
|
|
||||||
if (test.getBlock().getType().isSolid()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,11 +202,18 @@ public class Bot extends EntityPlayer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void addFriction() {
|
public void addFriction() {
|
||||||
velocity.setX(velocity.getX() * 0.5);
|
double x = velocity.getX();
|
||||||
velocity.setZ(velocity.getZ() * 0.5);
|
double z = velocity.getZ();
|
||||||
|
|
||||||
|
velocity.setX(x < frictionMin ? 0 : x * 0.5);
|
||||||
|
velocity.setZ(z < frictionMin ? 0 : z * 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void despawn() {
|
public void despawn() {
|
||||||
|
getBukkitEntity().remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void remove() {
|
||||||
for (Player player : Bukkit.getOnlinePlayers()) {
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
|
PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
|
||||||
connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, this));
|
connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, this));
|
||||||
@@ -245,10 +275,14 @@ public class Bot extends EntityPlayer {
|
|||||||
|
|
||||||
private void kb(Location loc1, Location loc2) {
|
private void kb(Location loc1, Location loc2) {
|
||||||
Vector diff = loc1.toVector().subtract(loc2.toVector()).normalize();
|
Vector diff = loc1.toVector().subtract(loc2.toVector()).normalize();
|
||||||
diff.multiply(0.25);
|
diff.multiply(0.5);
|
||||||
diff.setY(0.5);
|
diff.setY(kbUp);
|
||||||
|
|
||||||
velocity.add(diff);
|
Vector vel = velocity.clone().add(diff);
|
||||||
|
if (vel.length() > 1) vel.normalize();
|
||||||
|
if (vel.getY() > kbUp) vel.setY(kbUp);
|
||||||
|
|
||||||
|
velocity = vel;
|
||||||
kbTicks = 10;
|
kbTicks = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package net.nuggetmc.ai.bot;
|
|||||||
|
|
||||||
import net.minecraft.server.v1_16_R3.PlayerConnection;
|
import net.minecraft.server.v1_16_R3.PlayerConnection;
|
||||||
import net.nuggetmc.ai.PlayerAI;
|
import net.nuggetmc.ai.PlayerAI;
|
||||||
|
import net.nuggetmc.ai.bot.agent.BotAgent;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Particle;
|
import org.bukkit.Particle;
|
||||||
@@ -13,12 +14,16 @@ import org.bukkit.event.Listener;
|
|||||||
import org.bukkit.event.player.PlayerJoinEvent;
|
import org.bukkit.event.player.PlayerJoinEvent;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
import java.text.NumberFormat;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
public class BotManager implements Listener {
|
public class BotManager implements Listener {
|
||||||
|
|
||||||
private final PlayerAI plugin;
|
private final PlayerAI plugin;
|
||||||
|
private final BotAgent agent;
|
||||||
|
private final NumberFormat numberFormat;
|
||||||
|
|
||||||
private final Set<Bot> bots = new HashSet<>();
|
private final Set<Bot> bots = new HashSet<>();
|
||||||
|
|
||||||
@@ -32,6 +37,8 @@ public class BotManager implements Listener {
|
|||||||
|
|
||||||
public BotManager(PlayerAI plugin) {
|
public BotManager(PlayerAI plugin) {
|
||||||
this.plugin = plugin;
|
this.plugin = plugin;
|
||||||
|
this.agent = new BotAgent(this);
|
||||||
|
this.numberFormat = NumberFormat.getInstance(Locale.US);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createBots(Player sender, String name, String skin, int n) {
|
public void createBots(Player sender, String name, String skin, int n) {
|
||||||
@@ -45,27 +52,28 @@ public class BotManager implements Listener {
|
|||||||
if (name.length() > 16) name = name.substring(0, 16);
|
if (name.length() > 16) name = name.substring(0, 16);
|
||||||
if (skin != null && skin.length() > 16) skin = skin.substring(0, 16);
|
if (skin != null && skin.length() > 16) skin = skin.substring(0, 16);
|
||||||
|
|
||||||
sender.sendMessage("Creating " + (n == 1 ? "new bot" : ChatColor.RED + String.valueOf(n) + ChatColor.RESET + " new bots")
|
sender.sendMessage("Creating " + (n == 1 ? "new bot" : ChatColor.RED + numberFormat.format(n) + ChatColor.RESET + " new bots")
|
||||||
+ " with name " + ChatColor.GREEN + name
|
+ " with name " + ChatColor.GREEN + name
|
||||||
+ (skin == null ? "" : ChatColor.RESET + " and skin " + ChatColor.GREEN + skin) + ChatColor.RESET + "...");
|
+ (skin == null ? "" : ChatColor.RESET + " and skin " + ChatColor.GREEN + skin)
|
||||||
|
+ ChatColor.RESET + "...");
|
||||||
|
|
||||||
skin = skin == null ? name : skin;
|
skin = skin == null ? name : skin;
|
||||||
|
|
||||||
|
double f = n < 100 ? .004 * n : .4;
|
||||||
|
|
||||||
for (int i = 0; i < n; i++) {
|
for (int i = 0; i < n; i++) {
|
||||||
Bot bot = Bot.createBot(loc, name, skin);
|
Bot bot = Bot.createBot(loc, name, skin);
|
||||||
if (i > 0) bot.setVelocity(new Vector(Math.random() - 0.5, 0.5, Math.random() - 0.5).normalize().multiply(0.4));
|
if (i > 0) 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);
|
world.spawnParticle(Particle.CLOUD, loc, 100, 1, 1, 1, 0.5);
|
||||||
|
|
||||||
double time = (System.currentTimeMillis() - timestamp) / 1000D;
|
sender.sendMessage("Process completed (" + ChatColor.RED + ((System.currentTimeMillis() - timestamp) / 1000D) + "s" + ChatColor.RESET + ").");
|
||||||
|
|
||||||
sender.sendMessage("Process completed (" + ChatColor.RED + time + "s" + ChatColor.RESET + ").");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
for (Bot bot : bots) {
|
for (Bot bot : bots) {
|
||||||
bot.despawn();
|
bot.remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
bots.clear();
|
bots.clear();
|
||||||
|
|||||||
70
src/main/java/net/nuggetmc/ai/bot/agent/BotAgent.java
Normal file
70
src/main/java/net/nuggetmc/ai/bot/agent/BotAgent.java
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package net.nuggetmc.ai.bot.agent;
|
||||||
|
|
||||||
|
import net.nuggetmc.ai.PlayerAI;
|
||||||
|
import net.nuggetmc.ai.bot.Bot;
|
||||||
|
import net.nuggetmc.ai.bot.BotManager;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
|
public class BotAgent {
|
||||||
|
|
||||||
|
private BotManager manager;
|
||||||
|
|
||||||
|
private byte quarterTick = 0;
|
||||||
|
|
||||||
|
public BotAgent(BotManager manager) {
|
||||||
|
this.manager = manager;
|
||||||
|
|
||||||
|
Bukkit.getScheduler().scheduleSyncRepeatingTask(PlayerAI.getInstance(), this::tick, 0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tick() {
|
||||||
|
quarterTick = (byte) ((quarterTick + 1) % 5);
|
||||||
|
manager.fetch().forEach(this::tickBot);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tickBot(Bot bot) {
|
||||||
|
Location loc = bot.getLocation();
|
||||||
|
|
||||||
|
Player player = nearestPlayer(loc);
|
||||||
|
if (player == null) return;
|
||||||
|
|
||||||
|
Location target = player.getLocation();
|
||||||
|
Vector vel = target.toVector().subtract(loc.toVector()).normalize();
|
||||||
|
|
||||||
|
if (quarterTick == 0) {
|
||||||
|
bot.faceLocation(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
vel.checkFinite();
|
||||||
|
vel.add(bot.velocity);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
vel = bot.velocity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vel.length() > 1) vel.normalize();
|
||||||
|
vel.multiply(0.3);
|
||||||
|
vel.setY(0.5);
|
||||||
|
|
||||||
|
if (bot.predictGround()) {
|
||||||
|
bot.jump(vel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Player nearestPlayer(Location loc) {
|
||||||
|
Player result = null;
|
||||||
|
|
||||||
|
for (Player player : Bukkit.getOnlinePlayers()) {
|
||||||
|
if (loc.getWorld() != player.getWorld()) continue;
|
||||||
|
|
||||||
|
if (result == null || loc.distance(player.getLocation()) < loc.distance(result.getLocation())) {
|
||||||
|
result = player;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user