Added entity properties & removed unnecessary reflection

This commit is contained in:
TheMode 2019-08-26 00:29:40 +02:00
parent e0eb35e81e
commit b13a888170
14 changed files with 242 additions and 160 deletions

View File

@ -18,4 +18,5 @@ dependencies {
compile 'com.github.Querz:NBT:4.1'
// https://mvnrepository.com/artifact/org.lz4/lz4-java
implementation 'com.github.luben:zstd-jni:1.4.3-1'
implementation 'com.esotericsoftware:reflectasm:1.11.9'
}

View File

@ -17,16 +17,14 @@ import fr.themode.minestom.net.PacketProcessor;
import fr.themode.minestom.net.packet.server.play.KeepAlivePacket;
import fr.themode.minestom.net.protocol.MinecraftProtocol;
import java.lang.reflect.InvocationTargetException;
public class Main {
// Thread number
public static final int THREAD_COUNT_PACKET_WRITER = 5;
public static final int THREAD_COUNT_CHUNK_IO = 2;
public static final int THREAD_COUNT_CHUNK_BATCH = 2;
public static final int THREAD_COUNT_ENTITIES = 1;
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 3;
public static final int THREAD_COUNT_CHUNK_BATCH = 3;
public static final int THREAD_COUNT_ENTITIES = 3;
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 2;
public static final int TICK_MS = 50;
public static final int TICK_PER_SECOND = 1000 / TICK_MS;
@ -65,12 +63,14 @@ public class Main {
@Override
public void onDisconnect(Server server, Connection connection) {
System.out.println("A DISCONNECTION");
System.out.println("A Disconnection");
if (packetProcessor.hasPlayerConnection(connection)) {
Player player = connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection));
if (player != null) {
Instance instance = player.getInstance();
if (instance != null) {
instance.removeEntity(player);
}
@ -85,17 +85,7 @@ public class Main {
@Override
public void onPacketReceive(Server server, Connection connection, Packet packet) {
try {
packetProcessor.process(connection, packet);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
packetProcessor.process(connection, packet);
}
@Override

View File

@ -26,11 +26,11 @@ public interface Viewable {
int size = getViewers().size();
if (size == 0)
return;
buffer.getData().retain(getViewers().size()).markReaderIndex();
getViewers().forEach(player -> {
player.getPlayerConnection().writeUnencodedPacket(buffer);
buffer.getData().retain(size).markReaderIndex();
for (Player viewer : getViewers()) {
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
buffer.getData().resetReaderIndex();
});
}
});
}
@ -40,11 +40,14 @@ public interface Viewable {
for (ServerPacket packet : packets) {
PacketWriter.writeCallbackPacket(packet, buffer -> {
buffer.getData().retain(getViewers().size()).markReaderIndex();
getViewers().forEach(player -> {
player.getPlayerConnection().writeUnencodedPacket(buffer);
int size = getViewers().size();
if (size == 0)
return;
buffer.getData().retain(size).markReaderIndex();
for (Player viewer : getViewers()) {
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
buffer.getData().resetReaderIndex();
});
}
});
}
}
@ -52,14 +55,15 @@ public interface Viewable {
default void sendPacketToViewersAndSelf(ServerPacket packet) {
if (this instanceof Player) {
PacketWriter.writeCallbackPacket(packet, buffer -> {
buffer.getData().retain(getViewers().size() + 1).markReaderIndex();
int size = getViewers().size();
buffer.getData().retain(size + 1).markReaderIndex();
((Player) this).getPlayerConnection().writeUnencodedPacket(buffer);
buffer.getData().resetReaderIndex();
if (!getViewers().isEmpty()) {
getViewers().forEach(player -> {
if (size != 0) {
for (Player viewer : getViewers()) {
buffer.getData().resetReaderIndex();
player.getPlayerConnection().writeUnencodedPacket(buffer);
});
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
}
}
});
}

View File

@ -109,21 +109,7 @@ public abstract class Entity implements Viewable, DataContainer {
if (instance == null)
return;
if (instance.hasEnabledAutoChunkLoad()) {
instance.loadChunk(position, chunk -> {
refreshPosition(position.getX(), position.getY(), position.getZ());
refreshView(position.getYaw(), position.getPitch());
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
entityTeleportPacket.entityId = getEntityId();
entityTeleportPacket.position = position;
entityTeleportPacket.onGround = onGround;
sendPacketToViewers(entityTeleportPacket);
if (callback != null)
callback.run();
});
} else {
if (isChunkUnloaded(position.getX(), position.getZ()))
return;
Runnable runnable = () -> {
refreshPosition(position.getX(), position.getY(), position.getZ());
refreshView(position.getYaw(), position.getPitch());
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
@ -131,6 +117,18 @@ public abstract class Entity implements Viewable, DataContainer {
entityTeleportPacket.position = position;
entityTeleportPacket.onGround = onGround;
sendPacketToViewers(entityTeleportPacket);
};
if (instance.hasEnabledAutoChunkLoad()) {
instance.loadChunk(position, chunk -> {
runnable.run();
if (callback != null)
callback.run();
});
} else {
if (isChunkUnloaded(position.getX(), position.getZ()))
return;
runnable.run();
if (callback != null)
callback.run();
}
@ -196,7 +194,7 @@ public abstract class Entity implements Viewable, DataContainer {
// Velocity
if (velocityTime != 0) {
if (time >= velocityTime) {
// TODO send synchronization packet?
sendPositionSynchronization(); // Send synchronization after velocity ended
resetVelocity();
} else {
if (this instanceof Player) {
@ -215,7 +213,7 @@ public abstract class Entity implements Viewable, DataContainer {
update();
// Synchronization
// Scheduled synchronization
if (time - lastSynchronizationTime >= synchronizationDelay) {
lastSynchronizationTime = System.currentTimeMillis();
sendPositionSynchronization();
@ -309,7 +307,14 @@ public abstract class Entity implements Viewable, DataContainer {
if (instance != null) {
SetPassengersPacket passengersPacket = new SetPassengersPacket();
passengersPacket.vehicleEntityId = getEntityId();
passengersPacket.passengersId = new int[]{entity.getEntityId()}; // TODO all passengers not only the new
int[] passengers = new int[this.passengers.size()];
int counter = 0;
for (Entity passenger : this.passengers) {
passengers[counter++] = passenger.getEntityId();
}
passengersPacket.passengersId = passengers;
sendPacketToViewers(passengersPacket);
}
}

View File

@ -49,13 +49,15 @@ public class EntityManager {
int chunkZ = chunkPos[1];
boolean isLast = i == visibleChunks.length - 1;
Consumer<Chunk> callback = isLast ? chunk -> {
System.out.println("END CHUNK LOADING");
playerCache.spawned = true;
playerCache.setInstance(spawningInstance);
PlayerSpawnEvent spawnEvent = new PlayerSpawnEvent();
playerCache.callEvent(PlayerSpawnEvent.class, spawnEvent);
playerCache.updateViewPosition(chunk);
} : null;
spawningInstance.loadChunk(chunkX, chunkZ, callback); // TODO loadOptionalChunk for not loading chunks when autoload is false
// WARNING: if auto load is disabled and no chunks are loaded beforehand, player will be stuck.
spawningInstance.loadChunk(chunkX, chunkZ, callback);
}
});

View File

@ -1,25 +1,31 @@
package fr.themode.minestom.entity;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.entity.property.Attribute;
import fr.themode.minestom.event.PickupItemEvent;
import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.server.play.CollectItemPacket;
import fr.themode.minestom.net.packet.server.play.EntityPropertiesPacket;
import java.util.Set;
// TODO attributes https://wiki.vg/Protocol#Entity_Properties
public abstract class LivingEntity extends Entity {
protected boolean canPickupItem;
protected boolean isDead;
protected float health;
private float[] attributeValues = new float[Attribute.values().length];
private boolean isHandActive;
private boolean activeHand;
private boolean riptideSpinAttack;
public LivingEntity(int entityType) {
super(entityType);
setupAttributes();
}
public abstract void kill();
@ -73,6 +79,33 @@ public abstract class LivingEntity extends Entity {
return buffer;
}
public float getHealth() {
return health;
}
public void setHealth(float health) {
this.health = health;
if (this.health <= 0) {
kill();
}
}
public float getMaxHealth() {
return getAttributeValue(Attribute.MAX_HEALTH);
}
public void heal() {
setHealth(getAttributeValue(Attribute.MAX_HEALTH));
}
public void setAttribute(Attribute attribute, float value) {
this.attributeValues[attribute.ordinal()] = value;
}
public float getAttributeValue(Attribute attribute) {
return this.attributeValues[attribute.ordinal()];
}
public boolean isDead() {
return isDead;
}
@ -94,4 +127,28 @@ public abstract class LivingEntity extends Entity {
public void refreshIsDead(boolean isDead) {
this.isDead = isDead;
}
protected EntityPropertiesPacket getPropertiesPacket() {
EntityPropertiesPacket propertiesPacket = new EntityPropertiesPacket();
propertiesPacket.entityId = getEntityId();
int length = Attribute.values().length;
EntityPropertiesPacket.Property[] properties = new EntityPropertiesPacket.Property[length];
for (int i = 0; i < length; i++) {
Attribute attribute = Attribute.values()[i];
EntityPropertiesPacket.Property property = new EntityPropertiesPacket.Property();
property.key = attribute.getKey();
property.value = getAttributeValue(attribute);
properties[i] = property;
}
propertiesPacket.properties = properties;
return propertiesPacket;
}
private void setupAttributes() {
for (Attribute attribute : Attribute.values()) {
setAttribute(attribute, attribute.getDefaultValue());
}
}
}

View File

@ -4,8 +4,7 @@ import fr.themode.minestom.Main;
import fr.themode.minestom.bossbar.BossBar;
import fr.themode.minestom.chat.Chat;
import fr.themode.minestom.data.Data;
import fr.themode.minestom.data.DataType;
import fr.themode.minestom.entity.demo.ChickenCreature;
import fr.themode.minestom.entity.property.Attribute;
import fr.themode.minestom.event.*;
import fr.themode.minestom.instance.Chunk;
import fr.themode.minestom.instance.CustomBlock;
@ -14,7 +13,6 @@ import fr.themode.minestom.instance.InstanceContainer;
import fr.themode.minestom.instance.demo.ChunkGeneratorDemo;
import fr.themode.minestom.inventory.Inventory;
import fr.themode.minestom.inventory.PlayerInventory;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.play.*;
@ -45,6 +43,8 @@ public class Player extends LivingEntity {
private GameMode gameMode;
private LevelType levelType;
private static InstanceContainer instanceContainer;
static {
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
//instance = Main.getInstanceManager().createInstance(new File("C:\\Users\\themo\\OneDrive\\Bureau\\Minestom data"));
@ -62,13 +62,14 @@ public class Player extends LivingEntity {
}
protected Set<Entity> viewableEntity = new CopyOnWriteArraySet<>();
private float health;
private PlayerSettings settings;
private PlayerInventory inventory;
private short heldSlot;
private Inventory openInventory;
private int food;
private float foodSaturation;
private CustomBlock targetCustomBlock;
private BlockPosition targetBlockPosition;
@ -81,17 +82,15 @@ public class Player extends LivingEntity {
private float sideways;
private float forward;
private static InstanceContainer instanceContainer;
private float foodSaturation;
protected boolean spawned;
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
super(93); // FIXME verify
super(93);
this.uuid = uuid;
this.username = username;
this.playerConnection = playerConnection;
playerConnection.sendPacket(getPropertiesPacket()); // Send default properties
refreshHealth();
this.settings = new PlayerSettings();
@ -115,11 +114,11 @@ public class Player extends LivingEntity {
});
setEventCallback(PlayerBlockPlaceEvent.class, event -> {
sendMessage("Placed block! " + event.getHand());
/*sendMessage("Placed block! " + event.getHand());
int value = getData().getOrDefault("test", 0);
getData().set("test", value + 1, DataType.INTEGER);
System.out.println("OLD DATA VALUE: " + value);
System.out.println("OLD DATA VALUE: " + value);*/
if (event.getHand() != Hand.MAIN)
return;
@ -129,10 +128,10 @@ public class Player extends LivingEntity {
sendMessage("Saved in " + (System.currentTimeMillis() - time) + " ms");
});*/
/*for (Player player : instance.getPlayers()) {
for (Player player : instance.getPlayers()) {
if (player != this)
player.teleport(getPosition());
}*/
}
});
setEventCallback(PickupItemEvent.class, event -> {
@ -146,10 +145,10 @@ public class Player extends LivingEntity {
setEventCallback(PlayerSpawnEvent.class, event -> {
System.out.println("SPAWN ");
setGameMode(GameMode.CREATIVE);
setGameMode(GameMode.SURVIVAL);
teleport(new Position(0, 66, 0));
ChickenCreature chickenCreature = new ChickenCreature();
/*ChickenCreature chickenCreature = new ChickenCreature();
chickenCreature.refreshPosition(2, 65, 2);
chickenCreature.setInstance(getInstance());
@ -160,7 +159,7 @@ public class Player extends LivingEntity {
itemEntity.setNoGravity(true);
itemEntity.setInstance(getInstance());
//itemEntity.remove();
}
}*/
TeamsPacket teamsPacket = new TeamsPacket();
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
@ -173,6 +172,9 @@ public class Player extends LivingEntity {
teamsPacket.collisionRule = "never";
teamsPacket.entities = new String[]{getUsername()};
sendPacketToViewersAndSelf(teamsPacket);
setAttribute(Attribute.MAX_HEALTH, 21);
heal();
});
}
@ -301,7 +303,7 @@ public class Player extends LivingEntity {
connection.sendPacket(getMetadataPacket());
for (EntityEquipmentPacket.Slot slot : EntityEquipmentPacket.Slot.values()) {
syncEquipment(slot); // TODO only send packets to "player" and not all viewers
player.playerConnection.sendPacket(getEquipmentPacket(slot));
}
}
@ -324,7 +326,13 @@ public class Player extends LivingEntity {
@Override
public void kill() {
this.isDead = true;
setHealth(-1);
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);
}
public void sendBlockBreakAnimation(BlockPosition blockPosition, byte destroyStage) {
@ -341,6 +349,9 @@ public class Player extends LivingEntity {
}
public void damage(float amount) {
if (getGameMode() == GameMode.CREATIVE)
return;
AnimationPacket animationPacket = new AnimationPacket();
animationPacket.entityId = getEntityId();
animationPacket.animation = AnimationPacket.Animation.TAKE_DAMAGE;
@ -348,23 +359,17 @@ public class Player extends LivingEntity {
setHealth(health - amount);
}
public float getHealth() {
return health;
@Override
public void setAttribute(Attribute attribute, float value) {
super.setAttribute(attribute, value);
if (playerConnection != null)
playerConnection.sendPacket(getPropertiesPacket());
}
@Override
public void setHealth(float health) {
this.health = health;
super.setHealth(health);
sendUpdateHealthPacket();
if (this.health <= 0) {
// Kill player
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);
}
}
public int getFood() {
@ -408,12 +413,13 @@ public class Player extends LivingEntity {
spawnPlayerPacket.playerUuid = getUuid();
spawnPlayerPacket.position = getPosition();
sendPacketToViewers(spawnPlayerPacket);
playerConnection.sendPacket(getPropertiesPacket());
sendUpdateHealthPacket();
});
}
private void refreshHealth() {
// TODO improve
this.health = 20;
heal();
this.food = 20;
this.foodSaturation = 5;
}
@ -473,8 +479,7 @@ public class Player extends LivingEntity {
}
UpdateViewPositionPacket updateViewPositionPacket = new UpdateViewPositionPacket(newChunk);
playerConnection.sendPacket(updateViewPositionPacket);
updateViewPosition(newChunk);
}
@Override
@ -625,11 +630,20 @@ public class Player extends LivingEntity {
}
public void syncEquipment(EntityEquipmentPacket.Slot slot) {
sendPacketToViewers(getEquipmentPacket(slot));
}
protected EntityEquipmentPacket getEquipmentPacket(EntityEquipmentPacket.Slot slot) {
EntityEquipmentPacket equipmentPacket = new EntityEquipmentPacket();
equipmentPacket.entityId = getEntityId();
equipmentPacket.slot = slot;
equipmentPacket.itemStack = inventory.getEquipment(slot);
sendPacketToViewers(equipmentPacket);
return equipmentPacket;
}
protected void updateViewPosition(Chunk chunk) {
UpdateViewPositionPacket updateViewPositionPacket = new UpdateViewPositionPacket(chunk);
playerConnection.sendPacket(updateViewPositionPacket);
}
public void addPacketToQueue(ClientPlayPacket packet) {

View File

@ -0,0 +1,30 @@
package fr.themode.minestom.entity.property;
public enum Attribute {
MAX_HEALTH("generic.maxHealth", 20),
FOLLOW_RANGE("generic.followRange", 32),
KNOCKBACK_RESISTANCE("generic.knockbackResistance", 0),
MOVEMENT_SPEED("generic.movementSpeed", 0.7f),
ATTACK_DAMAGE("generic.attackDamage", 2),
ATTACK_SPEED("generic.attackSpeed", 4),
FLYING_SPEED("generic.flyingSpeed", 0.4f),
HORSE_JUMP_STRENGTH("horse.jumpStrength", 0.7f),
ZOMBIE_SPAWN_REINFORCEMENTS("zombie.spawnReinforcements", 0);
private String key;
private float defaultValue;
Attribute(String key, float defaultValue) {
this.key = key;
this.defaultValue = defaultValue;
}
public String getKey() {
return key;
}
public float getDefaultValue() {
return defaultValue;
}
}

View File

@ -13,7 +13,6 @@ import fr.themode.minestom.net.packet.client.handler.ClientStatusPacketsHandler;
import fr.themode.minestom.net.packet.client.handshake.HandshakePacket;
import fr.themode.minestom.net.player.PlayerConnection;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
@ -42,7 +41,7 @@ public class PacketProcessor {
private List<Integer> printBlackList = Arrays.asList(17, 18, 19);
public void process(Connection connection, Packet packet) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
public void process(Connection connection, Packet packet) {
int id = packet.get(PACKET_ID_IDENTIFIER);
Buffer buffer = packet.getPayload();
connectionPlayerConnectionMap.get(connection);
@ -66,17 +65,17 @@ public class PacketProcessor {
switch (connectionState) {
case PLAY:
Player player = connectionManager.getPlayer(playerConnection);
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(id);
playPacket.read(buffer);
player.addPacketToQueue(playPacket); // Processed during player tick update
break;
case LOGIN:
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(id);
loginPacket.read(buffer);
loginPacket.process(playerConnection, connectionManager);
break;
case STATUS:
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(id);
statusPacket.read(buffer);
statusPacket.process(playerConnection, connectionManager);
break;

View File

@ -17,7 +17,7 @@ public class PacketWriter {
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<Buffer> consumer) {
batchesPool.execute(() -> {
Packet p = PacketUtils.writePacket(serverPacket);
consumer.accept(PacketUtils.encode(p)); // TODO accept in another thread?
consumer.accept(PacketUtils.encode(p));
});
}

View File

@ -1,5 +1,6 @@
package fr.themode.minestom.net.packet.client.handler;
import com.esotericsoftware.reflectasm.ConstructorAccess;
import fr.themode.minestom.net.packet.client.ClientPacket;
import java.util.HashMap;
@ -7,14 +8,14 @@ import java.util.Map;
public class ClientPacketsHandler {
private Map<Integer, Class<? extends ClientPacket>> idPacketMap = new HashMap<>();
private Map<Integer, ConstructorAccess<? extends ClientPacket>> constructorAccessMap = new HashMap<>();
public void register(int id, Class<? extends ClientPacket> packet) {
this.idPacketMap.put(id, packet);
this.constructorAccessMap.put(id, ConstructorAccess.get(packet));
}
public Class<? extends ClientPacket> getPacketClass(int id) {
return idPacketMap.get(id);
public ClientPacket getPacketInstance(int id) {
return constructorAccessMap.get(id).newInstance();
}
}

View File

@ -21,26 +21,6 @@ import java.util.UUID;
public class LoginStartPacket implements ClientPreplayPacket {
// Test
/*private static Instance instance;
static {
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
instance = Main.getInstanceManager().createInstance(new File("C:\\Users\\themo\\OneDrive\\Bureau\\Minestom data"));
//instance = Main.getInstanceManager().createInstance();
instance.setChunkGenerator(chunkGeneratorDemo);
int loopStart = -2;
int loopEnd = 2;
long time = System.currentTimeMillis();
for (int x = loopStart; x < loopEnd; x++)
for (int z = loopStart; z < loopEnd; z++) {
instance.loadChunk(x, z, chunk -> {
System.out.println("JE SUIS LE CALLBACK CHUNK");
});
}
System.out.println("Time to load all chunks: " + (System.currentTimeMillis() - time) + " ms");
}*/
public String username;
@Override
@ -110,51 +90,9 @@ public class LoginStartPacket implements ClientPreplayPacket {
playerInfoPacket.playerInfos.add(addPlayer);
connection.sendPacket(playerInfoPacket);
// Next is optional TODO put all that somewhere else (LoginEvent)
// TODO LoginEvent in another thread (here we are in netty thread)
Main.getEntityManager().addWaitingPlayer(player);
// TODO REMOVE EVERYTHING DOWN THERE
//player.setInstance(instance);
/*for (int cx = 0; cx < 4; cx++)
for (int cz = 0; cz < 4; cz++) {
ChickenCreature chickenCreature = new ChickenCreature();
chickenCreature.refreshPosition(0 + (float) cx * 1, 65, 0 + (float) cz * 1);
//chickenCreature.setOnFire(true);
chickenCreature.setInstance(instance);
//chickenCreature.addPassenger(player);
}
PlayerInventory inventory = player.getInventory();
inventory.addItemStack(new ItemStack(Material.BOW, (byte) 1));
inventory.addItemStack(new ItemStack(Material.ARROW, (byte) 100));
/*Inventory inv = new Inventory(InventoryType.WINDOW_3X3, "Salut je suis le titre");
inv.setItemStack(0, new ItemStack(1, (byte) 1));
player.openInventory(inv);
inv.setItemStack(1, new ItemStack(1, (byte) 2));
BossBar bossBar = new BossBar("Bossbar Title", BarColor.BLUE, BarDivision.SEGMENT_12);
bossBar.setProgress(0.75f);
bossBar.addViewer(player);
for (int ix = 0; ix < 4; ix++)
for (int iz = 0; iz < 4; iz++) {
ItemEntity itemEntity = new ItemEntity(new ItemStack(1, (byte) 32));
itemEntity.refreshPosition(ix, 66, iz);
itemEntity.setNoGravity(true);
itemEntity.setInstance(instance);
//itemEntity.remove();
}
TestArrow arrow = new TestArrow(player);
arrow.refreshPosition(5, 65, 5);
arrow.setInstance(instance);
arrow.setNoGravity(true);
DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
/*DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
argumentNode.flags = 0b1010;
argumentNode.children = new int[0];

View File

@ -0,0 +1,41 @@
package fr.themode.minestom.net.packet.server.play;
import fr.adamaq01.ozao.net.Buffer;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.utils.Utils;
public class EntityPropertiesPacket implements ServerPacket {
public int entityId;
public Property[] properties;
@Override
public void write(Buffer buffer) {
Utils.writeVarInt(buffer, entityId);
buffer.putInt(properties.length);
for (Property property : properties) {
property.write(buffer);
}
}
@Override
public int getId() {
return 0x58;
}
public static class Property {
public String key;
public double value;
private void write(Buffer buffer) {
Utils.writeString(buffer, key);
buffer.putDouble(value);
// TODO Modifiers
Utils.writeVarInt(buffer, 0);
}
}
}

View File

@ -172,7 +172,7 @@ public class Utils {
buffer.putByte((byte) 0); // End display compound
buffer.putByte((byte) 0); // End nbt TODO
buffer.putByte((byte) 0); // End nbt
}
}