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

View File

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

View File

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

View File

@ -25,10 +25,34 @@ public class BoundingBox {
(getMinZ() <= boundingBox.getMaxZ() && getMaxZ() >= boundingBox.getMinZ()); (getMinZ() <= boundingBox.getMaxZ() && getMaxZ() >= boundingBox.getMinZ());
} }
// FIXME: seems to do not work properly
public boolean intersect(BlockPosition blockPosition) { public boolean intersect(BlockPosition blockPosition) {
final float x = 1.6f; final float x = 1.6f;
final float y = 1; final float y = 1;
final float z = 1.6f; 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 minX = blockPosition.getX() - (x / 2) + 0.5f;
float maxX = 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 checkY = getMinY() + y < maxY && getMaxY() + y > minY;
boolean checkZ = getMinZ() + z / 2 < maxZ && getMaxZ() - z / 2 > minZ; boolean checkZ = getMinZ() + z / 2 < maxZ && getMaxZ() - z / 2 > minZ;
return checkX && checkY && checkZ; return checkX && checkY && checkZ;
} }*/
public boolean intersect(float x, float y, float z) { public boolean intersect(float x, float y, float z) {
return (x >= getMinX() && x <= getMaxX()) && 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 xAir = getInstance().getBlockId(xBlock) == Material.AIR.getId();
boolean yAir = getInstance().getBlockId(yBlock) == Material.AIR.getId(); boolean yAir = getInstance().getBlockId(yBlock) == Material.AIR.getId();
boolean zAir = getInstance().getBlockId(zBlock) == 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; boolean xIntersect = boundingBox.intersect(xBlock);
newY = yAir ? newY : boundingBox.intersect(yBlock) ? Math.round(position.getY()) : newY; boolean yIntersect = boundingBox.intersect(yBlock);
newZ = zAir ? newZ : boundingBox.intersect(zBlock) ? Math.round(position.getZ()) : newZ; 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); refreshPosition(newX, newY, newZ);
if (this instanceof ObjectEntity) { if (this instanceof ObjectEntity) {

View File

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

View File

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

View File

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

View File

@ -7,7 +7,6 @@ import fr.themode.minestom.utils.BlockPosition;
public class RedstonePlacementRule extends BlockPlacementRule { public class RedstonePlacementRule extends BlockPlacementRule {
public RedstonePlacementRule() { public RedstonePlacementRule() {
super(Block.REDSTONE_WIRE); super(Block.REDSTONE_WIRE);
} }
@ -18,6 +17,11 @@ public class RedstonePlacementRule extends BlockPlacementRule {
int y = blockPosition.getY(); int y = blockPosition.getY();
int z = blockPosition.getZ(); int z = blockPosition.getZ();
if (isAir(instance, x, y - 1, z)) {
return Block.AIR.getBlockId();
}
String east = "none"; String east = "none";
String north = "none"; String north = "none";
String power = "0"; String power = "0";
@ -67,4 +71,9 @@ public class RedstonePlacementRule extends BlockPlacementRule {
return Block.getBlockFromId(blockId) == Block.REDSTONE_WIRE; 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.entity.Player;
import fr.themode.minestom.net.player.PlayerConnection; 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.*;
import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.CopyOnWriteArraySet;
@ -14,7 +14,7 @@ public class ConnectionManager {
private Set<Player> players = new CopyOnWriteArraySet<>(); private Set<Player> players = new CopyOnWriteArraySet<>();
private Map<PlayerConnection, Player> connectionPlayerMap = Collections.synchronizedMap(new HashMap<>()); private Map<PlayerConnection, Player> connectionPlayerMap = Collections.synchronizedMap(new HashMap<>());
private Consumer<ResponseData> responseDataConsumer; private ResponseDataConsumer responseDataConsumer;
private Consumer<Player> playerInitialization; private Consumer<Player> playerInitialization;
public Player getPlayer(PlayerConnection connection) { public Player getPlayer(PlayerConnection connection) {
@ -49,11 +49,11 @@ public class ConnectionManager {
broadcastMessage(message, null); broadcastMessage(message, null);
} }
public Consumer<ResponseData> getResponseDataConsumer() { public ResponseDataConsumer getResponseDataConsumer() {
return responseDataConsumer; return responseDataConsumer;
} }
public void setResponseDataConsumer(Consumer<ResponseData> responseDataConsumer) { public void setResponseDataConsumer(ResponseDataConsumer responseDataConsumer) {
this.responseDataConsumer = responseDataConsumer; this.responseDataConsumer = responseDataConsumer;
} }

View File

@ -5,7 +5,8 @@ import fr.themode.minestom.net.packet.client.ClientPacket;
public class ClientPacketsHandler { public class ClientPacketsHandler {
private static final int SIZE = 0xFF; // Max packet id
private static final int SIZE = 0x2E;
private ConstructorAccess[] constructorAccesses = new ConstructorAccess[SIZE]; 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.packet.server.handshake.ResponsePacket;
import fr.themode.minestom.net.player.PlayerConnection; import fr.themode.minestom.net.player.PlayerConnection;
import fr.themode.minestom.ping.ResponseData; import fr.themode.minestom.ping.ResponseData;
import fr.themode.minestom.ping.ResponseDataConsumer;
import java.util.function.Consumer;
public class StatusRequestPacket implements ClientPreplayPacket { public class StatusRequestPacket implements ClientPreplayPacket {
@Override @Override
public void process(PlayerConnection connection, ConnectionManager connectionManager) { public void process(PlayerConnection connection, ConnectionManager connectionManager) {
Consumer<ResponseData> consumer = MinecraftServer.getConnectionManager().getResponseDataConsumer(); ResponseDataConsumer consumer = MinecraftServer.getConnectionManager().getResponseDataConsumer();
ResponseData responseData = new ResponseData(); ResponseData responseData = new ResponseData();
if (responseData == null) if (responseData == null)
throw new NullPointerException("You need to register a ResponseDataConsumer"); throw new NullPointerException("You need to register a ResponseDataConsumer");
consumer.accept(responseData); consumer.accept(connection, responseData);
ResponsePacket responsePacket = new ResponsePacket(); ResponsePacket responsePacket = new ResponsePacket();
responsePacket.jsonResponse = responseData.build().toString(); 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.ServerPacket;
import fr.themode.minestom.net.packet.server.ServerPacketIdentifier; import fr.themode.minestom.net.packet.server.ServerPacketIdentifier;
import java.util.function.Consumer;
public class ParticlePacket implements ServerPacket { public class ParticlePacket implements ServerPacket {
public int particleId; public int particleId;
@ -13,7 +15,7 @@ public class ParticlePacket implements ServerPacket {
public float particleData; public float particleData;
public int particleCount; public int particleCount;
public int blockId; public Consumer<PacketWriter> dataConsumer;
@Override @Override
public void write(PacketWriter writer) { public void write(PacketWriter writer) {
@ -27,8 +29,10 @@ public class ParticlePacket implements ServerPacket {
writer.writeFloat(offsetZ); writer.writeFloat(offsetZ);
writer.writeFloat(particleData); writer.writeFloat(particleData);
writer.writeInt(particleCount); writer.writeInt(particleCount);
if (particleId == 3)
writer.writeVarInt(blockId); if (dataConsumer != null) {
dataConsumer.accept(writer);
}
} }
@Override @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.net.packet.server.ServerPacket;
import fr.themode.minestom.utils.PacketUtils; import fr.themode.minestom.utils.PacketUtils;
import java.io.IOException;
import java.net.SocketAddress;
public class PlayerConnection { public class PlayerConnection {
private Client client; private Client client;
@ -36,6 +39,15 @@ public class PlayerConnection {
client.flush(); client.flush();
} }
public SocketAddress getRemoteAddress() {
try {
return client.getChannel().getRemoteAddress();
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public Client getClient() { public Client getClient() {
return client; 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.entity.EntityType;
import fr.themode.minestom.instance.block.Block; import fr.themode.minestom.instance.block.Block;
import fr.themode.minestom.item.Material; import fr.themode.minestom.item.Material;
import fr.themode.minestom.particle.Particle;
import fr.themode.minestom.sound.Sound; import fr.themode.minestom.sound.Sound;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -23,16 +24,19 @@ public class RegistryMain {
public static final String ITEMS_PATH = "registry/registries.json"; public static final String ITEMS_PATH = "registry/registries.json";
public static final String ENTITIES_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 SOUNDS_PATH = "registry/registries.json";
public static final String PARTICLES_PATH = "registry/registries.json";
public static void main(String[] args) { public static void main(String[] args) {
List<RegistryBlock> blocks = parseBlocks(BLOCKS_PATH); List<RegistryBlock> blocks = parseBlocks(BLOCKS_PATH);
List<RegistryItem> items = parseItems(ITEMS_PATH); List<RegistryItem> items = parseItems(ITEMS_PATH);
List<RegistryEntityType> entities = parseEntities(ENTITIES_PATH); List<RegistryEntityType> entities = parseEntities(ENTITIES_PATH);
List<RegistrySound> sounds = parseSounds(SOUNDS_PATH); List<RegistrySound> sounds = parseSounds(SOUNDS_PATH);
List<RegistryParticle> particles = parseParticles(PARTICLES_PATH);
//writeBlocksClass(blocks); //writeBlocksClass(blocks);
//writeItemsClass(items); //writeItemsClass(items);
//writeEntitiesClass(entities); //writeEntitiesClass(entities);
writeSoundsClass(sounds); //writeSoundsClass(sounds);
writeParticlesClass(particles);
} }
public static void registerBlocks() { 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) { private static void writeBlocksClass(List<RegistryBlock> blocks) {
for (RegistryBlock registryBlock : blocks) { for (RegistryBlock registryBlock : blocks) {
String line = registryBlock.name + ","; 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) { private static List<RegistryBlock> parseBlocks(String path) {
List<RegistryBlock> blocks = new ArrayList<>(); List<RegistryBlock> blocks = new ArrayList<>();
@ -279,4 +299,34 @@ public class RegistryMain {
return registrySounds; 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) { public static void readItemStackNBT(PacketReader reader, Consumer<ItemStack> consumer, ItemStack item) {
reader.readByte(typeId -> { reader.readByte(typeId -> {
//System.out.println("DEBUG TYPE: " + typeId);
switch (typeId) { switch (typeId) {
case 0x00: // TAG_End case 0x00: // TAG_End
// End of item NBT // End of item NBT
@ -37,6 +38,15 @@ public class NbtReaderUtils {
case 0x03: // TAG_Int case 0x03: // TAG_Int
reader.readShortSizedString((name, length) -> { 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 // Unbreakable
if (name.equals("Unbreakable")) { if (name.equals("Unbreakable")) {
reader.readInteger(value -> { reader.readInteger(value -> {
@ -64,6 +74,14 @@ public class NbtReaderUtils {
break; break;
case 0x09: // TAG_List case 0x09: // TAG_List
reader.readShortSizedString((name, length) -> {
if (name.equals("StoredEnchantments")) {
// TODO
}
});
break; break;
case 0x0A: // TAG_Compound case 0x0A: // TAG_Compound