diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt index 096f58816..71cd971b5 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/Tags.kt @@ -47,10 +47,10 @@ fun addTags(tagsProvider: TagsProvider) { MBlocks.STORAGE_CABLE ) - tagsProvider.items.appender(MItemTags.CRAFTING_TABLES).add(Items.CRAFTING_TABLE) - tagsProvider.blocks.appender(MBlockTags.CRAFTING_TABLES).add(Blocks.CRAFTING_TABLE) + tagsProvider.items.Appender(MItemTags.CRAFTING_TABLES).add(Items.CRAFTING_TABLE) + tagsProvider.blocks.Appender(MBlockTags.CRAFTING_TABLES).add(Blocks.CRAFTING_TABLE) - tagsProvider.items.appender(MItemTags.MINECART_CARGO_CRATES).add(MItems.CARGO_CRATE_MINECARTS.values) + tagsProvider.items.Appender(MItemTags.MINECART_CARGO_CRATES).add(MItems.CARGO_CRATE_MINECARTS.values) tagsProvider.items.forge("hardened_glass").add(MRegistry.INDUSTRIAL_GLASS.allItems.values) tagsProvider.items.forge("hardened_glass/colorless").add(MRegistry.INDUSTRIAL_GLASS.item) @@ -74,25 +74,25 @@ fun addTags(tagsProvider: TagsProvider) { MRegistry.INDUSTRIAL_GLASS.forEachBlock { s, _, block -> tagsProvider.blocks.forge("hardened_glass/$s").add(block) } MRegistry.INDUSTRIAL_GLASS_PANE.forEachBlock { s, _, block -> tagsProvider.blocks.forge("hardened_glass_panes/$s").add(block) } - tagsProvider.items.appender(MItemTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allItems.values) - tagsProvider.blocks.appender(MBlockTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values) - tagsProvider.blocks.appender(MBlockTags.CARGO_CRATES).add(MRegistry.CARGO_CRATES.allBlocks.values) + tagsProvider.items.Appender(MItemTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allItems.values) + tagsProvider.blocks.Appender(MBlockTags.INDUSTRIAL_GLASS).add(MRegistry.INDUSTRIAL_GLASS.allBlocks.values) + tagsProvider.blocks.Appender(MBlockTags.CARGO_CRATES).add(MRegistry.CARGO_CRATES.allBlocks.values) - tagsProvider.items.appender(ItemTags.DOORS).add(MItems.TRITANIUM_DOOR.values) - tagsProvider.blocks.appender(BlockTags.DOORS).add(MBlocks.TRITANIUM_DOOR.values) + tagsProvider.items.Appender(ItemTags.DOORS).add(MItems.TRITANIUM_DOOR.values) + tagsProvider.blocks.Appender(BlockTags.DOORS).add(MBlocks.TRITANIUM_DOOR.values) - tagsProvider.items.appender(ItemTags.TRAPDOORS).add(MItems.TRITANIUM_TRAPDOOR.values) - tagsProvider.blocks.appender(BlockTags.TRAPDOORS).add(MBlocks.TRITANIUM_TRAPDOOR.values) + tagsProvider.items.Appender(ItemTags.TRAPDOORS).add(MItems.TRITANIUM_TRAPDOOR.values) + tagsProvider.blocks.Appender(BlockTags.TRAPDOORS).add(MBlocks.TRITANIUM_TRAPDOOR.values) - tagsProvider.blocks.appender(BlockTags.PRESSURE_PLATES).add(MRegistry.TRITANIUM_PRESSURE_PLATE.allBlocks.values) + tagsProvider.blocks.Appender(BlockTags.PRESSURE_PLATES).add(MRegistry.TRITANIUM_PRESSURE_PLATE.allBlocks.values) - tagsProvider.items.appender(MItemTags.MACHINES).add(MItems.MACHINES) - tagsProvider.blocks.appender(MBlockTags.MACHINES).add(MItems.MACHINES.stream().map { it!!.block }) + tagsProvider.items.Appender(MItemTags.MACHINES).add(MItems.MACHINES) + tagsProvider.blocks.Appender(MBlockTags.MACHINES).add(MItems.MACHINES.stream().map { it!!.block }) - tagsProvider.blocks.appender(BlockTags.ANVIL).add(MBlocks.TRITANIUM_ANVIL) + tagsProvider.blocks.Appender(BlockTags.ANVIL).add(MBlocks.TRITANIUM_ANVIL) - tagsProvider.items.appender(MItemTags.TRITANIUM_NUGGETS).add(MItems.TRITANIUM_NUGGET) - tagsProvider.items.appender(MItemTags.NUGGETS).add(MItems.TRITANIUM_NUGGET) + tagsProvider.items.Appender(MItemTags.TRITANIUM_NUGGETS).add(MItems.TRITANIUM_NUGGET) + tagsProvider.items.Appender(MItemTags.NUGGETS).add(MItems.TRITANIUM_NUGGET) tagsProvider.items.forge("armors") .add("helmets", MItems.TRITANIUM_HELMET) @@ -113,30 +113,30 @@ fun addTags(tagsProvider: TagsProvider) { .add("shields", MItems.TRITANIUM_SHIELD) tagsProvider.items.forge("shears").add(MItems.TRITANIUM_SHEARS) - tagsProvider.blocks.appender(BlockTags.STAIRS) + tagsProvider.blocks.Appender(BlockTags.STAIRS) .add(MRegistry.FLOOR_TILES_STAIRS.blocks.values) .add(MRegistry.TRITANIUM_STAIRS.allBlocks.values) .add(MRegistry.TRITANIUM_STRIPED_STAIRS.flatBlocks) .add(MBlocks.TRITANIUM_STRIPED_STAIRS) - tagsProvider.blocks.appender(BlockTags.SLABS) + tagsProvider.blocks.Appender(BlockTags.SLABS) .add(MRegistry.TRITANIUM_SLAB.allBlocks.values) .add(MRegistry.TRITANIUM_STRIPED_SLAB.flatBlocks) .add(MRegistry.FLOOR_TILES_SLAB.blocks.values) .add(MBlocks.TRITANIUM_STRIPED_SLAB) - tagsProvider.blocks.appender(BlockTags.WALLS) + tagsProvider.blocks.Appender(BlockTags.WALLS) .add(MRegistry.TRITANIUM_WALL.allBlocks.values) .add(MRegistry.TRITANIUM_STRIPED_WALL.flatBlocks) .add(MBlocks.TRITANIUM_STRIPED_WALL) - tagsProvider.items.appender(ItemTags.SLABS) + tagsProvider.items.Appender(ItemTags.SLABS) .add(MRegistry.TRITANIUM_SLAB.allItems.values) .add(MRegistry.TRITANIUM_STRIPED_SLAB.flatItems) .add(MRegistry.FLOOR_TILES_SLAB.items.values) .add(MItems.TRITANIUM_STRIPED_SLAB) - tagsProvider.items.appender(ItemTags.WALLS) + tagsProvider.items.Appender(ItemTags.WALLS) .add(MRegistry.TRITANIUM_WALL.allItems.values) .add(MRegistry.TRITANIUM_STRIPED_WALL.flatItems) .add(MItems.TRITANIUM_STRIPED_WALL) diff --git a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt index 67bbdcb67..370522b10 100644 --- a/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt +++ b/src/data/kotlin/ru/dbotthepony/mc/otm/datagen/tags/TagsProvider.kt @@ -22,62 +22,110 @@ import ru.dbotthepony.mc.otm.datagen.DataGen import java.util.stream.Stream import net.minecraft.data.tags.TagsProvider as MinecraftTagsProvider -interface MTagAppender { - fun add(value: T): MTagAppender - fun addSafe(value: T): Boolean - fun add(vararg values: T): MTagAppender - fun addSafe(vararg values: T): Boolean { - var any = false - for (value in values) any = addSafe(value) - return any - } - - fun add(values: Collection): MTagAppender - fun add(values: Stream): MTagAppender = add(values.toList()) - - fun addSafe(values: Collection): Boolean { - var any = false - for (value in values) any = addSafe(value) - return any - } -} - -interface ForgeTagAppender : MTagAppender { - fun add(key: String, value: T): ForgeTagAppender - fun addSafe(key: String, value: T): Boolean - fun add(key: String, vararg values: T): ForgeTagAppender - fun addSafe(key: String, vararg values: T): Boolean { - var any = false - for (value in values) any = addSafe(key, value) - return any - } - - fun add(key: String, values: Collection): ForgeTagAppender - - fun addSafe(key: String, values: Collection): Boolean { - var any = false - for (value in values) any = addSafe(key, value) - return any - } -} - -private fun vanillaLookup(key: ResourceKey>): (T) -> ResourceLocation? { +private fun vanillaLookup(key: ResourceKey>): (T) -> ResourceLocation { val registry by lazy { (BuiltInRegistries.REGISTRY.get(key.location()) ?: throw NoSuchElementException("No such registry $key")) as Registry } - return { registry.getKey(it) } + return { registry.getKey(it) ?: throw NoSuchElementException("Registry $key does not contain $it") } } -class TagsProvider( - private val event: GatherDataEvent -) { - inner class Delegate private constructor(key: ResourceKey>, val lookup: (T) -> ResourceLocation?) : MinecraftTagsProvider(event.generator.packOutput, key, event.lookupProvider, DataGen.MOD_ID, event.existingFileHelper) { - constructor(registry: IForgeRegistry) : this(registry.registryKey, registry::getKey) +class TagsProvider(private val event: GatherDataEvent) { + inner class Delegate private constructor(key: ResourceKey>, val lookup: (T) -> ResourceLocation) : MinecraftTagsProvider(event.generator.packOutput, key, event.lookupProvider, DataGen.MOD_ID, event.existingFileHelper) { + constructor(registry: IForgeRegistry) : this(registry.registryKey, { registry.getKey(it) ?: throw NoSuchElementException("Registry $registry does not contain $it") }) constructor(key: ResourceKey>) : this(key, vanillaLookup(key)) init { - event.generator.addProvider(true, this) + if (isRegistered) + event.generator.addProvider(event.includeServer(), this) + else + delegates.add(this) } - private val tags = HashMap, ObjectArraySet>() + private val tags = HashMap, ObjectArraySet>() + private val rigidTags = HashMap, ObjectArraySet>>() + private val tagInTag = HashMap, ObjectArraySet>>() + + inner class Appender(val tag: TagKey) { + constructor(tag: ResourceLocation) : this(TagKey.create(registryKey, tag)) + + private val locations by lazy { tags.computeIfAbsent(tag) { ObjectArraySet() } } + private val rigidLocations by lazy { rigidTags.computeIfAbsent(tag) { ObjectArraySet() } } + private val tagsInTags by lazy { tagInTag.computeIfAbsent(tag) { ObjectArraySet() } } + + fun add(value: ResourceLocation): Appender { + if (!locations.add(value)) { + throw IllegalStateException("Tag $tag of registry $registryKey already contains $value") + } + + return this + } + + fun add(value: ResourceKey): Appender { + require(value.registry() == registryKey) { "Invalid registry in provided ResourceKey: ${value.registry()} (this tag appender is for $registryKey)" } + + if (!rigidLocations.add(value)) { + throw IllegalStateException("Tag $tag of registry $registryKey already contains $value") + } + + return this + } + + fun add(value: TagKey): Appender { + require(value.registry() == registryKey) { "Invalid registry in provided ResourceKey: ${value.registry()} (this tag appender is for $registryKey)" } + + if (!tagsInTags.add(value)) { + throw IllegalStateException("Tag $tag of registry $registryKey already contains $value") + } + + return this + } + + fun add(value: T): Appender { + return add(ResourceKey.create(registryKey, lookup.invoke(value))) + } + + fun add(values: Collection): Appender { + for (value in values) add(value) + return this + } + + fun add(vararg values: T): Appender { + for (value in values) add(value) + return this + } + + fun add(vararg values: ResourceKey): Appender { + for (value in values) add(value) + return this + } + + fun add(vararg values: TagKey): Appender { + for (value in values) add(value) + return this + } + + fun add(vararg values: ResourceLocation): Appender { + for (value in values) add(value) + return this + } + + fun add(values: Stream): Appender { + values.forEach { add(it) } + return this + } + + fun leaf(name: String) = Appender(TagKey.create(tag.registry, ResourceLocation(tag.location.namespace, tag.location.path + "/$name"))) + + fun add(leaf: String, value: T) = also { leaf(leaf).add(value) } + fun add(leaf: String, value: TagKey) = also { leaf(leaf).add(value) } + fun add(leaf: String, vararg value: T) = also { leaf(leaf).add(*value) } + fun add(leaf: String, vararg value: TagKey) = also { leaf(leaf).add(*value) } + fun add(leaf: String, value: Stream) = also { leaf(leaf).add(value) } + fun add(leaf: String, value: ResourceKey) = also { leaf(leaf).add(value) } + fun add(leaf: String, vararg value: ResourceKey) = also { leaf(leaf).add(*value) } + fun add(leaf: String, value: ResourceLocation) = also { leaf(leaf).add(value) } + fun add(leaf: String, vararg value: ResourceLocation) = also { leaf(leaf).add(*value) } + } + + fun forge(path: String) = Appender(ResourceLocation("forge", path)) override fun addTags(provider: HolderLookup.Provider) { if (tags.isEmpty()) { @@ -85,121 +133,64 @@ class TagsProvider( } for ((tag, values) in tags) { - tag(tag).also { - for (value in values) { - it.add(ResourceKey.create(registryKey, lookup(value) ?: throw NoSuchElementException("$value is missing from $registryKey"))) - } + val appender = tag(tag) + + for (value in values) { + appender.addOptional(value) + } + } + + for ((tag, values) in rigidTags) { + val appender = tag(tag) + + for (value in values) { + appender.add(value) + } + } + + for ((tag, values) in tagInTag) { + val appender = tag(tag) + + for (value in values) { + appender.addTag(value) } } } + } - fun getSet(tag: TagKey): MutableSet { - return tags.computeIfAbsent(tag) { ObjectArraySet() } - } + private val delegates = ArrayList>() + private var isRegistered = false - fun getSet(location: ResourceLocation) = getSet(TagKey.create(registryKey, location)) + fun register() { + if (!isRegistered) { + isRegistered = true - fun appender(tag: TagKey, message: ((T) -> Any) = { "$it is already in $tag" }): MTagAppender { - val list = getSet(tag) - - return object : MTagAppender { - override fun add(value: T): MTagAppender { - if (!list.add(value)) { - throw IllegalStateException(message.invoke(value).toString()) - } - - return this - } - - override fun add(values: Collection): MTagAppender { - for (value in values) add(value) - return this - } - - override fun addSafe(value: T): Boolean { - return list.add(value) - } - - override fun add(vararg values: T): MTagAppender { - values.forEach(this::add) - return this - } + for (value in delegates) { + event.generator.addProvider(event.includeServer(), value) } - } - fun forge(path: String): ForgeTagAppender { - val parent by lazy { appender(ResourceLocation("forge", path)) } - - return object : ForgeTagAppender { - override fun add(key: String, value: T): ForgeTagAppender { - val tag = TagKey.create(registryKey, ResourceLocation("forge", "$path/$key")) - - if (!getSet(tag).add(value)) { - throw IllegalStateException("$value is already in $tag") - } - - return this - } - - override fun addSafe(key: String, value: T): Boolean { - val tag = TagKey.create(registryKey, ResourceLocation("forge", "$path/$key")) - return getSet(tag).add(value) - } - - override fun add(key: String, vararg values: T): ForgeTagAppender { - for (value in values) add(key, value) - return this - } - - override fun add(key: String, values: Collection): ForgeTagAppender { - for (value in values) add(key, value) - return this - } - - override fun add(value: T): MTagAppender { - return parent.add(value) - } - - override fun addSafe(value: T): Boolean { - return parent.addSafe(value) - } - - override fun add(vararg values: T): MTagAppender { - return parent.add(*values) - } - - override fun add(values: Collection): MTagAppender { - return parent.add(values) - } - } - } - - fun appender(location: ResourceLocation): MTagAppender { - return appender(TagKey.create(registryKey, location)) - } - - fun appender(location: ResourceLocation, message: (T) -> Any): MTagAppender { - return appender(TagKey.create(registryKey, location), message) + delegates.clear() } } val blocks = Delegate(ForgeRegistries.BLOCKS) val items = Delegate(ForgeRegistries.ITEMS) val mobEffects = Delegate(ForgeRegistries.MOB_EFFECTS) + val damageTypes = Delegate(Registries.DAMAGE_TYPE) - val androidImmuneEffects = mobEffects.appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS) + val androidImmuneEffects = mobEffects.Appender(MatteryPlayerCapability.ANDROID_IMMUNE_EFFECTS) - val requiresShovel = blocks.appender(BlockTags.MINEABLE_WITH_SHOVEL) - val requiresAxe = blocks.appender(BlockTags.MINEABLE_WITH_AXE) - val requiresHoe = blocks.appender(BlockTags.MINEABLE_WITH_HOE) - val requiresPickaxe = blocks.appender(BlockTags.MINEABLE_WITH_PICKAXE) + val requiresShovel = blocks.Appender(BlockTags.MINEABLE_WITH_SHOVEL) + val requiresAxe = blocks.Appender(BlockTags.MINEABLE_WITH_AXE) + val requiresHoe = blocks.Appender(BlockTags.MINEABLE_WITH_HOE) + val requiresPickaxe = blocks.Appender(BlockTags.MINEABLE_WITH_PICKAXE) - val requiresStoneTool = blocks.appender(BlockTags.NEEDS_STONE_TOOL) - val requiresIronTool = blocks.appender(BlockTags.NEEDS_IRON_TOOL) - val requiresDiamondTool = blocks.appender(BlockTags.NEEDS_DIAMOND_TOOL) + val requiresStoneTool = blocks.Appender(BlockTags.NEEDS_STONE_TOOL) + val requiresIronTool = blocks.Appender(BlockTags.NEEDS_IRON_TOOL) + val requiresDiamondTool = blocks.Appender(BlockTags.NEEDS_DIAMOND_TOOL) - val witherImmune = blocks.appender(BlockTags.WITHER_IMMUNE) - val dragonImmune = blocks.appender(BlockTags.DRAGON_IMMUNE) + val witherImmune = blocks.Appender(BlockTags.WITHER_IMMUNE) + val dragonImmune = blocks.Appender(BlockTags.DRAGON_IMMUNE) fun stoneOre(key: String, block: Block): TagsProvider { ore(key, block) @@ -233,9 +224,9 @@ class TagsProvider( val b = TagKey.create(Registries.BLOCK, forgeKey) val i = TagKey.create(Registries.ITEM, forgeKey) - items.getSet(i).add(block.asItem()) + items.Appender(i).add(block.asItem()) itemOres.add(block.asItem()) - blocks.getSet(b).add(block) + blocks.Appender(b).add(block) blockOres.add(block) return this @@ -286,7 +277,7 @@ class TagsProvider( // val itemOreRatesDense = items.forge("ore_rates/dense") val gameEvents = Delegate(Registries.GAME_EVENT) - val vibrations = gameEvents.appender(GameEventTags.VIBRATIONS) + val vibrations = gameEvents.Appender(GameEventTags.VIBRATIONS) fun requiresPickaxe(block: Block, tier: Tier? = null): TagsProvider { requiresPickaxe.add(block)