starting of 1.16.2 support

This commit is contained in:
Eoghanmc22 2020-08-12 13:08:04 -04:00
parent 7aaf6a6ec8
commit 6259f624f3
26 changed files with 652 additions and 316 deletions

View File

@ -1,115 +0,0 @@
//==============================
// AUTOGENERATED BY EnumGenerator
//==============================
package net.minestom.server.instance;
import net.minestom.server.registry.Registries;
import net.minestom.server.utils.NamespaceID;
@SuppressWarnings({"deprecation"})
public enum Biome {
OCEAN("minecraft:ocean", 0),
PLAINS("minecraft:plains", 1),
DESERT("minecraft:desert", 2),
MOUNTAINS("minecraft:mountains", 3),
FOREST("minecraft:forest", 4),
TAIGA("minecraft:taiga", 5),
SWAMP("minecraft:swamp", 6),
RIVER("minecraft:river", 7),
NETHER_WASTES("minecraft:nether_wastes", 8),
THE_END("minecraft:the_end", 9),
FROZEN_OCEAN("minecraft:frozen_ocean", 10),
FROZEN_RIVER("minecraft:frozen_river", 11),
SNOWY_TUNDRA("minecraft:snowy_tundra", 12),
SNOWY_MOUNTAINS("minecraft:snowy_mountains", 13),
MUSHROOM_FIELDS("minecraft:mushroom_fields", 14),
MUSHROOM_FIELD_SHORE("minecraft:mushroom_field_shore", 15),
BEACH("minecraft:beach", 16),
DESERT_HILLS("minecraft:desert_hills", 17),
WOODED_HILLS("minecraft:wooded_hills", 18),
TAIGA_HILLS("minecraft:taiga_hills", 19),
MOUNTAIN_EDGE("minecraft:mountain_edge", 20),
JUNGLE("minecraft:jungle", 21),
JUNGLE_HILLS("minecraft:jungle_hills", 22),
JUNGLE_EDGE("minecraft:jungle_edge", 23),
DEEP_OCEAN("minecraft:deep_ocean", 24),
STONE_SHORE("minecraft:stone_shore", 25),
SNOWY_BEACH("minecraft:snowy_beach", 26),
BIRCH_FOREST("minecraft:birch_forest", 27),
BIRCH_FOREST_HILLS("minecraft:birch_forest_hills", 28),
DARK_FOREST("minecraft:dark_forest", 29),
SNOWY_TAIGA("minecraft:snowy_taiga", 30),
SNOWY_TAIGA_HILLS("minecraft:snowy_taiga_hills", 31),
GIANT_TREE_TAIGA("minecraft:giant_tree_taiga", 32),
GIANT_TREE_TAIGA_HILLS("minecraft:giant_tree_taiga_hills", 33),
WOODED_MOUNTAINS("minecraft:wooded_mountains", 34),
SAVANNA("minecraft:savanna", 35),
SAVANNA_PLATEAU("minecraft:savanna_plateau", 36),
BADLANDS("minecraft:badlands", 37),
WOODED_BADLANDS_PLATEAU("minecraft:wooded_badlands_plateau", 38),
BADLANDS_PLATEAU("minecraft:badlands_plateau", 39),
SMALL_END_ISLANDS("minecraft:small_end_islands", 40),
END_MIDLANDS("minecraft:end_midlands", 41),
END_HIGHLANDS("minecraft:end_highlands", 42),
END_BARRENS("minecraft:end_barrens", 43),
WARM_OCEAN("minecraft:warm_ocean", 44),
LUKEWARM_OCEAN("minecraft:lukewarm_ocean", 45),
COLD_OCEAN("minecraft:cold_ocean", 46),
DEEP_WARM_OCEAN("minecraft:deep_warm_ocean", 47),
DEEP_LUKEWARM_OCEAN("minecraft:deep_lukewarm_ocean", 48),
DEEP_COLD_OCEAN("minecraft:deep_cold_ocean", 49),
DEEP_FROZEN_OCEAN("minecraft:deep_frozen_ocean", 50),
THE_VOID("minecraft:the_void", 127),
SUNFLOWER_PLAINS("minecraft:sunflower_plains", 129),
DESERT_LAKES("minecraft:desert_lakes", 130),
GRAVELLY_MOUNTAINS("minecraft:gravelly_mountains", 131),
FLOWER_FOREST("minecraft:flower_forest", 132),
TAIGA_MOUNTAINS("minecraft:taiga_mountains", 133),
SWAMP_HILLS("minecraft:swamp_hills", 134),
ICE_SPIKES("minecraft:ice_spikes", 140),
MODIFIED_JUNGLE("minecraft:modified_jungle", 149),
MODIFIED_JUNGLE_EDGE("minecraft:modified_jungle_edge", 151),
TALL_BIRCH_FOREST("minecraft:tall_birch_forest", 155),
TALL_BIRCH_HILLS("minecraft:tall_birch_hills", 156),
DARK_FOREST_HILLS("minecraft:dark_forest_hills", 157),
SNOWY_TAIGA_MOUNTAINS("minecraft:snowy_taiga_mountains", 158),
GIANT_SPRUCE_TAIGA("minecraft:giant_spruce_taiga", 160),
GIANT_SPRUCE_TAIGA_HILLS("minecraft:giant_spruce_taiga_hills", 161),
MODIFIED_GRAVELLY_MOUNTAINS("minecraft:modified_gravelly_mountains", 162),
SHATTERED_SAVANNA("minecraft:shattered_savanna", 163),
SHATTERED_SAVANNA_PLATEAU("minecraft:shattered_savanna_plateau", 164),
ERODED_BADLANDS("minecraft:eroded_badlands", 165),
MODIFIED_WOODED_BADLANDS_PLATEAU("minecraft:modified_wooded_badlands_plateau", 166),
MODIFIED_BADLANDS_PLATEAU("minecraft:modified_badlands_plateau", 167),
BAMBOO_JUNGLE("minecraft:bamboo_jungle", 168),
BAMBOO_JUNGLE_HILLS("minecraft:bamboo_jungle_hills", 169),
SOUL_SAND_VALLEY("minecraft:soul_sand_valley", 170),
CRIMSON_FOREST("minecraft:crimson_forest", 171),
WARPED_FOREST("minecraft:warped_forest", 172),
BASALT_DELTAS("minecraft:basalt_deltas", 173),
;
private String namespaceID;
private int id;
Biome(String namespaceID, int id) {
this.namespaceID = namespaceID;
this.id = id;
Registries.biomes.put(NamespaceID.from(namespaceID), this);
}
public int getId() {
return id;
}
public String getNamespaceID() {
return namespaceID;
}
public static Biome fromId(int id) {
for(Biome o : values()) {
if(o.getId() == id) {
return o;
}
}
return null;
}
}

