mirror of
https://github.com/Minestom/Minestom.git
synced 2025-01-28 02:51:42 +01:00
Added entity properties & removed unnecessary reflection
This commit is contained in:
parent
e0eb35e81e
commit
b13a888170
@ -18,4 +18,5 @@ dependencies {
|
|||||||
compile 'com.github.Querz:NBT:4.1'
|
compile 'com.github.Querz:NBT:4.1'
|
||||||
// https://mvnrepository.com/artifact/org.lz4/lz4-java
|
// https://mvnrepository.com/artifact/org.lz4/lz4-java
|
||||||
implementation 'com.github.luben:zstd-jni:1.4.3-1'
|
implementation 'com.github.luben:zstd-jni:1.4.3-1'
|
||||||
|
implementation 'com.esotericsoftware:reflectasm:1.11.9'
|
||||||
}
|
}
|
||||||
|
@ -17,16 +17,14 @@ import fr.themode.minestom.net.PacketProcessor;
|
|||||||
import fr.themode.minestom.net.packet.server.play.KeepAlivePacket;
|
import fr.themode.minestom.net.packet.server.play.KeepAlivePacket;
|
||||||
import fr.themode.minestom.net.protocol.MinecraftProtocol;
|
import fr.themode.minestom.net.protocol.MinecraftProtocol;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
|
|
||||||
public class Main {
|
public class Main {
|
||||||
|
|
||||||
// Thread number
|
// Thread number
|
||||||
public static final int THREAD_COUNT_PACKET_WRITER = 5;
|
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_IO = 2;
|
||||||
public static final int THREAD_COUNT_CHUNK_BATCH = 2;
|
public static final int THREAD_COUNT_CHUNK_BATCH = 3;
|
||||||
public static final int THREAD_COUNT_ENTITIES = 1;
|
public static final int THREAD_COUNT_ENTITIES = 3;
|
||||||
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 3;
|
public static final int THREAD_COUNT_PLAYERS_ENTITIES = 2;
|
||||||
|
|
||||||
public static final int TICK_MS = 50;
|
public static final int TICK_MS = 50;
|
||||||
public static final int TICK_PER_SECOND = 1000 / TICK_MS;
|
public static final int TICK_PER_SECOND = 1000 / TICK_MS;
|
||||||
@ -65,12 +63,14 @@ public class Main {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onDisconnect(Server server, Connection connection) {
|
public void onDisconnect(Server server, Connection connection) {
|
||||||
System.out.println("A DISCONNECTION");
|
System.out.println("A Disconnection");
|
||||||
if (packetProcessor.hasPlayerConnection(connection)) {
|
if (packetProcessor.hasPlayerConnection(connection)) {
|
||||||
Player player = connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection));
|
Player player = connectionManager.getPlayer(packetProcessor.getPlayerConnection(connection));
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
|
|
||||||
Instance instance = player.getInstance();
|
Instance instance = player.getInstance();
|
||||||
|
|
||||||
|
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
instance.removeEntity(player);
|
instance.removeEntity(player);
|
||||||
}
|
}
|
||||||
@ -85,17 +85,7 @@ public class Main {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketReceive(Server server, Connection connection, Packet packet) {
|
public void onPacketReceive(Server server, Connection connection, Packet packet) {
|
||||||
try {
|
packetProcessor.process(connection, packet);
|
||||||
packetProcessor.process(connection, packet);
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -26,11 +26,11 @@ public interface Viewable {
|
|||||||
int size = getViewers().size();
|
int size = getViewers().size();
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return;
|
return;
|
||||||
buffer.getData().retain(getViewers().size()).markReaderIndex();
|
buffer.getData().retain(size).markReaderIndex();
|
||||||
getViewers().forEach(player -> {
|
for (Player viewer : getViewers()) {
|
||||||
player.getPlayerConnection().writeUnencodedPacket(buffer);
|
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
|
||||||
buffer.getData().resetReaderIndex();
|
buffer.getData().resetReaderIndex();
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,11 +40,14 @@ public interface Viewable {
|
|||||||
|
|
||||||
for (ServerPacket packet : packets) {
|
for (ServerPacket packet : packets) {
|
||||||
PacketWriter.writeCallbackPacket(packet, buffer -> {
|
PacketWriter.writeCallbackPacket(packet, buffer -> {
|
||||||
buffer.getData().retain(getViewers().size()).markReaderIndex();
|
int size = getViewers().size();
|
||||||
getViewers().forEach(player -> {
|
if (size == 0)
|
||||||
player.getPlayerConnection().writeUnencodedPacket(buffer);
|
return;
|
||||||
|
buffer.getData().retain(size).markReaderIndex();
|
||||||
|
for (Player viewer : getViewers()) {
|
||||||
|
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
|
||||||
buffer.getData().resetReaderIndex();
|
buffer.getData().resetReaderIndex();
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,14 +55,15 @@ public interface Viewable {
|
|||||||
default void sendPacketToViewersAndSelf(ServerPacket packet) {
|
default void sendPacketToViewersAndSelf(ServerPacket packet) {
|
||||||
if (this instanceof Player) {
|
if (this instanceof Player) {
|
||||||
PacketWriter.writeCallbackPacket(packet, buffer -> {
|
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);
|
((Player) this).getPlayerConnection().writeUnencodedPacket(buffer);
|
||||||
buffer.getData().resetReaderIndex();
|
buffer.getData().resetReaderIndex();
|
||||||
if (!getViewers().isEmpty()) {
|
if (size != 0) {
|
||||||
getViewers().forEach(player -> {
|
for (Player viewer : getViewers()) {
|
||||||
buffer.getData().resetReaderIndex();
|
buffer.getData().resetReaderIndex();
|
||||||
player.getPlayerConnection().writeUnencodedPacket(buffer);
|
viewer.getPlayerConnection().writeUnencodedPacket(buffer);
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -109,21 +109,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
if (instance == null)
|
if (instance == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (instance.hasEnabledAutoChunkLoad()) {
|
Runnable runnable = () -> {
|
||||||
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;
|
|
||||||
refreshPosition(position.getX(), position.getY(), position.getZ());
|
refreshPosition(position.getX(), position.getY(), position.getZ());
|
||||||
refreshView(position.getYaw(), position.getPitch());
|
refreshView(position.getYaw(), position.getPitch());
|
||||||
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
EntityTeleportPacket entityTeleportPacket = new EntityTeleportPacket();
|
||||||
@ -131,6 +117,18 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
entityTeleportPacket.position = position;
|
entityTeleportPacket.position = position;
|
||||||
entityTeleportPacket.onGround = onGround;
|
entityTeleportPacket.onGround = onGround;
|
||||||
sendPacketToViewers(entityTeleportPacket);
|
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)
|
if (callback != null)
|
||||||
callback.run();
|
callback.run();
|
||||||
}
|
}
|
||||||
@ -196,7 +194,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
// Velocity
|
// Velocity
|
||||||
if (velocityTime != 0) {
|
if (velocityTime != 0) {
|
||||||
if (time >= velocityTime) {
|
if (time >= velocityTime) {
|
||||||
// TODO send synchronization packet?
|
sendPositionSynchronization(); // Send synchronization after velocity ended
|
||||||
resetVelocity();
|
resetVelocity();
|
||||||
} else {
|
} else {
|
||||||
if (this instanceof Player) {
|
if (this instanceof Player) {
|
||||||
@ -215,7 +213,7 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
|
|
||||||
update();
|
update();
|
||||||
|
|
||||||
// Synchronization
|
// Scheduled synchronization
|
||||||
if (time - lastSynchronizationTime >= synchronizationDelay) {
|
if (time - lastSynchronizationTime >= synchronizationDelay) {
|
||||||
lastSynchronizationTime = System.currentTimeMillis();
|
lastSynchronizationTime = System.currentTimeMillis();
|
||||||
sendPositionSynchronization();
|
sendPositionSynchronization();
|
||||||
@ -309,7 +307,14 @@ public abstract class Entity implements Viewable, DataContainer {
|
|||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
SetPassengersPacket passengersPacket = new SetPassengersPacket();
|
SetPassengersPacket passengersPacket = new SetPassengersPacket();
|
||||||
passengersPacket.vehicleEntityId = getEntityId();
|
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);
|
sendPacketToViewers(passengersPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,13 +49,15 @@ public class EntityManager {
|
|||||||
int chunkZ = chunkPos[1];
|
int chunkZ = chunkPos[1];
|
||||||
boolean isLast = i == visibleChunks.length - 1;
|
boolean isLast = i == visibleChunks.length - 1;
|
||||||
Consumer<Chunk> callback = isLast ? chunk -> {
|
Consumer<Chunk> callback = isLast ? chunk -> {
|
||||||
System.out.println("END CHUNK LOADING");
|
|
||||||
playerCache.spawned = true;
|
playerCache.spawned = true;
|
||||||
playerCache.setInstance(spawningInstance);
|
playerCache.setInstance(spawningInstance);
|
||||||
PlayerSpawnEvent spawnEvent = new PlayerSpawnEvent();
|
PlayerSpawnEvent spawnEvent = new PlayerSpawnEvent();
|
||||||
playerCache.callEvent(PlayerSpawnEvent.class, spawnEvent);
|
playerCache.callEvent(PlayerSpawnEvent.class, spawnEvent);
|
||||||
|
playerCache.updateViewPosition(chunk);
|
||||||
} : null;
|
} : 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
@ -1,25 +1,31 @@
|
|||||||
package fr.themode.minestom.entity;
|
package fr.themode.minestom.entity;
|
||||||
|
|
||||||
import fr.adamaq01.ozao.net.Buffer;
|
import fr.adamaq01.ozao.net.Buffer;
|
||||||
|
import fr.themode.minestom.entity.property.Attribute;
|
||||||
import fr.themode.minestom.event.PickupItemEvent;
|
import fr.themode.minestom.event.PickupItemEvent;
|
||||||
import fr.themode.minestom.instance.Chunk;
|
import fr.themode.minestom.instance.Chunk;
|
||||||
import fr.themode.minestom.item.ItemStack;
|
import fr.themode.minestom.item.ItemStack;
|
||||||
import fr.themode.minestom.net.packet.server.play.CollectItemPacket;
|
import fr.themode.minestom.net.packet.server.play.CollectItemPacket;
|
||||||
|
import fr.themode.minestom.net.packet.server.play.EntityPropertiesPacket;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
// TODO attributes https://wiki.vg/Protocol#Entity_Properties
|
|
||||||
public abstract class LivingEntity extends Entity {
|
public abstract class LivingEntity extends Entity {
|
||||||
|
|
||||||
protected boolean canPickupItem;
|
protected boolean canPickupItem;
|
||||||
protected boolean isDead;
|
protected boolean isDead;
|
||||||
|
|
||||||
|
protected float health;
|
||||||
|
|
||||||
|
private float[] attributeValues = new float[Attribute.values().length];
|
||||||
|
|
||||||
private boolean isHandActive;
|
private boolean isHandActive;
|
||||||
private boolean activeHand;
|
private boolean activeHand;
|
||||||
private boolean riptideSpinAttack;
|
private boolean riptideSpinAttack;
|
||||||
|
|
||||||
public LivingEntity(int entityType) {
|
public LivingEntity(int entityType) {
|
||||||
super(entityType);
|
super(entityType);
|
||||||
|
setupAttributes();
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract void kill();
|
public abstract void kill();
|
||||||
@ -73,6 +79,33 @@ public abstract class LivingEntity extends Entity {
|
|||||||
return buffer;
|
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() {
|
public boolean isDead() {
|
||||||
return isDead;
|
return isDead;
|
||||||
}
|
}
|
||||||
@ -94,4 +127,28 @@ public abstract class LivingEntity extends Entity {
|
|||||||
public void refreshIsDead(boolean isDead) {
|
public void refreshIsDead(boolean isDead) {
|
||||||
this.isDead = 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());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,7 @@ import fr.themode.minestom.Main;
|
|||||||
import fr.themode.minestom.bossbar.BossBar;
|
import fr.themode.minestom.bossbar.BossBar;
|
||||||
import fr.themode.minestom.chat.Chat;
|
import fr.themode.minestom.chat.Chat;
|
||||||
import fr.themode.minestom.data.Data;
|
import fr.themode.minestom.data.Data;
|
||||||
import fr.themode.minestom.data.DataType;
|
import fr.themode.minestom.entity.property.Attribute;
|
||||||
import fr.themode.minestom.entity.demo.ChickenCreature;
|
|
||||||
import fr.themode.minestom.event.*;
|
import fr.themode.minestom.event.*;
|
||||||
import fr.themode.minestom.instance.Chunk;
|
import fr.themode.minestom.instance.Chunk;
|
||||||
import fr.themode.minestom.instance.CustomBlock;
|
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.instance.demo.ChunkGeneratorDemo;
|
||||||
import fr.themode.minestom.inventory.Inventory;
|
import fr.themode.minestom.inventory.Inventory;
|
||||||
import fr.themode.minestom.inventory.PlayerInventory;
|
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.client.ClientPlayPacket;
|
||||||
import fr.themode.minestom.net.packet.server.ServerPacket;
|
import fr.themode.minestom.net.packet.server.ServerPacket;
|
||||||
import fr.themode.minestom.net.packet.server.play.*;
|
import fr.themode.minestom.net.packet.server.play.*;
|
||||||
@ -45,6 +43,8 @@ public class Player extends LivingEntity {
|
|||||||
private GameMode gameMode;
|
private GameMode gameMode;
|
||||||
private LevelType levelType;
|
private LevelType levelType;
|
||||||
|
|
||||||
|
private static InstanceContainer instanceContainer;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
|
ChunkGeneratorDemo chunkGeneratorDemo = new ChunkGeneratorDemo();
|
||||||
//instance = Main.getInstanceManager().createInstance(new File("C:\\Users\\themo\\OneDrive\\Bureau\\Minestom data"));
|
//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<>();
|
protected Set<Entity> viewableEntity = new CopyOnWriteArraySet<>();
|
||||||
private float health;
|
|
||||||
|
|
||||||
private PlayerSettings settings;
|
private PlayerSettings settings;
|
||||||
private PlayerInventory inventory;
|
private PlayerInventory inventory;
|
||||||
private short heldSlot;
|
private short heldSlot;
|
||||||
private Inventory openInventory;
|
private Inventory openInventory;
|
||||||
|
|
||||||
private int food;
|
private int food;
|
||||||
|
private float foodSaturation;
|
||||||
|
|
||||||
private CustomBlock targetCustomBlock;
|
private CustomBlock targetCustomBlock;
|
||||||
private BlockPosition targetBlockPosition;
|
private BlockPosition targetBlockPosition;
|
||||||
@ -81,17 +82,15 @@ public class Player extends LivingEntity {
|
|||||||
private float sideways;
|
private float sideways;
|
||||||
private float forward;
|
private float forward;
|
||||||
|
|
||||||
private static InstanceContainer instanceContainer;
|
|
||||||
private float foodSaturation;
|
|
||||||
|
|
||||||
protected boolean spawned;
|
protected boolean spawned;
|
||||||
|
|
||||||
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
public Player(UUID uuid, String username, PlayerConnection playerConnection) {
|
||||||
super(93); // FIXME verify
|
super(93);
|
||||||
this.uuid = uuid;
|
this.uuid = uuid;
|
||||||
this.username = username;
|
this.username = username;
|
||||||
this.playerConnection = playerConnection;
|
this.playerConnection = playerConnection;
|
||||||
|
|
||||||
|
playerConnection.sendPacket(getPropertiesPacket()); // Send default properties
|
||||||
refreshHealth();
|
refreshHealth();
|
||||||
|
|
||||||
this.settings = new PlayerSettings();
|
this.settings = new PlayerSettings();
|
||||||
@ -115,11 +114,11 @@ public class Player extends LivingEntity {
|
|||||||
});
|
});
|
||||||
|
|
||||||
setEventCallback(PlayerBlockPlaceEvent.class, event -> {
|
setEventCallback(PlayerBlockPlaceEvent.class, event -> {
|
||||||
sendMessage("Placed block! " + event.getHand());
|
/*sendMessage("Placed block! " + event.getHand());
|
||||||
int value = getData().getOrDefault("test", 0);
|
int value = getData().getOrDefault("test", 0);
|
||||||
getData().set("test", value + 1, DataType.INTEGER);
|
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)
|
if (event.getHand() != Hand.MAIN)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -129,10 +128,10 @@ public class Player extends LivingEntity {
|
|||||||
sendMessage("Saved in " + (System.currentTimeMillis() - time) + " ms");
|
sendMessage("Saved in " + (System.currentTimeMillis() - time) + " ms");
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
/*for (Player player : instance.getPlayers()) {
|
for (Player player : instance.getPlayers()) {
|
||||||
if (player != this)
|
if (player != this)
|
||||||
player.teleport(getPosition());
|
player.teleport(getPosition());
|
||||||
}*/
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
setEventCallback(PickupItemEvent.class, event -> {
|
setEventCallback(PickupItemEvent.class, event -> {
|
||||||
@ -146,10 +145,10 @@ public class Player extends LivingEntity {
|
|||||||
|
|
||||||
setEventCallback(PlayerSpawnEvent.class, event -> {
|
setEventCallback(PlayerSpawnEvent.class, event -> {
|
||||||
System.out.println("SPAWN ");
|
System.out.println("SPAWN ");
|
||||||
setGameMode(GameMode.CREATIVE);
|
setGameMode(GameMode.SURVIVAL);
|
||||||
teleport(new Position(0, 66, 0));
|
teleport(new Position(0, 66, 0));
|
||||||
|
|
||||||
ChickenCreature chickenCreature = new ChickenCreature();
|
/*ChickenCreature chickenCreature = new ChickenCreature();
|
||||||
chickenCreature.refreshPosition(2, 65, 2);
|
chickenCreature.refreshPosition(2, 65, 2);
|
||||||
chickenCreature.setInstance(getInstance());
|
chickenCreature.setInstance(getInstance());
|
||||||
|
|
||||||
@ -160,7 +159,7 @@ public class Player extends LivingEntity {
|
|||||||
itemEntity.setNoGravity(true);
|
itemEntity.setNoGravity(true);
|
||||||
itemEntity.setInstance(getInstance());
|
itemEntity.setInstance(getInstance());
|
||||||
//itemEntity.remove();
|
//itemEntity.remove();
|
||||||
}
|
}*/
|
||||||
|
|
||||||
TeamsPacket teamsPacket = new TeamsPacket();
|
TeamsPacket teamsPacket = new TeamsPacket();
|
||||||
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
|
teamsPacket.teamName = "TEAMNAME" + new Random().nextInt(100);
|
||||||
@ -173,6 +172,9 @@ public class Player extends LivingEntity {
|
|||||||
teamsPacket.collisionRule = "never";
|
teamsPacket.collisionRule = "never";
|
||||||
teamsPacket.entities = new String[]{getUsername()};
|
teamsPacket.entities = new String[]{getUsername()};
|
||||||
sendPacketToViewersAndSelf(teamsPacket);
|
sendPacketToViewersAndSelf(teamsPacket);
|
||||||
|
|
||||||
|
setAttribute(Attribute.MAX_HEALTH, 21);
|
||||||
|
heal();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,7 +303,7 @@ public class Player extends LivingEntity {
|
|||||||
connection.sendPacket(getMetadataPacket());
|
connection.sendPacket(getMetadataPacket());
|
||||||
|
|
||||||
for (EntityEquipmentPacket.Slot slot : EntityEquipmentPacket.Slot.values()) {
|
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
|
@Override
|
||||||
public void kill() {
|
public void kill() {
|
||||||
this.isDead = true;
|
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) {
|
public void sendBlockBreakAnimation(BlockPosition blockPosition, byte destroyStage) {
|
||||||
@ -341,6 +349,9 @@ public class Player extends LivingEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void damage(float amount) {
|
public void damage(float amount) {
|
||||||
|
if (getGameMode() == GameMode.CREATIVE)
|
||||||
|
return;
|
||||||
|
|
||||||
AnimationPacket animationPacket = new AnimationPacket();
|
AnimationPacket animationPacket = new AnimationPacket();
|
||||||
animationPacket.entityId = getEntityId();
|
animationPacket.entityId = getEntityId();
|
||||||
animationPacket.animation = AnimationPacket.Animation.TAKE_DAMAGE;
|
animationPacket.animation = AnimationPacket.Animation.TAKE_DAMAGE;
|
||||||
@ -348,23 +359,17 @@ public class Player extends LivingEntity {
|
|||||||
setHealth(health - amount);
|
setHealth(health - amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public float getHealth() {
|
@Override
|
||||||
return health;
|
public void setAttribute(Attribute attribute, float value) {
|
||||||
|
super.setAttribute(attribute, value);
|
||||||
|
if (playerConnection != null)
|
||||||
|
playerConnection.sendPacket(getPropertiesPacket());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setHealth(float health) {
|
public void setHealth(float health) {
|
||||||
this.health = health;
|
super.setHealth(health);
|
||||||
sendUpdateHealthPacket();
|
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() {
|
public int getFood() {
|
||||||
@ -408,12 +413,13 @@ public class Player extends LivingEntity {
|
|||||||
spawnPlayerPacket.playerUuid = getUuid();
|
spawnPlayerPacket.playerUuid = getUuid();
|
||||||
spawnPlayerPacket.position = getPosition();
|
spawnPlayerPacket.position = getPosition();
|
||||||
sendPacketToViewers(spawnPlayerPacket);
|
sendPacketToViewers(spawnPlayerPacket);
|
||||||
|
playerConnection.sendPacket(getPropertiesPacket());
|
||||||
|
sendUpdateHealthPacket();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void refreshHealth() {
|
private void refreshHealth() {
|
||||||
// TODO improve
|
heal();
|
||||||
this.health = 20;
|
|
||||||
this.food = 20;
|
this.food = 20;
|
||||||
this.foodSaturation = 5;
|
this.foodSaturation = 5;
|
||||||
}
|
}
|
||||||
@ -473,8 +479,7 @@ public class Player extends LivingEntity {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateViewPositionPacket updateViewPositionPacket = new UpdateViewPositionPacket(newChunk);
|
updateViewPosition(newChunk);
|
||||||
playerConnection.sendPacket(updateViewPositionPacket);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -625,11 +630,20 @@ public class Player extends LivingEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void syncEquipment(EntityEquipmentPacket.Slot slot) {
|
public void syncEquipment(EntityEquipmentPacket.Slot slot) {
|
||||||
|
sendPacketToViewers(getEquipmentPacket(slot));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected EntityEquipmentPacket getEquipmentPacket(EntityEquipmentPacket.Slot slot) {
|
||||||
EntityEquipmentPacket equipmentPacket = new EntityEquipmentPacket();
|
EntityEquipmentPacket equipmentPacket = new EntityEquipmentPacket();
|
||||||
equipmentPacket.entityId = getEntityId();
|
equipmentPacket.entityId = getEntityId();
|
||||||
equipmentPacket.slot = slot;
|
equipmentPacket.slot = slot;
|
||||||
equipmentPacket.itemStack = inventory.getEquipment(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) {
|
public void addPacketToQueue(ClientPlayPacket packet) {
|
||||||
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
@ -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.packet.client.handshake.HandshakePacket;
|
||||||
import fr.themode.minestom.net.player.PlayerConnection;
|
import fr.themode.minestom.net.player.PlayerConnection;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -42,7 +41,7 @@ public class PacketProcessor {
|
|||||||
|
|
||||||
private List<Integer> printBlackList = Arrays.asList(17, 18, 19);
|
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);
|
int id = packet.get(PACKET_ID_IDENTIFIER);
|
||||||
Buffer buffer = packet.getPayload();
|
Buffer buffer = packet.getPayload();
|
||||||
connectionPlayerConnectionMap.get(connection);
|
connectionPlayerConnectionMap.get(connection);
|
||||||
@ -66,17 +65,17 @@ public class PacketProcessor {
|
|||||||
switch (connectionState) {
|
switch (connectionState) {
|
||||||
case PLAY:
|
case PLAY:
|
||||||
Player player = connectionManager.getPlayer(playerConnection);
|
Player player = connectionManager.getPlayer(playerConnection);
|
||||||
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
|
ClientPlayPacket playPacket = (ClientPlayPacket) playPacketsHandler.getPacketInstance(id);
|
||||||
playPacket.read(buffer);
|
playPacket.read(buffer);
|
||||||
player.addPacketToQueue(playPacket); // Processed during player tick update
|
player.addPacketToQueue(playPacket); // Processed during player tick update
|
||||||
break;
|
break;
|
||||||
case LOGIN:
|
case LOGIN:
|
||||||
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
|
ClientPreplayPacket loginPacket = (ClientPreplayPacket) loginPacketsHandler.getPacketInstance(id);
|
||||||
loginPacket.read(buffer);
|
loginPacket.read(buffer);
|
||||||
loginPacket.process(playerConnection, connectionManager);
|
loginPacket.process(playerConnection, connectionManager);
|
||||||
break;
|
break;
|
||||||
case STATUS:
|
case STATUS:
|
||||||
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketClass(id).getDeclaredConstructor().newInstance();
|
ClientPreplayPacket statusPacket = (ClientPreplayPacket) statusPacketsHandler.getPacketInstance(id);
|
||||||
statusPacket.read(buffer);
|
statusPacket.read(buffer);
|
||||||
statusPacket.process(playerConnection, connectionManager);
|
statusPacket.process(playerConnection, connectionManager);
|
||||||
break;
|
break;
|
||||||
|
@ -17,7 +17,7 @@ public class PacketWriter {
|
|||||||
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<Buffer> consumer) {
|
public static void writeCallbackPacket(ServerPacket serverPacket, Consumer<Buffer> consumer) {
|
||||||
batchesPool.execute(() -> {
|
batchesPool.execute(() -> {
|
||||||
Packet p = PacketUtils.writePacket(serverPacket);
|
Packet p = PacketUtils.writePacket(serverPacket);
|
||||||
consumer.accept(PacketUtils.encode(p)); // TODO accept in another thread?
|
consumer.accept(PacketUtils.encode(p));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package fr.themode.minestom.net.packet.client.handler;
|
package fr.themode.minestom.net.packet.client.handler;
|
||||||
|
|
||||||
|
import com.esotericsoftware.reflectasm.ConstructorAccess;
|
||||||
import fr.themode.minestom.net.packet.client.ClientPacket;
|
import fr.themode.minestom.net.packet.client.ClientPacket;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -7,14 +8,14 @@ import java.util.Map;
|
|||||||
|
|
||||||
public class ClientPacketsHandler {
|
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) {
|
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) {
|
public ClientPacket getPacketInstance(int id) {
|
||||||
return idPacketMap.get(id);
|
return constructorAccessMap.get(id).newInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,26 +21,6 @@ import java.util.UUID;
|
|||||||
|
|
||||||
public class LoginStartPacket implements ClientPreplayPacket {
|
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;
|
public String username;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -110,51 +90,9 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
|||||||
playerInfoPacket.playerInfos.add(addPlayer);
|
playerInfoPacket.playerInfos.add(addPlayer);
|
||||||
connection.sendPacket(playerInfoPacket);
|
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);
|
Main.getEntityManager().addWaitingPlayer(player);
|
||||||
|
|
||||||
|
/*DeclareCommandsPacket declareCommandsPacket = new DeclareCommandsPacket();
|
||||||
// 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.Node argumentNode = new DeclareCommandsPacket.Node();
|
DeclareCommandsPacket.Node argumentNode = new DeclareCommandsPacket.Node();
|
||||||
argumentNode.flags = 0b1010;
|
argumentNode.flags = 0b1010;
|
||||||
argumentNode.children = new int[0];
|
argumentNode.children = new int[0];
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -172,7 +172,7 @@ public class Utils {
|
|||||||
|
|
||||||
buffer.putByte((byte) 0); // End display compound
|
buffer.putByte((byte) 0); // End display compound
|
||||||
|
|
||||||
buffer.putByte((byte) 0); // End nbt TODO
|
buffer.putByte((byte) 0); // End nbt
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user