Files
Tplus/src/main/java/net/nuggetmc/ai/bot/Bot.java

459 lines
14 KiB
Java
Raw Normal View History

package net.nuggetmc.ai.bot;
2021-06-26 19:43:58 -05:00
import com.mojang.authlib.GameProfile;
import com.mojang.datafixers.util.Pair;
2021-06-26 19:43:58 -05:00
import net.minecraft.server.v1_16_R3.*;
import net.nuggetmc.ai.PlayerAI;
2021-07-12 18:24:10 -05:00
import net.nuggetmc.ai.utils.BotUtils;
import net.nuggetmc.ai.utils.MathUtils;
import net.nuggetmc.ai.utils.MojangAPI;
import org.bukkit.Material;
import org.bukkit.SoundCategory;
2021-06-26 19:43:58 -05:00
import org.bukkit.World;
import org.bukkit.*;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
2021-06-26 19:43:58 -05:00
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;
2021-06-26 19:43:58 -05:00
import org.bukkit.entity.Player;
import org.bukkit.util.Vector;
import java.util.ArrayList;
import java.util.List;
2021-07-09 15:49:10 -05:00
import java.util.Objects;
2021-06-26 19:43:58 -05:00
import java.util.UUID;
public class Bot extends EntityPlayer {
2021-06-26 19:43:58 -05:00
public Vector velocity;
2021-06-29 16:29:30 -05:00
private byte aliveTicks;
2021-06-26 19:43:58 -05:00
private byte kbTicks;
2021-06-28 15:17:32 -05:00
private byte jumpTicks;
private byte groundTicks;
2021-06-26 19:43:58 -05:00
2021-07-09 15:49:10 -05:00
private final Vector offset;
2021-06-29 16:29:30 -05:00
public Bot(MinecraftServer minecraftServer, WorldServer worldServer, GameProfile profile, PlayerInteractManager manager) {
2021-06-26 19:43:58 -05:00
super(minecraftServer, worldServer, profile, manager);
2021-06-29 16:29:30 -05:00
this.velocity = new Vector(0, 0, 0);
this.offset = MathUtils.circleOffset(3);
2021-06-29 17:05:11 -05:00
datawatcher.set(new DataWatcherObject<>(16, DataWatcherRegistry.a), (byte) 0xFF);
2021-06-26 19:43:58 -05:00
}
public static Bot createBot(Location loc, String name, String[] skin) {
2021-06-26 19:43:58 -05:00
MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer()).getServer();
2021-07-09 15:49:10 -05:00
WorldServer nmsWorld = ((CraftWorld) Objects.requireNonNull(loc.getWorld())).getHandle();
2021-06-26 19:43:58 -05:00
2021-07-12 18:24:10 -05:00
UUID uuid = BotUtils.randomSteveUUID();
2021-06-26 19:43:58 -05:00
2021-06-29 17:05:11 -05:00
CustomGameProfile profile = new CustomGameProfile(uuid, name, skin);
2021-06-26 19:43:58 -05:00
PlayerInteractManager interactManager = new PlayerInteractManager(nmsWorld);
Bot bot = new Bot(nmsServer, nmsWorld, profile, interactManager);
2021-06-26 19:43:58 -05:00
bot.playerConnection = new PlayerConnection(nmsServer, new NetworkManager(EnumProtocolDirection.CLIENTBOUND), bot);
bot.setLocation(loc.getX(), loc.getY(), loc.getZ(), loc.getYaw(), loc.getPitch());
bot.getBukkitEntity().setNoDamageTicks(0);
nmsWorld.addEntity(bot);
2021-06-26 19:43:58 -05:00
2021-06-29 17:05:11 -05:00
bot.renderAll();
2021-06-26 19:43:58 -05:00
PlayerAI.getInstance().getManager().add(bot);
2021-06-26 19:43:58 -05:00
return bot;
2021-06-26 19:43:58 -05:00
}
public Vector prevVel = new Vector(0, 0, 0);
public int velCount;
public static Bot createBot(Location loc, String name, String skinName) {
return createBot(loc, name, MojangAPI.getSkin(skinName));
2021-06-26 19:43:58 -05:00
}
private void renderAll() {
Packet<?>[] packets = getRenderPackets();
Bukkit.getOnlinePlayers().forEach(p -> render(((CraftPlayer) p).getHandle().playerConnection, packets, false));
}
2021-06-26 19:43:58 -05:00
public void render(PlayerConnection connection, Packet<?>[] packets, boolean login) {
connection.sendPacket(packets[0]);
connection.sendPacket(packets[1]);
connection.sendPacket(packets[2]);
2021-06-26 19:43:58 -05:00
if (login) {
Bukkit.getScheduler().runTaskLater(PlayerAI.getInstance(), () -> connection.sendPacket(packets[3]), 10);
2021-06-26 19:43:58 -05:00
} else {
connection.sendPacket(packets[3]);
2021-06-26 19:43:58 -05:00
}
}
public void render(PlayerConnection connection, boolean login) {
render(connection, getRenderPackets(), login);
}
private Packet<?>[] getRenderPackets() {
return new Packet[] {
new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, this),
new PacketPlayOutNamedEntitySpawn(this),
new PacketPlayOutEntityMetadata(this.getId(), this.getDataWatcher(), true),
new PacketPlayOutEntityHeadRotation(this, (byte) ((this.yaw * 256f) / 360f))
};
}
2021-06-29 16:29:30 -05:00
public Vector getOffset() {
return offset;
}
2021-06-28 15:17:32 -05:00
public Vector getVelocity() {
return velocity.clone();
}
2021-06-26 19:43:58 -05:00
public void setVelocity(Vector vector) {
this.velocity = vector;
}
public void addVelocity(Vector vector) {
2021-06-28 15:17:32 -05:00
try {
velocity.checkFinite();
} catch (IllegalArgumentException e) {
velocity = vector;
return;
}
2021-06-26 19:43:58 -05:00
this.velocity.add(vector);
}
2021-06-29 16:29:30 -05:00
public boolean tickDelay(int i) {
return aliveTicks % i == 0;
}
2021-06-26 19:43:58 -05:00
@Override
public void tick() {
super.tick();
2021-06-29 16:29:30 -05:00
aliveTicks++;
2021-06-26 19:43:58 -05:00
if (noDamageTicks > 0) --noDamageTicks;
if (kbTicks > 0) --kbTicks;
2021-06-28 15:17:32 -05:00
if (jumpTicks > 0) --jumpTicks;
if (checkGround()) {
if (groundTicks < 5) groundTicks++;
2021-06-28 15:17:32 -05:00
} else {
groundTicks = 0;
}
2021-06-26 19:43:58 -05:00
2021-07-04 03:15:30 -05:00
Player player = getBukkitEntity();
if (player.isDead()) return;
2021-06-26 19:43:58 -05:00
2021-07-04 03:15:30 -05:00
updateLocation();
double health = player.getHealth();
double maxHealth = player.getHealthScale();
2021-07-09 15:49:10 -05:00
double regenAmount = 0.05;
2021-06-26 19:43:58 -05:00
double amount;
2021-06-26 20:00:57 -05:00
if (health < maxHealth - regenAmount) {
amount = health + regenAmount;
2021-06-26 19:43:58 -05:00
} else {
amount = maxHealth;
}
2021-07-04 03:15:30 -05:00
player.setHealth(amount);
2021-06-26 19:43:58 -05:00
}
private void updateLocation() {
2021-06-27 21:45:11 -05:00
double y;
// Check to reset y velocity if staying in the same position
if (isInWater()) {
y = Math.min(velocity.getY() + 0.1, 0.1);
addFriction(0.8);
velocity.setY(y);
2021-06-26 19:43:58 -05:00
}
else {
if (groundTicks != 0) {
velocity.setY(0);
addFriction(0.5);
y = 0;
} else {
y = velocity.getY();
}
velocity.setY(Math.max(velocity.getY() - 0.1, -3.5));
}
2021-06-28 15:17:32 -05:00
2021-06-27 21:45:11 -05:00
this.move(EnumMoveType.SELF, new Vec3D(velocity.getX(), y, velocity.getZ()));
2021-06-26 19:43:58 -05:00
}
@Override
public boolean isInWater() {
Location loc = getLocation();
for (int i = 0; i <= 2; i++) {
Material type = loc.getBlock().getType();
if (type == Material.WATER || type == Material.LAVA) {
return true;
}
loc.add(0, 0.9, 0);
}
return false;
}
2021-06-28 15:17:32 -05:00
public void jump(Vector vel) {
if (jumpTicks == 0 && groundTicks > 1) {
jumpTicks = 4;
velocity = vel;
}
}
2021-07-01 01:12:18 -05:00
public void jump() {
jump(new Vector(0, 0.5, 0));
}
2021-06-29 16:29:30 -05:00
public void attack(org.bukkit.entity.Entity entity) {
faceLocation(entity.getLocation());
punch();
attack(((CraftEntity) entity).getHandle());
}
public void punch() {
2021-07-04 03:15:30 -05:00
swingHand(EnumHand.MAIN_HAND);
2021-06-29 16:29:30 -05:00
}
public boolean checkGround() {
2021-06-26 19:43:58 -05:00
double vy = velocity.getY();
if (vy > 0) {
return false;
}
World world = getBukkitEntity().getWorld();
AxisAlignedBB box = getBoundingBox();
double[] xVals = new double[] {
box.minX,
box.maxX
2021-06-26 19:43:58 -05:00
};
double[] zVals = new double[] {
box.minZ,
box.maxZ
2021-06-26 19:43:58 -05:00
};
for (double x : xVals) {
for (double z : zVals) {
Location loc = new Location(world, x, locY() - 0.01, z);
Block block = world.getBlockAt(loc);
if (block.getType().isSolid() && BotUtils.solidAt(loc)) {
2021-06-29 16:29:30 -05:00
return true;
}
2021-06-26 19:43:58 -05:00
}
}
return false;
}
@Override
public boolean isOnGround() {
return groundTicks != 0;
}
public void addFriction(double factor) {
2021-07-09 15:49:10 -05:00
double frictionMin = 0.01;
2021-06-28 15:17:32 -05:00
double x = velocity.getX();
double z = velocity.getZ();
velocity.setX(Math.abs(x) < frictionMin ? 0 : x * factor);
velocity.setZ(Math.abs(z) < frictionMin ? 0 : z * factor);
2021-06-26 19:43:58 -05:00
}
public void despawn() {
2021-06-28 15:17:32 -05:00
getBukkitEntity().remove();
}
public void remove() {
for (Player player : Bukkit.getOnlinePlayers()) {
PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
connection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, this));
}
2021-06-26 19:43:58 -05:00
getBukkitEntity().remove();
}
@Override
public void collide(Entity entity) {
if (!this.isSameVehicle(entity) && !entity.noclip && !this.noclip) {
double d0 = entity.locX() - this.locX();
double d1 = entity.locZ() - this.locZ();
double d2 = MathHelper.a(d0, d1);
if (d2 >= 0.009999999776482582D) {
d2 = MathHelper.sqrt(d2);
d0 /= d2;
d1 /= d2;
double d3 = 1.0D / d2;
if (d3 > 1.0D) {
d3 = 1.0D;
}
d0 *= d3;
d1 *= d3;
d0 *= 0.05000000074505806D;
d1 *= 0.05000000074505806D;
d0 *= 1.0F - this.I;
d1 *= 1.0F - this.I;
if (!this.isVehicle()) {
velocity.add(new Vector(-d0 * 3, 0.0D, -d1 * 3));
}
if (!entity.isVehicle()) {
entity.i(d0, 0.0D, d1);
}
}
}
}
@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();
kb(loc1, loc2);
2021-06-26 19:43:58 -05:00
}
return damaged;
}
private void kb(Location loc1, Location loc2) {
2021-07-09 15:49:10 -05:00
double kbUp = 0.3;
2021-07-04 03:15:30 -05:00
Vector vel = loc1.toVector().subtract(loc2.toVector()).setY(0).normalize().multiply(0.3);
2021-06-28 15:17:32 -05:00
if (isOnGround()) vel.multiply(0.8).setY(0.4);
2021-06-30 02:18:31 -05:00
else if (vel.getY() > kbUp) vel.setY(kbUp);
2021-06-26 19:43:58 -05:00
2021-06-28 15:17:32 -05:00
velocity = vel;
2021-06-26 19:43:58 -05:00
kbTicks = 10;
}
2021-06-28 03:14:07 -05:00
public Location getLocation() {
return getBukkitEntity().getLocation();
}
2021-06-26 19:43:58 -05:00
public void faceLocation(Location loc) {
look(loc.toVector().subtract(getLocation().toVector()), false);
}
public void look(BlockFace face) {
look(face.getDirection(), face == BlockFace.DOWN || face == BlockFace.UP);
}
private void look(Vector dir, boolean keepYaw) {
float yaw, pitch;
if (keepYaw) {
yaw = this.yaw;
pitch = MathUtils.fetchPitch(dir);
} else {
float[] vals = MathUtils.fetchYawPitch(dir);
yaw = vals[0];
pitch = vals[1];
PacketPlayOutEntityHeadRotation packet = new PacketPlayOutEntityHeadRotation(getBukkitEntity().getHandle(), (byte) (yaw * 256 / 360f));
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet));
}
setYawPitch(yaw, pitch);
// this causes a lot of lag lol
//PacketPlayOutEntity.PacketPlayOutEntityLook packet = new PacketPlayOutEntity.PacketPlayOutEntityLook(getId(), (byte) (yaw * 256 / 360f), (byte) (pitch * 256 / 360f), isOnGround());
//Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet));
}
public void attemptBlockPlace(Location loc, Material type) {
setItem(new org.bukkit.inventory.ItemStack(Material.COBBLESTONE));
punch();
Block block = loc.getBlock();
World world = loc.getWorld();
if (!block.getType().isSolid()) {
block.setType(type);
if (world != null) world.playSound(loc, Sound.BLOCK_STONE_PLACE, SoundCategory.BLOCKS, 1, 1);
}
2021-06-26 19:43:58 -05:00
}
public void setItem(org.bukkit.inventory.ItemStack item) {
if (item == null) item = new org.bukkit.inventory.ItemStack(Material.AIR);
CraftPlayer player = getBukkitEntity();
player.getInventory().setItemInMainHand(item);
List<Pair<EnumItemSlot, ItemStack>> equipment = new ArrayList<>();
equipment.add(new Pair<>(EnumItemSlot.MAINHAND, CraftItemStack.asNMSCopy(item)));
PacketPlayOutEntityEquipment packet = new PacketPlayOutEntityEquipment(player.getEntityId(), equipment);
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet));
}
public void swim() {
getBukkitEntity().setSwimming(true);
registerPose(EntityPose.SWIMMING);
}
public void sneak() {
getBukkitEntity().setSneaking(true);
registerPose(EntityPose.CROUCHING);
}
public void stand() {
Player player = getBukkitEntity();
player.setSneaking(false);
player.setSwimming(false);
registerPose(EntityPose.STANDING);
}
private void registerPose(EntityPose pose) {
datawatcher.set(DataWatcherRegistry.s.a(6), pose);
PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(getId(), datawatcher, false);
Bukkit.getOnlinePlayers().forEach(p -> ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet));
}
2021-06-26 19:43:58 -05:00
@Override
public void playerTick() {
if (this.hurtTicks > 0) {
this.hurtTicks -= 1;
}
entityBaseTick();
tickPotionEffects();
this.aU = (int) this.aT;
this.aL = this.aK;
this.lastYaw = this.yaw;
this.lastPitch = this.pitch;
}
}