View File

@ -1259,7 +1259,7 @@ public enum Block {
private NamespaceID blockEntity;
private boolean singleState;
private List<BlockAlternative> alternatives = new ArrayList<BlockAlternative>();
private List<BlockAlternative> alternatives = new ArrayList<>();
Block(String namespaceID, short defaultID, double hardness, double resistance, boolean isAir, boolean isSolid, NamespaceID blockEntity, boolean singleState) {
this.namespaceID = namespaceID;

View File

@ -4,7 +4,6 @@ import java.util.HashMap;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.Material;
import net.minestom.server.instance.Biome;
import net.minestom.server.item.Enchantment;
import net.minestom.server.entity.EntityType;
import net.minestom.server.particle.Particle;
@ -23,10 +22,6 @@ public class Registries {
@Deprecated
public static final HashMap<NamespaceID, Material> materials = new HashMap<>();
/** Should only be used for internal code, please use the get* methods. */
@Deprecated
public static final HashMap<NamespaceID, Biome> biomes = new HashMap<>();
/** Should only be used for internal code, please use the get* methods. */
@Deprecated
public static final HashMap<NamespaceID, Enchantment> enchantments = new HashMap<>();
@ -76,16 +71,6 @@ public class Registries {
return materials.getOrDefault(id, Material.AIR);
}
/** Returns the corresponding Biome matching the given id. Returns null if none match. */
public static Biome getBiome(String id) {
return getBiome(NamespaceID.from(id));
}
/** Returns the corresponding Biome matching the given id. Returns null if none match. */
public static Biome getBiome(NamespaceID id) {
return biomes.get(id);
}
/** Returns the corresponding Enchantment matching the given id. Returns null if none match. */
public static Enchantment getEnchantment(String id) {
return getEnchantment(NamespaceID.from(id));

View File

@ -2,7 +2,6 @@ package net.minestom.codegen;
import net.minestom.server.entity.EntityType;
import net.minestom.server.fluids.Fluid;
import net.minestom.server.instance.Biome;
import net.minestom.server.instance.block.Block;
import net.minestom.server.item.Enchantment;
import net.minestom.server.item.Material;
@ -31,7 +30,6 @@ public class RegistriesGenerator implements CodeGenerator {
private static final String[] types = {
Block.class.getCanonicalName(),
Material.class.getCanonicalName(),
Biome.class.getCanonicalName(),
Enchantment.class.getCanonicalName(),
EntityType.class.getCanonicalName(),
Particle.class.getCanonicalName(),

View File

@ -8,6 +8,7 @@ import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.instance.block.Block;
import net.minestom.server.network.ConnectionManager;
import net.minestom.server.utils.Position;
import net.minestom.server.world.biomes.Biome;
import java.util.Arrays;
import java.util.List;
@ -59,7 +60,7 @@ public class MainDemo {
@Override
public void fillBiomes(Biome[] biomes, int chunkX, int chunkZ) {
Arrays.fill(biomes, Biome.PLAINS);
Arrays.fill(biomes, MinecraftServer.getBiomeManager().getById(0));
}
@Override

View File

@ -39,7 +39,7 @@ import java.util.UUID;
public class PlayerInit {
private static volatile InstanceContainer instanceContainer;
private static volatile InstanceContainer netherTest;
//private static volatile InstanceContainer netherTest;
private static volatile Inventory inventory;
@ -52,22 +52,22 @@ public class PlayerInit {
instanceContainer.enableAutoChunkLoad(true);
instanceContainer.setChunkGenerator(noiseTestGenerator);
netherTest = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.NETHER);
/*netherTest = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.NETHER);
netherTest.enableAutoChunkLoad(true);
netherTest.setChunkGenerator(noiseTestGenerator);
InstanceContainer end = MinecraftServer.getInstanceManager().createInstanceContainer(DimensionType.END);
end.enableAutoChunkLoad(true);
end.setChunkGenerator(noiseTestGenerator);
end.setChunkGenerator(noiseTestGenerator);*/
// Load some chunks beforehand
final int loopStart = -4;
final int loopEnd = 4;
final int loopStart = -10;
final int loopEnd = 10;
for (int x = loopStart; x < loopEnd; x++)
for (int z = loopStart; z < loopEnd; z++) {
instanceContainer.loadChunk(x, z);
netherTest.loadChunk(x, z);
end.loadChunk(x, z);
//netherTest.loadChunk(x, z);
//end.loadChunk(x, z);
}
inventory = new Inventory(InventoryType.CHEST_1_ROW, "Test inventory");

View File

@ -29,10 +29,10 @@ public class DimensionCommand implements CommandProcessor {
Instance instance = player.getInstance();
DimensionType targetDimensionType = DimensionType.NETHER;
if (instance.getDimensionType() == targetDimensionType) {
targetDimensionType = DimensionType.OVERWORLD;
}
DimensionType targetDimensionType = DimensionType.OVERWORLD;
//if (instance.getDimensionType() == targetDimensionType) {
// targetDimensionType = DimensionType.OVERWORLD;
//}
DimensionType finalTargetDimensionType = targetDimensionType;
Optional<Instance> targetInstance = MinecraftServer.getInstanceManager().getInstances().stream().filter(in -> in.getDimensionType() == finalTargetDimensionType).findFirst();

View File

@ -1,6 +1,7 @@
package fr.themode.demo.generator;
import net.minestom.server.instance.Biome;
import net.minestom.server.MinecraftServer;
import net.minestom.server.world.biomes.Biome;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.ChunkGenerator;
import net.minestom.server.instance.ChunkPopulator;
@ -24,7 +25,7 @@ public class ChunkGeneratorDemo extends ChunkGenerator {
@Override
public void fillBiomes(Biome[] biomes, int chunkX, int chunkZ) {
Arrays.fill(biomes, Biome.PLAINS);
Arrays.fill(biomes, MinecraftServer.getBiomeManager().getById(0));
}
@Override

View File

@ -2,7 +2,8 @@ package fr.themode.demo.generator;
import de.articdive.jnoise.JNoise;
import de.articdive.jnoise.interpolation.InterpolationType;
import net.minestom.server.instance.Biome;
import net.minestom.server.MinecraftServer;
import net.minestom.server.world.biomes.Biome;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.ChunkGenerator;
import net.minestom.server.instance.ChunkPopulator;
@ -36,7 +37,7 @@ public class NoiseTestGenerator extends ChunkGenerator {
@Override
public void fillBiomes(Biome[] biomes, int chunkX, int chunkZ) {
Arrays.fill(biomes, Biome.PLAINS);
Arrays.fill(biomes, MinecraftServer.getBiomeManager().getById(0));
}
@Override

View File

@ -16,7 +16,6 @@ import net.minestom.server.extras.mojangAuth.MojangCrypt;
import net.minestom.server.fluids.Fluid;
import net.minestom.server.gamedata.loottables.LootTableManager;
import net.minestom.server.gamedata.tags.TagManager;
import net.minestom.server.instance.Biome;
import net.minestom.server.instance.InstanceManager;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockManager;
@ -45,6 +44,7 @@ import net.minestom.server.utils.thread.MinestomThread;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.Difficulty;
import net.minestom.server.world.DimensionTypeManager;
import net.minestom.server.world.biomes.BiomeManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -56,7 +56,7 @@ public class MinecraftServer {
@Getter
private final static Logger LOGGER = LoggerFactory.getLogger(MinecraftServer.class);
public static final int PROTOCOL_VERSION = 736;
public static final int PROTOCOL_VERSION = 751;
// Threads
public static final String THREAD_NAME_BENCHMARK = "Ms-Benchmark";
@ -81,7 +81,7 @@ public class MinecraftServer {
public static final int THREAD_COUNT_PARALLEL_CHUNK_SAVING = 4;
// Config
public static final int CHUNK_VIEW_DISTANCE = 10;
public static final int CHUNK_VIEW_DISTANCE = 5;
public static final int ENTITY_VIEW_DISTANCE = 5;
public static final int COMPRESSION_THRESHOLD = 256;
// Can be modified at performance cost when decreased
@ -112,6 +112,7 @@ public class MinecraftServer {
private static SchedulerManager schedulerManager;
private static BenchmarkManager benchmarkManager;
private static DimensionTypeManager dimensionTypeManager;
private static BiomeManager biomeManager;
private static AdvancementManager advancementManager;
private static PluginManager pluginManager;
@ -149,7 +150,6 @@ public class MinecraftServer {
Sound.values();
Particle.values();
StatisticType.values();
Biome.values();
Fluid.values();
connectionManager = new ConnectionManager();
@ -167,6 +167,7 @@ public class MinecraftServer {
schedulerManager = new SchedulerManager();
benchmarkManager = new BenchmarkManager();
dimensionTypeManager = new DimensionTypeManager();
biomeManager = new BiomeManager();
advancementManager = new AdvancementManager();
updateManager = new UpdateManager();
@ -290,6 +291,10 @@ public class MinecraftServer {
return dimensionTypeManager;
}
public static BiomeManager getBiomeManager() {
return biomeManager;
}
public static AdvancementManager getAdvancementManager() {
return advancementManager;
}

View File

@ -25,6 +25,7 @@ import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.utils.time.CooldownUtils;
import net.minestom.server.utils.time.UpdateOption;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.biomes.Biome;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;

View File

@ -1,6 +1,7 @@
package net.minestom.server.instance;
import net.minestom.server.instance.batch.ChunkBatch;
import net.minestom.server.world.biomes.Biome;
import java.util.List;

View File

@ -29,6 +29,7 @@ import net.minestom.server.utils.thread.MinestomThread;
import net.minestom.server.utils.time.TimeUnit;
import net.minestom.server.utils.validate.Check;
import net.minestom.server.world.DimensionType;
import net.minestom.server.world.biomes.Biome;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
@ -425,7 +426,7 @@ public class InstanceContainer extends Instance {
protected void createChunk(int chunkX, int chunkZ, Consumer<Chunk> callback) {
Biome[] biomes = new Biome[Chunk.BIOME_COUNT];
if (chunkGenerator == null) {
Arrays.fill(biomes, Biome.THE_VOID);
Arrays.fill(biomes, MinecraftServer.getBiomeManager().getById(0));
} else {
chunkGenerator.fillBiomes(biomes, chunkX, chunkZ);
}

View File

@ -7,7 +7,7 @@ import java.util.function.Supplier;
public class ClientPacketsHandler {
// Max packet id
private static final int SIZE = 0x2F;
private static final int SIZE = 0x30;
private final Supplier<? extends ClientPacket>[] supplierAccesses = new Supplier[SIZE];

View File

@ -33,23 +33,31 @@ public class ClientPlayPacketsHandler extends ClientPacketsHandler {
register(0x1B, ClientPlayerDiggingPacket::new);
register(0x1C, ClientEntityActionPacket::new);
register(0x1D, ClientSteerVehiclePacket::new);
register(0x1E, ClientRecipeBookData::new);
register(0x1F, ClientNameItemPacket::new);
register(0x20, ClientResourcePackStatusPacket::new);
register(0x21, ClientAdvancementTabPacket::new);
register(0x22, ClientSelectTradePacket::new);
register(0x1E, ClientRecipeBookData::new);
register(0x1F, ClientRecipeBookData::new);
register(0x20, ClientNameItemPacket::new);
register(0x21, ClientResourcePackStatusPacket::new);
register(0x22, ClientAdvancementTabPacket::new);
register(0x23, ClientSelectTradePacket::new);
// Set Beacon Effect??
register(0x24, ClientHeldItemChangePacket::new);
register(0x25, ClientUpdateCommandBlockPacket::new);
register(0x26, ClientUpdateCommandBlockMinecartPacket::new);
register(0x27, ClientCreativeInventoryActionPacket::new);
register(0x25, ClientHeldItemChangePacket::new);
register(0x26, ClientUpdateCommandBlockPacket::new);
register(0x27, ClientUpdateCommandBlockMinecartPacket::new);
register(0x28, ClientCreativeInventoryActionPacket::new);
//Update Jigsaw Block??
//Update Structure Block??
register(0x2A, ClientUpdateSignPacket::new);
register(0x2B, ClientAnimationPacket::new);
register(0x2B, ClientUpdateSignPacket::new);
register(0x2C, ClientAnimationPacket::new);
//Spectate??
register(0x2D, ClientPlayerBlockPlacementPacket::new);
register(0x2E, ClientUseItemPacket::new);
register(0x2E, ClientPlayerBlockPlacementPacket::new);
register(0x2F, ClientUseItemPacket::new);
}
}

View File

@ -17,51 +17,51 @@ public class ServerPacketIdentifier {
public static final int BOSS_BAR = 0x0C;
public static final int SERVER_DIFFICULTY = 0x0D;
public static final int CHAT_MESSAGE = 0x0E;
public static final int MULTI_BLOCK_CHANGE = 0x0F;
public static final int TAB_COMPLETE = 0x10;
public static final int DECLARE_COMMANDS = 0x11;
public static final int WINDOW_CONFIRMATION = 0x12;
public static final int CLOSE_WINDOW = 0x13;
public static final int WINDOW_ITEMS = 0x14;
public static final int WINDOW_PROPERTY = 0x15;
public static final int SET_SLOT = 0x16;
public static final int SET_COOLDOWN = 0x17;
public static final int PLUGIN_MESSAGE = 0x18;
public static final int NAMED_SOUND_EFFECT = 0x19;
public static final int DISCONNECT = 0x1A;
public static final int ENTITY_STATUS = 0x1B;
public static final int EXPLOSION = 0x1C;
public static final int UNLOAD_CHUNK = 0x1D;
public static final int CHANGE_GAME_STATE = 0x1E;
public static final int OPEN_HORSE_WINDOW = 0x1F;
public static final int KEEP_ALIVE = 0x20;
public static final int CHUNK_DATA = 0x21;
public static final int EFFECT = 0x22;
public static final int PARTICLE = 0x23;
public static final int UPDATE_LIGHT = 0x24;
public static final int JOIN_GAME = 0x25;
public static final int TAB_COMPLETE = 0x0F;
public static final int DECLARE_COMMANDS = 0x10;
public static final int WINDOW_CONFIRMATION = 0x11;
public static final int CLOSE_WINDOW = 0x12;
public static final int WINDOW_ITEMS = 0x13;
public static final int WINDOW_PROPERTY = 0x14;
public static final int SET_SLOT = 0x15;
public static final int SET_COOLDOWN = 0x16;
public static final int PLUGIN_MESSAGE = 0x17;
public static final int NAMED_SOUND_EFFECT = 0x18;
public static final int DISCONNECT = 0x19;
public static final int ENTITY_STATUS = 0x1A;
public static final int EXPLOSION = 0x1B;
public static final int UNLOAD_CHUNK = 0x1C;
public static final int CHANGE_GAME_STATE = 0x1D;
public static final int OPEN_HORSE_WINDOW = 0x1E;
public static final int KEEP_ALIVE = 0x1F;
public static final int CHUNK_DATA = 0x20;
public static final int EFFECT = 0x21;
public static final int PARTICLE = 0x22;
public static final int UPDATE_LIGHT = 0x23;
public static final int JOIN_GAME = 0x24;
public static final int MAP_DATA = 0x26;
public static final int TRADE_LIST = 0x27;
public static final int ENTITY_POSITION = 0x28;
public static final int ENTITY_POSITION_AND_ROTATION = 0x29;
public static final int ENTITY_ROTATION = 0x2A;
public static final int ENTITY_MOVEMENT = 0x2B;
public static final int VEHICLE_MOVE = 0x2C;
public static final int OPEN_BOOK = 0x2D;
public static final int OPEN_WINDOW = 0x2E;
public static final int OPEN_SIGN_EDITOR = 0x2F;
public static final int CRAFT_RECIPE_RESPONSE = 0x30;
public static final int PLAYER_ABILITIES = 0x31;
public static final int COMBAT_EVENT = 0x32;
public static final int PLAYER_INFO = 0x33;
public static final int FACE_PLAYER = 0x34;
public static final int PLAYER_POSITION_AND_LOOK = 0x35;
public static final int UNLOCK_RECIPES = 0x36;
public static final int DESTROY_ENTITIES = 0x37;
public static final int REMOVE_ENTITY_EFFECT = 0x38;
public static final int RESOURCE_PACK_SEND = 0x39;
public static final int RESPAWN = 0x3A;
public static final int ENTITY_HEAD_LOOK = 0x3B;
public static final int TRADE_LIST = 0x26;
public static final int ENTITY_POSITION = 0x27;
public static final int ENTITY_POSITION_AND_ROTATION = 0x28;
public static final int ENTITY_ROTATION = 0x29;
public static final int ENTITY_MOVEMENT = 0x2A;
public static final int VEHICLE_MOVE = 0x2B;
public static final int OPEN_BOOK = 0x2C;
public static final int OPEN_WINDOW = 0x2D;
public static final int OPEN_SIGN_EDITOR = 0x2E;
public static final int CRAFT_RECIPE_RESPONSE = 0x2F;
public static final int PLAYER_ABILITIES = 0x30;
public static final int COMBAT_EVENT = 0x31;
public static final int PLAYER_INFO = 0x32;
public static final int FACE_PLAYER = 0x33;
public static final int PLAYER_POSITION_AND_LOOK = 0x34;
public static final int UNLOCK_RECIPES = 0x35;
public static final int DESTROY_ENTITIES = 0x36;
public static final int REMOVE_ENTITY_EFFECT = 0x37;
public static final int RESOURCE_PACK_SEND = 0x38;
public static final int RESPAWN = 0x39;
public static final int ENTITY_HEAD_LOOK = 0x3A;
public static final int MULTI_BLOCK_CHANGE = 0x3B;
public static final int SELECT_ADVANCEMENT_TAB = 0x3C;
public static final int WORLD_BORDER = 0x3D;
public static final int CAMERA = 0x3E;

View File

@ -8,13 +8,12 @@ import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.world.DimensionType;
import net.minestom.server.world.LevelType;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
public class JoinGamePacket implements ServerPacket {
public int entityId;
public GameMode gameMode = GameMode.SURVIVAL;
//Todo implement
public DimensionType dimensionType = DimensionType.OVERWORLD;
public long hashedSeed;
public byte maxPlayers = 0; // Unused
@ -33,24 +32,28 @@ public class JoinGamePacket implements ServerPacket {
gameModeId |= 8;
writer.writeInt(entityId);
//hardcore
writer.writeBoolean(false);
writer.writeByte((byte) gameModeId);
//Previous Gamemode
writer.writeByte((byte) gameModeId);
//array of worlds
writer.writeVarInt(1);
writer.writeSizedString("test:spawn_name");
writer.writeSizedString("minestom:world");
NBTCompound nbt = new NBTCompound();
NBTCompound dimensions = MinecraftServer.getDimensionTypeManager().toNBT();
NBTCompound biomes = MinecraftServer.getBiomeManager().toNBT();
NBTList<NBTCompound> dimensionList = new NBTList<>(NBTTypes.TAG_Compound);
for(DimensionType type : MinecraftServer.getDimensionTypeManager().unmodifiableList()) {
dimensionList.add(type.toNBT());
}
writer.writeNBT("", new NBTCompound().set("dimension", dimensionList));
nbt.set("minecraft:dimension_type", dimensions);
nbt.set("minecraft:worldgen/biome", biomes);
writer.writeNBT("", nbt);
writer.writeNBT("", dimensionType.toNBT2());
writer.writeSizedString(dimensionType.getName().toString());
writer.writeSizedString(identifier+"_"+ dimensionType.getName().getPath());
writer.writeLong(hashedSeed);
writer.writeByte(maxPlayers);
writer.writeVarInt(maxPlayers);
writer.writeVarInt(viewDistance);
writer.writeBoolean(reducedDebugInfo);
writer.writeBoolean(enableRespawnScreen);

View File

@ -3,7 +3,7 @@ package net.minestom.server.network.packet.server.play;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.Data;
import net.minestom.server.instance.Biome;
import net.minestom.server.world.biomes.Biome;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.CustomBlock;
@ -89,7 +89,7 @@ public class ChunkDataPacket implements ServerPacket {
// Biome data
if (fullChunk) {
for (int i = 0; i < biomes.length; i++) {
writer.writeInt(biomes[i].getId());
writer.writeVarInt(biomes[i].getId());
}
}

View File

@ -3,7 +3,9 @@ package net.minestom.server.network.packet.server.play;
import net.minestom.server.network.packet.PacketWriter;
import net.minestom.server.network.packet.server.ServerPacket;
import net.minestom.server.network.packet.server.ServerPacketIdentifier;
import net.minestom.server.utils.chunk.ChunkUtils;
//todo
public class MultiBlockChangePacket implements ServerPacket {
public int chunkX;
@ -12,8 +14,7 @@ public class MultiBlockChangePacket implements ServerPacket {
@Override
public void write(PacketWriter writer) {
writer.writeInt(chunkX);
writer.writeInt(chunkZ);
writer.writeLong(ChunkUtils.getChunkIndex(chunkX, chunkZ));
if (blockChanges != null) {
int length = blockChanges.length;

View File

@ -1,8 +1,9 @@
package net.minestom.server.reader;
import io.netty.buffer.Unpooled;
import net.minestom.server.MinecraftServer;
import net.minestom.server.data.Data;
import net.minestom.server.instance.Biome;
import net.minestom.server.world.biomes.Biome;
import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance;
import net.minestom.server.instance.batch.ChunkBatch;
@ -23,7 +24,7 @@ public class ChunkReader {
Biome[] biomes = new Biome[Chunk.BIOME_COUNT];
for (int i = 0; i < biomes.length; i++) {
biomes[i] = Biome.fromId(stream.readByte());
biomes[i] = MinecraftServer.getBiomeManager().getById(stream.readByte());
}
final Chunk chunk = new Chunk(biomes, chunkX, chunkZ);

View File

@ -7,6 +7,7 @@ import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
/**
* https://minecraft.gamepedia.com/Custom_dimension
@ -15,96 +16,96 @@ import java.util.Optional;
@Builder(builderMethodName = "hiddenBuilder", access = AccessLevel.PRIVATE)
public class DimensionType {
public static final DimensionType OVERWORLD = DimensionType.builder(NamespaceID.from("minecraft:overworld"))
.ultrawarm(false)
.natural(true)
.shrunk(false)
.piglinSafe(false)
.respawnAnchorSafe(false)
.bedSafe(true)
.raidCapable(true)
.skylightEnabled(true)
.ceilingEnabled(false)
.fixedTime(Optional.empty())
.ambientLight(0.0f)
.logicalHeight(256)
.infiniburn(NamespaceID.from("minecraft:infiniburn_overworld"))
.build();
private static final AtomicInteger idCounter = new AtomicInteger(0);
public static final DimensionType NETHER = DimensionType.builder(NamespaceID.from("minecraft:the_nether"))
.ultrawarm(true)
.natural(false)
.shrunk(true)
.piglinSafe(true)
.respawnAnchorSafe(true)
.bedSafe(false)
.raidCapable(false)
.skylightEnabled(false)
.ceilingEnabled(true)
.fixedTime(Optional.of(18000L))
.ambientLight(0.1f)
.logicalHeight(128)
.infiniburn(NamespaceID.from("minecraft:infiniburn_nether"))
.build();
public static final DimensionType OVERWORLD = DimensionType.builder(NamespaceID.from("minecraft:overworld"))
.ultrawarm(false)
.natural(true)
.shrunk(false)
.piglinSafe(false)
.respawnAnchorSafe(false)
.bedSafe(true)
.raidCapable(true)
.skylightEnabled(true)
.ceilingEnabled(false)
.fixedTime(Optional.empty())
.ambientLight(0.0f)
.logicalHeight(256)
.infiniburn(NamespaceID.from("minecraft:infiniburn_overworld"))
.build();
public static final DimensionType END = DimensionType.builder(NamespaceID.from("minecraft:the_end"))
.ultrawarm(false)
.natural(false)
.shrunk(false)
.piglinSafe(false)
.respawnAnchorSafe(false)
.bedSafe(false)
.raidCapable(true)
.skylightEnabled(false)
.ceilingEnabled(false)
.fixedTime(Optional.of(6000L))
.ambientLight(0.0f)
.logicalHeight(256)
.infiniburn(NamespaceID.from("minecraft:infiniburn_end"))
.build();
private final int id = idCounter.getAndIncrement();
private final NamespaceID name;
private final boolean natural;
private final float ambientLight;
private final boolean ceilingEnabled;
private final boolean skylightEnabled;
@Builder.Default
private final Optional<Long> fixedTime = Optional.empty();
private final boolean shrunk;
private final boolean raidCapable;
private final boolean respawnAnchorSafe;
private final boolean ultrawarm;
@Builder.Default
private final boolean bedSafe = true;
private final boolean piglinSafe;
@Builder.Default
private final int logicalHeight = 256;
@Builder.Default
private final int coordinateScale = 1;
@Builder.Default
private final NamespaceID infiniburn = NamespaceID.from("minecraft:infiniburn_overworld");
private final NamespaceID name;
private final boolean natural;
private final float ambientLight;
private final boolean ceilingEnabled;
private final boolean skylightEnabled;
@Builder.Default private final Optional<Long> fixedTime = Optional.empty();
private final boolean shrunk;
private final boolean raidCapable;
private final boolean respawnAnchorSafe;
private final boolean ultrawarm;
@Builder.Default private final boolean bedSafe = true;
private final boolean piglinSafe;
@Builder.Default private final int logicalHeight = 256;
@Builder.Default private final NamespaceID infiniburn = NamespaceID.from("minecraft:infiniburn_overworld");
public static DimensionTypeBuilder builder(NamespaceID name) {
return hiddenBuilder().name(name);
}
public NBTCompound toNBT() {
NBTCompound nbt = new NBTCompound()
.setString("name", name.toString())
.setFloat("ambient_light", ambientLight)
.setString("infiniburn", infiniburn.toString())
.setByte("natural", (byte) (natural ? 0x01 : 0x00))
.setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00))
.setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00))
.setByte("shrunk", (byte) (shrunk ? 0x01 : 0x00))
.setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00))
.setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00))
.setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00))
.setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00))
.setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00))
.setInt("logical_height", logicalHeight)
;
fixedTime.ifPresent(time -> nbt.setLong("fixed_time", time));
return nbt;
}
public NBTCompound toNBT() {
NBTCompound nbt = new NBTCompound();
NBTCompound element = new NBTCompound()
.setFloat("ambient_light", ambientLight)
.setString("infiniburn", infiniburn.toString())
.setByte("natural", (byte) (natural ? 0x01 : 0x00))
.setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00))
.setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00))
.setByte("shrunk", (byte) (shrunk ? 0x01 : 0x00))
.setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00))
.setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00))
.setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00))
.setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00))
.setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00))
.setInt("logical_height", logicalHeight)
.setInt("coordinate_scale", coordinateScale);
fixedTime.ifPresent(time -> element.setLong("fixed_time", time));
nbt.setString("name", name.toString());
nbt.setInt("id", id);
nbt.set("element", element);
return nbt;
}
@Override
public String toString() {
return name.toString();
}
public NBTCompound toNBT2() {
NBTCompound nbt = new NBTCompound()
.setFloat("ambient_light", ambientLight)
.setString("infiniburn", infiniburn.toString())
.setByte("natural", (byte) (natural ? 0x01 : 0x00))
.setByte("has_ceiling", (byte) (ceilingEnabled ? 0x01 : 0x00))
.setByte("has_skylight", (byte) (skylightEnabled ? 0x01 : 0x00))
.setByte("shrunk", (byte) (shrunk ? 0x01 : 0x00))
.setByte("ultrawarm", (byte) (ultrawarm ? 0x01 : 0x00))
.setByte("has_raids", (byte) (raidCapable ? 0x01 : 0x00))
.setByte("respawn_anchor_works", (byte) (respawnAnchorSafe ? 0x01 : 0x00))
.setByte("bed_works", (byte) (bedSafe ? 0x01 : 0x00))
.setByte("piglin_safe", (byte) (piglinSafe ? 0x01 : 0x00))
.setInt("logical_height", logicalHeight)
.setInt("coordinate_scale", coordinateScale)
.setString("name", name.toString());
fixedTime.ifPresent(time -> nbt.setLong("fixed_time", time));
return nbt;
}
public static DimensionTypeBuilder builder(NamespaceID name) {
return hiddenBuilder().name(name);
}
@Override
public String toString() {
return name.toString();
}
}

View File

@ -1,5 +1,9 @@
package net.minestom.server.world;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@ -7,7 +11,7 @@ import java.util.List;
/**
* Allows servers to register custom dimensions. Also used during player joining to send the list of all existing dimensions.
*
* Contains {@link DimensionType#OVERWORLD}, {@link DimensionType#NETHER}, {@link DimensionType#END} by default but can be removed.
* Contains {@link DimensionType#OVERWORLD} by default but can be removed.
*/
public class DimensionTypeManager {
@ -15,8 +19,6 @@ public class DimensionTypeManager {
public DimensionTypeManager() {
addDimension(DimensionType.OVERWORLD);
addDimension(DimensionType.NETHER);
addDimension(DimensionType.END);
}
/**
@ -44,4 +46,16 @@ public class DimensionTypeManager {
return Collections.unmodifiableList(dimensionTypes);
}
public NBTCompound toNBT() {
NBTCompound dimensions = new NBTCompound();
dimensions.setString("type", "minecraft:dimension_type");
NBTList<NBTCompound> dimensionList = new NBTList<>(NBTTypes.TAG_Compound);
for (DimensionType dimensionType : dimensionTypes) {
dimensionList.add(dimensionType.toNBT());
}
dimensions.set("value", dimensionList);
return dimensions;
}
}

View File

@ -0,0 +1,98 @@
package net.minestom.server.world.biomes;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.concurrent.atomic.AtomicInteger;
@Getter
@Builder
@ToString
@EqualsAndHashCode
public class Biome {
private static final AtomicInteger idCounter = new AtomicInteger(0);
public static final Biome EXAMPLE = Biome.builder()
.category(Biome.Category.NONE)
.name(NamespaceID.from("minecraft:plains"))
.effects(BiomeEffects.builder()
.fog_color(0x34e38c)
.sky_color(0xdae334)
.water_color(0x349ae3)
.water_fog_color(0x3460e3)
.build())
.build();
private final int id = idCounter.getAndIncrement();
private final NamespaceID name;
@Builder.Default private final float depth = 0.2F;
@Builder.Default private final float temperature = 0.25F;
@Builder.Default private final float scale = 0.2F;
@Builder.Default private final float downfall = 0.8F;
@Builder.Default private final Category category = Category.NONE;
private final BiomeEffects effects;
@Builder.Default private final Precipitation precipitation = Precipitation.RAIN;
@Builder.Default
private TemperatureModifier temperature_modifier = TemperatureModifier.NONE;
public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound();
nbt.setString("name", name.toString());
nbt.setInt("id", id);
NBTCompound element = new NBTCompound();
element.setFloat("depth", depth);
element.setFloat("temperature", temperature);
element.setFloat("scale", scale);
element.setFloat("downfall", downfall);
element.setString("category", category.getType());
element.setString("precipitation", precipitation.getType());
if (temperature_modifier != TemperatureModifier.NONE)
element.setString("temperature_modifier", temperature_modifier.getType());
element.set("effects", effects.toNbt());
nbt.set("element", element);
return nbt;
}
public enum Precipitation {
RAIN("rain"), NONE("none"), SNOW("snow");
@Getter
String type;
Precipitation(String type) {
this.type = type;
}
}
public enum Category {
NONE("none"), TAIGA("taiga"), EXTREME_HILLS("extreme_hills"), JUNGLE("jungle"), MESA("mesa"), PLAINS("plains"),
SAVANNA("savanna"), ICY("icy"), THE_END("the_end"), BEACH("beach"), FOREST("forest"), OCEAN("ocean"),
DESERT("desert"), RIVER("river"), SWAMP("swamp"), MUSHROOM("mushroom"), NETHER("nether");
@Getter
String type;
Category(String type) {
this.type = type;
}
}
public enum TemperatureModifier {
NONE("none"), FROZEN("frozen");
@Getter
String type;
TemperatureModifier(String type) {
this.type = type;
}
}
}

View File

@ -0,0 +1,127 @@
package net.minestom.server.world.biomes;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
@Getter
@Builder
@ToString
@EqualsAndHashCode
public class BiomeEffects {
private final int fog_color;
private final int sky_color;
private final int water_color;
private final int water_fog_color;
@Builder.Default private int foliage_color = -1;
@Builder.Default private int grass_color = -1;
@Builder.Default private GrassColorModifier grass_color_modifier = null;
@Builder.Default private BiomeParticles biomeParticles = null;
@Builder.Default private NamespaceID ambient_sound = null;
@Builder.Default private MoodSound mood_sound = null;
@Builder.Default private AdditionsSound additions_sound = null;
@Builder.Default private Music music = null;
public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound();
nbt.setInt("fog_color", fog_color);
if (foliage_color != -1)
nbt.setInt("foliage_color", foliage_color);
if (grass_color != -1)
nbt.setInt("grass_color", grass_color);
nbt.setInt("sky_color", sky_color);
nbt.setInt("water_color", water_color);
nbt.setInt("water_fog_color", water_fog_color);
if (grass_color_modifier != null)
nbt.setString("grass_color_modifier", grass_color_modifier.getType());
if (biomeParticles != null)
nbt.set("particle", biomeParticles.toNbt());
if (ambient_sound != null)
nbt.setString("ambient_sound", ambient_sound.toString());
if (mood_sound != null)
nbt.set("mood_sound", mood_sound.toNbt());
if (additions_sound != null)
nbt.set("additions_sound", additions_sound.toNbt());
if (music != null)
nbt.set("music", music.toNbt());
return nbt;
}
public enum GrassColorModifier {
NONE("none"), DARK_FOREST("dark_forest"), SWAMP("swamp");
@Getter
String type;
GrassColorModifier(String type) {
this.type = type;
}
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class MoodSound {
private final NamespaceID sound;
private final int tick_delay;
private final int block_search_extent;
private final double offset;
public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound();
nbt.setString("sound", sound.toString());
nbt.setInt("tick_delay", tick_delay);
nbt.setInt("block_search_extent", block_search_extent);
nbt.setDouble("offset", offset);
return nbt;
}
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class AdditionsSound {
private final NamespaceID sound;
private final double tick_chance;
public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound();
nbt.setString("sound", sound.toString());
nbt.setDouble("tick_chance", tick_chance);
return nbt;
}
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class Music {
private final NamespaceID sound;
private final int min_delay;
private final int max_delay;
private final boolean replace_current_music;
public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound();
nbt.setString("sound", sound.toString());
nbt.setInt("min_delay", min_delay);
nbt.setInt("max_delay", max_delay);
nbt.setByte("replace_current_music", replace_current_music ? (byte) 1 : (byte) 0);
return nbt;
}
}
}

View File

@ -0,0 +1,82 @@
package net.minestom.server.world.biomes;
import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import org.jglrxavpok.hephaistos.nbt.NBTList;
import org.jglrxavpok.hephaistos.nbt.NBTTypes;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Allows servers to register custom dimensions. Also used during player joining to send the list of all existing dimensions.
*
* Contains {@link Biome#EXAMPLE} by default but can be removed.
*/
public class BiomeManager {
private List<Biome> biomes = new LinkedList<>();
public BiomeManager() {
addBiome(Biome.EXAMPLE);
}
/**
* Add a new biome. This does NOT send the new list to players.
* @param biome
*/
public void addBiome(Biome biome) {
biomes.add(biome);
}
/**
* Removes a biome. This does NOT send the new list to players.
* @param biome
* @return if the biome type was removed, false if it was not present before
*/
public boolean removeBiome(Biome biome) {
return biomes.remove(biome);
}
/**
* Returns an immutable copy of the biomes already registered
* @return
*/
public List<Biome> unmodifiableList() {
return Collections.unmodifiableList(biomes);
}
public Biome getById(int id) {
Biome biome = null;
for (final Biome biomeT : biomes) {
if (biomeT.getId() == id) {
biome = biomeT;
break;
}
}
return biome;
}
public Biome getByName(NamespaceID namespaceID) {
Biome biome = null;
for (final Biome biomeT : biomes) {
if (biomeT.getName().equals(namespaceID)) {
biome = biomeT;
break;
}
}
return biome;
}
public NBTCompound toNBT() {
NBTCompound biomes = new NBTCompound();
biomes.setString("type", "minecraft:worldgen/biome");
NBTList<NBTCompound> biomesList = new NBTList<>(NBTTypes.TAG_Compound);
for (Biome biome : this.biomes) {
biomesList.add(biome.toNbt());
}
biomes.set("value", biomesList);
return biomes;
}
}

View File

@ -0,0 +1,122 @@
package net.minestom.server.world.biomes;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockAlternative;
import net.minestom.server.item.ItemStack;
import net.minestom.server.utils.NamespaceID;
import org.jglrxavpok.hephaistos.nbt.NBTCompound;
import java.util.Map;
@Getter
@Builder
@ToString
@EqualsAndHashCode
public class BiomeParticles {
private final float probability;
private final ParticleOptions options;
public NBTCompound toNbt() {
NBTCompound nbt = new NBTCompound();
nbt.setFloat("probability", probability);
nbt.set("options", options.toNbt());
return nbt;
}
public interface ParticleOptions {
NBTCompound toNbt();
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class BlockParticle implements ParticleOptions {
//TODO also can be falling_dust
private static final String type = "block";
private final BlockAlternative block;
@Override
public NBTCompound toNbt() {
NBTCompound nbtCompound = new NBTCompound();
Block block1 = Block.fromStateId(block.getId());
nbtCompound.setString("type", type);
nbtCompound.setString("Name", block1.getName());
Map<String, String> propertiesMap = block.createPropertiesMap();
if (propertiesMap.size() != 0) {
NBTCompound properties = new NBTCompound();
propertiesMap.forEach(properties::setString);
nbtCompound.set("Properties", properties);
}
return nbtCompound;
}
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class DustParticle implements ParticleOptions {
private static final String type = "dust";
private final float red;
private final float green;
private final float blue;
private final float scale;
@Override
public NBTCompound toNbt() {
NBTCompound nbtCompound = new NBTCompound();
nbtCompound.setString("type", type);
nbtCompound.setFloat("r", red);
nbtCompound.setFloat("g", green);
nbtCompound.setFloat("b", blue);
nbtCompound.setFloat("scale", scale);
return nbtCompound;
}
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class ItemParticle implements ParticleOptions {
private static final String type = "item";
private final ItemStack item;
@Override
public NBTCompound toNbt() {
//todo test count might be wrong type
NBTCompound nbtCompound = item.toNBT();
nbtCompound.setString("type", type);
return nbtCompound;
}
}
@Getter
@Builder
@ToString
@EqualsAndHashCode
public static class NormalParticle implements ParticleOptions {
private final NamespaceID type;
@Override
public NBTCompound toNbt() {
NBTCompound nbtCompound = new NBTCompound();
nbtCompound.setString("type", type.toString());
return nbtCompound;
}
}
}