2021-08-24 19:54:46 -05:00
package net.nuggetmc.tplus.bot ;
2021-06-26 19:43:58 -05:00
import com.mojang.authlib.GameProfile ;
2021-07-10 23:51:14 -05:00
import com.mojang.datafixers.util.Pair ;
2021-08-21 13:36:10 -05:00
import io.netty.util.concurrent.Future ;
import io.netty.util.concurrent.GenericFutureListener ;
2021-07-21 13:52:21 -05:00
import net.minecraft.server.v1_16_R3.Chunk ;
2021-06-26 19:43:58 -05:00
import net.minecraft.server.v1_16_R3.* ;
2021-08-24 19:54:46 -05:00
import net.nuggetmc.tplus.TerminatorPlus ;
import net.nuggetmc.tplus.bot.agent.Agent ;
import net.nuggetmc.tplus.bot.agent.legacyagent.ai.NeuralNetwork ;
import net.nuggetmc.tplus.bot.event.BotDamageByPlayerEvent ;
import net.nuggetmc.tplus.bot.event.BotFallDamageEvent ;
import net.nuggetmc.tplus.bot.event.BotKilledByPlayerEvent ;
import net.nuggetmc.tplus.utils.* ;
2021-07-10 23:51:14 -05:00
import org.bukkit.Material ;
import org.bukkit.SoundCategory ;
2021-06-26 19:43:58 -05:00
import org.bukkit.World ;
2021-07-10 23:51:14 -05:00
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.CraftPlayer ;
2021-07-10 23:51:14 -05:00
import org.bukkit.craftbukkit.v1_16_R3.inventory.CraftItemStack ;
2021-07-16 03:41:21 -05:00
import org.bukkit.entity.Damageable ;
2021-06-26 19:43:58 -05:00
import org.bukkit.entity.Player ;
2021-07-24 23:34:07 -05:00
import org.bukkit.inventory.ItemStack ;
2021-07-23 17:25:10 -05:00
import org.bukkit.scheduler.BukkitScheduler ;
2021-06-26 19:43:58 -05:00
import org.bukkit.util.Vector ;
2021-08-21 13:36:10 -05:00
import javax.annotation.Nullable ;
2021-07-10 23:51:14 -05:00
import java.util.ArrayList ;
2021-07-16 03:41:21 -05:00
import java.util.Collections ;
2021-07-09 15:49:10 -05:00
import java.util.Objects ;
2021-06-26 19:43:58 -05:00
import java.util.UUID ;
2021-06-27 00:26:45 -05:00
public class Bot extends EntityPlayer {
2021-06-26 19:43:58 -05:00
2021-07-23 17:25:10 -05:00
private final TerminatorPlus plugin ;
private final BukkitScheduler scheduler ;
2021-07-24 23:34:07 -05:00
private final Agent agent ;
2021-07-23 17:25:10 -05:00
2021-07-23 03:47:11 -05:00
private NeuralNetwork network ;
public NeuralNetwork getNeuralNetwork ( ) {
return network ;
}
public void setNeuralNetwork ( NeuralNetwork network ) {
this . network = network ;
}
public boolean hasNeuralNetwork ( ) {
return network ! = null ;
}
2021-07-24 23:34:07 -05:00
public ItemStack defaultItem ;
2021-07-23 17:25:10 -05:00
private boolean shield ;
private boolean blocking ;
private boolean blockUse ;
2021-07-21 13:52:21 -05:00
2021-07-23 03:47:11 -05:00
private Vector velocity ;
2021-07-16 03:41:21 -05:00
private Vector oldVelocity ;
2021-07-24 23:34:07 -05:00
private boolean removeOnDeath ;
private int aliveTicks ;
private int kills ;
2021-06-26 19:43:58 -05:00
2021-07-16 03:41:21 -05:00
private byte fireTicks ;
2021-06-28 15:17:32 -05:00
private byte groundTicks ;
2021-07-16 03:41:21 -05:00
private byte jumpTicks ;
private byte noFallTicks ;
2021-06-26 19:43:58 -05:00
2021-07-09 15:49:10 -05:00
private final Vector offset ;
2021-08-25 12:30:03 -04:00
public static boolean mobTargeting ;
2021-06-29 16:29:30 -05:00
2021-07-16 03:41:21 -05:00
private Bot ( MinecraftServer minecraftServer , WorldServer worldServer , GameProfile profile , PlayerInteractManager manager ) {
2021-06-26 19:43:58 -05:00
super ( minecraftServer , worldServer , profile , manager ) ;
2021-07-23 17:25:10 -05:00
this . plugin = TerminatorPlus . getInstance ( ) ;
this . scheduler = Bukkit . getScheduler ( ) ;
2021-07-24 23:34:07 -05:00
this . agent = plugin . getManager ( ) . getAgent ( ) ;
this . defaultItem = new ItemStack ( Material . AIR ) ;
2021-06-29 16:29:30 -05:00
this . velocity = new Vector ( 0 , 0 , 0 ) ;
2021-07-16 03:41:21 -05:00
this . oldVelocity = velocity . clone ( ) ;
this . noFallTicks = 60 ;
this . fireTicks = 0 ;
2021-07-23 03:47:11 -05:00
this . removeOnDeath = true ;
2021-06-29 16:29:30 -05:00
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
}
2021-07-21 13:52:21 -05:00
public static Bot createBot ( Location loc , String name ) {
2021-07-23 03:47:11 -05:00
return createBot ( loc , name , MojangAPI . getSkin ( name ) ) ;
2021-07-21 13:52:21 -05:00
}
2021-07-23 03:47:11 -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-08-24 19:54:46 -05:00
CustomGameProfile profile = new CustomGameProfile ( uuid , ChatUtils . trim16 ( name ) , skin ) ;
2021-06-26 19:43:58 -05:00
PlayerInteractManager interactManager = new PlayerInteractManager ( nmsWorld ) ;
2021-06-27 00:26:45 -05:00
Bot bot = new Bot ( nmsServer , nmsWorld , profile , interactManager ) ;
2021-06-26 19:43:58 -05:00
2021-08-21 13:36:10 -05:00
bot . playerConnection = new PlayerConnection ( nmsServer , new NetworkManager ( EnumProtocolDirection . CLIENTBOUND ) {
@Override
public void sendPacket ( Packet < ? > packet , @Nullable GenericFutureListener < ? extends Future < ? super Void > > genericfuturelistener ) { }
} , bot ) ;
2021-06-27 00:26:45 -05:00
bot . setLocation ( loc . getX ( ) , loc . getY ( ) , loc . getZ ( ) , loc . getYaw ( ) , loc . getPitch ( ) ) ;
bot . getBukkitEntity ( ) . setNoDamageTicks ( 0 ) ;
2021-08-25 15:57:06 -04:00
Bukkit . getOnlinePlayers ( ) . forEach ( p - > ( ( CraftPlayer ) p ) . getHandle ( ) . playerConnection . sendPacket (
new PacketPlayOutPlayerInfo ( PacketPlayOutPlayerInfo . EnumPlayerInfoAction . ADD_PLAYER , bot ) ) ) ;
2021-08-25 12:30:03 -04:00
if ( mobTargeting )
nmsWorld . addPlayerJoin ( bot ) ;
else
nmsWorld . addEntity ( bot ) ;
2021-06-26 19:43:58 -05:00
2021-06-29 17:05:11 -05:00
bot . renderAll ( ) ;
2021-08-25 15:57:06 -04:00
2021-07-21 13:52:21 -05:00
TerminatorPlus . getInstance ( ) . getManager ( ) . add ( bot ) ;
2021-06-26 19:43:58 -05:00
2021-06-27 00:26:45 -05:00
return bot ;
2021-06-26 19:43:58 -05:00
}
2021-07-10 23:51:14 -05:00
private void renderAll ( ) {
2021-08-25 16:18:10 -04:00
Packet < ? > [ ] packets = getRenderPacketsNoInfo ( ) ;
Bukkit . getOnlinePlayers ( ) . forEach ( p - > renderNoInfo ( ( ( CraftPlayer ) p ) . getHandle ( ) . playerConnection , packets , false ) ) ;
2021-07-10 23:51:14 -05:00
}
2021-06-26 19:43:58 -05:00
2021-07-16 03:41:21 -05:00
private void render ( PlayerConnection connection , Packet < ? > [ ] packets , boolean login ) {
2021-07-10 23:51:14 -05:00
connection . sendPacket ( packets [ 0 ] ) ;
connection . sendPacket ( packets [ 1 ] ) ;
connection . sendPacket ( packets [ 2 ] ) ;
2021-06-26 19:43:58 -05:00
if ( login ) {
2021-07-23 17:25:10 -05:00
scheduler . runTaskLater ( plugin , ( ) - > connection . sendPacket ( packets [ 3 ] ) , 10 ) ;
2021-06-26 19:43:58 -05:00
} else {
2021-07-10 23:51:14 -05:00
connection . sendPacket ( packets [ 3 ] ) ;
2021-06-26 19:43:58 -05:00
}
}
2021-08-25 15:57:06 -04:00
2021-08-25 16:18:10 -04:00
private void renderNoInfo ( PlayerConnection connection , Packet < ? > [ ] packets , boolean login ) {
2021-08-25 15:57:06 -04:00
connection . sendPacket ( packets [ 0 ] ) ;
connection . sendPacket ( packets [ 1 ] ) ;
if ( login ) {
scheduler . runTaskLater ( plugin , ( ) - > connection . sendPacket ( packets [ 2 ] ) , 10 ) ;
} else {
connection . sendPacket ( packets [ 2 ] ) ;
}
}
2021-06-26 19:43:58 -05:00
2021-07-10 23:51:14 -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-08-25 15:57:06 -04:00
2021-08-25 16:18:10 -04:00
private Packet < ? > [ ] getRenderPacketsNoInfo ( ) {
2021-08-25 15:57:06 -04:00
return new Packet [ ] {
new PacketPlayOutNamedEntitySpawn ( this ) ,
new PacketPlayOutEntityMetadata ( this . getId ( ) , this . getDataWatcher ( ) , true ) ,
new PacketPlayOutEntityHeadRotation ( this , ( byte ) ( ( this . yaw * 256f ) / 360f ) )
2021-07-10 23:51:14 -05:00
} ;
}
2021-07-24 23:34:07 -05:00
public void setDefaultItem ( ItemStack item ) {
this . defaultItem = item ;
}
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 ;
}
2021-07-19 17:35:28 -05:00
public void addVelocity ( Vector vector ) { // This can cause lag? (maybe i fixed it with the new static method)
if ( MathUtils . isNotFinite ( vector ) ) {
2021-06-28 15:17:32 -05:00
velocity = vector ;
return ;
}
2021-07-19 17:35:28 -05:00
velocity . add ( vector ) ;
2021-06-26 19:43:58 -05:00
}
2021-07-24 23:34:07 -05:00
public int getAliveTicks ( ) {
return aliveTicks ;
}
2021-06-29 16:29:30 -05:00
public boolean tickDelay ( int i ) {
return aliveTicks % i = = 0 ;
}
2021-07-16 03:41:21 -05:00
private void sendPacket ( Packet < ? > packet ) {
Bukkit . getOnlinePlayers ( ) . forEach ( p - > ( ( CraftPlayer ) p ) . getHandle ( ) . playerConnection . sendPacket ( packet ) ) ;
}
2021-06-26 19:43:58 -05:00
@Override
public void tick ( ) {
2021-07-21 13:52:21 -05:00
loadChunks ( ) ;
2021-06-26 19:43:58 -05:00
super . tick ( ) ;
2021-07-16 03:41:21 -05:00
if ( ! isAlive ( ) ) return ;
2021-06-29 16:29:30 -05:00
aliveTicks + + ;
2021-07-16 03:41:21 -05:00
if ( fireTicks > 0 ) - - fireTicks ;
2021-06-26 19:43:58 -05:00
if ( noDamageTicks > 0 ) - - noDamageTicks ;
2021-06-28 15:17:32 -05:00
if ( jumpTicks > 0 ) - - jumpTicks ;
2021-07-16 03:41:21 -05:00
if ( noFallTicks > 0 ) - - noFallTicks ;
2021-06-28 15:17:32 -05:00
2021-07-10 23:51:14 -05:00
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
updateLocation ( ) ;
2021-07-16 03:41:21 -05:00
float health = getHealth ( ) ;
float maxHealth = getMaxHealth ( ) ;
2021-07-21 13:52:21 -05:00
float regenAmount = 0 . 025f ;
2021-07-16 03:41:21 -05:00
float amount ;
2021-06-26 19:43:58 -05:00
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-16 03:41:21 -05:00
setHealth ( amount ) ;
fireDamageCheck ( ) ;
fallDamageCheck ( ) ;
2021-08-25 12:13:23 -04:00
2021-08-25 21:58:50 -05:00
if ( locY ( ) < - 64 ) {
an ( ) ;
}
2021-07-16 03:41:21 -05:00
oldVelocity = velocity . clone ( ) ;
}
2021-07-21 13:52:21 -05:00
private void loadChunks ( ) {
net . minecraft . server . v1_16_R3 . World world = getWorld ( ) ;
for ( int i = chunkX - 1 ; i < = chunkX + 1 ; i + + ) {
for ( int j = chunkZ - 1 ; j < = chunkZ + 1 ; j + + ) {
Chunk chunk = world . getChunkAt ( i , j ) ;
if ( ! chunk . loaded ) {
2021-08-21 13:36:10 -05:00
chunk . loaded = true ;
2021-07-21 13:52:21 -05:00
}
}
}
}
2021-07-16 03:41:21 -05:00
private void fireDamageCheck ( ) {
2021-07-19 17:35:28 -05:00
if ( ! isAlive ( ) ) {
return ; // maybe also have packet reset thing
}
2021-07-16 03:41:21 -05:00
Material type = getLocation ( ) . getBlock ( ) . getType ( ) ;
2021-07-19 17:35:28 -05:00
if ( type = = Material . WATER ) {
setOnFirePackets ( false ) ; // maybe also play extinguish noise?
fireTicks = 0 ;
return ;
}
2021-07-16 03:41:21 -05:00
boolean lava = type = = org . bukkit . Material . LAVA ;
if ( lava | | type = = org . bukkit . Material . FIRE | | type = = Material . SOUL_FIRE ) {
ignite ( ) ;
}
if ( noDamageTicks = = 0 ) {
if ( lava ) {
damageEntity ( DamageSource . LAVA , 4 ) ;
noDamageTicks = 12 ;
} else if ( fireTicks > 1 ) {
damageEntity ( DamageSource . FIRE , 1 ) ;
noDamageTicks = 20 ;
}
}
if ( fireTicks = = 1 ) {
setOnFirePackets ( false ) ;
}
}
public void ignite ( ) {
if ( fireTicks < = 1 ) setOnFirePackets ( true ) ;
fireTicks = 100 ;
}
public void setOnFirePackets ( boolean onFire ) {
datawatcher . set ( new DataWatcherObject < > ( 0 , DataWatcherRegistry . a ) , onFire ? ( byte ) 1 : ( byte ) 0 ) ;
sendPacket ( new PacketPlayOutEntityMetadata ( getId ( ) , datawatcher , false ) ) ;
}
2021-07-19 17:35:28 -05:00
public boolean isOnFire ( ) {
return fireTicks ! = 0 ;
}
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 ) ;
2021-07-16 03:41:21 -05:00
2021-07-23 17:25:10 -05:00
plugin . getManager ( ) . getAgent ( ) . onFallDamage ( event ) ;
2021-07-19 17:35:28 -05:00
if ( ! event . isCancelled ( ) ) {
damageEntity ( DamageSource . FALL , ( float ) Math . pow ( 3 . 6 , - oldVelocity . getY ( ) ) ) ;
}
}
}
public boolean isFalling ( ) {
return velocity . getY ( ) < - 0 . 8 ;
2021-06-26 19:43:58 -05:00
}
2021-07-23 17:25:10 -05:00
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 ) ) ;
2021-07-23 03:47:11 -05:00
}
2021-06-26 19:43:58 -05:00
private void updateLocation ( ) {
2021-06-27 21:45:11 -05:00
double y ;
2021-07-19 17:35:28 -05:00
MathUtils . clean ( velocity ) ; // TODO lag????
2021-07-12 18:20:17 -05:00
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
}
2021-07-12 18:20:17 -05:00
else {
if ( groundTicks ! = 0 ) {
velocity . setY ( 0 ) ;
addFriction ( 0 . 5 ) ;
y = 0 ;
} else {
y = velocity . getY ( ) ;
2021-07-19 17:35:28 -05:00
velocity . setY ( Math . max ( y - 0 . 1 , - 3 . 5 ) ) ;
2021-07-12 18:20:17 -05:00
}
}
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
}
2021-07-12 18:20:17 -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-07-23 03:47:11 -05:00
public void walk ( Vector vel ) {
double max = 0 . 4 ;
Vector sum = velocity . clone ( ) . add ( vel ) ;
if ( sum . length ( ) > max ) sum . normalize ( ) . multiply ( max ) ;
velocity = sum ;
}
2021-07-16 03:59:24 -05:00
public void attack ( org . bukkit . entity . Entity entity ) {
2021-06-29 16:29:30 -05:00
faceLocation ( entity . getLocation ( ) ) ;
punch ( ) ;
2021-07-16 03:41:21 -05:00
2021-08-21 13:36:10 -05:00
double damage = ItemUtils . getLegacyAttackDamage ( defaultItem ) ;
2021-07-16 03:41:21 -05:00
if ( entity instanceof Damageable ) {
2021-08-21 13:36:10 -05:00
( ( Damageable ) entity ) . damage ( damage , getBukkitEntity ( ) ) ;
2021-07-16 03:41:21 -05:00
}
2021-06-29 16:29:30 -05:00
}
public void punch ( ) {
2021-07-04 03:15:30 -05:00
swingHand ( EnumHand . MAIN_HAND ) ;
2021-06-29 16:29:30 -05:00
}
2021-07-10 23:51:14 -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 [ ] {
2021-07-12 18:20:17 -05:00
box . minX ,
box . maxX
2021-06-26 19:43:58 -05:00
} ;
double [ ] zVals = new double [ ] {
2021-07-12 18:20:17 -05:00
box . minZ ,
box . maxZ
2021-06-26 19:43:58 -05:00
} ;
for ( double x : xVals ) {
for ( double z : zVals ) {
2021-07-12 18:20:17 -05:00
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 ;
}
2021-07-10 23:51:14 -05:00
@Override
public boolean isOnGround ( ) {
return groundTicks ! = 0 ;
}
2021-07-12 18:20:17 -05:00
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 ( ) ;
2021-07-12 18:20:17 -05:00
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
}
2021-07-16 03:41:21 -05:00
public void removeVisually ( ) {
this . removeTab ( ) ;
this . setDead ( ) ;
}
private void removeTab ( ) {
sendPacket ( new PacketPlayOutPlayerInfo ( PacketPlayOutPlayerInfo . EnumPlayerInfoAction . REMOVE_PLAYER , this ) ) ;
}
2021-07-24 23:34:07 -05:00
public void setRemoveOnDeath ( boolean enabled ) {
this . removeOnDeath = enabled ;
}
2021-07-16 03:41:21 -05:00
private void setDead ( ) {
2021-08-21 13:36:10 -05:00
sendPacket ( new PacketPlayOutEntityDestroy ( getId ( ) ) ) ;
2021-07-16 03:41:21 -05:00
this . dead = true ;
this . defaultContainer . b ( this ) ;
if ( this . activeContainer ! = null ) {
this . activeContainer . b ( this ) ;
2021-06-28 13:18:49 -05:00
}
2021-07-16 03:41:21 -05:00
}
2021-06-28 13:18:49 -05:00
2021-07-16 03:41:21 -05:00
private void dieCheck ( ) {
if ( removeOnDeath ) {
2021-08-26 19:18:09 -04:00
//scheduler.runTask(plugin, () -> plugin.getManager().remove(this)); // maybe making this later will fix the concurrentmodificationexception?
plugin . getManager ( ) . remove ( this ) ; //this should fix the concurrentmodificationexception mentioned above, I used the ConcurrentHashMap.newKeySet to make a "ConcurrentHashSet"
2021-07-23 17:25:10 -05:00
scheduler . runTaskLater ( plugin , this : : setDead , 30 ) ;
2021-07-23 03:47:11 -05:00
this . removeTab ( ) ;
2021-07-16 03:41:21 -05:00
}
}
@Override
public void die ( ) {
super . die ( ) ;
this . dieCheck ( ) ;
}
@Override
public void die ( DamageSource damageSource ) {
super . die ( damageSource ) ;
this . dieCheck ( ) ;
2021-06-26 19:43:58 -05:00
}
@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 ) {
net . minecraft . server . v1_16_R3 . Entity attacker = damagesource . getEntity ( ) ;
2021-07-23 17:25:10 -05:00
float damage ;
2021-07-24 23:34:07 -05:00
boolean playerInstance = attacker instanceof EntityPlayer ;
2021-07-23 17:25:10 -05:00
2021-07-24 23:34:07 -05:00
Player killer ;
2021-06-26 19:43:58 -05:00
2021-07-24 23:34:07 -05:00
if ( playerInstance ) {
killer = ( ( EntityPlayer ) attacker ) . getBukkitEntity ( ) ;
BotDamageByPlayerEvent event = new BotDamageByPlayerEvent ( this , killer , f ) ;
agent . onPlayerDamage ( event ) ;
2021-07-23 17:25:10 -05:00
if ( event . isCancelled ( ) ) {
return false ;
}
damage = event . getDamage ( ) ;
} else {
2021-07-24 23:34:07 -05:00
killer = null ;
2021-07-23 17:25:10 -05:00
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 ) {
2021-07-24 23:34:07 -05:00
if ( playerInstance & & ! isAlive ( ) ) {
agent . onBotKilledByPlayer ( new BotKilledByPlayerEvent ( this , killer ) ) ;
}
2021-07-23 17:25:10 -05:00
kb ( getLocation ( ) , attacker . getBukkitEntity ( ) . getLocation ( ) ) ;
2021-06-26 19:43:58 -05:00
}
return damaged ;
}
2021-06-28 13:18:49 -05:00
private void kb ( Location loc1 , Location loc2 ) {
2021-07-10 23:51:14 -05:00
Vector vel = loc1 . toVector ( ) . subtract ( loc2 . toVector ( ) ) . setY ( 0 ) . normalize ( ) . multiply ( 0 . 3 ) ;
2021-06-28 15:17:32 -05:00
2021-07-10 23:51:14 -05:00
if ( isOnGround ( ) ) vel . multiply ( 0 . 8 ) . setY ( 0 . 4 ) ;
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
}
2021-06-28 03:14:07 -05:00
2021-07-24 23:34:07 -05:00
public int getKills ( ) {
return kills ;
}
public void incrementKills ( ) {
kills + + ;
}
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 ) {
2021-07-10 23:51:14 -05:00
look ( loc . toVector ( ) . subtract ( getLocation ( ) . toVector ( ) ) , false ) ;
}
2021-06-28 13:18:49 -05:00
2021-07-10 23:51:14 -05:00
public void look ( BlockFace face ) {
look ( face . getDirection ( ) , face = = BlockFace . DOWN | | face = = BlockFace . UP ) ;
}
2021-06-28 13:18:49 -05:00
2021-07-10 23:51:14 -05:00
private void look ( Vector dir , boolean keepYaw ) {
float yaw , pitch ;
2021-06-28 13:18:49 -05:00
2021-07-10 23:51:14 -05:00
if ( keepYaw ) {
yaw = this . yaw ;
pitch = MathUtils . fetchPitch ( dir ) ;
} else {
float [ ] vals = MathUtils . fetchYawPitch ( dir ) ;
yaw = vals [ 0 ] ;
pitch = vals [ 1 ] ;
2021-07-12 18:20:17 -05:00
2021-07-16 03:41:21 -05:00
sendPacket ( new PacketPlayOutEntityHeadRotation ( getBukkitEntity ( ) . getHandle ( ) , ( byte ) ( yaw * 256 / 360f ) ) ) ;
2021-07-10 23:51:14 -05:00
}
setYawPitch ( yaw , pitch ) ;
}
2021-07-19 17:35:28 -05:00
public void attemptBlockPlace ( Location loc , Material type , boolean down ) {
if ( down ) {
look ( BlockFace . DOWN ) ;
} else {
faceLocation ( loc ) ;
}
2021-07-10 23:51:14 -05:00
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-28 13:18:49 -05:00
}
2021-06-26 19:43:58 -05:00
}
2021-07-10 23:51:14 -05:00
public void setItem ( org . bukkit . inventory . ItemStack item ) {
2021-07-23 17:25:10 -05:00
setItem ( item , EnumItemSlot . MAINHAND ) ;
}
2021-07-10 23:51:14 -05:00
2021-07-23 17:25:10 -05:00
public void setItemOffhand ( org . bukkit . inventory . ItemStack item ) {
setItem ( item , EnumItemSlot . OFFHAND ) ;
}
2021-08-25 17:54:32 -05:00
public void setItem ( org . bukkit . inventory . ItemStack item , EnumItemSlot slot ) {
2021-07-24 23:34:07 -05:00
if ( item = = null ) item = defaultItem ;
2021-07-23 17:25:10 -05:00
if ( slot = = EnumItemSlot . MAINHAND ) {
getBukkitEntity ( ) . getInventory ( ) . setItemInMainHand ( item ) ;
} else if ( slot = = EnumItemSlot . OFFHAND ) {
getBukkitEntity ( ) . getInventory ( ) . setItemInOffHand ( item ) ;
}
2021-07-10 23:51:14 -05:00
2021-07-16 03:41:21 -05:00
sendPacket ( new PacketPlayOutEntityEquipment ( getId ( ) , new ArrayList < > ( Collections . singletonList (
2021-07-23 17:25:10 -05:00
new Pair < > ( slot , CraftItemStack . asNMSCopy ( item ) )
2021-07-16 03:41:21 -05:00
) ) ) ) ;
2021-07-10 23:51:14 -05:00
}
public void swim ( ) {
2021-07-12 18:20:17 -05:00
getBukkitEntity ( ) . setSwimming ( true ) ;
2021-07-10 23:51:14 -05:00
registerPose ( EntityPose . SWIMMING ) ;
}
public void sneak ( ) {
2021-07-12 18:20:17 -05:00
getBukkitEntity ( ) . setSneaking ( true ) ;
2021-07-10 23:51:14 -05:00
registerPose ( EntityPose . CROUCHING ) ;
}
public void stand ( ) {
2021-07-12 18:20:17 -05:00
Player player = getBukkitEntity ( ) ;
player . setSneaking ( false ) ;
player . setSwimming ( false ) ;
2021-07-10 23:51:14 -05:00
registerPose ( EntityPose . STANDING ) ;
}
private void registerPose ( EntityPose pose ) {
datawatcher . set ( DataWatcherRegistry . s . a ( 6 ) , pose ) ;
2021-07-16 03:41:21 -05:00
sendPacket ( new PacketPlayOutEntityMetadata ( getId ( ) , datawatcher , false ) ) ;
2021-07-10 23:51:14 -05:00
}
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 ;
}
}