mirror of
https://github.com/Minestom/Minestom.git
synced 2024-12-26 02:57:37 +01:00
custom block with custom hardness
This commit is contained in:
parent
57def5aaac
commit
0d40be1552
@ -7,7 +7,9 @@ import fr.adamaq01.ozao.net.server.ServerHandler;
|
||||
import fr.adamaq01.ozao.net.server.backend.tcp.TCPServer;
|
||||
import fr.themode.minestom.entity.EntityManager;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.BlockManager;
|
||||
import fr.themode.minestom.instance.InstanceManager;
|
||||
import fr.themode.minestom.instance.demo.StoneBlock;
|
||||
import fr.themode.minestom.net.ConnectionManager;
|
||||
import fr.themode.minestom.net.PacketProcessor;
|
||||
import fr.themode.minestom.net.packet.server.play.DestroyEntitiesPacket;
|
||||
@ -26,6 +28,7 @@ public class Main {
|
||||
|
||||
// In-Game Manager
|
||||
private static InstanceManager instanceManager;
|
||||
private static BlockManager blockManager;
|
||||
private static EntityManager entityManager;
|
||||
|
||||
public static void main(String[] args) {
|
||||
@ -33,8 +36,11 @@ public class Main {
|
||||
packetProcessor = new PacketProcessor();
|
||||
|
||||
instanceManager = new InstanceManager();
|
||||
blockManager = new BlockManager();
|
||||
entityManager = new EntityManager();
|
||||
|
||||
blockManager.registerBlock("stone", StoneBlock::new);
|
||||
|
||||
server = new TCPServer(new MinecraftProtocol()).addHandler(new ServerHandler() {
|
||||
@Override
|
||||
public void onConnect(Server server, Connection connection) {
|
||||
@ -123,6 +129,10 @@ public class Main {
|
||||
return instanceManager;
|
||||
}
|
||||
|
||||
public static BlockManager getBlockManager() {
|
||||
return blockManager;
|
||||
}
|
||||
|
||||
public static EntityManager getEntityManager() {
|
||||
return entityManager;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package fr.themode.minestom.entity;
|
||||
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.instance.CustomBlock;
|
||||
import fr.themode.minestom.inventory.Inventory;
|
||||
import fr.themode.minestom.inventory.PlayerInventory;
|
||||
import fr.themode.minestom.item.ItemStack;
|
||||
@ -25,6 +26,7 @@ public class Player extends LivingEntity {
|
||||
private short heldSlot;
|
||||
private Inventory openInventory;
|
||||
|
||||
private CustomBlock targetCustomBlock;
|
||||
private Position targetBlockPosition;
|
||||
private long targetBlockTime;
|
||||
|
||||
@ -41,20 +43,17 @@ public class Player extends LivingEntity {
|
||||
public void update() {
|
||||
|
||||
// Target block stage
|
||||
if (instance != null && targetBlockPosition != null) {
|
||||
int timeBreak = 750; // In ms
|
||||
if (instance != null && targetCustomBlock != null) {
|
||||
int timeBreak = targetCustomBlock.getBreakDelay(this);
|
||||
int animationCount = 10;
|
||||
long since = System.currentTimeMillis() - targetBlockTime;
|
||||
byte stage = (byte) (since / (timeBreak / animationCount));
|
||||
BlockBreakAnimationPacket breakAnimationPacket = new BlockBreakAnimationPacket();
|
||||
breakAnimationPacket.entityId = getEntityId() + 1;
|
||||
breakAnimationPacket.blockPosition = targetBlockPosition;
|
||||
breakAnimationPacket.destroyStage = stage;
|
||||
sendBlockBreakAnimation(targetBlockPosition, stage);// TODO send to all near players
|
||||
if (stage > 9) {
|
||||
instance.setBlock(targetBlockPosition.getX(), targetBlockPosition.getY(), targetBlockPosition.getZ(), (short) 0);
|
||||
refreshTargetBlock(null);
|
||||
testParticle(targetBlockPosition.getX() + 0.5f, targetBlockPosition.getY(), targetBlockPosition.getZ() + 0.5f);
|
||||
resetTargetBlock();
|
||||
}
|
||||
playerConnection.sendPacket(breakAnimationPacket); // TODO send to all online players
|
||||
}
|
||||
|
||||
|
||||
@ -74,6 +73,29 @@ public class Player extends LivingEntity {
|
||||
playerConnection.sendPacket(new UpdateViewPositionPacket(Math.floorDiv((int) x, 16), Math.floorDiv((int) z, 16)));
|
||||
}
|
||||
|
||||
public void sendBlockBreakAnimation(Position blockPosition, byte destroyStage) {
|
||||
BlockBreakAnimationPacket breakAnimationPacket = new BlockBreakAnimationPacket();
|
||||
breakAnimationPacket.entityId = getEntityId() + 1;
|
||||
breakAnimationPacket.blockPosition = blockPosition;
|
||||
breakAnimationPacket.destroyStage = destroyStage;
|
||||
playerConnection.sendPacket(breakAnimationPacket);
|
||||
}
|
||||
|
||||
private void testParticle(float x, float y, float z) {
|
||||
ParticlePacket particlePacket = new ParticlePacket();
|
||||
particlePacket.particleId = 3; // Block particle
|
||||
particlePacket.longDistance = false;
|
||||
particlePacket.x = x;
|
||||
particlePacket.y = y;
|
||||
particlePacket.z = z;
|
||||
particlePacket.offsetX = 0.55f;
|
||||
particlePacket.offsetY = 0.75f;
|
||||
particlePacket.offsetZ = 0.55f;
|
||||
particlePacket.particleData = 0.25f;
|
||||
particlePacket.particleCount = 100;
|
||||
playerConnection.sendPacket(particlePacket);
|
||||
}
|
||||
|
||||
public void sendMessage(String message) {
|
||||
ChatMessagePacket chatMessagePacket = new ChatMessagePacket("{\"text\": \"" + message + "\"}", ChatMessagePacket.Position.CHAT);
|
||||
playerConnection.sendPacket(chatMessagePacket);
|
||||
@ -136,6 +158,10 @@ public class Player extends LivingEntity {
|
||||
return openInventory;
|
||||
}
|
||||
|
||||
public CustomBlock getCustomBlockTarget() {
|
||||
return targetCustomBlock;
|
||||
}
|
||||
|
||||
public void openInventory(Inventory inventory) {
|
||||
if (inventory == null)
|
||||
throw new IllegalArgumentException("Inventory cannot be null, use Player#closeInventory() to close current");
|
||||
@ -200,11 +226,18 @@ public class Player extends LivingEntity {
|
||||
this.openInventory = openInventory;
|
||||
}
|
||||
|
||||
public void refreshTargetBlock(Position targetBlockPosition) {
|
||||
public void refreshTargetBlock(CustomBlock targetCustomBlock, Position targetBlockPosition) {
|
||||
this.targetCustomBlock = targetCustomBlock;
|
||||
this.targetBlockPosition = targetBlockPosition;
|
||||
this.targetBlockTime = targetBlockPosition == null ? 0 : System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void resetTargetBlock() {
|
||||
this.targetCustomBlock = null;
|
||||
this.targetBlockPosition = null;
|
||||
this.targetBlockTime = 0;
|
||||
}
|
||||
|
||||
public long getLastKeepAlive() {
|
||||
return lastKeepAlive;
|
||||
}
|
||||
|
@ -1,23 +0,0 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
public class Block {
|
||||
|
||||
private short type;
|
||||
|
||||
public Block(short type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public short getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(short type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("CustomBlock{type=%s}", type);
|
||||
}
|
||||
}
|
@ -59,7 +59,7 @@ public class BlockBatch {
|
||||
private short blockId;
|
||||
|
||||
public void apply(Chunk chunk) {
|
||||
chunk.setBlock(x, y, z, blockId);
|
||||
chunk.setBlock((byte) x, (byte) y, (byte) z, blockId);
|
||||
}
|
||||
|
||||
}
|
||||
|
19
src/main/java/fr/themode/minestom/instance/BlockManager.java
Normal file
19
src/main/java/fr/themode/minestom/instance/BlockManager.java
Normal file
@ -0,0 +1,19 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BlockManager {
|
||||
|
||||
private Map<String, CustomBlock> blocks = new HashMap<>();
|
||||
|
||||
public void registerBlock(String id, Supplier<CustomBlock> blocks) {
|
||||
this.blocks.put(id, blocks.get());
|
||||
}
|
||||
|
||||
public CustomBlock getBlock(String id) {
|
||||
return this.blocks.get(id);
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +1,24 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.entity.Entity;
|
||||
import fr.themode.minestom.entity.EntityCreature;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
public class Chunk {
|
||||
|
||||
private static final int CHUNK_SIZE = 16 * 256 * 16;
|
||||
|
||||
protected Set<EntityCreature> creatures = new CopyOnWriteArraySet<>();
|
||||
protected Set<Player> players = new CopyOnWriteArraySet<>();
|
||||
private int chunkX, chunkZ;
|
||||
private Biome biome;
|
||||
private HashMap<Short, Short> blocks = new HashMap<>(); // Index/BlockID
|
||||
private short[] blocksId = new short[CHUNK_SIZE];
|
||||
private String[] customBlocks = new String[CHUNK_SIZE];
|
||||
|
||||
public Chunk(Biome biome, int chunkX, int chunkZ) {
|
||||
this.biome = biome;
|
||||
@ -23,18 +26,27 @@ public class Chunk {
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
protected void setBlock(int x, int y, int z, short blockId) {
|
||||
short index = (short) (x & 0x000F);
|
||||
index |= (y << 4) & 0x0FF0;
|
||||
index |= (z << 12) & 0xF000;
|
||||
this.blocks.put(index, blockId);
|
||||
protected void setBlock(byte x, byte y, byte z, short blockId) {
|
||||
int index = getIndex(x, y, z);
|
||||
this.blocksId[index] = blockId;
|
||||
if (blockId == 0) {
|
||||
this.customBlocks[index] = null;
|
||||
}
|
||||
}
|
||||
|
||||
public short getBlockId(int x, int y, int z) {
|
||||
short index = (short) (x & 0x000F);
|
||||
index |= (y << 4) & 0x0FF0;
|
||||
index |= (z << 12) & 0xF000;
|
||||
return this.blocks.getOrDefault(index, (short) 0);
|
||||
protected void setBlock(byte x, byte y, byte z, String blockId) {
|
||||
int index = getIndex(x, y, z);
|
||||
CustomBlock customBlock = Main.getBlockManager().getBlock(blockId);
|
||||
this.blocksId[index] = customBlock.getType();
|
||||
this.customBlocks[index] = blockId;
|
||||
}
|
||||
|
||||
public short getBlockId(byte x, byte y, byte z) {
|
||||
return this.blocksId[getIndex(x, y, z)];
|
||||
}
|
||||
|
||||
public String getCustomBlockId(byte x, byte y, byte z) {
|
||||
return this.customBlocks[getIndex(x, y, z)];
|
||||
}
|
||||
|
||||
public void addEntity(Entity entity) {
|
||||
@ -65,8 +77,8 @@ public class Chunk {
|
||||
}
|
||||
}
|
||||
|
||||
public HashMap<Short, Short> getBlocks() {
|
||||
return blocks;
|
||||
public short[] getBlocksId() {
|
||||
return blocksId;
|
||||
}
|
||||
|
||||
public Biome getBiome() {
|
||||
@ -88,4 +100,11 @@ public class Chunk {
|
||||
public Set<Player> getPlayers() {
|
||||
return Collections.unmodifiableSet(players);
|
||||
}
|
||||
|
||||
private int getIndex(byte x, byte y, byte z) {
|
||||
short index = (short) (x & 0x000F);
|
||||
index |= (y << 4) & 0x0FF0;
|
||||
index |= (z << 12) & 0xF000;
|
||||
return index & 0xffff;
|
||||
}
|
||||
}
|
||||
|
21
src/main/java/fr/themode/minestom/instance/CustomBlock.java
Normal file
21
src/main/java/fr/themode/minestom/instance/CustomBlock.java
Normal file
@ -0,0 +1,21 @@
|
||||
package fr.themode.minestom.instance;
|
||||
|
||||
import fr.themode.minestom.entity.Player;
|
||||
|
||||
public abstract class CustomBlock {
|
||||
|
||||
private short type;
|
||||
|
||||
public CustomBlock(short type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/*
|
||||
Time in ms
|
||||
*/
|
||||
public abstract int getBreakDelay(Player player);
|
||||
|
||||
public short getType() {
|
||||
return type;
|
||||
}
|
||||
}
|
@ -25,20 +25,32 @@ public class Instance {
|
||||
this.uniqueId = uniqueId;
|
||||
}
|
||||
|
||||
// TODO BlockBatch with pool
|
||||
public synchronized void setBlock(int x, int y, int z, short blockId) {
|
||||
final int chunkX = Math.floorDiv(x, 16);
|
||||
final int chunkZ = Math.floorDiv(z, 16);
|
||||
Chunk chunk = getChunk(chunkX, chunkZ);
|
||||
if (chunk == null) {
|
||||
chunk = createChunk(Biome.VOID, chunkX, chunkZ);
|
||||
}
|
||||
Chunk chunk = getChunkAt(x, z);
|
||||
synchronized (chunk) {
|
||||
chunk.setBlock(x % 16, y, z % 16, blockId);
|
||||
chunk.setBlock((byte) (x % 16), (byte) y, (byte) (z % 16), blockId);
|
||||
sendChunkUpdate(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void setBlock(int x, int y, int z, String blockId) {
|
||||
Chunk chunk = getChunkAt(x, z);
|
||||
synchronized (chunk) {
|
||||
chunk.setBlock((byte) (x % 16), (byte) y, (byte) (z % 16), blockId);
|
||||
sendChunkUpdate(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
public short getBlockId(int x, int y, int z) {
|
||||
Chunk chunk = getChunkAt(x, z);
|
||||
return chunk.getBlockId((byte) (x % 16), (byte) y, (byte) (z % 16));
|
||||
}
|
||||
|
||||
public String getCustomBlockId(int x, int y, int z) {
|
||||
Chunk chunk = getChunkAt(x, z);
|
||||
return chunk.getCustomBlockId((byte) (x % 16), (byte) y, (byte) (z % 16));
|
||||
}
|
||||
|
||||
public BlockBatch createBlockBatch() {
|
||||
return new BlockBatch(this);
|
||||
}
|
||||
@ -48,7 +60,7 @@ public class Instance {
|
||||
if (chunk.getChunkX() == chunkX && chunk.getChunkZ() == chunkZ)
|
||||
return chunk;
|
||||
}
|
||||
return null;
|
||||
return createChunk(Biome.VOID, chunkX, chunkZ); // TODO generation API
|
||||
}
|
||||
|
||||
public Chunk getChunkAt(double x, double z) {
|
||||
|
@ -0,0 +1,16 @@
|
||||
package fr.themode.minestom.instance.demo;
|
||||
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.CustomBlock;
|
||||
|
||||
public class StoneBlock extends CustomBlock {
|
||||
|
||||
public StoneBlock() {
|
||||
super((short) 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBreakDelay(Player player) {
|
||||
return 750;
|
||||
}
|
||||
}
|
@ -15,7 +15,10 @@ import fr.themode.minestom.net.ConnectionState;
|
||||
import fr.themode.minestom.net.packet.client.ClientPreplayPacket;
|
||||
import fr.themode.minestom.net.packet.server.login.JoinGamePacket;
|
||||
import fr.themode.minestom.net.packet.server.login.LoginSuccessPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.*;
|
||||
import fr.themode.minestom.net.packet.server.play.PlayerInfoPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.PlayerPositionAndLookPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.SpawnPlayerPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.SpawnPositionPacket;
|
||||
import fr.themode.minestom.net.player.PlayerConnection;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
import fr.themode.minestom.world.Dimension;
|
||||
@ -148,15 +151,6 @@ public class LoginStartPacket implements ClientPreplayPacket {
|
||||
player.openInventory(inv);
|
||||
inv.setItemStack(1, new ItemStack(1, (byte) 2));
|
||||
inv.updateItems();
|
||||
|
||||
|
||||
EntityEffectPacket entityEffectPacket = new EntityEffectPacket();
|
||||
entityEffectPacket.entityId = player.getEntityId();
|
||||
entityEffectPacket.effectId = 4;
|
||||
entityEffectPacket.amplifier = -1;
|
||||
entityEffectPacket.duration = 3600;
|
||||
entityEffectPacket.flags = 0;
|
||||
connection.sendPacket(entityEffectPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -25,7 +25,7 @@ public class ClientPlayerBlockPlacementPacket implements ClientPlayPacket {
|
||||
int offsetY = blockFace == ClientPlayerDiggingPacket.BlockFace.BOTTOM ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.TOP ? 1 : 0;
|
||||
int offsetZ = blockFace == ClientPlayerDiggingPacket.BlockFace.NORTH ? -1 : blockFace == ClientPlayerDiggingPacket.BlockFace.SOUTH ? 1 : 0;
|
||||
|
||||
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, (short) 1);
|
||||
instance.setBlock(position.getX() + offsetX, position.getY() + offsetY, position.getZ() + offsetZ, "stone");
|
||||
player.getInventory().refreshSlot(player.getHeldSlot());
|
||||
// TODO consume block in hand for survival players
|
||||
/*Random random = new Random();
|
||||
|
@ -1,10 +1,14 @@
|
||||
package fr.themode.minestom.net.packet.client.play;
|
||||
|
||||
import fr.adamaq01.ozao.net.Buffer;
|
||||
import fr.themode.minestom.Main;
|
||||
import fr.themode.minestom.entity.GameMode;
|
||||
import fr.themode.minestom.entity.Player;
|
||||
import fr.themode.minestom.instance.CustomBlock;
|
||||
import fr.themode.minestom.instance.Instance;
|
||||
import fr.themode.minestom.net.packet.client.ClientPlayPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.EntityEffectPacket;
|
||||
import fr.themode.minestom.net.packet.server.play.RemoveEntityEffectPacket;
|
||||
import fr.themode.minestom.utils.Position;
|
||||
import fr.themode.minestom.utils.Utils;
|
||||
|
||||
@ -24,19 +28,56 @@ public class ClientPlayerDiggingPacket implements ClientPlayPacket {
|
||||
instance.setBlock(position.getX(), position.getY(), position.getZ(), (short) 0);
|
||||
}
|
||||
} else if (player.getGameMode() == GameMode.SURVIVAL) {
|
||||
player.refreshTargetBlock(position);
|
||||
// TODO survival mining
|
||||
Instance instance = player.getInstance();
|
||||
if (instance != null) {
|
||||
String customBlockId = instance.getCustomBlockId(position.getX(), position.getY(), position.getZ());
|
||||
if (customBlockId != null) {
|
||||
CustomBlock customBlock = Main.getBlockManager().getBlock(customBlockId);
|
||||
player.refreshTargetBlock(customBlock, position);
|
||||
addEffect(player);
|
||||
} else {
|
||||
player.resetTargetBlock();
|
||||
removeEffect(player);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CANCELLED_DIGGING:
|
||||
player.refreshTargetBlock(null);
|
||||
player.sendBlockBreakAnimation(position, (byte) -1);
|
||||
player.resetTargetBlock();
|
||||
removeEffect(player);
|
||||
break;
|
||||
case FINISHED_DIGGING:
|
||||
player.refreshTargetBlock(null);
|
||||
if (player.getCustomBlockTarget() != null) {
|
||||
player.resetTargetBlock();
|
||||
removeEffect(player);
|
||||
} else {
|
||||
Instance instance = player.getInstance();
|
||||
if (instance != null) {
|
||||
instance.setBlock(position.getX(), position.getY(), position.getZ(), (short) 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void addEffect(Player player) {
|
||||
EntityEffectPacket entityEffectPacket = new EntityEffectPacket();
|
||||
entityEffectPacket.entityId = player.getEntityId();
|
||||
entityEffectPacket.effectId = 4;
|
||||
entityEffectPacket.amplifier = -1;
|
||||
entityEffectPacket.duration = 0;
|
||||
entityEffectPacket.flags = 0;
|
||||
player.getPlayerConnection().sendPacket(entityEffectPacket);
|
||||
}
|
||||
|
||||
private void removeEffect(Player player) {
|
||||
RemoveEntityEffectPacket removeEntityEffectPacket = new RemoveEntityEffectPacket();
|
||||
removeEntityEffectPacket.entityId = player.getEntityId();
|
||||
removeEntityEffectPacket.effectId = 4;
|
||||
player.getPlayerConnection().sendPacket(removeEntityEffectPacket);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void read(Buffer buffer) {
|
||||
this.status = Status.values()[Utils.readVarInt(buffer)];
|
||||
|
@ -74,11 +74,11 @@ public class ChunkDataPacket implements ServerPacket {
|
||||
|
||||
private Short[] getSection(Chunk chunk, int section) {
|
||||
Short[] blocks = new Short[16 * 16 * 16];
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (byte y = 0; y < 16; y++) {
|
||||
for (byte x = 0; x < 16; x++) {
|
||||
for (byte z = 0; z < 16; z++) {
|
||||
int index = (((y * 16) + x) * 16) + z;
|
||||
blocks[index] = chunk.getBlockId(x, y + 16 * section, z);
|
||||
blocks[index] = chunk.getBlockId(x, (byte) (y + 16 * section), z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,36 @@
|
||||
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 ParticlePacket implements ServerPacket {
|
||||
|
||||
public int particleId;
|
||||
public boolean longDistance;
|
||||
public float x, y, z;
|
||||
public float offsetX, offsetY, offsetZ;
|
||||
public float particleData;
|
||||
public int particleCount;
|
||||
// TODO data
|
||||
|
||||
@Override
|
||||
public void write(Buffer buffer) {
|
||||
buffer.putInt(particleId);
|
||||
buffer.putBoolean(longDistance);
|
||||
buffer.putFloat(x);
|
||||
buffer.putFloat(y);
|
||||
buffer.putFloat(z);
|
||||
buffer.putFloat(offsetX);
|
||||
buffer.putFloat(offsetY);
|
||||
buffer.putFloat(offsetZ);
|
||||
buffer.putFloat(particleData);
|
||||
buffer.putInt(particleCount);
|
||||
Utils.writeVarInt(buffer, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return 0x23;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user