Update + added particles

This commit is contained in:
Felix Cravic 2020-04-15 13:20:28 +02:00
parent c2580789b9
commit db9549560c
22 changed files with 362 additions and 55 deletions

View File

@ -9,6 +9,8 @@ An example of how to use the Minestom library is available [here](src/main/java/
Minecraft evolved a lot since its release, most of the servers today do not take advantage of vanilla features and even have to struggle because of them. Our target audience is those who want to make a completely different server compared to default Minecraft gamemode such as survival or creative building.
The goal is to offer more performance for those who need it, Minecraft being single-threaded is the most important problem for them.
In other words, it makes sense to use Minestom when it takes less time to implement everything you want than removing everything you don't need.
# API features
Even if we do not include anything by default in the game, we simplify the way you add them, here is a preview.

View File

@ -1,10 +1,8 @@
package fr.themode.demo;
import fr.themode.demo.entity.ChickenCreature;
import fr.themode.demo.generator.ChunkGeneratorDemo;
import fr.themode.minestom.MinecraftServer;
import fr.themode.minestom.benchmark.BenchmarkManager;
import fr.themode.minestom.benchmark.ThreadResult;
import fr.themode.minestom.entity.Entity;
import fr.themode.minestom.entity.EntityCreature;
import fr.themode.minestom.entity.GameMode;
@ -16,13 +14,12 @@ import fr.themode.minestom.inventory.InventoryType;
import fr.themode.minestom.item.ItemStack;
import fr.themode.minestom.net.ConnectionManager;
import fr.themode.minestom.timer.TaskRunnable;
import fr.themode.minestom.utils.MathUtils;
import fr.themode.minestom.utils.Position;
import fr.themode.minestom.utils.Vector;
import fr.themode.minestom.utils.time.TimeUnit;
import fr.themode.minestom.utils.time.UpdateOption;
import java.util.Map;
import java.util.UUID;
public class PlayerInit {
@ -51,10 +48,10 @@ public class PlayerInit {
MinecraftServer.getSchedulerManager().addRepeatingTask(new TaskRunnable() {
@Override
public void run() {
long ramUsage = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
ramUsage /= 1e6; // To MB
long ramUsage = benchmarkManager.getUsedMemory();
ramUsage /= 1e6; // bytes to MB
String benchmarkMessage = "";
/*String benchmarkMessage = "";
for (Map.Entry<String, ThreadResult> resultEntry : benchmarkManager.getResultMap().entrySet()) {
String name = resultEntry.getKey();
ThreadResult result = resultEntry.getValue();
@ -66,7 +63,7 @@ public class PlayerInit {
benchmarkMessage += "\n";
}
if (benchmarkMessage.length() > 0)
System.out.println(benchmarkMessage);
System.out.println(benchmarkMessage);*/
for (Player player : connectionManager.getOnlinePlayers()) {
player.sendHeaderFooter("RAM USAGE: " + ramUsage + " MB", "", '&');
@ -74,12 +71,14 @@ public class PlayerInit {
}
}, new UpdateOption(5, TimeUnit.TICK));
connectionManager.setResponseDataConsumer(responseData -> {
connectionManager.setResponseDataConsumer((playerConnection, responseData) -> {
responseData.setName("1.15.2");
responseData.setProtocol(578);
responseData.setMaxPlayer(100);
responseData.setOnline(0);
responseData.setDescription("test");
responseData.addPlayer("A name", UUID.randomUUID());
responseData.addPlayer("Could be some message", UUID.randomUUID());
responseData.setDescription("IP test: " + playerConnection.getRemoteAddress());
responseData.setFavicon("data:image/png;base64,<data>");
});
@ -114,8 +113,8 @@ public class PlayerInit {
p.teleport(player.getPosition());
}
ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
chickenCreature.setInstance(player.getInstance());
//ChickenCreature chickenCreature = new ChickenCreature(player.getPosition());
//chickenCreature.setInstance(player.getInstance());
});
@ -128,7 +127,7 @@ public class PlayerInit {
});
player.setEventCallback(PlayerSpawnEvent.class, event -> {
player.setGameMode(GameMode.CREATIVE);
player.setGameMode(GameMode.SURVIVAL);
player.teleport(new Position(0, 66, 0));
/*Random random = new Random();
@ -159,7 +158,7 @@ public class PlayerInit {
});
inventory.setItemStack(0, item.clone());
player.openInventory(inventory);
//player.openInventory(inventory);
player.getInventory().addItemStack(new ItemStack((short) 1, (byte) 100));

View File

@ -100,6 +100,7 @@ public class MinecraftServer {
RegistryMain.registerItems();
RegistryMain.registerEntities();
RegistryMain.registerSounds();
RegistryMain.registerParticles();
minecraftServer = new MinecraftServer();

View File

@ -74,6 +74,10 @@ public class BenchmarkManager {
this.enabled = false;
}
public long getUsedMemory() {
return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
}
public Map<String, ThreadResult> getResultMap() {
return Collections.unmodifiableMap(resultMap);
}

View File

@ -25,10 +25,34 @@ public class BoundingBox {
(getMinZ() <= boundingBox.getMaxZ() && getMaxZ() >= boundingBox.getMinZ());
}
// FIXME: seems to do not work properly
public boolean intersect(BlockPosition blockPosition) {
final float x = 1.6f;
final float y = 1;
final float z = 1.6f;
float minX = blockPosition.getX() - (x / 2) + 0.5f;
float maxX = blockPosition.getX() + (x / 2) + 0.5f;
float minY = blockPosition.getY();
float maxY = blockPosition.getY() + y;
float minZ = blockPosition.getZ() - (z / 2) + 0.5f;
float maxZ = blockPosition.getZ() + (z / 2) + 0.5f;
if (getMinX() > maxX) return false;
if (getMaxX() < minX) return false;
if (getMinY() > maxY) return false;
if (getMaxY() < minY) return false;
if (getMinZ() > maxZ) return false;
return !(getMaxZ() < minZ);
}
/*public boolean intersect(BlockPosition blockPosition) {
final float x = 1.6f;
final float y = 1;
final float z = 1.6f;
float minX = blockPosition.getX() - (x / 2) + 0.5f;
float maxX = blockPosition.getX() + (x / 2) + 0.5f;
@ -42,7 +66,7 @@ public class BoundingBox {
boolean checkY = getMinY() + y < maxY && getMaxY() + y > minY;
boolean checkZ = getMinZ() + z / 2 < maxZ && getMaxZ() - z / 2 > minZ;
return checkX && checkY && checkZ;
}
}*/
public boolean intersect(float x, float y, float z) {
return (x >= getMinX() && x <= getMaxX()) &&

View File

@ -226,10 +226,15 @@ public abstract class Entity implements Viewable, DataContainer {
boolean xAir = getInstance().getBlockId(xBlock) == Material.AIR.getId();
boolean yAir = getInstance().getBlockId(yBlock) == Material.AIR.getId();
boolean zAir = getInstance().getBlockId(zBlock) == Material.AIR.getId();
System.out.println(xAir + " : " + yAir + " : " + zAir);
newX = xAir ? newX : boundingBox.intersect(xBlock) ? Math.round(position.getX()) : newX;
newY = yAir ? newY : boundingBox.intersect(yBlock) ? Math.round(position.getY()) : newY;
newZ = zAir ? newZ : boundingBox.intersect(zBlock) ? Math.round(position.getZ()) : newZ;
boolean xIntersect = boundingBox.intersect(xBlock);
boolean yIntersect = boundingBox.intersect(yBlock);
boolean zIntersect = boundingBox.intersect(zBlock);
System.out.println(xIntersect + " : " + yIntersect + " : " + zIntersect);
newX = xAir ? newX : xIntersect ? position.getX() : newX;
newY = yAir ? newY : yIntersect ? position.getY() : newY;
newZ = zAir ? newZ : zIntersect ? position.getZ() : newZ;
refreshPosition(newX, newY, newZ);
if (this instanceof ObjectEntity) {

View File

@ -6,6 +6,9 @@ public class PlayerBlockBreakEvent extends CancellableEvent {
private BlockPosition blockPosition;
private short blockId;
private boolean customBlock;
public PlayerBlockBreakEvent(BlockPosition blockPosition) {
this.blockPosition = blockPosition;
}
@ -13,4 +16,22 @@ public class PlayerBlockBreakEvent extends CancellableEvent {
public BlockPosition getBlockPosition() {
return blockPosition;
}
public short getResultBlock() {
return blockId;
}
public void setResultBlock(short blockId) {
this.blockId = blockId;
this.customBlock = false;
}
public boolean isResultCustomBlock() {
return customBlock;
}
public void setResultCustomBlock(short customBlockId) {
this.blockId = customBlockId;
this.customBlock = true;
}
}

View File

@ -11,6 +11,8 @@ import fr.themode.minestom.instance.block.rule.BlockPlacementRule;
import fr.themode.minestom.net.PacketWriterUtils;
import fr.themode.minestom.net.packet.server.play.BlockChangePacket;
import fr.themode.minestom.net.packet.server.play.ParticlePacket;
import fr.themode.minestom.particle.Particle;
import fr.themode.minestom.particle.ParticleCreator;
import fr.themode.minestom.utils.BlockPosition;
import fr.themode.minestom.utils.ChunkUtils;
import fr.themode.minestom.utils.SerializerUtils;
@ -165,23 +167,26 @@ public class InstanceContainer extends Instance {
PlayerBlockBreakEvent blockBreakEvent = new PlayerBlockBreakEvent(blockPosition);
player.callEvent(PlayerBlockBreakEvent.class, blockBreakEvent);
if (!blockBreakEvent.isCancelled()) {
// TODO blockbreak setBlock result
int x = blockPosition.getX();
int y = blockPosition.getY();
int z = blockPosition.getZ();
setBlock(x, y, z, (short) 0);
ParticlePacket particlePacket = new ParticlePacket(); // TODO change to a proper particle API
particlePacket.particleId = 3; // Block particle
particlePacket.longDistance = false;
particlePacket.x = x + 0.5f;
particlePacket.y = y;
particlePacket.z = z + 0.5f;
particlePacket.offsetX = 0.4f;
particlePacket.offsetY = 0.5f;
particlePacket.offsetZ = 0.4f;
particlePacket.particleData = 0.3f;
particlePacket.particleCount = 125;
particlePacket.blockId = blockId;
// Break or change the broken block based on event result
short resultBlockId = blockBreakEvent.getResultBlock();
boolean custom = blockBreakEvent.isResultCustomBlock();
if (custom) {
setCustomBlock(x, y, z, resultBlockId);
} else {
setBlock(x, y, z, resultBlockId);
}
ParticlePacket particlePacket = ParticleCreator.createParticlePacket(Particle.BLOCK, false,
x + 0.5f, y, z + 0.5f,
0.4f, 0.5f, 0.4f,
0.3f, 125, writer -> {
writer.writeVarInt(blockId);
});
chunk.sendPacketToViewers(particlePacket);
} else {
sendChunkSectionUpdate(chunk, ChunkUtils.getSectionAt(blockPosition.getY()), player);

View File

@ -12,7 +12,7 @@ public class BlockManager {
private Short2ObjectMap<CustomBlock> blocksInternalId = new Short2ObjectOpenHashMap<>();
private Map<String, CustomBlock> blocksId = new HashMap<>();
private Map<Block, BlockPlacementRule> placementRules = new HashMap<>();
private Short2ObjectOpenHashMap<BlockPlacementRule> placementRules = new Short2ObjectOpenHashMap<>();
public void registerCustomBlock(CustomBlock customBlock) {
String identifier = customBlock.getIdentifier();
@ -22,12 +22,13 @@ public class BlockManager {
}
public void registerBlockPlacementRule(BlockPlacementRule blockPlacementRule) {
this.placementRules.put(blockPlacementRule.getBlock(), blockPlacementRule);
this.placementRules.put(blockPlacementRule.getBlockId(), blockPlacementRule);
}
public BlockPlacementRule getBlockPlacementRule(short blockId) {
Block block = Block.getBlockFromId(blockId);
return this.placementRules.get(block);
Block block = Block.getBlockFromId(blockId); // Convert block alternative
blockId = block.getBlockId();
return this.placementRules.get(blockId);
}
public CustomBlock getBlock(String identifier) {

View File

@ -6,15 +6,19 @@ import fr.themode.minestom.utils.BlockPosition;
public abstract class BlockPlacementRule {
private Block block;
private short blockId;
public BlockPlacementRule(short blockId) {
this.blockId = blockId;
}
public BlockPlacementRule(Block block) {
this.block = block;
this(block.getBlockId());
}
public abstract short blockRefresh(Instance instance, BlockPosition blockPosition);
public Block getBlock() {
return block;
public short getBlockId() {
return blockId;
}
}

View File

@ -7,7 +7,6 @@ import fr.themode.minestom.utils.BlockPosition;
public class RedstonePlacementRule extends BlockPlacementRule {
public RedstonePlacementRule() {
super(Block.REDSTONE_WIRE);
}
@ -18,6 +17,11 @@ public class RedstonePlacementRule extends BlockPlacementRule {
int y = blockPosition.getY();
int z = blockPosition.getZ();
if (isAir(instance, x, y - 1, z)) {
return Block.AIR.getBlockId();
}
String east = "none";
String north = "none";
String power = "0";
@ -67,4 +71,9 @@ public class RedstonePlacementRule extends BlockPlacementRule {
return Block.getBlockFromId(blockId) == Block.REDSTONE_WIRE;
}
private boolean isAir(Instance instance, int x, int y, int z) {
short blockId = instance.getBlockId(x, y, z);
return Block.getBlockFromId(blockId) == Block.AIR;
}
}

View File

@ -2,7 +2,7 @@ package fr.themode.minestom.net;
import fr.themode.minestom.entity.Player;
import fr.themode.minestom.net.player.PlayerConnection;
import fr.themode.minestom.ping.ResponseData;
import fr.themode.minestom.ping.ResponseDataConsumer;
import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
@ -14,7 +14,7 @@ public class ConnectionManager {
private Set<Player> players = new CopyOnWriteArraySet<>();
private Map<PlayerConnection, Player> connectionPlayerMap = Collections.synchronizedMap(new HashMap<>());
private Consumer<ResponseData> responseDataConsumer;
private ResponseDataConsumer responseDataConsumer;
private Consumer<Player> playerInitialization;
public Player getPlayer(PlayerConnection connection) {
@ -49,11 +49,11 @@ public class ConnectionManager {
broadcastMessage(message, null);
}
public Consumer<ResponseData> getResponseDataConsumer() {
public ResponseDataConsumer getResponseDataConsumer() {
return responseDataConsumer;
}
public void setResponseDataConsumer(Consumer<ResponseData> responseDataConsumer) {
public void setResponseDataConsumer(ResponseDataConsumer responseDataConsumer) {
this.responseDataConsumer = responseDataConsumer;
}

View File

@ -5,7 +5,8 @@ import fr.themode.minestom.net.packet.client.ClientPacket;
public class ClientPacketsHandler {
private static final int SIZE = 0xFF;
// Max packet id
private static final int SIZE = 0x2E;
private ConstructorAccess[] constructorAccesses = new ConstructorAccess[SIZE];

View File

@ -7,18 +7,17 @@ import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
import fr.themode.minestom.net.packet.server.handshake.ResponsePacket;
import fr.themode.minestom.net.player.PlayerConnection;
import fr.themode.minestom.ping.ResponseData;
import java.util.function.Consumer;
import fr.themode.minestom.ping.ResponseDataConsumer;
public class StatusRequestPacket implements ClientPreplayPacket {
@Override
public void process(PlayerConnection connection, ConnectionManager connectionManager) {
Consumer<ResponseData> consumer = MinecraftServer.getConnectionManager().getResponseDataConsumer();
ResponseDataConsumer consumer = MinecraftServer.getConnectionManager().getResponseDataConsumer();
ResponseData responseData = new ResponseData();
if (responseData == null)
throw new NullPointerException("You need to register a ResponseDataConsumer");
consumer.accept(responseData);
consumer.accept(connection, responseData);
ResponsePacket responsePacket = new ResponsePacket();
responsePacket.jsonResponse = responseData.build().toString();

View File

@ -4,6 +4,8 @@ import fr.themode.minestom.net.packet.PacketWriter;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.net.packet.server.ServerPacketIdentifier;
import java.util.function.Consumer;
public class ParticlePacket implements ServerPacket {
public int particleId;
@ -13,7 +15,7 @@ public class ParticlePacket implements ServerPacket {
public float particleData;
public int particleCount;
public int blockId;
public Consumer<PacketWriter> dataConsumer;
@Override
public void write(PacketWriter writer) {
@ -27,8 +29,10 @@ public class ParticlePacket implements ServerPacket {
writer.writeFloat(offsetZ);
writer.writeFloat(particleData);
writer.writeInt(particleCount);
if (particleId == 3)
writer.writeVarInt(blockId);
if (dataConsumer != null) {
dataConsumer.accept(writer);
}
}
@Override

View File

@ -6,6 +6,9 @@ import fr.themode.minestom.net.ConnectionState;
import fr.themode.minestom.net.packet.server.ServerPacket;
import fr.themode.minestom.utils.PacketUtils;
import java.io.IOException;
import java.net.SocketAddress;
public class PlayerConnection {
private Client client;
@ -36,6 +39,15 @@ public class PlayerConnection {
client.flush();
}
public SocketAddress getRemoteAddress() {
try {
return client.getChannel().getRemoteAddress();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public Client getClient() {
return client;
}

View File

@ -0,0 +1,87 @@
package fr.themode.minestom.particle;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public enum Particle {
AMBIENT_ENTITY_EFFECT,
ANGRY_VILLAGER,
BARRIER,
BLOCK,
BUBBLE,
CLOUD,
CRIT,
DAMAGE_INDICATOR,
DRAGON_BREATH,
DRIPPING_LAVA,
FALLING_LAVA,
LANDING_LAVA,
DRIPPING_WATER,
FALLING_WATER,
DUST,
EFFECT,
ELDER_GUARDIAN,
ENCHANTED_HIT,
ENCHANT,
END_ROD,
ENTITY_EFFECT,
EXPLOSION_EMITTER,
EXPLOSION,
FALLING_DUST,
FIREWORK,
FISHING,
FLAME,
FLASH,
HAPPY_VILLAGER,
COMPOSTER,
HEART,
INSTANT_EFFECT,
ITEM,
ITEM_SLIME,
ITEM_SNOWBALL,
LARGE_SMOKE,
LAVA,
MYCELIUM,
NOTE,
POOF,
PORTAL,
RAIN,
SMOKE,
SNEEZE,
SPIT,
SQUID_INK,
SWEEP_ATTACK,
TOTEM_OF_UNDYING,
UNDERWATER,
SPLASH,
WITCH,
BUBBLE_POP,
CURRENT_DOWN,
BUBBLE_COLUMN_UP,
NAUTILUS,
DOLPHIN,
CAMPFIRE_COSY_SMOKE,
CAMPFIRE_SIGNAL_SMOKE,
DRIPPING_HONEY,
FALLING_HONEY,
LANDING_HONEY,
FALLING_NECTAR;
private static Int2ObjectOpenHashMap<Particle> map = new Int2ObjectOpenHashMap();
private int id;
public static Particle fromId(int id) {
return map.get(id);
}
public void setIdentifier(int id) {
this.id = id;
map.put(id, this);
}
public int getId() {
return id;
}
}

View File

@ -0,0 +1,43 @@
package fr.themode.minestom.particle;
import fr.themode.minestom.net.packet.PacketWriter;
import fr.themode.minestom.net.packet.server.play.ParticlePacket;
import java.util.function.Consumer;
public class ParticleCreator {
public static ParticlePacket createParticlePacket(Particle particle, boolean distance,
double x, double y, double z,
float offsetX, float offsetY, float offsetZ,
float particleData, int count, Consumer<PacketWriter> dataWriter) {
ParticlePacket particlePacket = new ParticlePacket();
particlePacket.particleId = particle.getId();
particlePacket.longDistance = distance;
particlePacket.x = x;
particlePacket.y = y;
particlePacket.z = z;
particlePacket.offsetX = offsetX;
particlePacket.offsetY = offsetY;
particlePacket.offsetZ = offsetZ;
particlePacket.particleData = particleData;
particlePacket.particleCount = count;
particlePacket.dataConsumer = dataWriter;
return particlePacket;
}
public static ParticlePacket createParticlePacket(Particle particle,
double x, double y, double z,
float offsetX, float offsetY, float offsetZ,
int count) {
return createParticlePacket(particle, false,
x, y, z,
offsetX, offsetY, offsetZ,
0, count, null);
}
}

View File

@ -0,0 +1,10 @@
package fr.themode.minestom.ping;
import fr.themode.minestom.net.player.PlayerConnection;
@FunctionalInterface
public interface ResponseDataConsumer {
void accept(PlayerConnection playerConnection, ResponseData responseData);
}

View File

@ -7,6 +7,7 @@ import com.google.gson.JsonObject;
import fr.themode.minestom.entity.EntityType;
import fr.themode.minestom.instance.block.Block;
import fr.themode.minestom.item.Material;
import fr.themode.minestom.particle.Particle;
import fr.themode.minestom.sound.Sound;
import java.io.BufferedReader;
@ -23,16 +24,19 @@ public class RegistryMain {
public static final String ITEMS_PATH = "registry/registries.json";
public static final String ENTITIES_PATH = "registry/registries.json";
public static final String SOUNDS_PATH = "registry/registries.json";
public static final String PARTICLES_PATH = "registry/registries.json";
public static void main(String[] args) {
List<RegistryBlock> blocks = parseBlocks(BLOCKS_PATH);
List<RegistryItem> items = parseItems(ITEMS_PATH);
List<RegistryEntityType> entities = parseEntities(ENTITIES_PATH);
List<RegistrySound> sounds = parseSounds(SOUNDS_PATH);
List<RegistryParticle> particles = parseParticles(PARTICLES_PATH);
//writeBlocksClass(blocks);
//writeItemsClass(items);
//writeEntitiesClass(entities);
writeSoundsClass(sounds);
//writeSoundsClass(sounds);
writeParticlesClass(particles);
}
public static void registerBlocks() {
@ -90,6 +94,15 @@ public class RegistryMain {
}
}
public static void registerParticles() {
List<RegistryParticle> registryParticles = parseParticles(PARTICLES_PATH);
for (RegistryParticle registryParticle : registryParticles) {
Particle particle = Particle.valueOf(registryParticle.name);
particle.setIdentifier(registryParticle.id);
}
}
private static void writeBlocksClass(List<RegistryBlock> blocks) {
for (RegistryBlock registryBlock : blocks) {
String line = registryBlock.name + ",";
@ -119,6 +132,13 @@ public class RegistryMain {
}
}
private static void writeParticlesClass(List<RegistryParticle> particles) {
for (RegistryParticle registryParticle : particles) {
String line = registryParticle.name + ",";
System.out.println(line);
}
}
private static List<RegistryBlock> parseBlocks(String path) {
List<RegistryBlock> blocks = new ArrayList<>();
@ -279,4 +299,34 @@ public class RegistryMain {
return registrySounds;
}
private static List<RegistryParticle> parseParticles(String path) {
List<RegistryParticle> registryParticles = new ArrayList<>();
BufferedReader bufferedReader = null;
try {
bufferedReader = new BufferedReader(new FileReader(path));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Gson gson = new Gson();
JsonObject obj = gson.fromJson(bufferedReader, JsonObject.class);
JsonObject itemsObject = obj.getAsJsonObject("minecraft:particle_type");
JsonObject entriesObject = itemsObject.getAsJsonObject("entries");
Set<Map.Entry<String, JsonElement>> entriesEntries = entriesObject.entrySet();//will return members of your object
for (Map.Entry<String, JsonElement> entryEntry : entriesEntries) {
RegistryParticle registryParticle = new RegistryParticle();
registryParticles.add(registryParticle);
String item = entryEntry.getKey();
String itemName = item.toUpperCase().replace("MINECRAFT:", "").replace(".", "_");
registryParticle.name = itemName;
short id = entryEntry.getValue().getAsJsonObject().get("protocol_id").getAsShort();
registryParticle.id = id;
}
return registryParticles;
}
}

View File

@ -0,0 +1,8 @@
package fr.themode.minestom.registry;
public class RegistryParticle {
protected String name;
protected int id;
}

View File

@ -13,6 +13,7 @@ public class NbtReaderUtils {
public static void readItemStackNBT(PacketReader reader, Consumer<ItemStack> consumer, ItemStack item) {
reader.readByte(typeId -> {
//System.out.println("DEBUG TYPE: " + typeId);
switch (typeId) {
case 0x00: // TAG_End
// End of item NBT
@ -37,6 +38,15 @@ public class NbtReaderUtils {
case 0x03: // TAG_Int
reader.readShortSizedString((name, length) -> {
// Damage
if (name.equals("Damage")) {
reader.readInteger(damage -> {
//item.setDamage(damage);
// TODO short vs int damage
readItemStackNBT(reader, consumer, item);
});
}
// Unbreakable
if (name.equals("Unbreakable")) {
reader.readInteger(value -> {
@ -64,6 +74,14 @@ public class NbtReaderUtils {
break;
case 0x09: // TAG_List
reader.readShortSizedString((name, length) -> {
if (name.equals("StoredEnchantments")) {
// TODO
}
});
break;
case 0x0A: // TAG_Compound