diff --git a/src/main/java/ru/bclib/api/TagAPI.java b/src/main/java/ru/bclib/api/TagAPI.java index 46d9adff..3d108372 100644 --- a/src/main/java/ru/bclib/api/TagAPI.java +++ b/src/main/java/ru/bclib/api/TagAPI.java @@ -20,7 +20,9 @@ import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import ru.bclib.BCLib; +import java.util.List; import java.util.Map; +import java.util.Random; import java.util.Set; import java.util.function.Supplier; @@ -29,60 +31,60 @@ public class TagAPI { private static final Map> TAGS_ITEM = Maps.newConcurrentMap(); // Vanilla Block Tags - public static final ResourceLocation NAMED_SOUL_SPEED_BLOCKS = new ResourceLocation("soul_speed_blocks"); - public static final ResourceLocation NAMED_SOUL_FIRE_BASE_BLOCKS = new ResourceLocation("soul_fire_base_blocks"); - public static final ResourceLocation NAMED_CLIMBABLE = new ResourceLocation("climbable"); - public static final ResourceLocation NAMED_NYLIUM = new ResourceLocation("nylium"); - public static final ResourceLocation NAMED_ANVIL = new ResourceLocation("anvil"); - public static final ResourceLocation NAMED_WALLS = new ResourceLocation("walls"); - public static final ResourceLocation LEAVES = new ResourceLocation("leaves"); - public static final ResourceLocation NAMED_MINEABLE_AXE = new ResourceLocation("mineable/axe"); - public static final ResourceLocation NAMED_MINEABLE_PICKAXE = new ResourceLocation("mineable/pickaxe"); - public static final ResourceLocation NAMED_MINEABLE_SHOVEL = new ResourceLocation("mineable/shovel"); - public static final ResourceLocation NAMED_MINEABLE_HOE = new ResourceLocation("mineable/hoe"); + public static final TagLocation NAMED_SOUL_SPEED_BLOCKS = new TagLocation<>("soul_speed_blocks"); + public static final TagLocation NAMED_SOUL_FIRE_BASE_BLOCKS = new TagLocation<>("soul_fire_base_blocks"); + public static final TagLocation NAMED_CLIMBABLE = new TagLocation<>("climbable"); + public static final TagLocation NAMED_NYLIUM = new TagLocation<>("nylium"); + public static final TagLocation NAMED_ANVIL = new TagLocation<>("anvil"); + public static final TagLocation NAMED_WALLS = new TagLocation<>("walls"); + public static final TagLocation LEAVES = new TagLocation<>("leaves"); + public static final TagLocation NAMED_MINEABLE_AXE = new TagLocation<>("mineable/axe"); + public static final TagLocation NAMED_MINEABLE_PICKAXE = new TagLocation<>("mineable/pickaxe"); + public static final TagLocation NAMED_MINEABLE_SHOVEL = new TagLocation<>("mineable/shovel"); + public static final TagLocation NAMED_MINEABLE_HOE = new TagLocation<>("mineable/hoe"); // Block Tags - public static final Tag.Named BLOCK_BOOKSHELVES = makeCommonBlockTag("bookshelves"); - public static final Tag.Named BLOCK_GEN_TERRAIN = makeBlockTag(BCLib.MOD_ID, "gen_terrain"); - public static final Tag.Named BLOCK_NETHER_GROUND = makeBlockTag(BCLib.MOD_ID, "nether_ground"); - public static final Tag.Named BLOCK_END_GROUND = makeBlockTag(BCLib.MOD_ID, "end_ground"); + public static final TagNamed BLOCK_BOOKSHELVES = makeCommonBlockTag("bookshelves"); + public static final TagNamed BLOCK_GEN_TERRAIN = makeBlockTag(BCLib.MOD_ID, "gen_terrain"); + public static final TagNamed BLOCK_NETHER_GROUND = makeBlockTag(BCLib.MOD_ID, "nether_ground"); + public static final TagNamed BLOCK_END_GROUND = makeBlockTag(BCLib.MOD_ID, "end_ground"); - public static final Tag.Named BLOCK_CHEST = makeCommonBlockTag("chest"); - public static final Tag.Named BLOCK_WOODEN_CHEST = makeCommonBlockTag("wooden_chests"); - public static final Tag.Named BLOCK_BARREL = makeCommonBlockTag("barrel"); - public static final Tag.Named BLOCK_WOODEN_BARREL = makeCommonBlockTag("wooden_barrels"); - public static final Tag.Named BLOCK_END_STONES = makeCommonBlockTag("end_stones"); - public static final Tag.Named BLOCK_NETHER_STONES = makeCommonBlockTag("nether_stones"); - public static final Tag.Named BLOCK_NETHER_PORTAL_FRAME = makeCommonBlockTag("nether_pframe"); - public static final Tag.Named BLOCK_WORKBENCHES = makeCommonBlockTag("workbench"); - public static final Tag.Named BLOCK_SAPLINGS = makeCommonBlockTag("saplings"); - public static final Tag.Named BLOCK_LEAVES = makeCommonBlockTag("leaves"); - public static final Tag.Named BLOCK_IMMOBILE = makeCommonBlockTag("immobile"); - public static final Tag.Named BLOCK_SOUL_GROUND = makeCommonBlockTag("soul_ground"); - public static final Tag.Named BLOCK_NETHERRACK = makeCommonBlockTag("netherrack"); - public static final Tag.Named BLOCK_NETHER_MYCELIUM = makeCommonBlockTag("nether_mycelium"); + public static final TagNamed BLOCK_CHEST = makeCommonBlockTag("chest"); + public static final TagNamed BLOCK_WOODEN_CHEST = makeCommonBlockTag("wooden_chests"); + public static final TagNamed BLOCK_BARREL = makeCommonBlockTag("barrel"); + public static final TagNamed BLOCK_WOODEN_BARREL = makeCommonBlockTag("wooden_barrels"); + public static final TagNamed BLOCK_END_STONES = makeCommonBlockTag("end_stones"); + public static final TagNamed BLOCK_NETHER_STONES = makeCommonBlockTag("nether_stones"); + public static final TagNamed BLOCK_NETHER_PORTAL_FRAME = makeCommonBlockTag("nether_pframe"); + public static final TagNamed BLOCK_WORKBENCHES = makeCommonBlockTag("workbench"); + public static final TagNamed BLOCK_SAPLINGS = makeCommonBlockTag("saplings"); + public static final TagNamed BLOCK_LEAVES = makeCommonBlockTag("leaves"); + public static final TagNamed BLOCK_IMMOBILE = makeCommonBlockTag("immobile"); + public static final TagNamed BLOCK_SOUL_GROUND = makeCommonBlockTag("soul_ground"); + public static final TagNamed BLOCK_NETHERRACK = makeCommonBlockTag("netherrack"); + public static final TagNamed BLOCK_NETHER_MYCELIUM = makeCommonBlockTag("nether_mycelium"); - public static final Tag.Named BLOCK_DRAGON_IMMUNE = getMCBlockTag("dragon_immune"); + public static final TagNamed BLOCK_DRAGON_IMMUNE = getMCBlockTag("dragon_immune"); - public static final Tag.Named MINEABLE_AXE = getMCBlockTag("mineable/axe"); - public static final Tag.Named MINEABLE_PICKAXE = getMCBlockTag("mineable/pickaxe"); - public static final Tag.Named MINEABLE_SHOVEL = getMCBlockTag("mineable/shovel"); - public static final Tag.Named MINEABLE_HOE = getMCBlockTag("mineable/hoe"); + public static final TagNamed MINEABLE_AXE = getMCBlockTag("mineable/axe"); + public static final TagNamed MINEABLE_PICKAXE = getMCBlockTag("mineable/pickaxe"); + public static final TagNamed MINEABLE_SHOVEL = getMCBlockTag("mineable/shovel"); + public static final TagNamed MINEABLE_HOE = getMCBlockTag("mineable/hoe"); // Item Tags - public static final Tag.Named ITEM_CHEST = makeCommonItemTag("chest"); - public static final Tag.Named ITEM_WOODEN_CHEST = makeCommonItemTag("wooden_chests"); - public static final Tag.Named ITEM_BARREL = makeCommonItemTag("barrel"); - public static final Tag.Named ITEM_WOODEN_BARREL = makeCommonItemTag("wooden_barrels"); - public static final Tag.Named ITEM_IRON_INGOTS = makeCommonItemTag("iron_ingots"); - public static final Tag.Named ITEM_FURNACES = makeCommonItemTag("furnaces"); - public static final Tag.Named ITEM_WORKBENCHES = makeCommonItemTag("workbench"); - public final static Tag.Named ITEM_HAMMERS = makeCommonItemTag("hammers"); - public static final Tag.Named ITEM_SAPLINGS = makeCommonItemTag("saplings"); - public static final Tag.Named ITEM_LEAVES = makeCommonItemTag("leaves"); - public static final Tag.Named ITEM_SHEARS = getMCItemTag("shears"); - public static final Tag.Named ITEM_COMMON_SHEARS = makeCommonItemTag("shears"); - public static final Tag.Named ITEM_SOUL_GROUND = makeCommonItemTag("soul_ground"); + public static final TagNamed ITEM_CHEST = makeCommonItemTag("chest"); + public static final TagNamed ITEM_WOODEN_CHEST = makeCommonItemTag("wooden_chests"); + public static final TagNamed ITEM_BARREL = makeCommonItemTag("barrel"); + public static final TagNamed ITEM_WOODEN_BARREL = makeCommonItemTag("wooden_barrels"); + public static final TagNamed ITEM_IRON_INGOTS = makeCommonItemTag("iron_ingots"); + public static final TagNamed ITEM_FURNACES = makeCommonItemTag("furnaces"); + public static final TagNamed ITEM_WORKBENCHES = makeCommonItemTag("workbench"); + public final static TagNamed ITEM_HAMMERS = makeCommonItemTag("hammers"); + public static final TagNamed ITEM_SAPLINGS = makeCommonItemTag("saplings"); + public static final TagNamed ITEM_LEAVES = makeCommonItemTag("leaves"); + public static final TagNamed ITEM_SHEARS = getMCItemTag("shears"); + public static final TagNamed ITEM_COMMON_SHEARS = makeCommonItemTag("shears"); + public static final TagNamed ITEM_SOUL_GROUND = makeCommonItemTag("soul_ground"); /** * Get or create {@link Tag.Named}. @@ -91,9 +93,9 @@ public class TagAPI { * @param id - {@link ResourceLocation} tag id. * @return {@link Tag.Named}. */ - public static Tag.Named makeTag(Supplier> containerSupplier, ResourceLocation id) { + public static TagNamed makeTag(Supplier> containerSupplier, TagLocation id) { Tag tag = containerSupplier.get().getTag(id); - return tag == null ? new TagDelegate<>(id, containerSupplier) : (Named) tag; + return tag == null ? new Delegate<>(id, containerSupplier) : CommonDelegate.proxy((Named) tag); } /** @@ -103,8 +105,8 @@ public class TagAPI { * @param name - {@link String} tag name. * @return {@link Block} {@link Tag.Named}. */ - public static Tag.Named makeBlockTag(String modID, String name) { - return makeTag(BlockTags::getAllTags, new ResourceLocation(modID, name)); + public static TagNamed makeBlockTag(String modID, String name) { + return makeTag(BlockTags::getAllTags, new TagLocation<>(modID, name)); } /** @@ -114,8 +116,8 @@ public class TagAPI { * @param name - {@link String} tag name. * @return {@link Item} {@link Tag.Named}. */ - public static Tag.Named makeItemTag(String modID, String name) { - return makeTag(ItemTags::getAllTags, new ResourceLocation(modID, name)); + public static TagNamed makeItemTag(String modID, String name) { + return makeTag(ItemTags::getAllTags, new TagLocation<>(modID, name)); } /** @@ -125,8 +127,8 @@ public class TagAPI { * @return {@link Block} {@link Tag.Named}. * @see Fabric Wiki (Tags) */ - public static Tag.Named makeCommonBlockTag(String name) { - return makeTag(BlockTags::getAllTags, new ResourceLocation("c", name)); + public static TagNamed makeCommonBlockTag(String name) { + return makeTag(BlockTags::getAllTags, new TagLocation<>("c", name)); } /** @@ -136,8 +138,8 @@ public class TagAPI { * @return {@link Item} {@link Tag.Named}. * @see Fabric Wiki (Tags) */ - public static Tag.Named makeCommonItemTag(String name) { - return makeTag(ItemTags::getAllTags, new ResourceLocation("c", name)); + public static TagNamed makeCommonItemTag(String name) { + return makeTag(ItemTags::getAllTags, new TagLocation<>("c", name)); } /** @@ -146,10 +148,10 @@ public class TagAPI { * @param name - {@link String} tag name. * @return {@link Block} {@link Tag.Named}. */ - public static Tag.Named getMCBlockTag(String name) { + public static TagNamed getMCBlockTag(String name) { ResourceLocation id = new ResourceLocation(name); Tag tag = BlockTags.getAllTags().getTag(id); - return tag == null ? (Named) TagFactory.BLOCK.create(id): (Named) tag; + return CommonDelegate.proxy(tag == null ? (Named) TagFactory.BLOCK.create(id): (Named) tag); } /** @@ -158,10 +160,10 @@ public class TagAPI { * @param name - {@link String} tag name. * @return {@link Item} {@link Tag.Named}. */ - public static Tag.Named getMCItemTag(String name) { + public static TagNamed getMCItemTag(String name) { ResourceLocation id = new ResourceLocation(name); Tag tag = ItemTags.getAllTags().getTag(id); - return tag == null ? (Named) TagRegistry.item(id) : (Named) tag; + return CommonDelegate.proxy(tag == null ? (Named) TagRegistry.item(id) : (Named) tag); } /** @@ -180,21 +182,31 @@ public class TagAPI { /** * Adds multiple Tags to one Block. - * @param tagIDs array of {@link ResourceLocation} tag IDs. + * @param tagIDs array of {@link TagLocation} tag IDs. * @param block The {@link Block} to add tag. */ - public static void addBlockTags(Block block, ResourceLocation... tagIDs) { - for (ResourceLocation tagID : tagIDs) { - addBlockTag(tagID, block); + @SafeVarargs + public static void addBlockTags(Block block, TagLocation... tagIDs) { + for (TagLocation tagID : tagIDs) { + addBlockTagUntyped(tagID, block); } } + /** + * Adds one Tag to multiple Blocks. + * @param tagID {@link TagLocation} tag ID. + * @param blocks array of {@link Block} to add into tag. + */ + public static void addBlockTag(TagLocation tagID, Block... blocks) { + addBlockTagUntyped(tagID, blocks); + } + /** * Adds one Tag to multiple Blocks. * @param tagID {@link ResourceLocation} tag ID. * @param blocks array of {@link Block} to add into tag. */ - public static void addBlockTag(ResourceLocation tagID, Block... blocks) { + protected static void addBlockTagUntyped(ResourceLocation tagID, Block... blocks) { Set set = TAGS_BLOCK.computeIfAbsent(tagID, k -> Sets.newHashSet()); for (Block block : blocks) { ResourceLocation id = Registry.BLOCK.getKey(block); @@ -206,21 +218,31 @@ public class TagAPI { /** * Adds multiple Tags to one Item. - * @param tagIDs array of {@link ResourceLocation} tag IDs. + * @param tagIDs array of {@link TagLocation} tag IDs. * @param item The {@link Item} to add tag. */ - public static void addItemTags(ItemLike item, ResourceLocation... tagIDs) { - for (ResourceLocation tagID : tagIDs) { - addItemTag(tagID, item); + @SafeVarargs + public static void addItemTags(ItemLike item, TagLocation... tagIDs) { + for (TagLocation tagID : tagIDs) { + addItemTagUntyped(tagID, item); } } + /** + * Adds one Tag to multiple Items. + * @param tagID {@link TagLocation} tag ID. + * @param items array of {@link ItemLike} to add into tag. + */ + public static void addItemTag(TagLocation tagID, ItemLike... items) { + addItemTagUntyped(tagID, items); + } + /** * Adds one Tag to multiple Items. * @param tagID {@link ResourceLocation} tag ID. * @param items array of {@link ItemLike} to add into tag. */ - public static void addItemTag(ResourceLocation tagID, ItemLike... items) { + protected static void addItemTagUntyped(ResourceLocation tagID, ItemLike... items) { Set set = TAGS_ITEM.computeIfAbsent(tagID, k -> Sets.newHashSet()); for (ItemLike item : items) { ResourceLocation id = Registry.ITEM.getKey(item.asItem()); @@ -286,7 +308,7 @@ public class TagAPI { */ @Deprecated public static void addTag(Tag.Named tag, ItemLike... items) { - addItemTag(tag.getName(), items); + addItemTagUntyped(tag.getName(), items); } /** @@ -304,7 +326,7 @@ public class TagAPI { @SafeVarargs public static void addTags(ItemLike item, Tag.Named... tags) { for (Tag.Named tag : tags) { - addItemTag(tag.getName(), item); + addItemTagUntyped(tag.getName(), item); } } @@ -344,7 +366,7 @@ public class TagAPI { */ @Deprecated public static void addTag(Tag.Named tag, Block... blocks) { - addBlockTag(tag.getName(), blocks); + addBlockTagUntyped(tag.getName(), blocks); } /** @@ -368,4 +390,79 @@ public class TagAPI { addTag(BLOCK_GEN_TERRAIN, block); addTag(BLOCK_END_GROUND, block); } + + /** + * Extends {@link Tag.Named} to return a type safe {@link TagLocation}. This Type was introduced to + * allow type-safe definition of Tags using their ResourceLocation. + * @param The Type of the underlying {@link Tag} + */ + public interface TagNamed extends Tag.Named{ + TagLocation getName(); + } + + /** + * Extends (without changing) {@link ResourceLocation}. This Type was introduced to allow type-safe definition af + * Tags using their ResourceLocation. + * @param The Type of the underlying {@link Tag} + */ + public static class TagLocation extends ResourceLocation { + public TagLocation(String string) { + super(string); + } + + public TagLocation(String string, String string2) { + super(string, string2); + } + } + + private abstract static class CommonDelegate implements TagNamed { + protected final Tag.Named delegate; + protected CommonDelegate(Tag.Named source){ + this.delegate = source; + } + + public static TagNamed proxy(Tag.Named source){ + if (source instanceof TagNamed typed) return typed; + return new ProxyDelegate<>(source); + } + + @Override + public boolean contains(T object) { + return delegate.contains(object); + } + + @Override + public List getValues() { + return delegate.getValues(); + } + + @Override + public T getRandomElement(Random random) { + return delegate.getRandomElement(random); + } + } + + private static final class ProxyDelegate extends CommonDelegate{ + private final TagLocation id; + private ProxyDelegate(Tag.Named source) { + super( source); + id = new TagLocation<>(source.getName() + .getNamespace(), source.getName() + .getPath()); + } + @Override + public TagLocation getName(){ + return id; + } + } + + private static final class Delegate extends CommonDelegate{ + public Delegate(TagLocation id, Supplier> containerSupplier) { + super( new TagDelegate<>(id, containerSupplier)); + } + @Override + public TagLocation getName(){ + return (TagLocation)delegate.getName(); + } + } }