diff --git a/build.gradle b/build.gradle index 9392dc647..986c6a9c4 100644 --- a/build.gradle +++ b/build.gradle @@ -164,7 +164,7 @@ dependencies { } api "com.github.Minestom:DependencyGetter:v1.0.1" - implementation 'com.github.Minestom:MinestomDataGenerator:b13c934eba' + implementation 'com.github.Minestom:MinestomDataGenerator:7636d5d473' // Adventure, for user-interface api "net.kyori:adventure-api:$adventureVersion" diff --git a/code-generators/build.gradle b/code-generators/build.gradle index 675f41670..ec6adec11 100644 --- a/code-generators/build.gradle +++ b/code-generators/build.gradle @@ -25,7 +25,7 @@ dependencies { // SLF4J is the base logger for most libraries, therefore we can hook it into log4j2. implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.14.1' // Contains the json files - implementation 'com.github.Minestom:MinestomDataGenerator:b13c934eba' + implementation 'com.github.Minestom:MinestomDataGenerator:7636d5d473' } diff --git a/src/main/java/net/minestom/server/MinecraftServer.java b/src/main/java/net/minestom/server/MinecraftServer.java index f23b5dd38..a2981821b 100644 --- a/src/main/java/net/minestom/server/MinecraftServer.java +++ b/src/main/java/net/minestom/server/MinecraftServer.java @@ -28,7 +28,6 @@ import net.minestom.server.network.packet.server.play.ServerDifficultyPacket; import net.minestom.server.network.packet.server.play.UpdateViewDistancePacket; import net.minestom.server.ping.ResponseDataConsumer; import net.minestom.server.recipe.RecipeManager; -import net.minestom.server.registry.ResourceGatherer; import net.minestom.server.scoreboard.TeamManager; import net.minestom.server.storage.StorageLocation; import net.minestom.server.storage.StorageManager; @@ -46,8 +45,6 @@ import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.io.IOException; - /** * The main server class used to start the server and retrieve all the managers. *

