Minestom/src/main/java/fr/themode/minestom/entity/Player.java

767 lines
27 KiB
Java
Raw Normal View History

2019-08-03 15:25:24 +02:00
package fr.themode.minestom.entity;
import fr.themode.minestom.Main;
2019-08-19 17:04:19 +02:00
import fr.themode.minestom.bossbar.BossBar;
import fr.themode.minestom.chat.Chat;
2019-08-25 20:03:43 +02:00
import fr.themode.minestom.data.Data;
import fr.themode.minestom.entity.property.Attribute;
import fr.themode.minestom.event.*;
2019-08-25 20:03:43 +02:00
import fr.themode.minestom.instance.Chunk;
2019-08-18 23:52:11 +02:00
import fr.themode.minestom.instance.CustomBlock;
import fr.themode.minestom.instance.Instance;
2019-08-24 21:41:43 +02:00
import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
2019-08-13 17:52:09 +02:00
import fr.themode.minestom.inventory.Inventory;
2019-08-12 08:30:59 +02:00
import fr.themode.minestom.inventory.PlayerInventory;
2019-08-27 20:49:11 +02:00
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
2019-08-20 22:40:57 +02:00
import fr.themode.minestom.net.packet.server.ServerPacket;
2019-08-12 08:30:59 +02:00
import fr.themode.minestom.net.packet.server.play.*;
2019-08-03 15:25:24 +02:00
import fr.themode.minestom.net.player.PlayerConnection;
2019-08-26 04:39:58 +02:00
import fr.themode.minestom.utils.*;
2019-08-21 16:50:52 +02:00
import fr.themode.minestom.world.Dimension;
import fr.themode.minestom.world.LevelType;
2019-08-03 15:25:24 +02:00
2019-08-19 17:04:19 +02:00
import java.util.Collections;
2019-08-24 20:34:01 +02:00
import java.util.Random;
2019-08-19 17:04:19 +02:00
import java.util.Set;
import java.util.UUID;
2019-08-23 15:37:38 +02:00
import java.util.concurrent.ConcurrentLinkedQueue;
2019-08-19 17:04:19 +02:00
import java.util.concurrent.CopyOnWriteArraySet;
2019-08-10 08:44:35 +02:00
public class Player extends LivingEntity {
private long lastKeepAlive;
2019-08-10 04:16:01 +02:00
private String username;
2019-08-03 15:25:24 +02:00
private PlayerConnection playerConnection;
2019-08-23 15:37:38 +02:00
private ConcurrentLinkedQueue<ClientPlayPacket> packets = new ConcurrentLinkedQueue<>();
2019-08-03 15:25:24 +02:00
2019-08-21 16:50:52 +02:00
private Dimension dimension;
2019-08-12 08:30:59 +02:00
private GameMode gameMode;
2019-08-21 16:50:52 +02:00
private LevelType levelType;
2019-08-24 20:34:01 +02:00
2019-08-27 20:49:11 +02:00
protected boolean onGround;
private static InstanceContainer instanceContainer;
2019-08-25 20:03:43 +02:00
static {
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
//instance = Main.getInstanceManager().createInstance(new File("C:\\Users\\themo\\OneDrive\\Bureau\\Minestom data"));
instanceContainer = Main.getInstanceManager().createInstanceContainer();
instanceContainer.enableAutoChunkLoad(true);
instanceContainer.setChunkGenerator(chunkGeneratorDemo);
2019-08-26 04:39:58 +02:00
int loopStart = -2;
int loopEnd = 2;
2019-08-25 20:03:43 +02:00
long time = System.currentTimeMillis();
for (int x = loopStart; x < loopEnd; x++)
for (int z = loopStart; z < loopEnd; z++) {
instanceContainer.loadChunk(x, z);
}
System.out.println("Time to load all chunks: " + (System.currentTimeMillis() - time) + " ms");
}
protected Set<Entity> viewableEntity = new CopyOnWriteArraySet<>();
2019-08-21 16:50:52 +02:00
private PlayerSettings settings;
2019-08-12 08:30:59 +02:00
private PlayerInventory inventory;
private short heldSlot;
2019-08-13 17:52:09 +02:00
private Inventory openInventory;
2019-08-25 20:03:43 +02:00
private int food;
private float foodSaturation;
2019-08-12 08:30:59 +02:00
2019-08-18 23:52:11 +02:00
private CustomBlock targetCustomBlock;
2019-08-21 16:50:52 +02:00
private BlockPosition targetBlockPosition;
2019-08-18 20:38:09 +02:00
private long targetBlockTime;
2019-08-22 14:52:32 +02:00
private byte targetLastStage;
2019-08-18 20:38:09 +02:00
2019-08-19 17:04:19 +02:00
private Set<BossBar> bossBars = new CopyOnWriteArraySet<>();
// Vehicle
private float sideways;
private float forward;
protected boolean spawned;
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
2019-08-27 20:49:11 +02:00
super(100);
this.uuid = uuid;
this.username = username;
this.playerConnection = playerConnection;
2019-08-12 08:30:59 +02:00
playerConnection.sendPacket(getPropertiesPacket()); // Send default properties
2019-08-25 20:03:43 +02:00
refreshHealth();
2019-08-24 20:34:01 +02:00
this.settings = new PlayerSettings();
2019-08-12 08:30:59 +02:00
this.inventory = new PlayerInventory(this);
2019-08-24 20:34:01 +02:00
setCanPickupItem(true); // By default
2019-08-21 16:50:52 +02:00
setEventCallback(AttackEvent.class, event -> {
Entity entity = event.getTarget();
if (entity instanceof EntityCreature) {
2019-08-27 20:49:11 +02:00
((EntityCreature) entity).damage(-1);
Vector velocity = getPosition().clone().getDirection().multiply(6);
velocity.setY(4f);
entity.setVelocity(velocity, 150);
sendMessage("You attacked an entity!");
2019-08-24 20:34:01 +02:00
} else if (entity instanceof Player) {
Player player = (Player) entity;
Vector velocity = getPosition().clone().getDirection().multiply(6);
velocity.setY(3.5f);
player.setVelocity(velocity, 150);
2019-08-25 20:03:43 +02:00
player.damage(2);
2019-08-24 20:34:01 +02:00
sendMessage("ATTACK");
2019-08-21 16:50:52 +02:00
}
});
2019-08-22 14:52:32 +02:00
2019-08-25 20:03:43 +02:00
setEventCallback(PlayerBlockPlaceEvent.class, event -> {
/*sendMessage("Placed block! " + event.getHand());
2019-08-25 20:03:43 +02:00
int value = getData().getOrDefault("test", 0);
getData().set("test", value + 1, DataType.INTEGER);
System.out.println("OLD DATA VALUE: " + value);*/
if (event.getHand() != Hand.MAIN)
return;
2019-08-24 20:34:01 +02:00
/*sendMessage("Save chunk data...");
long time = System.currentTimeMillis();
getInstance().saveToFolder(() -> {
sendMessage("Saved in " + (System.currentTimeMillis() - time) + " ms");
2019-08-24 20:34:01 +02:00
});*/
for (Player player : instance.getPlayers()) {
2019-08-25 20:03:43 +02:00
if (player != this)
player.teleport(getPosition());
}
2019-08-24 20:34:01 +02:00
});
setEventCallback(PickupItemEvent.class, event -> {
event.setCancelled(!getInventory().addItemStack(event.getItemStack())); // Cancel event if player does not have enough inventory space
});
setEventCallback(PlayerLoginEvent.class, event -> {
2019-08-24 21:41:43 +02:00
event.setSpawningInstance(instanceContainer);
2019-08-25 20:03:43 +02:00
setData(new Data());
});
2019-08-25 20:03:43 +02:00
setEventCallback(PlayerSpawnEvent.class, event -> {
2019-08-26 04:39:58 +02:00
System.out.println("SPAWN");
2019-08-27 05:23:25 +02:00
setGameMode(GameMode.SURVIVAL);
teleport(new Position(0, 66, 0));
2019-08-25 20:03:43 +02:00
2019-08-29 02:15:52 +02:00
/*ChickenCreature chickenCreature = new ChickenCreature();
2019-08-25 20:03:43 +02:00
chickenCreature.refreshPosition(2, 65, 2);
chickenCreature.setInstance(getInstance());
2019-08-24 20:34:01 +02:00
2019-08-24 21:41:43 +02:00
for (int ix = 0; ix < 4; ix++)
2019-08-24 20:34:01 +02:00
for (int iz = 0; iz < 4; iz++) {
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
2019-08-27 20:49:11 +02:00
itemEntity.refreshPosition(ix, 68, iz);
//itemEntity.setNoGravity(true);
2019-08-24 21:41:43 +02:00
itemEntity.setInstance(getInstance());
2019-08-24 20:34:01 +02:00
//itemEntity.remove();
2019-08-29 02:15:52 +02:00
}*/
getInventory().addItemStack(new ItemStack(1, (byte) 100));
2019-08-24 20:34:01 +02:00
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
teamsPacket.action = TeamsPacket.Action.CREATE_TEAM;
teamsPacket.teamDisplayName = Chat.rawText("WOWdisplay");
teamsPacket.nameTagVisibility = "always";
teamsPacket.teamColor = 2;
teamsPacket.teamPrefix = Chat.rawText("pre");
teamsPacket.teamSuffix = Chat.rawText("suf");
teamsPacket.collisionRule = "never";
teamsPacket.entities = new String[]{getUsername()};
sendPacketToViewersAndSelf(teamsPacket);
2019-08-26 04:39:58 +02:00
setAttribute(Attribute.MAX_HEALTH, 40);
heal();
2019-08-22 14:52:32 +02:00
});
}
2019-08-10 08:44:35 +02:00
@Override
public void update() {
2019-08-24 20:34:01 +02:00
playerConnection.flush();
ClientPlayPacket packet;
2019-08-23 15:37:38 +02:00
while ((packet = packets.poll()) != null) {
packet.process(this);
}
2019-08-18 20:38:09 +02:00
2019-08-24 20:34:01 +02:00
super.update(); // Super update (item pickup)
2019-08-18 20:38:09 +02:00
// Target block stage
if (targetCustomBlock != null) {
2019-08-18 23:52:11 +02:00
int timeBreak = targetCustomBlock.getBreakDelay(this);
2019-08-18 20:38:09 +02:00
int animationCount = 10;
long since = System.currentTimeMillis() - targetBlockTime;
byte stage = (byte) (since / (timeBreak / animationCount));
2019-08-22 14:52:32 +02:00
if (stage != targetLastStage) {
sendBlockBreakAnimation(targetBlockPosition, stage);
}
this.targetLastStage = stage;
2019-08-18 20:38:09 +02:00
if (stage > 9) {
2019-08-25 20:03:43 +02:00
instance.breakBlock(this, targetBlockPosition);
2019-08-18 23:52:11 +02:00
resetTargetBlock();
2019-08-18 20:38:09 +02:00
}
}
// Multiplayer sync
2019-08-21 16:50:52 +02:00
Position position = getPosition();
boolean positionChanged = position.getX() != lastX || position.getZ() != lastZ || position.getY() != lastY;
boolean viewChanged = position.getYaw() != lastYaw || position.getPitch() != lastPitch;
2019-08-20 22:40:57 +02:00
ServerPacket updatePacket = null;
ServerPacket optionalUpdatePacket = null;
if (positionChanged && viewChanged) {
EntityLookAndRelativeMovePacket entityLookAndRelativeMovePacket = new EntityLookAndRelativeMovePacket();
entityLookAndRelativeMovePacket.entityId = getEntityId();
2019-08-21 16:50:52 +02:00
entityLookAndRelativeMovePacket.deltaX = (short) ((position.getX() * 32 - lastX * 32) * 128);
entityLookAndRelativeMovePacket.deltaY = (short) ((position.getY() * 32 - lastY * 32) * 128);
entityLookAndRelativeMovePacket.deltaZ = (short) ((position.getZ() * 32 - lastZ * 32) * 128);
entityLookAndRelativeMovePacket.yaw = position.getYaw();
entityLookAndRelativeMovePacket.pitch = position.getPitch();
2019-08-20 22:40:57 +02:00
entityLookAndRelativeMovePacket.onGround = onGround;
2019-08-21 16:50:52 +02:00
lastX = position.getX();
lastY = position.getY();
lastZ = position.getZ();
lastYaw = position.getYaw();
lastPitch = position.getPitch();
2019-08-20 22:40:57 +02:00
updatePacket = entityLookAndRelativeMovePacket;
} else if (positionChanged) {
EntityRelativeMovePacket entityRelativeMovePacket = new EntityRelativeMovePacket();
entityRelativeMovePacket.entityId = getEntityId();
2019-08-21 16:50:52 +02:00
entityRelativeMovePacket.deltaX = (short) ((position.getX() * 32 - lastX * 32) * 128);
entityRelativeMovePacket.deltaY = (short) ((position.getY() * 32 - lastY * 32) * 128);
entityRelativeMovePacket.deltaZ = (short) ((position.getZ() * 32 - lastZ * 32) * 128);
2019-08-20 22:40:57 +02:00
entityRelativeMovePacket.onGround = onGround;
2019-08-21 16:50:52 +02:00
lastX = position.getX();
lastY = position.getY();
lastZ = position.getZ();
2019-08-20 22:40:57 +02:00
updatePacket = entityRelativeMovePacket;
} else if (viewChanged) {
EntityLookPacket entityLookPacket = new EntityLookPacket();
entityLookPacket.entityId = getEntityId();
2019-08-21 16:50:52 +02:00
entityLookPacket.yaw = position.getYaw();
entityLookPacket.pitch = position.getPitch();
2019-08-20 22:40:57 +02:00
entityLookPacket.onGround = onGround;
2019-08-21 16:50:52 +02:00
lastYaw = position.getYaw();
lastPitch = position.getPitch();
2019-08-20 22:40:57 +02:00
updatePacket = entityLookPacket;
2019-08-24 20:34:01 +02:00
}
if (viewChanged) {
EntityHeadLookPacket entityHeadLookPacket = new EntityHeadLookPacket();
entityHeadLookPacket.entityId = getEntityId();
entityHeadLookPacket.yaw = position.getYaw();
2019-08-20 22:40:57 +02:00
optionalUpdatePacket = entityHeadLookPacket;
}
2019-08-24 20:34:01 +02:00
2019-08-20 22:40:57 +02:00
if (updatePacket != null) {
if (optionalUpdatePacket != null) {
sendPacketsToViewers(updatePacket, optionalUpdatePacket);
} else {
sendPacketToViewers(updatePacket);
}
}
2019-08-24 20:34:01 +02:00
}
@Override
public void spawn() {
2019-08-20 22:40:57 +02:00
}
2019-08-27 20:49:11 +02:00
@Override
public boolean isOnGround() {
return onGround;
}
2019-08-25 20:03:43 +02:00
@Override
public void remove() {
clearBossBars();
if (getOpenInventory() != null)
getOpenInventory().removeViewer(this);
this.viewableEntity.forEach(entity -> entity.removeViewer(this));
super.remove();
}
2019-08-20 22:40:57 +02:00
@Override
public void addViewer(Player player) {
super.addViewer(player);
PlayerConnection connection = player.getPlayerConnection();
String property = "eyJ0aW1lc3RhbXAiOjE1NjU0ODMwODQwOTYsInByb2ZpbGVJZCI6ImFiNzBlY2I0MjM0NjRjMTRhNTJkN2EwOTE1MDdjMjRlIiwicHJvZmlsZU5hbWUiOiJUaGVNb2RlOTExIiwidGV4dHVyZXMiOnsiU0tJTiI6eyJ1cmwiOiJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2RkOTE2NzJiNTE0MmJhN2Y3MjA2ZTRjN2IwOTBkNzhlM2Y1ZDc2NDdiNWFmZDIyNjFhZDk4OGM0MWI2ZjcwYTEifX19";
SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket();
spawnPlayerPacket.entityId = getEntityId();
spawnPlayerPacket.playerUuid = getUuid();
2019-08-21 16:50:52 +02:00
spawnPlayerPacket.position = getPosition();
2019-08-20 22:40:57 +02:00
PlayerInfoPacket pInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.ADD_PLAYER);
PlayerInfoPacket.AddPlayer addP = new PlayerInfoPacket.AddPlayer(getUuid(), getUsername(), GameMode.CREATIVE, 10);
PlayerInfoPacket.AddPlayer.Property p = new PlayerInfoPacket.AddPlayer.Property("textures", property);//new PlayerInfoPacket.AddPlayer.Property("textures", properties.get(onlinePlayer.getUsername()));
addP.properties.add(p);
pInfoPacket.playerInfos.add(addP);
connection.sendPacket(pInfoPacket);
connection.sendPacket(spawnPlayerPacket);
2019-08-24 20:34:01 +02:00
connection.sendPacket(getMetadataPacket());
2019-08-20 22:40:57 +02:00
for (EntityEquipmentPacket.Slot slot : EntityEquipmentPacket.Slot.values()) {
player.playerConnection.sendPacket(getEquipmentPacket(slot));
2019-08-20 22:40:57 +02:00
}
}
@Override
public void removeViewer(Player player) {
super.removeViewer(player);
PlayerInfoPacket playerInfoPacket = new PlayerInfoPacket(PlayerInfoPacket.Action.REMOVE_PLAYER);
playerInfoPacket.playerInfos.add(new PlayerInfoPacket.RemovePlayer(getUuid()));
player.playerConnection.sendPacket(playerInfoPacket);
}
@Override
public void setInstance(Instance instance) {
if (!spawned)
throw new IllegalStateException("Player#setInstance is only available during and after PlayerSpawnEvent");
super.setInstance(instance);
}
2019-08-24 20:34:01 +02:00
@Override
public void kill() {
this.isDead = true;
refreshIsDead(true);
EntityStatusPacket entityStatusPacket = new EntityStatusPacket();
entityStatusPacket.entityId = getEntityId();
entityStatusPacket.status = 3; // Death sound/animation
sendPacketToViewers(entityStatusPacket);
DeathEvent deathEvent = new DeathEvent();
callEvent(DeathEvent.class, deathEvent);
2019-08-24 20:34:01 +02:00
}
2019-08-21 16:50:52 +02:00
public void sendBlockBreakAnimation(BlockPosition blockPosition, byte destroyStage) {
2019-08-18 23:52:11 +02:00
BlockBreakAnimationPacket breakAnimationPacket = new BlockBreakAnimationPacket();
breakAnimationPacket.entityId = getEntityId() + 1;
breakAnimationPacket.blockPosition = blockPosition;
breakAnimationPacket.destroyStage = destroyStage;
2019-08-22 14:52:32 +02:00
sendPacketToViewersAndSelf(breakAnimationPacket);
2019-08-18 23:52:11 +02:00
}
2019-08-18 20:38:09 +02:00
public void sendMessage(String message) {
2019-08-19 17:04:19 +02:00
ChatMessagePacket chatMessagePacket = new ChatMessagePacket(Chat.rawText(message), ChatMessagePacket.Position.CHAT);
2019-08-18 20:38:09 +02:00
playerConnection.sendPacket(chatMessagePacket);
}
2019-08-27 20:49:11 +02:00
@Override
public void damage(float value) {
if (getGameMode() == GameMode.CREATIVE)
return;
2019-08-27 20:49:11 +02:00
super.damage(value);
2019-08-25 20:03:43 +02:00
}
@Override
public void setAttribute(Attribute attribute, float value) {
super.setAttribute(attribute, value);
if (playerConnection != null)
playerConnection.sendPacket(getPropertiesPacket());
2019-08-25 20:03:43 +02:00
}
@Override
2019-08-25 20:03:43 +02:00
public void setHealth(float health) {
super.setHealth(health);
2019-08-25 20:03:43 +02:00
sendUpdateHealthPacket();
}
public int getFood() {
return food;
}
public void setFood(int food) {
this.food = food;
sendUpdateHealthPacket();
}
public float getFoodSaturation() {
return foodSaturation;
}
public void setFoodSaturation(float foodSaturation) {
this.foodSaturation = foodSaturation;
sendUpdateHealthPacket();
}
public void respawn() {
if (!isDead())
return;
refreshHealth();
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.dimension = getDimension();
respawnPacket.gameMode = getGameMode();
respawnPacket.levelType = getLevelType();
getPlayerConnection().sendPacket(respawnPacket);
PlayerRespawnEvent respawnEvent = new PlayerRespawnEvent(getPosition());
callEvent(PlayerRespawnEvent.class, respawnEvent);
refreshIsDead(false);
// Runnable called when teleportation is successfull (after loading and sending necessary chunk)
teleport(respawnEvent.getRespawnPosition(), () -> {
getInventory().update();
SpawnPlayerPacket spawnPlayerPacket = new SpawnPlayerPacket();
spawnPlayerPacket.entityId = getEntityId();
spawnPlayerPacket.playerUuid = getUuid();
spawnPlayerPacket.position = getPosition();
sendPacketToViewers(spawnPlayerPacket);
playerConnection.sendPacket(getPropertiesPacket());
sendUpdateHealthPacket();
2019-08-25 20:03:43 +02:00
});
}
private void refreshHealth() {
heal();
2019-08-25 20:03:43 +02:00
this.food = 20;
this.foodSaturation = 5;
}
protected void sendUpdateHealthPacket() {
UpdateHealthPacket updateHealthPacket = new UpdateHealthPacket();
2019-08-26 04:39:58 +02:00
updateHealthPacket.health = getHealth();
2019-08-25 20:03:43 +02:00
updateHealthPacket.food = food;
updateHealthPacket.foodSaturation = foodSaturation;
playerConnection.sendPacket(updateHealthPacket);
}
protected void onChunkChange(Chunk lastChunk, Chunk newChunk) {
2019-08-26 04:39:58 +02:00
float dx = newChunk.getChunkX() - lastChunk.getChunkX();
float dz = newChunk.getChunkZ() - lastChunk.getChunkZ();
double distance = Math.sqrt(dx * dx + dz * dz);
boolean isFar = distance >= Main.CHUNK_VIEW_DISTANCE / 2;
2019-08-27 05:23:25 +02:00
long[] lastVisibleChunks = ChunkUtils.getChunksInRange(new Position(16 * lastChunk.getChunkX(), 0, 16 * lastChunk.getChunkZ()), Main.CHUNK_VIEW_DISTANCE);
long[] updatedVisibleChunks = ChunkUtils.getChunksInRange(new Position(16 * newChunk.getChunkX(), 0, 16 * newChunk.getChunkZ()), Main.CHUNK_VIEW_DISTANCE);
2019-08-26 04:39:58 +02:00
int[] oldChunks = ArrayUtils.getDifferencesBetweenArray(lastVisibleChunks, updatedVisibleChunks);
int[] newChunks = ArrayUtils.getDifferencesBetweenArray(updatedVisibleChunks, lastVisibleChunks);
2019-08-25 20:03:43 +02:00
// Unload old chunks
2019-08-26 04:39:58 +02:00
for (int index : oldChunks) {
int[] chunkPos = ChunkUtils.getChunkCoord(lastVisibleChunks[index]);
UnloadChunkPacket unloadChunkPacket = new UnloadChunkPacket();
unloadChunkPacket.chunkX = chunkPos[0];
unloadChunkPacket.chunkZ = chunkPos[1];
playerConnection.sendPacket(unloadChunkPacket);
2019-08-25 20:03:43 +02:00
}
2019-08-26 04:39:58 +02:00
updateViewPosition(newChunk);
2019-08-25 20:03:43 +02:00
// Load new chunks
2019-08-26 04:39:58 +02:00
for (int i = 0; i < newChunks.length; i++) {
boolean isLast = i == newChunks.length - 1;
int index = newChunks[i];
int[] chunkPos = ChunkUtils.getChunkCoord(updatedVisibleChunks[index]);
instance.loadOptionalChunk(chunkPos[0], chunkPos[1], chunk -> {
if (chunk == null) {
2019-08-27 05:23:25 +02:00
return; // Cannot load chunk (auto load not enabled)
2019-08-25 20:03:43 +02:00
}
2019-08-26 04:39:58 +02:00
instance.sendChunk(this, chunk);
2019-08-27 05:23:25 +02:00
if (isFar && isLast) {
2019-08-26 04:39:58 +02:00
updatePlayerPosition();
2019-08-27 05:23:25 +02:00
}
2019-08-26 04:39:58 +02:00
});
2019-08-25 20:03:43 +02:00
}
}
2019-08-21 16:50:52 +02:00
@Override
2019-08-25 20:03:43 +02:00
public void teleport(Position position, Runnable callback) {
super.teleport(position, () -> {
2019-08-27 20:49:11 +02:00
if (!instance.hasEnabledAutoChunkLoad() && ChunkUtils.isChunkUnloaded(instance, position.getX(), position.getZ()))
2019-08-25 20:03:43 +02:00
return;
2019-08-26 04:39:58 +02:00
updatePlayerPosition();
2019-08-25 20:03:43 +02:00
if (callback != null)
callback.run();
});
}
2019-08-22 14:52:32 +02:00
2019-08-25 20:03:43 +02:00
@Override
public void teleport(Position position) {
teleport(position, null);
2019-08-11 09:33:27 +02:00
}
public String getUsername() {
return username;
2019-08-10 08:44:35 +02:00
}
2019-08-03 15:25:24 +02:00
public PlayerConnection getPlayerConnection() {
return playerConnection;
}
2019-08-10 04:16:01 +02:00
2019-08-21 16:50:52 +02:00
public PlayerSettings getSettings() {
return settings;
}
2019-08-12 08:30:59 +02:00
public PlayerInventory getInventory() {
return inventory;
}
2019-08-21 16:50:52 +02:00
public Dimension getDimension() {
return dimension;
}
2019-08-12 08:30:59 +02:00
public GameMode getGameMode() {
return gameMode;
}
2019-08-21 16:50:52 +02:00
public void setDimension(Dimension dimension) {
if (dimension == null)
throw new IllegalArgumentException("Dimension cannot be null!");
if (dimension.equals(getDimension()))
return;
RespawnPacket respawnPacket = new RespawnPacket();
respawnPacket.dimension = dimension;
respawnPacket.gameMode = gameMode;
respawnPacket.levelType = levelType;
playerConnection.sendPacket(respawnPacket);
}
2019-08-20 22:40:57 +02:00
public void kick(String message) {
DisconnectPacket disconnectPacket = new DisconnectPacket();
disconnectPacket.message = message;
playerConnection.sendPacket(disconnectPacket);
playerConnection.getConnection().close();
}
2019-08-21 16:50:52 +02:00
public LevelType getLevelType() {
return levelType;
}
2019-08-12 08:30:59 +02:00
public void setGameMode(GameMode gameMode) {
ChangeGameStatePacket changeGameStatePacket = new ChangeGameStatePacket();
changeGameStatePacket.reason = ChangeGameStatePacket.Reason.CHANGE_GAMEMODE;
changeGameStatePacket.value = gameMode.getId();
playerConnection.sendPacket(changeGameStatePacket);
refreshGameMode(gameMode);
}
public void setHeldItemSlot(short slot) {
if (slot < 0 || slot > 8)
throw new IllegalArgumentException("Slot has to be between 0 and 8");
HeldItemChangePacket heldItemChangePacket = new HeldItemChangePacket();
heldItemChangePacket.slot = slot;
playerConnection.sendPacket(heldItemChangePacket);
refreshHeldSlot(slot);
}
public short getHeldSlot() {
return heldSlot;
}
2019-08-13 17:52:09 +02:00
public Inventory getOpenInventory() {
return openInventory;
}
2019-08-18 23:52:11 +02:00
public CustomBlock getCustomBlockTarget() {
return targetCustomBlock;
}
2019-08-19 17:04:19 +02:00
public Set<BossBar> getBossBars() {
return Collections.unmodifiableSet(bossBars);
}
public float getVehicleSideways() {
return sideways;
}
public float getVehicleForward() {
return forward;
}
2019-08-13 17:52:09 +02:00
public void openInventory(Inventory inventory) {
if (inventory == null)
throw new IllegalArgumentException("Inventory cannot be null, use Player#closeInventory() to close current");
if (getOpenInventory() != null) {
getOpenInventory().removeViewer(this);
}
OpenWindowPacket openWindowPacket = new OpenWindowPacket();
2019-08-27 05:23:25 +02:00
openWindowPacket.windowId = inventory.getWindowId();
2019-08-13 17:52:09 +02:00
openWindowPacket.windowType = inventory.getInventoryType().getWindowType();
openWindowPacket.title = inventory.getTitle();
playerConnection.sendPacket(openWindowPacket);
inventory.addViewer(this);
refreshOpenInventory(inventory);
}
public void closeInventory() {
Inventory openInventory = getOpenInventory();
CloseWindowPacket closeWindowPacket = new CloseWindowPacket();
if (openInventory == null) {
closeWindowPacket.windowId = 0;
} else {
2019-08-27 05:23:25 +02:00
closeWindowPacket.windowId = openInventory.getWindowId();
2019-08-13 17:52:09 +02:00
openInventory.removeViewer(this);
refreshOpenInventory(null);
}
playerConnection.sendPacket(closeWindowPacket);
2019-08-14 06:50:03 +02:00
inventory.update();
2019-08-13 17:52:09 +02:00
}
2019-08-25 20:03:43 +02:00
public void clearBossBars() {
this.bossBars.forEach(bossBar -> bossBar.removeViewer(this));
}
2019-08-20 22:40:57 +02:00
public void syncEquipment(EntityEquipmentPacket.Slot slot) {
sendPacketToViewers(getEquipmentPacket(slot));
}
protected EntityEquipmentPacket getEquipmentPacket(EntityEquipmentPacket.Slot slot) {
2019-08-20 22:40:57 +02:00
EntityEquipmentPacket equipmentPacket = new EntityEquipmentPacket();
equipmentPacket.entityId = getEntityId();
equipmentPacket.slot = slot;
equipmentPacket.itemStack = inventory.getEquipment(slot);
return equipmentPacket;
}
2019-08-27 05:23:25 +02:00
public void updateViewPosition(Chunk chunk) {
UpdateViewPositionPacket updateViewPositionPacket = new UpdateViewPositionPacket(chunk);
playerConnection.sendPacket(updateViewPositionPacket);
2019-08-20 22:40:57 +02:00
}
2019-08-26 04:39:58 +02:00
protected void updatePlayerPosition() {
PlayerPositionAndLookPacket positionAndLookPacket = new PlayerPositionAndLookPacket();
positionAndLookPacket.position = position;
positionAndLookPacket.flags = 0x00;
positionAndLookPacket.teleportId = 67;
playerConnection.sendPacket(positionAndLookPacket);
}
public void addPacketToQueue(ClientPlayPacket packet) {
2019-08-23 15:37:38 +02:00
this.packets.add(packet);
}
2019-08-21 16:50:52 +02:00
public void refreshDimension(Dimension dimension) {
this.dimension = dimension;
}
2019-08-12 08:30:59 +02:00
public void refreshGameMode(GameMode gameMode) {
this.gameMode = gameMode;
}
2019-08-21 16:50:52 +02:00
public void refreshLevelType(LevelType levelType) {
this.levelType = levelType;
}
2019-08-10 04:16:01 +02:00
public void refreshOnGround(boolean onGround) {
this.onGround = onGround;
}
public void refreshKeepAlive(long lastKeepAlive) {
this.lastKeepAlive = lastKeepAlive;
}
2019-08-12 08:30:59 +02:00
public void refreshHeldSlot(short slot) {
this.heldSlot = slot;
2019-08-20 22:40:57 +02:00
syncEquipment(EntityEquipmentPacket.Slot.MAIN_HAND);
2019-08-12 08:30:59 +02:00
}
2019-08-13 17:52:09 +02:00
public void refreshOpenInventory(Inventory openInventory) {
this.openInventory = openInventory;
}
2019-08-21 16:50:52 +02:00
public void refreshTargetBlock(CustomBlock targetCustomBlock, BlockPosition targetBlockPosition) {
2019-08-18 23:52:11 +02:00
this.targetCustomBlock = targetCustomBlock;
2019-08-18 20:38:09 +02:00
this.targetBlockPosition = targetBlockPosition;
this.targetBlockTime = targetBlockPosition == null ? 0 : System.currentTimeMillis();
}
2019-08-18 23:52:11 +02:00
public void resetTargetBlock() {
this.targetCustomBlock = null;
this.targetBlockPosition = null;
this.targetBlockTime = 0;
}
2019-08-19 17:04:19 +02:00
public void refreshAddBossbar(BossBar bossBar) {
this.bossBars.add(bossBar);
}
public void refreshRemoveBossbar(BossBar bossBar) {
this.bossBars.remove(bossBar);
}
public void refreshVehicleSteer(float sideways, float forward) {
this.sideways = sideways;
this.forward = forward;
}
public long getLastKeepAlive() {
return lastKeepAlive;
}
public enum Hand {
MAIN,
OFF
}
2019-08-21 16:50:52 +02:00
public enum MainHand {
LEFT,
RIGHT;
}
public enum ChatMode {
ENABLED,
COMMANDS_ONLY,
HIDDEN;
}
public class PlayerSettings {
private String locale;
private byte viewDistance;
private ChatMode chatMode;
private boolean chatColors;
private byte displayedSkinParts;
private MainHand mainHand;
public String getLocale() {
return locale;
}
public byte getViewDistance() {
return viewDistance;
}
public ChatMode getChatMode() {
return chatMode;
}
public boolean hasChatColors() {
return chatColors;
}
public byte getDisplayedSkinParts() {
return displayedSkinParts;
}
public MainHand getMainHand() {
return mainHand;
}
public void refresh(String locale, byte viewDistance, ChatMode chatMode, boolean chatColors, byte displayedSkinParts, MainHand mainHand) {
this.locale = locale;
this.viewDistance = viewDistance;
this.chatMode = chatMode;
this.chatColors = chatColors;
this.displayedSkinParts = displayedSkinParts;
this.mainHand = mainHand;
}
}
2019-08-03 15:25:24 +02:00
}