Core/src/eu/univento/core/api/fakeplayer/FakePlayer.java

232 lines
7.8 KiB
Java

package eu.univento.core.api.fakeplayer;
import com.mojang.authlib.GameProfile;
import eu.univento.core.Core;
import net.minecraft.server.v1_8_R3.*;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
import org.bukkit.entity.ArmorStand;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.scheduler.BukkitTask;
import java.lang.reflect.Field;
import java.util.Arrays;
/**
* @author joethei
* @version 0.3
*/
public class FakePlayer {
private static final double MOVE_SPEED = 4.3D / 20;
private Player player;
private int entityId;
private GameProfile gameProfile;
private DataWatcher dataWatcher;
private Location location;
private ArmorStand armorStand;
private LivingEntity target;
private BukkitTask task;
private boolean moveable;
public FakePlayer(GameProfile gameProfile, boolean moveable, Player player) {
this.player = player;
this.moveable = moveable;
this.entityId = (int) get(Entity.class, null, "entityCount");
set(Entity.class, null, "entityCount", this.entityId + 1);
this.gameProfile = gameProfile;
this.dataWatcher = new DataWatcher(null);
byte status = 0;
this.dataWatcher.a(0, status);
this.dataWatcher.a(10, (byte) 127);
this.dataWatcher.a(6, 20F);
}
private final BukkitRunnable tickTask = new BukkitRunnable() {
private int ticksLiving = 0;
@Override
public void run() {
if(target != null) {
followEntity(target);
ticksLiving++;
}
}
};
private byte changeMask(byte bitMask, int bit, boolean state) {
if(state)
return bitMask |= 1 << bit;
else
return bitMask &= ~(1 << bit);
}
public void setTarget(LivingEntity target) {
this.target = target;
}
public void clearTarget() {
this.target = null;
}
public void setFire(boolean fire) {
setStatus(0, fire);
}
public void setSneaking(boolean sneaking) {
setStatus(1, sneaking);
}
public void setSprinting(boolean sprinting) {
setStatus(3, sprinting);
}
public void setUseItem(boolean useItem) {
setStatus(4, useItem);
}
public void setInvisible(boolean invisible) {
setStatus(5, invisible);
}
private void setStatus(int data, boolean bool) {
DataWatcher dataWatcher = this.dataWatcher;
byte status = 0;
status = changeMask(status, data, bool);
dataWatcher.a(0, status);
dataWatcher.a(10, (byte) 127);
dataWatcher.a(6, 20F);
}
public void followEntity(LivingEntity entity) {
double diffX = entity.getLocation().getX() - location.getX();
double diffY = (entity.getLocation().getY() + entity.getEyeHeight() * 0.9D) - location.getY() + 1.6F;
double diffZ = entity.getLocation().getZ() - location.getZ();
double hypoXZ = Math.sqrt(diffX * diffX + diffZ * diffZ);
float yaw = (float) (Math.atan2(diffZ, diffX) * 180D / Math.PI) - 90F;
float pitch = (float) -(Math.atan2(diffY, hypoXZ) * 18D / Math.PI);
look(yaw, pitch);
if(moveable) {
if(Math.abs(diffX) > 3D || Math.abs(diffZ) > 3D) {
yaw = (float) Math.toRadians(yaw);
double x = Math.sin(yaw);
double z = Math.cos(yaw);
move(x * MOVE_SPEED, 0, z * MOVE_SPEED);
}
}
}
private void move(double x, int y, double z) {
sendPackets(new PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook(this.entityId, (byte) toFixedPointNumber(x), (byte) toFixedPointNumber(y), (byte) toFixedPointNumber(z), toAngle(location.getYaw()), toAngle(location.getPitch()), true));
this.location.add(toFixedPointNumber(x) / 32D, toFixedPointNumber(y) / 32D, toFixedPointNumber(z) / 32D);
this.armorStand.teleport(this.location);
}
public void spawn(Location location) {
PacketPlayOutNamedEntitySpawn playerSpawn = new PacketPlayOutNamedEntitySpawn();
set(playerSpawn, "a", this.entityId);
set(playerSpawn, "b", this.gameProfile.getId());
set(playerSpawn, "c", toFixedPointNumber(location.getX()));
set(playerSpawn, "d", toFixedPointNumber(location.getY()));
set(playerSpawn, "e", toFixedPointNumber(location.getZ()));
set(playerSpawn, "f", toAngle(location.getYaw()));
set(playerSpawn, "g", toAngle(location.getPitch()));
set(playerSpawn, "h", 0);
set(playerSpawn, "i", this.dataWatcher);
PacketPlayOutPlayerInfo playerInfo = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER);
set(playerInfo, "b", Arrays.asList(playerInfo.new PlayerInfoData(this.gameProfile, 0, WorldSettings.EnumGamemode.NOT_SET, new ChatComponentText(this.gameProfile.getName()))));
sendPackets(playerInfo, playerSpawn);
this.location = location;
this.armorStand = (ArmorStand) location.getWorld().spawnEntity(location, EntityType.ARMOR_STAND);
this.armorStand.setGravity(true);
this.armorStand.setVisible(false);
this.task = tickTask.runTaskTimer(Core.getInstance(), 0L, 1L);
}
public void despawn() {
PacketPlayOutPlayerInfo playerInfo = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER);
set(playerInfo, "b", Arrays.asList(playerInfo.new PlayerInfoData(this.gameProfile, 0, null, null)));
sendPackets(new PacketPlayOutEntityDestroy(this.entityId), playerInfo);
this.armorStand.remove();
this.armorStand = null;
this.task.cancel();
}
public void removeTablist() {
PacketPlayOutPlayerInfo playerInfo = new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER);
set(playerInfo, "b", Arrays.asList(playerInfo.new PlayerInfoData(this.gameProfile, 0, null, null)));
sendPackets(new PacketPlayOutEntityDestroy(this.entityId), playerInfo);
}
private void look(float yaw, float pitch) {
PacketPlayOutEntityHeadRotation headRotation = new PacketPlayOutEntityHeadRotation();
set(headRotation, "a", this.entityId);
set(headRotation, "b", toAngle(yaw));
sendPackets(headRotation, new PacketPlayOutEntity.PacketPlayOutEntityLook(this.entityId, toAngle(yaw), toAngle(pitch), false));
this.location.setYaw(yaw);
this.location.setPitch(pitch);
}
private int toFixedPointNumber(double value) {
return (int) Math.floor(value * 32D);
}
private byte toAngle(float value) {
return (byte) ((int) (value * 256.0F / 360.F));
}
public void sendPackets(Packet<?>... packets) {
for(Packet<?> packet : packets)
((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
}
private void set(Object instance, String name, Object value) {
set(instance.getClass(), instance, name, value);
}
private void set(Class<?> clazz, Object instance, String name, Object value) {
try{
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
field.set(instance, value);
}catch (Exception e) {
e.printStackTrace();
}
}
private Object get(Object instance, String name) {
return get(instance.getClass(), instance, name);
}
private Object get(Class<?> clazz, Object instance, String name) {
try{
Field field = clazz.getDeclaredField(name);
field.setAccessible(true);
return field.get(instance);
}catch (Exception e) {
e.printStackTrace();
}
return null;
}
}