From bf6313659ec82401da6f92bf41f2134222c0731a Mon Sep 17 00:00:00 2001 From: jglrxavpok Date: Tue, 30 Jun 2020 12:53:00 +0200 Subject: [PATCH 1/6] NamespaceID->Resource in Registries.java --- .../minestom/server/entity/EntityType.java | 4 + .../net/minestom/server/instance/Biome.java | 4 + .../minestom/server/instance/block/Block.java | 2 + .../net/minestom/server/item/Enchantment.java | 4 + .../net/minestom/server/item/Material.java | 4 + .../minestom/server/particle/Particle.java | 4 + .../minestom/server/potion/PotionType.java | 4 + .../minestom/server/registry/Registries.java | 145 ++++++++++++++ .../java/net/minestom/server/sound/Sound.java | 4 + .../minestom/server/stat/StatisticType.java | 4 + .../net/minestom/codegen/AllGenerators.java | 1 + .../minestom/codegen/BasicEnumGenerator.java | 6 + .../net/minestom/codegen/CodeGenerator.java | 4 + .../minestom/codegen/RegistriesGenerator.java | 182 ++++++++++++++++++ .../codegen/blocks/BlockEnumGenerator.java | 3 + .../codegen/items/ItemEnumGenerator.java | 6 + .../gamedata/loottables/entries/ItemType.java | 4 +- .../server/utils/item/NbtReaderUtils.java | 7 +- 18 files changed, 386 insertions(+), 6 deletions(-) create mode 100644 src/autogenerated/java/net/minestom/server/registry/Registries.java create mode 100644 src/generators/java/net/minestom/codegen/RegistriesGenerator.java diff --git a/src/autogenerated/java/net/minestom/server/entity/EntityType.java b/src/autogenerated/java/net/minestom/server/entity/EntityType.java index 88447e82d..12992bd1e 100644 --- a/src/autogenerated/java/net/minestom/server/entity/EntityType.java +++ b/src/autogenerated/java/net/minestom/server/entity/EntityType.java @@ -2,6 +2,9 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.entity; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum EntityType { AREA_EFFECT_CLOUD("minecraft:area_effect_cloud"), @@ -112,6 +115,7 @@ public enum EntityType { EntityType(String namespaceID) { this.namespaceID = namespaceID; + Registries.entityTypes.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/autogenerated/java/net/minestom/server/instance/Biome.java b/src/autogenerated/java/net/minestom/server/instance/Biome.java index 8be877299..459ee0985 100644 --- a/src/autogenerated/java/net/minestom/server/instance/Biome.java +++ b/src/autogenerated/java/net/minestom/server/instance/Biome.java @@ -2,6 +2,9 @@ // 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"), @@ -84,6 +87,7 @@ public enum Biome { Biome(String namespaceID) { this.namespaceID = namespaceID; + Registries.biomes.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/autogenerated/java/net/minestom/server/instance/block/Block.java b/src/autogenerated/java/net/minestom/server/instance/block/Block.java index f22800d17..eb93aca18 100644 --- a/src/autogenerated/java/net/minestom/server/instance/block/Block.java +++ b/src/autogenerated/java/net/minestom/server/instance/block/Block.java @@ -2,6 +2,7 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.instance.block; +import net.minestom.server.registry.Registries; import net.minestom.server.utils.NamespaceID; import java.util.List; import java.util.ArrayList; @@ -1136,6 +1137,7 @@ public enum Block { if(singleState) { addBlockAlternative(new BlockAlternative(defaultID)); } + Registries.blocks.put(NamespaceID.from(namespaceID), this); } public short getBlockId() { diff --git a/src/autogenerated/java/net/minestom/server/item/Enchantment.java b/src/autogenerated/java/net/minestom/server/item/Enchantment.java index 9356f8297..909319f9f 100644 --- a/src/autogenerated/java/net/minestom/server/item/Enchantment.java +++ b/src/autogenerated/java/net/minestom/server/item/Enchantment.java @@ -2,6 +2,9 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.item; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum Enchantment { PROTECTION("minecraft:protection"), @@ -46,6 +49,7 @@ public enum Enchantment { Enchantment(String namespaceID) { this.namespaceID = namespaceID; + Registries.enchantments.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/autogenerated/java/net/minestom/server/item/Material.java b/src/autogenerated/java/net/minestom/server/item/Material.java index 5e6ed7583..e3086f2ed 100644 --- a/src/autogenerated/java/net/minestom/server/item/Material.java +++ b/src/autogenerated/java/net/minestom/server/item/Material.java @@ -3,6 +3,9 @@ //============================== package net.minestom.server.item; import net.minestom.server.instance.block.Block; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum Material { AIR("minecraft:air", 0, Block.AIR), @@ -898,6 +901,7 @@ public enum Material { this.namespaceID = namespaceID; this.maxDefaultStackSize = maxDefaultStackSize; this.correspondingBlock = correspondingBlock; + Registries.materials.put(NamespaceID.from(namespaceID), this); } public short getId() { diff --git a/src/autogenerated/java/net/minestom/server/particle/Particle.java b/src/autogenerated/java/net/minestom/server/particle/Particle.java index abf214457..76ff7fc07 100644 --- a/src/autogenerated/java/net/minestom/server/particle/Particle.java +++ b/src/autogenerated/java/net/minestom/server/particle/Particle.java @@ -2,6 +2,9 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.particle; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum Particle { AMBIENT_ENTITY_EFFECT("minecraft:ambient_entity_effect"), @@ -71,6 +74,7 @@ public enum Particle { Particle(String namespaceID) { this.namespaceID = namespaceID; + Registries.particles.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/autogenerated/java/net/minestom/server/potion/PotionType.java b/src/autogenerated/java/net/minestom/server/potion/PotionType.java index cf9408f86..418283187 100644 --- a/src/autogenerated/java/net/minestom/server/potion/PotionType.java +++ b/src/autogenerated/java/net/minestom/server/potion/PotionType.java @@ -2,6 +2,9 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.potion; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum PotionType { EMPTY("minecraft:empty"), @@ -52,6 +55,7 @@ public enum PotionType { PotionType(String namespaceID) { this.namespaceID = namespaceID; + Registries.potionTypes.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/autogenerated/java/net/minestom/server/registry/Registries.java b/src/autogenerated/java/net/minestom/server/registry/Registries.java new file mode 100644 index 000000000..d6d33a396 --- /dev/null +++ b/src/autogenerated/java/net/minestom/server/registry/Registries.java @@ -0,0 +1,145 @@ +package net.minestom.server.registry; + +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; +import net.minestom.server.potion.PotionType; +import net.minestom.server.sound.Sound; +import net.minestom.server.stat.StatisticType; + +// AUTOGENERATED +public class Registries { + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap blocks = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap materials = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap biomes = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap enchantments = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap entityTypes = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap particles = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap potionTypes = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap sounds = new HashMap<>(); + + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap statisticTypes = new HashMap<>(); + + + /** Returns the corresponding Block matching the given id. Returns 'AIR' if none match. */ + public static Block getBlock(String id) { + return getBlock(NamespaceID.from(id)); + } + + /** Returns the corresponding Block matching the given id. Returns 'AIR' if none match. */ + public static Block getBlock(NamespaceID id) { + return blocks.getOrDefault(id, Block.AIR); + } + + /** Returns the corresponding Material matching the given id. Returns 'AIR' if none match. */ + public static Material getMaterial(String id) { + return getMaterial(NamespaceID.from(id)); + } + + /** Returns the corresponding Material matching the given id. Returns 'AIR' if none match. */ + public static Material getMaterial(NamespaceID id) { + 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)); + } + + /** Returns the corresponding Enchantment matching the given id. Returns null if none match. */ + public static Enchantment getEnchantment(NamespaceID id) { + return enchantments.get(id); + } + + /** Returns the corresponding EntityType matching the given id. Returns 'PIG' if none match. */ + public static EntityType getEntityType(String id) { + return getEntityType(NamespaceID.from(id)); + } + + /** Returns the corresponding EntityType matching the given id. Returns 'PIG' if none match. */ + public static EntityType getEntityType(NamespaceID id) { + return entityTypes.getOrDefault(id, EntityType.PIG); + } + + /** Returns the corresponding Particle matching the given id. Returns null if none match. */ + public static Particle getParticle(String id) { + return getParticle(NamespaceID.from(id)); + } + + /** Returns the corresponding Particle matching the given id. Returns null if none match. */ + public static Particle getParticle(NamespaceID id) { + return particles.get(id); + } + + /** Returns the corresponding PotionType matching the given id. Returns null if none match. */ + public static PotionType getPotionType(String id) { + return getPotionType(NamespaceID.from(id)); + } + + /** Returns the corresponding PotionType matching the given id. Returns null if none match. */ + public static PotionType getPotionType(NamespaceID id) { + return potionTypes.get(id); + } + + /** Returns the corresponding Sound matching the given id. Returns null if none match. */ + public static Sound getSound(String id) { + return getSound(NamespaceID.from(id)); + } + + /** Returns the corresponding Sound matching the given id. Returns null if none match. */ + public static Sound getSound(NamespaceID id) { + return sounds.get(id); + } + + /** Returns the corresponding StatisticType matching the given id. Returns null if none match. */ + public static StatisticType getStatisticType(String id) { + return getStatisticType(NamespaceID.from(id)); + } + + /** Returns the corresponding StatisticType matching the given id. Returns null if none match. */ + public static StatisticType getStatisticType(NamespaceID id) { + return statisticTypes.get(id); + } + + +} diff --git a/src/autogenerated/java/net/minestom/server/sound/Sound.java b/src/autogenerated/java/net/minestom/server/sound/Sound.java index 13816abe9..1988e1532 100644 --- a/src/autogenerated/java/net/minestom/server/sound/Sound.java +++ b/src/autogenerated/java/net/minestom/server/sound/Sound.java @@ -2,6 +2,9 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.sound; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum Sound { AMBIENT_CAVE("minecraft:ambient.cave"), @@ -819,6 +822,7 @@ public enum Sound { Sound(String namespaceID) { this.namespaceID = namespaceID; + Registries.sounds.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/autogenerated/java/net/minestom/server/stat/StatisticType.java b/src/autogenerated/java/net/minestom/server/stat/StatisticType.java index edb6a6763..55c951743 100644 --- a/src/autogenerated/java/net/minestom/server/stat/StatisticType.java +++ b/src/autogenerated/java/net/minestom/server/stat/StatisticType.java @@ -2,6 +2,9 @@ // AUTOGENERATED BY EnumGenerator //============================== package net.minestom.server.stat; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) public enum StatisticType { LEAVE_GAME("minecraft:leave_game"), @@ -80,6 +83,7 @@ public enum StatisticType { StatisticType(String namespaceID) { this.namespaceID = namespaceID; + Registries.statisticTypes.put(NamespaceID.from(namespaceID), this); } public int getId() { diff --git a/src/generators/java/net/minestom/codegen/AllGenerators.java b/src/generators/java/net/minestom/codegen/AllGenerators.java index 5394978fa..7bae48582 100644 --- a/src/generators/java/net/minestom/codegen/AllGenerators.java +++ b/src/generators/java/net/minestom/codegen/AllGenerators.java @@ -24,5 +24,6 @@ public class AllGenerators { ParticleEnumGenerator.main(args); StatsEnumGenerator.main(args); BiomesEnumGenerator.main(args); + RegistriesGenerator.main(args); } } diff --git a/src/generators/java/net/minestom/codegen/BasicEnumGenerator.java b/src/generators/java/net/minestom/codegen/BasicEnumGenerator.java index b6f3de09a..0b800045b 100644 --- a/src/generators/java/net/minestom/codegen/BasicEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/BasicEnumGenerator.java @@ -2,6 +2,7 @@ package net.minestom.codegen; import com.google.gson.Gson; import com.google.gson.JsonObject; +import net.minestom.server.registry.Registries; import net.minestom.server.utils.NamespaceID; import java.io.File; @@ -63,9 +64,14 @@ public abstract class BasicEnumGenerator extends MinestomEnumGenerator ").append(CodeGenerator.decapitalize(simpleType)).append('s'); + contents.append(" = new HashMap<>();").append("\n\n"); + } + + contents.append('\n'); + + // accessor methods + for (int i = 0; i < types.length; i++) { + String type = types[i]; + String simpleType = type.substring(type.lastIndexOf('.') + 1); + String defaultValue = defaults[i]; + + // Example: +/* + /** Returns 'AIR' if none match + public static Block getBlock(String id) { + return getBlock(NamespaceID.from(id)); + } + + /** Returns 'AIR' if none match + public static Block getBlock(NamespaceID id) { + return blocks.getOrDefault(id, AIR); + } +*/ + StringBuilder comment = new StringBuilder("/** Returns the corresponding "); + comment.append(simpleType).append(" matching the given id. Returns "); + if(defaultValue != null) { + comment.append('\'').append(defaultValue).append('\''); + } else { + comment.append("null"); + } + comment.append(" if none match. */"); + + // String variant + contents.append('\t').append(comment).append("\n"); + contents.append('\t'); + contents.append("public static ").append(simpleType).append(" get").append(simpleType).append("(String id) {\n"); + contents.append("\t\t").append("return get").append(simpleType).append("(NamespaceID.from(id));\n"); + + contents.append("\t}\n\n"); + + // NamespaceID variant + contents.append('\t').append(comment).append("\n"); + contents.append('\t'); + contents.append("public static ").append(simpleType).append(" get").append(simpleType).append("(NamespaceID id) {\n"); + contents.append("\t\t").append("return ").append(CodeGenerator.decapitalize(simpleType)).append("s."); + + if(defaultValue != null) { + contents.append("getOrDefault(id, ").append(simpleType).append('.').append(defaultValue).append(");"); + } else { + contents.append("get(id);"); + } + + contents.append("\n"); + + contents.append("\t}\n\n"); + } + + contents.append("\n}\n"); + + return contents.toString(); + } + + public static void main(String[] args) throws IOException { + // copy-pasted from BlockEnumGenerator, to stay consistent in the order of arguments + String targetVersion; + if(args.length < 1) { + System.err.println("Usage: [target folder]"); + return; + } + + targetVersion = args[0]; + + try { + ResourceGatherer.ensureResourcesArePresent(targetVersion, null); // TODO + } catch (IOException e) { + e.printStackTrace(); + } + + String targetPart = DEFAULT_TARGET_PATH; + if(args.length >= 2) { + targetPart = args[1]; + } + + File targetFolder = new File(targetPart); + if(!targetFolder.exists()) { + targetFolder.mkdirs(); + } + + new RegistriesGenerator().generateTo(targetFolder); + } + + private void generateTo(File targetFolder) throws IOException { + String code = generate(); + String folder = "net/minestom/server/registry"; + File parentFolder = new File(targetFolder, folder); + if(!parentFolder.exists()) { + parentFolder.mkdirs(); + } + + LOGGER.debug("Writing to file: "+parentFolder+"/Registries.java"); + try(Writer writer = new BufferedWriter(new FileWriter(new File(parentFolder, "Registries.java")))) { + writer.write(code); + } + } +} diff --git a/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java b/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java index c7746a782..d574c02be 100644 --- a/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java @@ -9,6 +9,7 @@ import net.minestom.codegen.EnumGenerator; import net.minestom.codegen.MinestomEnumGenerator; import net.minestom.codegen.PrismarinePaths; import net.minestom.server.instance.block.BlockAlternative; +import net.minestom.server.registry.Registries; import net.minestom.server.registry.ResourceGatherer; import net.minestom.server.utils.NamespaceID; import org.slf4j.Logger; @@ -240,6 +241,7 @@ public class BlockEnumGenerator extends MinestomEnumGenerator { protected void prepare(EnumGenerator generator) { String className = getClassName(); generator.addClassAnnotation("@SuppressWarnings({\"deprecation\"})"); + generator.addImport(Registries.class.getCanonicalName()); generator.addImport(NamespaceID.class.getCanonicalName()); generator.addImport(List.class.getCanonicalName()); generator.addImport(ArrayList.class.getCanonicalName()); @@ -272,6 +274,7 @@ public class BlockEnumGenerator extends MinestomEnumGenerator { generator.appendToConstructor("if(singleState) {"); generator.appendToConstructor("\taddBlockAlternative(new BlockAlternative(defaultID));"); generator.appendToConstructor("}"); + generator.appendToConstructor("Registries.blocks.put(NamespaceID.from(namespaceID), this);"); } @Override diff --git a/src/generators/java/net/minestom/codegen/items/ItemEnumGenerator.java b/src/generators/java/net/minestom/codegen/items/ItemEnumGenerator.java index 9dbd7a33f..30c24ba00 100644 --- a/src/generators/java/net/minestom/codegen/items/ItemEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/items/ItemEnumGenerator.java @@ -10,6 +10,7 @@ import net.minestom.codegen.PrismarinePaths; import net.minestom.codegen.blocks.*; import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.BlockAlternative; +import net.minestom.server.registry.Registries; import net.minestom.server.registry.ResourceGatherer; import net.minestom.server.utils.NamespaceID; import org.slf4j.Logger; @@ -130,7 +131,12 @@ public class ItemEnumGenerator extends MinestomEnumGenerator { protected void prepare(EnumGenerator generator) { String className = getClassName(); generator.addImport(Block.class.getCanonicalName()); + generator.addImport(Registries.class.getCanonicalName()); + generator.addImport(NamespaceID.class.getCanonicalName()); + generator.addClassAnnotation("@SuppressWarnings({\"deprecation\"})"); generator.setParams("String namespaceID", "int maxDefaultStackSize", "Block correspondingBlock"); + generator.appendToConstructor("Registries.materials.put(NamespaceID.from(namespaceID), this);"); + generator.addMethod("getId", "()", "short", "return (short)ordinal();"); generator.addMethod("getName", "()", "String", "return namespaceID;"); generator.addMethod("getMaxDefaultStackSize", "()", "int", "return maxDefaultStackSize;"); diff --git a/src/main/java/net/minestom/server/gamedata/loottables/entries/ItemType.java b/src/main/java/net/minestom/server/gamedata/loottables/entries/ItemType.java index 34d3c5b30..f637c34c6 100644 --- a/src/main/java/net/minestom/server/gamedata/loottables/entries/ItemType.java +++ b/src/main/java/net/minestom/server/gamedata/loottables/entries/ItemType.java @@ -6,6 +6,7 @@ import net.minestom.server.gamedata.loottables.LootTableEntryType; import net.minestom.server.gamedata.loottables.LootTableFunction; import net.minestom.server.gamedata.loottables.LootTableManager; import net.minestom.server.item.Material; +import net.minestom.server.registry.Registries; import net.minestom.server.utils.NamespaceID; import java.util.List; @@ -17,7 +18,6 @@ public class ItemType implements LootTableEntryType { @Override public LootTable.Entry create(LootTableManager lootTableManager, String name, List conditions, List children, boolean expand, List functions, int weight, int quality) { NamespaceID itemID = NamespaceID.from(name); - // TODO: handle non-vanilla IDs ? - return new ItemEntry(this, Material.valueOf(itemID.getPath().toUpperCase()), weight, quality, functions, conditions); + return new ItemEntry(this, Registries.getMaterial(itemID), weight, quality, functions, conditions); } } diff --git a/src/main/java/net/minestom/server/utils/item/NbtReaderUtils.java b/src/main/java/net/minestom/server/utils/item/NbtReaderUtils.java index e0cc46b58..53a55f98f 100644 --- a/src/main/java/net/minestom/server/utils/item/NbtReaderUtils.java +++ b/src/main/java/net/minestom/server/utils/item/NbtReaderUtils.java @@ -11,6 +11,7 @@ import net.minestom.server.item.attribute.AttributeSlot; import net.minestom.server.item.attribute.ItemAttribute; import net.minestom.server.network.packet.PacketReader; import net.minestom.server.potion.PotionType; +import net.minestom.server.registry.Registries; import java.util.ArrayList; import java.util.UUID; @@ -81,8 +82,7 @@ public class NbtReaderUtils { if (stringName.equals("Potion")) { String potionId = reader.readShortSizedString(); - potionId = potionId.replace("minecraft:", "").toUpperCase(); - PotionType potionType = PotionType.valueOf(potionId); + PotionType potionType = Registries.getPotionType(potionId); item.addPotionType(potionType); @@ -109,8 +109,7 @@ public class NbtReaderUtils { String id = reader.readShortSizedString(); // Convert id - id = id.replace("minecraft:", "").toUpperCase(); - Enchantment enchantment = Enchantment.valueOf(id); + Enchantment enchantment = Registries.getEnchantment(id); if (isEnchantment) { item.setEnchantment(enchantment, lvl); From 4ffde8feed473dcb419b475164611760afb1d5fd Mon Sep 17 00:00:00 2001 From: jglrxavpok Date: Tue, 30 Jun 2020 14:49:53 +0200 Subject: [PATCH 2/6] Added isLiquid utility method in Block --- .../java/net/minestom/server/instance/block/Block.java | 4 ++++ .../java/net/minestom/codegen/blocks/BlockEnumGenerator.java | 1 + 2 files changed, 5 insertions(+) diff --git a/src/autogenerated/java/net/minestom/server/instance/block/Block.java b/src/autogenerated/java/net/minestom/server/instance/block/Block.java index eb93aca18..b1628aad9 100644 --- a/src/autogenerated/java/net/minestom/server/instance/block/Block.java +++ b/src/autogenerated/java/net/minestom/server/instance/block/Block.java @@ -1160,6 +1160,10 @@ public enum Block { return isSolid; } + public boolean isLiquid() { + return this == WATER || this == LAVA; + } + public double getHardness() { return hardness; } diff --git a/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java b/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java index d574c02be..0a967c972 100644 --- a/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java +++ b/src/generators/java/net/minestom/codegen/blocks/BlockEnumGenerator.java @@ -254,6 +254,7 @@ public class BlockEnumGenerator extends MinestomEnumGenerator { generator.addMethod("hasBlockEntity", "()", "boolean", "return blockEntity != null;"); generator.addMethod("getBlockEntityName", "()", "NamespaceID", "return blockEntity;"); generator.addMethod("isSolid", "()", "boolean", "return isSolid;"); + generator.addMethod("isLiquid", "()", "boolean", "return this == WATER || this == LAVA;"); generator.addMethod("getHardness", "()", "double", "return hardness;"); generator.addMethod("getResistance", "()", "double", "return resistance;"); generator.addMethod("breaksInstantaneously", "()", "boolean", "return hardness == 0;"); From 1ddef81372a0ae5de1b0c9ea61ff760f68a2b81e Mon Sep 17 00:00:00 2001 From: jglrxavpok Date: Tue, 30 Jun 2020 18:07:47 +0200 Subject: [PATCH 3/6] Customizable chunk loader for InstanceContainers --- prismarine-minecraft-data | 2 +- .../server/instance/IChunkLoader.java | 8 +++++ .../minestom/server/instance/Instance.java | 1 - .../server/instance/InstanceContainer.java | 32 +++++++++++-------- ...der.java => MinestomBasicChunkLoader.java} | 28 ++++++++++++---- 5 files changed, 50 insertions(+), 21 deletions(-) create mode 100644 src/main/java/net/minestom/server/instance/IChunkLoader.java rename src/main/java/net/minestom/server/instance/{ChunkLoader.java => MinestomBasicChunkLoader.java} (54%) diff --git a/prismarine-minecraft-data b/prismarine-minecraft-data index 1e52503a6..fc2078a40 160000 --- a/prismarine-minecraft-data +++ b/prismarine-minecraft-data @@ -1 +1 @@ -Subproject commit 1e52503a6dbabd326bd0fee5e2aba5cd07b2a4f8 +Subproject commit fc2078a404b7b6041a1d60f15b6b2b482890bbfb diff --git a/src/main/java/net/minestom/server/instance/IChunkLoader.java b/src/main/java/net/minestom/server/instance/IChunkLoader.java new file mode 100644 index 000000000..2ec558b10 --- /dev/null +++ b/src/main/java/net/minestom/server/instance/IChunkLoader.java @@ -0,0 +1,8 @@ +package net.minestom.server.instance; + +import java.util.function.Consumer; + +public interface IChunkLoader { + void loadOrCreateChunk(Instance instance, int chunkX, int chunkZ, Consumer callback); + void saveChunk(Chunk chunk, Runnable callback); +} diff --git a/src/main/java/net/minestom/server/instance/Instance.java b/src/main/java/net/minestom/server/instance/Instance.java index feac75179..c221347e0 100644 --- a/src/main/java/net/minestom/server/instance/Instance.java +++ b/src/main/java/net/minestom/server/instance/Instance.java @@ -35,7 +35,6 @@ import java.util.function.Consumer; public abstract class Instance implements BlockModifier, EventHandler, DataContainer { - protected static final ChunkLoader CHUNK_LOADER_IO = new ChunkLoader(); protected static final BlockManager BLOCK_MANAGER = MinecraftServer.getBlockManager(); private Dimension dimension; diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index 5edfc61ee..b4e2d9cae 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -54,6 +54,7 @@ public class InstanceContainer extends Instance { private ReadWriteLock changingBlockLock = new ReentrantReadWriteLock(); private Map currentlyChangingBlocks = new HashMap<>(); + private IChunkLoader chunkLoader; private boolean autoChunkLoad; @@ -61,9 +62,12 @@ public class InstanceContainer extends Instance { super(uniqueId, dimension); this.storageFolder = storageFolder; + chunkLoader = new MinestomBasicChunkLoader(storageFolder); - if (storageFolder == null) + if (storageFolder == null) { return; + } + // Retrieve instance data this.uniqueId = storageFolder.getOrDefault(UUID_KEY, UUID.class, uniqueId); @@ -360,7 +364,7 @@ public class InstanceContainer extends Instance { @Override public void saveChunkToStorageFolder(Chunk chunk, Runnable callback) { Check.notNull(getStorageFolder(), "You cannot save the chunk if no StorageFolder has been defined"); - CHUNK_LOADER_IO.saveChunk(chunk, getStorageFolder(), callback); + chunkLoader.saveChunk(chunk, callback); } @Override @@ -387,17 +391,11 @@ public class InstanceContainer extends Instance { @Override protected void retrieveChunk(int chunkX, int chunkZ, Consumer callback) { - if (storageFolder != null) { - // Load from file if possible - CHUNK_LOADER_IO.loadChunk(this, chunkX, chunkZ, getStorageFolder(), chunk -> { - cacheChunk(chunk); - if (callback != null) - callback.accept(chunk); - }); - } else { - // Folder isn't defined, create new chunk - createChunk(chunkX, chunkZ, callback); - } + chunkLoader.loadOrCreateChunk(this, chunkX, chunkZ, chunk -> { + cacheChunk(chunk); + if (callback != null) + callback.accept(chunk); + }); } @Override @@ -499,6 +497,14 @@ public class InstanceContainer extends Instance { this.storageFolder = storageFolder; } + public IChunkLoader getChunkLoader() { + return chunkLoader; + } + + public void setChunkLoader(IChunkLoader chunkLoader) { + this.chunkLoader = chunkLoader; + } + private void sendBlockChange(Chunk chunk, BlockPosition blockPosition, short blockId) { BlockChangePacket blockChangePacket = new BlockChangePacket(); blockChangePacket.blockPosition = blockPosition; diff --git a/src/main/java/net/minestom/server/instance/ChunkLoader.java b/src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java similarity index 54% rename from src/main/java/net/minestom/server/instance/ChunkLoader.java rename to src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java index 168e06343..18a7f4de9 100644 --- a/src/main/java/net/minestom/server/instance/ChunkLoader.java +++ b/src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java @@ -2,17 +2,28 @@ package net.minestom.server.instance; import net.minestom.server.reader.ChunkReader; import net.minestom.server.storage.StorageFolder; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.io.IOException; import java.util.function.Consumer; -public class ChunkLoader { +public class MinestomBasicChunkLoader implements IChunkLoader { - private static String getChunkKey(int chunkX, int chunkZ) { - return chunkX + "." + chunkZ; + private final static Logger LOGGER = LoggerFactory.getLogger(MinestomBasicChunkLoader.class); + private StorageFolder storageFolder; + + public MinestomBasicChunkLoader(StorageFolder storageFolder) { + this.storageFolder = storageFolder; } - protected void saveChunk(Chunk chunk, StorageFolder storageFolder, Runnable callback) { + @Override + public void saveChunk(Chunk chunk, Runnable callback) { + if(storageFolder == null) { + callback.run(); + LOGGER.warn("No folder to save chunk!"); + return; + } int chunkX = chunk.getChunkX(); int chunkZ = chunk.getChunkZ(); @@ -27,8 +38,9 @@ public class ChunkLoader { } } - protected void loadChunk(Instance instance, int chunkX, int chunkZ, StorageFolder storageFolder, Consumer callback) { - byte[] bytes = storageFolder.get(getChunkKey(chunkX, chunkZ)); + @Override + public void loadOrCreateChunk(Instance instance, int chunkX, int chunkZ, Consumer callback) { + byte[] bytes = storageFolder == null ? null : storageFolder.get(getChunkKey(chunkX, chunkZ)); if (bytes == null) { // Not found, create a new chunk @@ -39,5 +51,9 @@ public class ChunkLoader { } } + private static String getChunkKey(int chunkX, int chunkZ) { + return chunkX + "." + chunkZ; + } + } From ef8c275c4d6281b73ce19e949ca97e334235b662 Mon Sep 17 00:00:00 2001 From: jglrxavpok Date: Tue, 30 Jun 2020 18:12:09 +0200 Subject: [PATCH 4/6] Moved chunk creation out of chunk loaders --- .../java/net/minestom/server/instance/IChunkLoader.java | 2 +- .../net/minestom/server/instance/InstanceContainer.java | 7 ++++++- .../minestom/server/instance/MinestomBasicChunkLoader.java | 6 +++--- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/minestom/server/instance/IChunkLoader.java b/src/main/java/net/minestom/server/instance/IChunkLoader.java index 2ec558b10..d147a4401 100644 --- a/src/main/java/net/minestom/server/instance/IChunkLoader.java +++ b/src/main/java/net/minestom/server/instance/IChunkLoader.java @@ -3,6 +3,6 @@ package net.minestom.server.instance; import java.util.function.Consumer; public interface IChunkLoader { - void loadOrCreateChunk(Instance instance, int chunkX, int chunkZ, Consumer callback); + boolean loadChunk(Instance instance, int chunkX, int chunkZ, Consumer callback); void saveChunk(Chunk chunk, Runnable callback); } diff --git a/src/main/java/net/minestom/server/instance/InstanceContainer.java b/src/main/java/net/minestom/server/instance/InstanceContainer.java index b4e2d9cae..42dc45d2b 100644 --- a/src/main/java/net/minestom/server/instance/InstanceContainer.java +++ b/src/main/java/net/minestom/server/instance/InstanceContainer.java @@ -391,11 +391,16 @@ public class InstanceContainer extends Instance { @Override protected void retrieveChunk(int chunkX, int chunkZ, Consumer callback) { - chunkLoader.loadOrCreateChunk(this, chunkX, chunkZ, chunk -> { + boolean loaded = chunkLoader.loadChunk(this, chunkX, chunkZ, chunk -> { cacheChunk(chunk); if (callback != null) callback.accept(chunk); }); + + if(!loaded) { + // Not found, create a new chunk + createChunk(chunkX, chunkZ, callback); + } } @Override diff --git a/src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java b/src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java index 18a7f4de9..38de6df0d 100644 --- a/src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java +++ b/src/main/java/net/minestom/server/instance/MinestomBasicChunkLoader.java @@ -39,15 +39,15 @@ public class MinestomBasicChunkLoader implements IChunkLoader { } @Override - public void loadOrCreateChunk(Instance instance, int chunkX, int chunkZ, Consumer callback) { + public boolean loadChunk(Instance instance, int chunkX, int chunkZ, Consumer callback) { byte[] bytes = storageFolder == null ? null : storageFolder.get(getChunkKey(chunkX, chunkZ)); if (bytes == null) { - // Not found, create a new chunk - instance.createChunk(chunkX, chunkZ, callback); + return false; } else { // Found, load from result bytes ChunkReader.readChunk(bytes, instance, chunkX, chunkZ, callback); + return true; } } From 2303b98024cb18a050ebeb93947f7b79bed1ddbd Mon Sep 17 00:00:00 2001 From: jglrxavpok Date: Tue, 30 Jun 2020 20:38:42 +0200 Subject: [PATCH 5/6] Send tags to player on connection --- .../net/minestom/server/fluids/Fluid.java | 37 +++++++++++ .../minestom/server/registry/Registries.java | 15 +++++ .../net/minestom/codegen/AllGenerators.java | 2 + .../minestom/codegen/RegistriesGenerator.java | 5 +- .../codegen/fluids/FluidEnumGenerator.java | 56 +++++++++++++++++ src/main/java/fr/themode/demo/PlayerInit.java | 5 +- .../demo/generator/NoiseTestGenerator.java | 2 +- .../net/minestom/server/entity/Player.java | 17 ++++-- .../event/player/UpdateTagListEvent.java | 17 ++++++ .../server/gamedata/tags/RequiredTag.java | 21 +++++++ .../minestom/server/gamedata/tags/Tag.java | 24 +++++++- .../server/gamedata/tags/TagManager.java | 61 +++++++++++++++++-- .../packet/server/play/TagsPacket.java | 50 +++++++++++++++ 13 files changed, 298 insertions(+), 14 deletions(-) create mode 100644 src/autogenerated/java/net/minestom/server/fluids/Fluid.java create mode 100644 src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java create mode 100644 src/main/java/net/minestom/server/event/player/UpdateTagListEvent.java create mode 100644 src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java create mode 100644 src/main/java/net/minestom/server/network/packet/server/play/TagsPacket.java diff --git a/src/autogenerated/java/net/minestom/server/fluids/Fluid.java b/src/autogenerated/java/net/minestom/server/fluids/Fluid.java new file mode 100644 index 000000000..a900f89a9 --- /dev/null +++ b/src/autogenerated/java/net/minestom/server/fluids/Fluid.java @@ -0,0 +1,37 @@ +//============================== +// AUTOGENERATED BY EnumGenerator +//============================== +package net.minestom.server.fluids; +import net.minestom.server.registry.Registries; +import net.minestom.server.utils.NamespaceID; +@SuppressWarnings({"deprecation"}) + +public enum Fluid { + EMPTY("minecraft:empty"), + FLOWING_WATER("minecraft:flowing_water"), + WATER("minecraft:water"), + FLOWING_LAVA("minecraft:flowing_lava"), + LAVA("minecraft:lava"), +; + private String namespaceID; + + Fluid(String namespaceID) { + this.namespaceID = namespaceID; + Registries.fluids.put(NamespaceID.from(namespaceID), this); + } + + public int getId() { + return ordinal(); + } + + public String getNamespaceID() { + return namespaceID; + } + + public static Fluid fromId(int id) { + if(id >= 0 && id < values().length) { + return values()[id]; + } + return EMPTY; + } +} diff --git a/src/autogenerated/java/net/minestom/server/registry/Registries.java b/src/autogenerated/java/net/minestom/server/registry/Registries.java index d6d33a396..a0cc042a7 100644 --- a/src/autogenerated/java/net/minestom/server/registry/Registries.java +++ b/src/autogenerated/java/net/minestom/server/registry/Registries.java @@ -11,6 +11,7 @@ import net.minestom.server.particle.Particle; import net.minestom.server.potion.PotionType; import net.minestom.server.sound.Sound; import net.minestom.server.stat.StatisticType; +import net.minestom.server.fluids.Fluid; // AUTOGENERATED public class Registries { @@ -50,6 +51,10 @@ public class Registries { @Deprecated public static final HashMap statisticTypes = new HashMap<>(); + /** Should only be used for internal code, please use the get* methods. */ + @Deprecated + public static final HashMap fluids = new HashMap<>(); + /** Returns the corresponding Block matching the given id. Returns 'AIR' if none match. */ public static Block getBlock(String id) { @@ -141,5 +146,15 @@ public class Registries { return statisticTypes.get(id); } + /** Returns the corresponding Fluid matching the given id. Returns 'EMPTY' if none match. */ + public static Fluid getFluid(String id) { + return getFluid(NamespaceID.from(id)); + } + + /** Returns the corresponding Fluid matching the given id. Returns 'EMPTY' if none match. */ + public static Fluid getFluid(NamespaceID id) { + return fluids.getOrDefault(id, Fluid.EMPTY); + } + } diff --git a/src/generators/java/net/minestom/codegen/AllGenerators.java b/src/generators/java/net/minestom/codegen/AllGenerators.java index 7bae48582..60a4f9218 100644 --- a/src/generators/java/net/minestom/codegen/AllGenerators.java +++ b/src/generators/java/net/minestom/codegen/AllGenerators.java @@ -3,6 +3,7 @@ package net.minestom.codegen; import net.minestom.codegen.blocks.BlockEnumGenerator; import net.minestom.codegen.enchantment.EnchantmentEnumGenerator; import net.minestom.codegen.entitytypes.EntityTypeEnumGenerator; +import net.minestom.codegen.fluids.FluidEnumGenerator; import net.minestom.codegen.items.ItemEnumGenerator; import net.minestom.codegen.particles.ParticleEnumGenerator; import net.minestom.codegen.potions.PotionEnumGenerator; @@ -24,6 +25,7 @@ public class AllGenerators { ParticleEnumGenerator.main(args); StatsEnumGenerator.main(args); BiomesEnumGenerator.main(args); + FluidEnumGenerator.main(args); RegistriesGenerator.main(args); } } diff --git a/src/generators/java/net/minestom/codegen/RegistriesGenerator.java b/src/generators/java/net/minestom/codegen/RegistriesGenerator.java index 761088ae3..ab96c5967 100644 --- a/src/generators/java/net/minestom/codegen/RegistriesGenerator.java +++ b/src/generators/java/net/minestom/codegen/RegistriesGenerator.java @@ -1,6 +1,7 @@ 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; @@ -37,6 +38,7 @@ public class RegistriesGenerator implements CodeGenerator { PotionType.class.getCanonicalName(), Sound.class.getCanonicalName(), StatisticType.class.getCanonicalName(), + Fluid.class.getCanonicalName(), }; private static final String[] defaults = { "AIR", @@ -47,7 +49,8 @@ public class RegistriesGenerator implements CodeGenerator { null, null, null, - null + null, + "EMPTY" }; @Override diff --git a/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java b/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java new file mode 100644 index 000000000..dff9e886a --- /dev/null +++ b/src/generators/java/net/minestom/codegen/fluids/FluidEnumGenerator.java @@ -0,0 +1,56 @@ +package net.minestom.codegen.fluids; + +import net.minestom.codegen.BasicEnumGenerator; +import net.minestom.server.registry.ResourceGatherer; + +import java.io.File; +import java.io.IOException; + +public class FluidEnumGenerator extends BasicEnumGenerator { + public static void main(String[] args) throws IOException { + String targetVersion; + if(args.length < 1) { + System.err.println("Usage: [target folder]"); + return; + } + + targetVersion = args[0]; + + try { + ResourceGatherer.ensureResourcesArePresent(targetVersion, null); // TODO + } catch (IOException e) { + e.printStackTrace(); + } + + String targetPart = DEFAULT_TARGET_PATH; + if(args.length >= 2) { + targetPart = args[1]; + } + + File targetFolder = new File(targetPart); + if(!targetFolder.exists()) { + targetFolder.mkdirs(); + } + + new FluidEnumGenerator(targetFolder); + } + + private FluidEnumGenerator(File targetFolder) throws IOException { + super(targetFolder); + } + + @Override + protected String getCategoryID() { + return "minecraft:fluid"; + } + + @Override + public String getPackageName() { + return "net.minestom.server.fluids"; + } + + @Override + public String getClassName() { + return "Fluid"; + } +} diff --git a/src/main/java/fr/themode/demo/PlayerInit.java b/src/main/java/fr/themode/demo/PlayerInit.java index 7e762abd0..43872d0f6 100644 --- a/src/main/java/fr/themode/demo/PlayerInit.java +++ b/src/main/java/fr/themode/demo/PlayerInit.java @@ -15,6 +15,7 @@ import net.minestom.server.event.item.ItemDropEvent; import net.minestom.server.event.item.ItemUpdateStateEvent; import net.minestom.server.event.item.PickupItemEvent; import net.minestom.server.event.player.*; +import net.minestom.server.gamedata.tags.TagManager; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; import net.minestom.server.instance.InstanceContainer; @@ -27,15 +28,18 @@ import net.minestom.server.item.ItemFlag; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; import net.minestom.server.network.ConnectionManager; +import net.minestom.server.network.packet.server.play.TagsPacket; import net.minestom.server.ping.ResponseDataConsumer; import net.minestom.server.timer.TaskRunnable; import net.minestom.server.utils.MathUtils; +import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.Position; import net.minestom.server.utils.Vector; import net.minestom.server.utils.time.TimeUnit; import net.minestom.server.utils.time.UpdateOption; import net.minestom.server.world.Dimension; +import java.io.FileNotFoundException; import java.util.Map; import java.util.UUID; @@ -115,7 +119,6 @@ public class PlayerInit { }); connectionManager.addPlayerInitialization(player -> { - player.addEventCallback(EntityAttackEvent.class, event -> { Entity entity = event.getTarget(); if (entity instanceof EntityCreature) { diff --git a/src/main/java/fr/themode/demo/generator/NoiseTestGenerator.java b/src/main/java/fr/themode/demo/generator/NoiseTestGenerator.java index 1a32a6922..e7eda8c05 100644 --- a/src/main/java/fr/themode/demo/generator/NoiseTestGenerator.java +++ b/src/main/java/fr/themode/demo/generator/NoiseTestGenerator.java @@ -27,7 +27,7 @@ public class NoiseTestGenerator extends ChunkGenerator { if (random.nextInt(100) > 10) { batch.setCustomBlock(x, y, z, "custom_block"); } else { - batch.setBlock(x, y, z, Block.DIAMOND_BLOCK); + batch.setBlock(x, y, z, Block.LAVA); } } } diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index 3b59c9c1d..64ba3264e 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -17,6 +17,7 @@ import net.minestom.server.event.item.ItemDropEvent; import net.minestom.server.event.item.ItemUpdateStateEvent; import net.minestom.server.event.item.PickupExperienceEvent; import net.minestom.server.event.player.*; +import net.minestom.server.gamedata.tags.TagManager; import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Instance; import net.minestom.server.instance.block.CustomBlock; @@ -38,15 +39,13 @@ import net.minestom.server.scoreboard.Team; import net.minestom.server.sound.Sound; import net.minestom.server.sound.SoundCategory; import net.minestom.server.stat.PlayerStatistic; -import net.minestom.server.utils.ArrayUtils; -import net.minestom.server.utils.BlockPosition; -import net.minestom.server.utils.MathUtils; -import net.minestom.server.utils.Position; +import net.minestom.server.utils.*; import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.validate.Check; import net.minestom.server.world.Dimension; import net.minestom.server.world.LevelType; +import java.io.FileNotFoundException; import java.util.*; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CopyOnWriteArraySet; @@ -237,6 +236,16 @@ public class Player extends LivingEntity implements CommandSender { } // Recipes end + // Send server tags + TagsPacket tags = new TagsPacket(); + TagManager tagManager = MinecraftServer.getTagManager(); + tagManager.addRequiredTagsToPacket(tags); + + UpdateTagListEvent event = new UpdateTagListEvent(tags); + callEvent(UpdateTagListEvent.class,event); + + sendPacketToViewersAndSelf(tags); + // Some client update playerConnection.sendPacket(getPropertiesPacket()); // Send default properties refreshHealth(); // Heal and send health packet diff --git a/src/main/java/net/minestom/server/event/player/UpdateTagListEvent.java b/src/main/java/net/minestom/server/event/player/UpdateTagListEvent.java new file mode 100644 index 000000000..ce375f039 --- /dev/null +++ b/src/main/java/net/minestom/server/event/player/UpdateTagListEvent.java @@ -0,0 +1,17 @@ +package net.minestom.server.event.player; + +import net.minestom.server.event.Event; +import net.minestom.server.network.packet.server.play.TagsPacket; + +public class UpdateTagListEvent extends Event { + + private TagsPacket packet; + + public UpdateTagListEvent(TagsPacket packet) { + this.packet = packet; + } + + public TagsPacket getTags() { + return packet; + } +} diff --git a/src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java b/src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java new file mode 100644 index 000000000..2bc2dcd24 --- /dev/null +++ b/src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java @@ -0,0 +1,21 @@ +package net.minestom.server.gamedata.tags; + +import net.minestom.server.utils.NamespaceID; + +public class RequiredTag { + private final Tag.BasicTypes type; + private final NamespaceID name; + + public RequiredTag(Tag.BasicTypes type, NamespaceID name) { + this.type = type; + this.name = name; + } + + public NamespaceID getName() { + return name; + } + + public Tag.BasicTypes getType() { + return type; + } +} diff --git a/src/main/java/net/minestom/server/gamedata/tags/Tag.java b/src/main/java/net/minestom/server/gamedata/tags/Tag.java index c95a2b677..8b052d92e 100644 --- a/src/main/java/net/minestom/server/gamedata/tags/Tag.java +++ b/src/main/java/net/minestom/server/gamedata/tags/Tag.java @@ -13,14 +13,16 @@ import java.util.Set; */ public class Tag { - public static final Tag EMPTY = new Tag(); + public static final Tag EMPTY = new Tag(NamespaceID.from("minestom:empty")); + private final NamespaceID name; private Set values; /** * Creates a new empty tag */ - public Tag() { + public Tag(NamespaceID name) { + this.name = name; values = new HashSet<>(); lockValues(); } @@ -32,7 +34,8 @@ public class Tag { * appends the contents of that pack to the one being constructed * @param container */ - public Tag(TagManager manager, String type, Tag lowerPriority, TagContainer container) throws FileNotFoundException { + public Tag(TagManager manager, NamespaceID name, String type, Tag lowerPriority, TagContainer container) throws FileNotFoundException { + this.name = name; values = new HashSet<>(); if(!container.replace) { values.addAll(lowerPriority.values); @@ -70,4 +73,19 @@ public class Tag { public Set getValues() { return values; } + + /** + * Returns the name of this tag + * @return + */ + public NamespaceID getName() { + return name; + } + + public enum BasicTypes { + BLOCKS, + ITEMS, + FLUIDS, + ENTITY_TYPES + } } diff --git a/src/main/java/net/minestom/server/gamedata/tags/TagManager.java b/src/main/java/net/minestom/server/gamedata/tags/TagManager.java index 28269854f..7c495f273 100644 --- a/src/main/java/net/minestom/server/gamedata/tags/TagManager.java +++ b/src/main/java/net/minestom/server/gamedata/tags/TagManager.java @@ -2,13 +2,17 @@ package net.minestom.server.gamedata.tags; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import net.minestom.server.network.packet.server.play.TagsPacket; import net.minestom.server.registry.ResourceGatherer; +import net.minestom.server.utils.BlockPosition; import net.minestom.server.utils.NamespaceID; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.*; import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; /** @@ -19,10 +23,14 @@ public class TagManager { private static final Logger LOGGER = LoggerFactory.getLogger(TagManager.class); private final Gson gson; private Map cache = new HashMap<>(); + private List requiredTags = new LinkedList<>(); public TagManager() { gson = new GsonBuilder() .create(); + + addRequiredTag(Tag.BasicTypes.FLUIDS, NamespaceID.from("lava")); + addRequiredTag(Tag.BasicTypes.FLUIDS, NamespaceID.from("water")); } /** @@ -57,7 +65,7 @@ public class TagManager { public Tag forceLoad(NamespaceID name, String tagType, ReaderSupplierWithFileNotFound readerSupplier) throws FileNotFoundException { Tag prev = cache.getOrDefault(name, Tag.EMPTY); FileNotFoundException[] ex = new FileNotFoundException[1]; // very ugly code but Java does not let its standard interfaces throw exceptions - Tag result = create(prev, tagType, readerSupplier); + Tag result = create(prev, name, tagType, readerSupplier); cache.put(name, result); return result; } @@ -74,7 +82,7 @@ public class TagManager { FileNotFoundException[] ex = new FileNotFoundException[1]; // very ugly code but Java does not let its standard interfaces throw exceptions Tag result = cache.computeIfAbsent(name, _name -> { try { - return create(prev, tagType, readerSupplier); + return create(prev, name, tagType, readerSupplier); } catch (FileNotFoundException e) { ex[0] = e; return Tag.EMPTY; @@ -86,16 +94,61 @@ public class TagManager { return result; } - private Tag create(Tag prev, String tagType, ReaderSupplierWithFileNotFound reader) throws FileNotFoundException { + private Tag create(Tag prev, NamespaceID name, String tagType, ReaderSupplierWithFileNotFound reader) throws FileNotFoundException { TagContainer container = gson.fromJson(reader.get(), TagContainer.class); try { - return new Tag(this, tagType, prev, container); + return new Tag(this, name, tagType, prev, container); } catch (FileNotFoundException e) { LOGGER.error("Failed to load tag due to error", e); return Tag.EMPTY; } } + /** + * Adds the required tags for the game to function correctly + * @param tags the packet to add the tags to + */ + public void addRequiredTagsToPacket(TagsPacket tags) { + for(RequiredTag requiredTag : requiredTags) { + Tag tag = silentLoad(requiredTag.getName(), requiredTag.getType().name().toLowerCase()); + switch (requiredTag.getType()) { + case BLOCKS: + tags.blockTags.add(tag); + break; + + case ITEMS: + tags.itemTags.add(tag); + break; + + case FLUIDS: + tags.fluidTags.add(tag); + break; + + case ENTITY_TYPES: + tags.entityTags.add(tag); + break; + } + } + } + + /** + * Adds a required tag to send to players when they connect + * @param type type of tag to send. Required so the client knows its use + * @param name the name of the tag to load + */ + public void addRequiredTag(Tag.BasicTypes type, NamespaceID name) { + requiredTags.add(new RequiredTag(type, name)); + } + + private Tag silentLoad(NamespaceID name, String type) { + try { + return load(name, type); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return Tag.EMPTY; + } + } + public interface ReaderSupplierWithFileNotFound { Reader get() throws FileNotFoundException; } diff --git a/src/main/java/net/minestom/server/network/packet/server/play/TagsPacket.java b/src/main/java/net/minestom/server/network/packet/server/play/TagsPacket.java new file mode 100644 index 000000000..080a47f61 --- /dev/null +++ b/src/main/java/net/minestom/server/network/packet/server/play/TagsPacket.java @@ -0,0 +1,50 @@ +package net.minestom.server.network.packet.server.play; + +import net.minestom.server.gamedata.tags.Tag; +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.registry.Registries; +import net.minestom.server.utils.NamespaceID; + +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +public class TagsPacket implements ServerPacket { + + public List blockTags = new LinkedList<>(); + public List itemTags = new LinkedList<>(); + public List fluidTags = new LinkedList<>(); + public List entityTags = new LinkedList<>(); + + @Override + public void write(PacketWriter writer) { + writeTags(writer, blockTags, name -> Registries.getBlock(name).ordinal()); + writeTags(writer, itemTags, name -> Registries.getMaterial(name).ordinal()); + writeTags(writer, fluidTags, name -> Registries.getFluid(name).ordinal()); + writeTags(writer, entityTags, name -> Registries.getEntityType(name).ordinal()); + } + + private void writeTags(PacketWriter writer, List tags, Function idSupplier) { + writer.writeVarInt(tags.size()); + for (Tag tag : tags) { + // name + writer.writeSizedString(tag.getName().toString()); + + Set values = tag.getValues(); + // count + writer.writeVarInt(values.size()); + // entries + for (NamespaceID name : values) { + writer.writeVarInt(idSupplier.apply(name)); + } + } + } + + @Override + public int getId() { + return ServerPacketIdentifier.TAGS; + } +} From 450603cac890e9c183e69b1d7ca0d274c6940048 Mon Sep 17 00:00:00 2001 From: jglrxavpok Date: Tue, 30 Jun 2020 21:06:06 +0200 Subject: [PATCH 6/6] Don't send tags packet to viewers --- src/main/java/net/minestom/server/entity/Player.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/minestom/server/entity/Player.java b/src/main/java/net/minestom/server/entity/Player.java index 64ba3264e..9edcce4cb 100644 --- a/src/main/java/net/minestom/server/entity/Player.java +++ b/src/main/java/net/minestom/server/entity/Player.java @@ -244,7 +244,7 @@ public class Player extends LivingEntity implements CommandSender { UpdateTagListEvent event = new UpdateTagListEvent(tags); callEvent(UpdateTagListEvent.class,event); - sendPacketToViewersAndSelf(tags); + getPlayerConnection().sendPacket(tags); // Some client update playerConnection.sendPacket(getPropertiesPacket()); // Send default properties