@@ -176,13 +173,6 @@ public final class MinecraftServer { nettyServer = new NettyServer(packetProcessor); - // Registry - try { - ResourceGatherer.ensureResourcesArePresent(VERSION_NAME); - } catch (IOException e) { - LOGGER.error("An error happened during resource gathering. Minestom will attempt to load anyway, but things may not work, and crashes can happen.", e); - } - initialized = true; minecraftServer = new MinecraftServer(); diff --git a/src/main/java/net/minestom/server/gamedata/loottables/LootTableManager.java b/src/main/java/net/minestom/server/gamedata/loottables/LootTableManager.java index c96d10384..5a160f454 100644 --- a/src/main/java/net/minestom/server/gamedata/loottables/LootTableManager.java +++ b/src/main/java/net/minestom/server/gamedata/loottables/LootTableManager.java @@ -5,17 +5,17 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializer; import net.minestom.server.MinecraftServer; import net.minestom.server.gamedata.Condition; -import net.minestom.server.registry.ResourceGatherer; import net.minestom.server.utils.NamespaceID; import net.minestom.server.utils.NamespaceIDHashMap; -import java.io.*; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.Reader; /** * Handles loading and configuration of loot tables */ public final class LootTableManager { - private NamespaceIDHashMap> conditionDeserializers = new NamespaceIDHashMap<>(); private NamespaceIDHashMap tableTypes = new NamespaceIDHashMap<>(); private NamespaceIDHashMap entryTypes = new NamespaceIDHashMap<>(); @@ -71,7 +71,8 @@ public final class LootTableManager { } public LootTable load(NamespaceID name) throws FileNotFoundException { - return load(name, new FileReader(new File(ResourceGatherer.DATA_FOLDER, "data/" + name.getDomain() + "/loot_tables/" + name.getPath() + ".json"))); + return null; // FIXME + //return load(name, new FileReader(new File(ResourceGatherer.DATA_FOLDER, "data/" + name.getDomain() + "/loot_tables/" + name.getPath() + ".json"))); } /** diff --git a/src/main/java/net/minestom/server/gamedata/loottables/entries/TagType.java b/src/main/java/net/minestom/server/gamedata/loottables/entries/TagType.java index 6aad1f812..b804af71f 100644 --- a/src/main/java/net/minestom/server/gamedata/loottables/entries/TagType.java +++ b/src/main/java/net/minestom/server/gamedata/loottables/entries/TagType.java @@ -6,9 +6,8 @@ import net.minestom.server.gamedata.loottables.LootTable; 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.utils.NamespaceID; +import net.minestom.server.gamedata.tags.Tag; -import java.io.FileNotFoundException; import java.util.List; /** @@ -17,11 +16,6 @@ import java.util.List; public class TagType implements LootTableEntryType { @Override public LootTable.Entry create(LootTableManager lootTableManager, String name, List conditions, List children, boolean expand, List functions, int weight, int quality) { - try { - return new TagEntry(this, MinecraftServer.getTagManager().load(NamespaceID.from(name), "items"), expand, weight, quality, conditions); - } catch (FileNotFoundException e) { - MinecraftServer.getExceptionManager().handleException(e); - return null; - } + return new TagEntry(this, MinecraftServer.getTagManager().getTag(Tag.BasicType.ITEMS, name), expand, weight, quality, conditions); } } diff --git a/src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java b/src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java deleted file mode 100644 index 2bc2dcd24..000000000 --- a/src/main/java/net/minestom/server/gamedata/tags/RequiredTag.java +++ /dev/null @@ -1,21 +0,0 @@ -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 7649f7309..884e25bf9 100644 --- a/src/main/java/net/minestom/server/gamedata/tags/Tag.java +++ b/src/main/java/net/minestom/server/gamedata/tags/Tag.java @@ -1,32 +1,34 @@ package net.minestom.server.gamedata.tags; +import net.minestom.server.entity.EntityType; +import net.minestom.server.instance.block.Block; +import net.minestom.server.item.Material; +import net.minestom.server.registry.Registries; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.io.FileNotFoundException; +import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; +import java.util.function.Function; /** * Represents a group of items, blocks, fluids, entity types or function. * Immutable by design */ -public class Tag { - - public static final Tag EMPTY = new Tag(NamespaceID.from("minestom:empty")); +public final class Tag { private final NamespaceID name; - - private Set values; + private final Set values; /** * Creates a new empty tag. This does not cache the tag. */ public Tag(NamespaceID name) { this.name = name; - values = new HashSet<>(); - lockValues(); + this.values = new HashSet<>(); } /** @@ -35,42 +37,10 @@ public class Tag { public Tag(NamespaceID name, Set values) { this.name = name; this.values = new HashSet<>(values); - lockValues(); } /** - * Creates a new tag with the contents of the container - * - * @param manager Used to load tag contents (as tags are valid values inside 'values') - * @param lowerPriority Tag contents from lower priority data packs. If 'replace' is false in 'container', - * appends the contents of that pack to the one being constructed - * @param container - */ - 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); - } - Objects.requireNonNull(container.values, "Attempted to load from a TagContainer with no 'values' array"); - for (String line : container.values) { - if (line.startsWith("#")) { // pull contents from a tag - Tag subtag = manager.load(NamespaceID.from(line.substring(1)), type); - values.addAll(subtag.values); - } else { - values.add(NamespaceID.from(line)); - } - } - - lockValues(); - } - - private void lockValues() { - values = Set.copyOf(values); - } - - /** - * Checks whether the given id in inside this tag + * Checks whether the given id in inside this tag. * * @param id the id to check against * @return 'true' iif this tag contains the given id @@ -85,40 +55,55 @@ public class Tag { * @return immutable set of values present in this tag */ public Set getValues() { - return values; + return Collections.unmodifiableSet(values); } /** * Returns the name of this tag - * - * @return */ public NamespaceID getName() { return name; } - public enum BasicTypes { - BLOCKS("minecraft:block"), - ITEMS("minecraft:item"), - FLUIDS("minecraft:fluid"), - ENTITY_TYPES("minecraft:entity_type"), - GAME_EVENTS("minecraft:game_event"); + public enum BasicType { + BLOCKS("minecraft:block", Registry.Resource.BLOCK_TAGS, + name -> Objects.requireNonNull(Block.fromNamespaceId(name)).id()), + ITEMS("minecraft:item", Registry.Resource.ITEM_TAGS, + name -> Objects.requireNonNull(Material.fromNamespaceId(name)).id()), + FLUIDS("minecraft:fluid", Registry.Resource.FLUID_TAGS, + name -> 1), // TODO + ENTITY_TYPES("minecraft:entity_type", Registry.Resource.ENTITY_TYPE_TAGS, + name -> Objects.requireNonNull(EntityType.fromNamespaceId(name)).id()), + GAME_EVENTS("minecraft:game_event", Registry.Resource.GAMEPLAY_TAGS, + name -> Registries.getFluid(name).ordinal()); - private final static BasicTypes[] VALUES = values(); + private final static BasicType[] VALUES = values(); private final String identifier; + private final Registry.Resource resource; + private final Function function; - BasicTypes(@NotNull String identifier) { + BasicType(@NotNull String identifier, + @NotNull Registry.Resource resource, + @NotNull Function function) { this.identifier = identifier; + this.resource = resource; + this.function = function; } - @NotNull - public String getIdentifier() { + public @NotNull String getIdentifier() { return identifier; } - @Nullable - public static BasicTypes fromIdentifer(@NotNull String identifier) { - for (BasicTypes value : VALUES) { + public Registry.Resource getResource() { + return resource; + } + + public Function getFunction() { + return function; + } + + public static @Nullable Tag.BasicType fromIdentifer(@NotNull String identifier) { + for (BasicType value : VALUES) { if (value.identifier.equals(identifier)) { return value; } diff --git a/src/main/java/net/minestom/server/gamedata/tags/TagContainer.java b/src/main/java/net/minestom/server/gamedata/tags/TagContainer.java deleted file mode 100644 index 7f181851a..000000000 --- a/src/main/java/net/minestom/server/gamedata/tags/TagContainer.java +++ /dev/null @@ -1,9 +0,0 @@ -package net.minestom.server.gamedata.tags; - -/** - * Meant only for parsing tag JSON - */ -public class TagContainer { - boolean replace; - String[] values; -} 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 30e46a0c9..c8805f8c3 100644 --- a/src/main/java/net/minestom/server/gamedata/tags/TagManager.java +++ b/src/main/java/net/minestom/server/gamedata/tags/TagManager.java @@ -1,340 +1,57 @@ package net.minestom.server.gamedata.tags; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import net.minestom.server.MinecraftServer; -import net.minestom.server.network.packet.server.play.TagsPacket; -import net.minestom.server.registry.ResourceGatherer; +import com.google.gson.JsonObject; +import net.minestom.server.registry.Registry; import net.minestom.server.utils.NamespaceID; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import org.jetbrains.annotations.Nullable; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.Reader; -import java.util.ArrayList; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; /** * Handles loading and caching of tags. */ -public class TagManager { - - private static final Logger LOGGER = LoggerFactory.getLogger(TagManager.class); - private final Gson gson; - private final Map cache = new ConcurrentHashMap<>(); - private final List requiredTags = new LinkedList<>(); +public final class TagManager { + private final Map> tagMap = new ConcurrentHashMap<>(); public TagManager() { - gson = new GsonBuilder() - .create(); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("acacia_logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("anvil")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("bamboo_plantable_on")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("banners")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("base_stone_nether")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("base_stone_overworld")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("beacon_base_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("beds")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("beehives")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("bee_growables")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("birch_logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("buttons")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("campfires")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("candles")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("candle_cakes")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("carpets")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("cauldrons")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("cave_vines")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("climbable")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("coal_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("copper_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("corals")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("coral_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("coral_plants")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("crimson_stems")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("crops")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("crystal_sound_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("dark_oak_logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("deepslate_ore_replaceables")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("diamond_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("dirt")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("doors")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("dragon_immune")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("dripstone_replaceable_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("emerald_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("enderman_holdable")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("features_cannot_replace")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("fences")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("fence_gates")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("fire")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("flowers")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("flower_pots")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("geode_invalid_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("gold_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("guarded_by_piglins")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("hoglin_repellents")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("ice")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("impermeable")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("infiniburn_end")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("infiniburn_nether")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("infiniburn_overworld")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("inside_step_sound_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("iron_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("jungle_logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("lapis_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("lava_pool_stone_replaceables")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("leaves")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("logs_that_burn")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("lush_ground_replaceable")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("moss_replaceable")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("mushroom_grow_block")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("needs_diamond_tool")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("needs_iron_tool")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("needs_stone_tool")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("non_flammable_wood")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("nylium")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("oak_logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("occludes_vibration_signals")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("piglin_repellents")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("planks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("portals")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("pressure_plates")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("prevent_mob_spawning_inside")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("rails")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("redstone_ores")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("sand")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("saplings")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("shulker_boxes")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("signs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("slabs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("small_dripleaf_placeable")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("small_flowers")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("snow")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("soul_fire_base_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("soul_speed_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("spruce_logs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("stairs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("standing_signs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("stone_bricks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("stone_ore_replaceables")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("stone_pressure_plates")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("strider_warm_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("tall_flowers")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("trapdoors")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("underwater_bonemeals")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("unstable_bottom_center")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("valid_spawn")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("walls")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wall_corals")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wall_post_override")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wall_signs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("warped_stems")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wart_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wither_immune")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wither_summon_base_blocks")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_buttons")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_doors")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_fences")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_pressure_plates")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_slabs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_stairs")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wooden_trapdoors")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("wool")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("mineable/axe")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("mineable/hoe")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("mineable/pickaxe")); - addRequiredTag(Tag.BasicTypes.BLOCKS, NamespaceID.from("mineable/shovel")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("arrows")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("axolotl_always_hostiles")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("axolotl_hunt_targets")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("beehive_inhabitors")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("freeze_hurts_extra_types")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("freeze_immune_entity_types")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("impact_projectiles")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("powder_snow_walkable_mobs")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("raiders")); - addRequiredTag(Tag.BasicTypes.ENTITY_TYPES, NamespaceID.from("skeletons")); - addRequiredTag(Tag.BasicTypes.FLUIDS, NamespaceID.from("lava")); - addRequiredTag(Tag.BasicTypes.FLUIDS, NamespaceID.from("water")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("acacia_logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("anvil")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("arrows")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("axolotl_tempt_items")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("banners")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("beacon_payment_items")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("beds")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("birch_logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("boats")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("buttons")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("candles")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("carpets")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("cluster_max_harvestables")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("coals")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("coal_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("copper_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("creeper_drop_music_discs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("crimson_stems")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("dark_oak_logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("diamond_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("doors")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("emerald_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("fences")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("fishes")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("flowers")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("fox_food")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("freeze_immune_wearables")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("gold_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("ignored_by_piglin_babies")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("iron_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("jungle_logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("lapis_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("leaves")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("lectern_books")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("logs_that_burn")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("music_discs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("non_flammable_wood")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("oak_logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("occludes_vibration_signals"));; - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("piglin_food")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("piglin_loved")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("piglin_repellents")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("planks")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("rails")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("redstone_ores")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("sand")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("saplings")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("signs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("slabs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("small_flowers")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("soul_fire_base_blocks")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("spruce_logs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("stairs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("stone_bricks")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("stone_crafting_materials")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("stone_tool_materials")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("tall_flowers")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("trapdoors")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("walls")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("warped_stems")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_buttons")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_doors")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_fences")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_pressure_plates")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_slabs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_stairs")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wooden_trapdoors")); - addRequiredTag(Tag.BasicTypes.ITEMS, NamespaceID.from("wool")); - addRequiredTag(Tag.BasicTypes.GAME_EVENTS, NamespaceID.from("ignore_vibrations_sneaking")); - addRequiredTag(Tag.BasicTypes.GAME_EVENTS, NamespaceID.from("vibrations")); + // Load required tags from files + for (var type : Tag.BasicType.values()) { + final var json = Registry.load(type.getResource()); + final var tagIdentifierMap = tagMap.computeIfAbsent(type, s -> new CopyOnWriteArrayList<>()); + json.keySet().forEach(tagName -> { + final var tag = new Tag(NamespaceID.from(tagName), getValues(json, tagName)); + tagIdentifierMap.add(tag); + }); + } } - /** - * Loads a tag with the given name. This method attempts to read from "data/<name.domain>/tags/<tagType>/<name.path>.json" if the given name is not already present in cache - * - * @param name - * @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants) - * @return - * @throws FileNotFoundException if the file does not exist - */ - public Tag load(NamespaceID name, String tagType) throws FileNotFoundException { - return load(name, tagType, () -> new FileReader(new File(ResourceGatherer.DATA_FOLDER, "data/" + name.getDomain() + "/tags/" + tagType + "/" + name.getPath() + ".json"))); + public @Nullable Tag getTag(Tag.BasicType type, String namespace) { + final var tags = tagMap.get(type); + for (var tag : tags) { + if (tag.getName().asString().equals(namespace)) + return tag; + } + return null; } - /** - * Loads a tag with the given name. This method attempts to read from 'reader' if the given name is not already present in cache - * - * @param name - * @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants) - * @param reader - * @return - */ - public Tag load(NamespaceID name, String tagType, Reader reader) throws FileNotFoundException { - return load(name, tagType, () -> reader); + public Map> getTagMap() { + return Collections.unmodifiableMap(tagMap); } - /** - * Loads a tag with the given name. This method reads from 'reader'. This will override the previous tag - * - * @param name - * @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants) - * @param readerSupplier - * @return - */ - public Tag forceLoad(NamespaceID name, String tagType, ReaderSupplierWithFileNotFound readerSupplier) throws FileNotFoundException { - Tag prev = cache.getOrDefault(name, Tag.EMPTY); - Tag result = create(prev, name, tagType, readerSupplier); - cache.put(name, result); + private Set getValues(JsonObject main, String value) { + JsonObject tagObject = main.getAsJsonObject(value); + final var tagValues = tagObject.getAsJsonArray("values"); + Set result = new HashSet<>(tagValues.size()); + tagValues.forEach(jsonElement -> { + final String tagString = jsonElement.getAsString(); + if (tagString.startsWith("#")) { + result.addAll(getValues(main, tagString.substring(1))); + } else { + result.add(NamespaceID.from(tagString)); + } + }); return result; } - - /** - * Loads a tag with the given name. This method attempts to read from 'reader' if the given name is not already present in cache - * - * @param name - * @param tagType the type of the tag to load, used to resolve paths (blocks, items, entity_types, fluids, functions are the vanilla variants) - * @param readerSupplier - * @return - */ - public Tag load(NamespaceID name, String tagType, ReaderSupplierWithFileNotFound readerSupplier) throws FileNotFoundException { - Tag prev = cache.getOrDefault(name, Tag.EMPTY); - Tag result = cache.get(name); - if (result == null) { - result = create(prev, name, tagType, readerSupplier); - cache.put(name, result); - } - return result; - } - - 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, 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 tagsPacket the packet to add the tags to - */ - public void addRequiredTagsToPacket(TagsPacket tagsPacket) { - for (RequiredTag requiredTag : requiredTags) { - final Tag tag = silentLoad(requiredTag.getName(), requiredTag.getType().name().toLowerCase()); - var map = tagsPacket.tagsMap.computeIfAbsent(requiredTag.getType(), s -> new ArrayList<>()); - map.add(tag); - } - } - - /** - * 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) { - MinecraftServer.getExceptionManager().handleException(e); - 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 index 14b9bb6a3..823eccf2a 100644 --- 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 @@ -1,34 +1,28 @@ package net.minestom.server.network.packet.server.play; import net.minestom.server.MinecraftServer; -import net.minestom.server.entity.EntityType; import net.minestom.server.gamedata.tags.Tag; -import net.minestom.server.instance.block.Block; -import net.minestom.server.item.Material; 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 net.minestom.server.utils.binary.BinaryReader; import net.minestom.server.utils.binary.BinaryWriter; import org.jetbrains.annotations.NotNull; -import java.util.*; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class TagsPacket implements ServerPacket { + private static final TagsPacket REQUIRED_TAGS_PACKET = new TagsPacket(MinecraftServer.getTagManager().getTagMap()); - private static final TagsPacket REQUIRED_TAGS_PACKET = new TagsPacket(); + public Map> tagsMap; - static { - MinecraftServer.getTagManager().addRequiredTagsToPacket(REQUIRED_TAGS_PACKET); + public TagsPacket(Map> tagsMap) { + this.tagsMap = tagsMap; } - public Map> tagsMap = new HashMap<>(); - - /** - * Default constructor, required for reflection operations. - */ public TagsPacket() { + this(new HashMap<>()); } @Override @@ -37,105 +31,14 @@ public class TagsPacket implements ServerPacket { for (var entry : tagsMap.entrySet()) { final var type = entry.getKey(); final var tags = entry.getValue(); - // Tag type writer.writeSizedString(type.getIdentifier()); - switch (type) { - case BLOCKS: { - // Number of tags - writer.writeVarInt(tags.size()); - for (Tag tag : tags) { - // name - writer.writeSizedString(tag.getName().toString()); - final Set values = tag.getValues(); - // count - writer.writeVarInt(values.size()); - // entries - for (NamespaceID name : values) { - Block b = Block.fromNamespaceId(name); - if (b == null) { - writer.writeVarInt(-1); - continue; - } - writer.writeVarInt(b.id()); - } - } - break; - } - case ENTITY_TYPES: { - // Number of tags - writer.writeVarInt(tags.size()); - for (Tag tag : tags) { - // name - writer.writeSizedString(tag.getName().toString()); - - final Set values = tag.getValues(); - // count - writer.writeVarInt(values.size()); - // entries - for (NamespaceID name : values) { - EntityType et = EntityType.fromNamespaceId(name); - if (et == null) { - writer.writeVarInt(-1); - } else { - writer.writeVarInt(et.id()); - } - } - } - break; - } - case FLUIDS: { - // Number of tags - writer.writeVarInt(tags.size()); - for (Tag tag : tags) { - // name - writer.writeSizedString(tag.getName().toString()); - - final Set values = tag.getValues(); - // count - writer.writeVarInt(values.size()); - // entries - for (NamespaceID name : values) { - writer.writeVarInt(Registries.getFluid(name).ordinal()); - } - } - break; - } - case GAME_EVENTS: { - // Number of tags - writer.writeVarInt(tags.size()); - for (Tag tag : tags) { - // name - writer.writeSizedString(tag.getName().toString()); - - final Set values = tag.getValues(); - // count - writer.writeVarInt(values.size()); - // entries - for (NamespaceID name : values) { - // TODO: GameEvents - writer.writeVarInt(-1); - } - } - break; - } - case ITEMS: { - // Number of tags - writer.writeVarInt(tags.size()); - for (Tag tag : tags) { - // name - writer.writeSizedString(tag.getName().toString()); - - final Set values = tag.getValues(); - // count - writer.writeVarInt(values.size()); - // entries - for (NamespaceID name : values) { - // FIXME: invalid namespace - final var material = Objects.requireNonNullElse(Material.fromNamespaceId(name), Material.AIR); - writer.writeVarInt(material.id()); - } - } - break; + writer.writeVarInt(tags.size()); + for (var tag : tags) { + writer.writeSizedString(tag.getName().asString()); + final var values = tag.getValues(); + writer.writeVarInt(values.size()); + for (var name : values) { + writer.writeVarInt(type.getFunction().apply(name.asString())); } } } @@ -148,7 +51,7 @@ public class TagsPacket implements ServerPacket { final int typeCount = reader.readVarInt(); for (int i = 0; i < typeCount; i++) { // Read tag type - final Tag.BasicTypes tagType = Tag.BasicTypes.fromIdentifer(reader.readSizedString()); + final Tag.BasicType tagType = Tag.BasicType.fromIdentifer(reader.readSizedString()); if (tagType == null) { throw new IllegalArgumentException("Tag type could not be resolved"); } @@ -173,8 +76,7 @@ public class TagsPacket implements ServerPacket { * * @return the default tags packet */ - @NotNull - public static TagsPacket getRequiredTagsPacket() { + public static @NotNull TagsPacket getRequiredTagsPacket() { return REQUIRED_TAGS_PACKET; } } diff --git a/src/main/java/net/minestom/server/registry/Registry.java b/src/main/java/net/minestom/server/registry/Registry.java index 2fc18266e..488ad880a 100644 --- a/src/main/java/net/minestom/server/registry/Registry.java +++ b/src/main/java/net/minestom/server/registry/Registry.java @@ -56,7 +56,13 @@ public class Registry { STATISTICS("custom_statistics"), POTION_EFFECTS("potion_effects"), POTION_TYPES("potions"), - PARTICLES("particles"); + PARTICLES("particles"), + + BLOCK_TAGS("tags/block_tags"), + ENTITY_TYPE_TAGS("tags/entity_type_tags"), + FLUID_TAGS("tags/fluid_tags"), + GAMEPLAY_TAGS("tags/gameplay_tags"), + ITEM_TAGS("tags/item_tags"); private final String name; diff --git a/src/main/java/net/minestom/server/registry/ResourceGatherer.java b/src/main/java/net/minestom/server/registry/ResourceGatherer.java deleted file mode 100644 index 307cd0ce7..000000000 --- a/src/main/java/net/minestom/server/registry/ResourceGatherer.java +++ /dev/null @@ -1,216 +0,0 @@ -package net.minestom.server.registry; - -import com.google.gson.Gson; -import com.google.gson.JsonArray; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import it.unimi.dsi.fastutil.io.FastBufferedInputStream; -import net.minestom.server.utils.StringUtils; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URL; -import java.nio.file.FileVisitResult; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; -import java.nio.file.attribute.BasicFileAttributes; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -/** - * Responsible for making sure Minestom has the necessary files to run (notably registry files) - */ -public class ResourceGatherer { - public static final File DATA_FOLDER = new File("./minecraft_data/"); - private static final Gson GSON = new Gson(); - private static final Logger LOGGER = LoggerFactory.getLogger(ResourceGatherer.class); - private static final File TMP_FOLDER = new File("./.minestom_tmp/"); - - /** - * Checks if registry/ folder is present - * If it is not, download the minecraft server jar, run the data generator and extract the wanted files - * If it is already present, directly return - */ - public static void ensureResourcesArePresent(String version) throws IOException { - if (DATA_FOLDER.exists()) { - return; - } - LOGGER.info("{} folder does not exist. Minestom will now generate the necessary files.", DATA_FOLDER); - - if (!TMP_FOLDER.exists() && !TMP_FOLDER.mkdirs()) { - throw new IOException("Failed to create tmp folder."); - } - - LOGGER.info("Starting download of Minecraft server jar for version {} from Mojang servers...", version); - File serverJar = downloadServerJar(version); - LOGGER.info("Download complete."); - - runDataGenerator(serverJar); - - moveAndCleanup(version); - LOGGER.info("Resource gathering done!"); - } - - private static void moveAndCleanup(String version) throws IOException { - Path dataFolderPath = DATA_FOLDER.toPath(); - Path tmpFolderPath = TMP_FOLDER.toPath(); - Path generatedFolder = tmpFolderPath.resolve("generated"); - LOGGER.info("Data generator successful, removing server jar"); - Files.delete(tmpFolderPath.resolve("server_" + version + ".jar")); - LOGGER.info("Removal successful, now moving data to {}", DATA_FOLDER); - Files.walkFileTree(tmpFolderPath, new SimpleFileVisitor<>() { - - @Override - public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { - Path relativePath = generatedFolder.relativize(dir); - if (dir.startsWith(generatedFolder)) { // don't copy logs - Path resolvedPath = dataFolderPath.resolve(relativePath); - LOGGER.info("> Creating sub-folder {}", resolvedPath); - Files.createDirectories(resolvedPath); - } - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { - LOGGER.info("> Deleting folder {}", dir); - Files.delete(dir); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Path relativePath = generatedFolder.relativize(file); - if (file.startsWith(generatedFolder)) { // don't copy logs - Path resolvedPath = dataFolderPath.resolve(relativePath); - LOGGER.info("> Moving {}", relativePath); - Files.move(file, resolvedPath); - } else { - LOGGER.info("> Deleting {}", relativePath); - Files.delete(file); - } - return FileVisitResult.CONTINUE; - } - }); - } - - private static void runDataGenerator(File serverJar) throws IOException { - final String javaExecutable = System.getProperty("java.home") + "/bin/java"; - ProcessBuilder dataGenerator = new ProcessBuilder(javaExecutable, "-cp", serverJar.getName(), "net.minecraft.data.Main", "--all", "--server", "--dev"); - dataGenerator.directory(TMP_FOLDER); - LOGGER.info("Now running data generator with options '--dev', '--server', '--all'"); - LOGGER.info("Executing: {}", String.join(StringUtils.SPACE, dataGenerator.command())); - LOGGER.info("Minestom will now wait for it to finish, here's its output:"); - LOGGER.info(""); - Process dataGeneratorProcess = dataGenerator.start(); - new BufferedReader( - new InputStreamReader(dataGeneratorProcess.getInputStream()) - ).lines().forEach(LOGGER::info); - new BufferedReader( - new InputStreamReader(dataGeneratorProcess.getErrorStream()) - ).lines().forEach(LOGGER::error); - LOGGER.info(""); - - try { - int resultCode = dataGeneratorProcess.waitFor(); - if (resultCode != 0) { - throw new IOException("Data generator finished with non-zero return code " + resultCode + " verify that you have 'java' cli"); - } - } catch (InterruptedException e) { - throw new IOException("Data generator was interrupted.", e); - } - } - - private static File downloadServerJar(String version) throws IOException { - // Mojang's version manifest is located at https://launchermeta.mojang.com/mc/game/version_manifest.json - // If we query this (it's a json object), we can then search for the id we want. - InputStream versionManifestStream = new URL("https://launchermeta.mojang.com/mc/game/version_manifest.json").openStream(); - LOGGER.debug("Successfully queried Mojang's version_manifest.json."); - - JsonObject versionManifestJson = GSON.fromJson(new InputStreamReader(versionManifestStream), JsonObject.class); - LOGGER.debug("Successfully read Mojang's version_manifest.json into a json object."); - - JsonArray versionArray = versionManifestJson.getAsJsonArray("versions"); - LOGGER.debug("Iterating over the version manifest to find a version with the id {}.", version); - - JsonObject versionEntry = null; - for (JsonElement element : versionArray) { - if (element.isJsonObject()) { - JsonObject entry = element.getAsJsonObject(); - if (entry.get("id").getAsString().equals(version)) { - LOGGER.debug("Successfully found a version with the id {}.", version); - versionEntry = entry; - break; - } - } - } - if (versionEntry == null) { - throw new IOException("Could not find " + version + " in Mojang's official list of minecraft versions."); - } - // We now have the entry we want and it gives us access to the json file containing the downloads. - String versionUrl = versionEntry.get("url").getAsString(); - InputStream versionStream = new URL(versionUrl).openStream(); - LOGGER.debug("Successfully queried {}.json.", version); - - JsonObject versionJson = GSON.fromJson(new InputStreamReader(versionStream), JsonObject.class); - LOGGER.debug("Successfully read {}.json into a json object.", version); - - // Now we need to navigate to "downloads.client.url" and "downloads.server.url" } - JsonObject downloadsJson = versionJson.getAsJsonObject("downloads"); - - // Designated spot if we ever need the client. - - // Server - { - JsonObject serverJson = downloadsJson.getAsJsonObject("server"); - final String jarURL = serverJson.get("url").getAsString(); - final String sha1 = serverJson.get("sha1").getAsString(); - - LOGGER.debug("Found all information required to download the server JAR file."); - LOGGER.debug("Attempting download."); - return download(version, jarURL, sha1); - } - } - - private static File download(@NotNull String version, @NotNull String url, @NotNull String sha1Source) throws IOException { - File target = new File(TMP_FOLDER, "server_" + version + ".jar"); - // Download - try (FastBufferedInputStream in = new FastBufferedInputStream(new URL(url).openStream())) { - Files.copy(in, target.toPath(), StandardCopyOption.REPLACE_EXISTING); - } catch (IOException e) { - throw new IOException("Failed to download Minecraft server jar.", e); - } - // Verify checksum - try (FileInputStream fis = new FileInputStream(target)) { - MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); - messageDigest.reset(); - messageDigest.update(fis.readAllBytes()); - byte[] digest = messageDigest.digest(); - StringBuffer sb = new StringBuffer(); - for (byte b : digest) { - sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); - } - // This just converts the sha1 back into a readable string. - String sha1Target = sb.toString(); - if (!sha1Target.equals(sha1Source)) { - LOGGER.error("The checksum test failed after downloading the Minecraft server jar."); - LOGGER.error("The expected checksum was: {}.", sha1Source); - LOGGER.error("The calculated checksum was: {}.", sha1Target); - throw new IOException("Failed to download Minecraft server jar."); - } - } catch (NoSuchAlgorithmException e) { - LOGGER.error("Failed to find SHA-1 hashing algorithm in Java Environment."); - throw new IOException("Failed to download Minecraft server jar."); - } - return target; - } -} diff --git a/src/test/java/loottables/TestLootTables.java b/src/test/java/loottables/TestLootTables.java index 45bc350e9..d84a8f714 100644 --- a/src/test/java/loottables/TestLootTables.java +++ b/src/test/java/loottables/TestLootTables.java @@ -1,6 +1,5 @@ package loottables; -import net.minestom.server.MinecraftServer; import net.minestom.server.data.Data; import net.minestom.server.data.DataImpl; import net.minestom.server.gamedata.conditions.SurvivesExplosionCondition; @@ -11,14 +10,12 @@ import net.minestom.server.gamedata.loottables.entries.ItemType; import net.minestom.server.gamedata.loottables.tabletypes.BlockType; import net.minestom.server.item.ItemStack; import net.minestom.server.item.Material; -import net.minestom.server.registry.ResourceGatherer; import net.minestom.server.utils.NamespaceID; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; -import java.io.IOException; import java.io.StringReader; import java.util.List; @@ -28,12 +25,6 @@ public class TestLootTables { @BeforeEach public void init() { - try { - ResourceGatherer.ensureResourcesArePresent(MinecraftServer.VERSION_NAME); - } catch (IOException e) { - e.printStackTrace(); - } - tableManager = new LootTableManager(); tableManager.registerConditionDeserializer(NamespaceID.from("minecraft:survives_explosion"), new SurvivesExplosionCondition.Deserializer()); tableManager.registerTableType(NamespaceID.from("minecraft:block"), new BlockType()); diff --git a/src/test/java/tags/TestTags.java b/src/test/java/tags/TestTags.java deleted file mode 100644 index 94da727cb..000000000 --- a/src/test/java/tags/TestTags.java +++ /dev/null @@ -1,104 +0,0 @@ -package tags; - -import net.minestom.server.gamedata.tags.Tag; -import net.minestom.server.gamedata.tags.TagManager; -import net.minestom.server.utils.NamespaceID; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.io.FileNotFoundException; -import java.io.StringReader; - -public class TestTags { - - private TagManager tags; - - @BeforeEach - public void init() { - tags = new TagManager(); - } - - @Test - public void testSubTag() throws FileNotFoundException { - String tag1 = "{\n" + - "\t\"replace\": false,\n" + - "\t\"values\": [\n" + - "\t\t\"minestom:an_item\"\n" + - "\t]\n" + - "}"; - - String tag2 = "{\n" + - "\t\"replace\": false,\n" + - "\t\"values\": [\n" + - "\t\t\"#minestom:test_sub\",\n" + - "\t\t\"minestom:some_other_item\"\n" + - "\t]\n" + - "}"; - Assertions.assertNotEquals(Tag.EMPTY, tags.load(NamespaceID.from("minestom:test_sub"), "any", new StringReader(tag1))); - Tag loaded = tags.load(NamespaceID.from("minestom:test"), "any", new StringReader(tag2)); - NamespaceID[] values = loaded.getValues().toArray(new NamespaceID[0]); - Assertions.assertEquals(2, values.length); - Assertions.assertTrue(loaded.contains(NamespaceID.from("minestom:an_item"))); - Assertions.assertTrue(loaded.contains(NamespaceID.from("minestom:some_other_item"))); - Assertions.assertFalse(loaded.contains(NamespaceID.from("minestom:some_other_item_that_is_not_in_the_tag"))); - } - - /** - * A value of 'true' in 'replace' should replace previous contents - */ - @Test - public void testReplacement() throws FileNotFoundException { - String tag1 = "{\n" + - "\t\"replace\": false,\n" + - "\t\"values\": [\n" + - "\t\t\"minestom:an_item\"\n" + - "\t]\n" + - "}"; - - String tag2 = "{\n" + - "\t\"replace\": true,\n" + - "\t\"values\": [\n" + - "\t\t\"minestom:some_other_item\"\n" + - "\t]\n" + - "}"; - Assertions.assertNotEquals(Tag.EMPTY, tags.load(NamespaceID.from("minestom:test"), "any", new StringReader(tag1))); - Tag loaded = tags.forceLoad(NamespaceID.from("minestom:test"), "any", () -> new StringReader(tag2)); - Assertions.assertNotEquals(Tag.EMPTY, loaded); - Assertions.assertEquals(1, loaded.getValues().size()); - Assertions.assertTrue(loaded.contains(NamespaceID.from("minestom:some_other_item"))); - Assertions.assertFalse(loaded.contains(NamespaceID.from("minestom:an_item"))); - } - - /** - * A value of 'false' in 'replace' should append to previous contents - */ - @Test - public void testAppend() throws FileNotFoundException { - String tag1 = "{\n" + - "\t\"replace\": false,\n" + - "\t\"values\": [\n" + - "\t\t\"minestom:an_item\"\n" + - "\t]\n" + - "}"; - - String tag2 = "{\n" + - "\t\"replace\": false,\n" + - "\t\"values\": [\n" + - "\t\t\"minestom:some_other_item\"\n" + - "\t]\n" + - "}"; - Assertions.assertNotEquals(Tag.EMPTY, tags.load(NamespaceID.from("minestom:test"), "any", new StringReader(tag1))); - Tag loaded = tags.forceLoad(NamespaceID.from("minestom:test"), "any", () -> new StringReader(tag2)); - Assertions.assertNotEquals(Tag.EMPTY, loaded); - Assertions.assertEquals(2, loaded.getValues().size()); - Assertions.assertTrue(loaded.contains(NamespaceID.from("minestom:some_other_item"))); - Assertions.assertTrue(loaded.contains(NamespaceID.from("minestom:an_item"))); - } - - @AfterEach - public void cleanup() { - tags = null; - } -}