Painter table

This commit is contained in:
DBotThePony 2023-08-15 20:04:27 +07:00
parent 615912de8b
commit 61b83d5f5a
Signed by: DBot
GPG Key ID: DCC23B5715498507
31 changed files with 1233 additions and 95 deletions

View File

@ -51,6 +51,7 @@ import ru.dbotthepony.mc.otm.datagen.recipes.addDecorativesRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addPlatePressRecipes import ru.dbotthepony.mc.otm.datagen.recipes.addPlatePressRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addShapelessRecipes import ru.dbotthepony.mc.otm.datagen.recipes.addShapelessRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addOreSmeltingRecipes import ru.dbotthepony.mc.otm.datagen.recipes.addOreSmeltingRecipes
import ru.dbotthepony.mc.otm.datagen.recipes.addPainterRecipes
import ru.dbotthepony.mc.otm.datagen.tags.TagsProvider import ru.dbotthepony.mc.otm.datagen.tags.TagsProvider
import ru.dbotthepony.mc.otm.datagen.tags.addTags import ru.dbotthepony.mc.otm.datagen.tags.addTags
import ru.dbotthepony.mc.otm.matter.MatterDataProvider import ru.dbotthepony.mc.otm.matter.MatterDataProvider
@ -562,6 +563,7 @@ object DataGen {
addDecorativesRecipes(recipeProvider, consumer) addDecorativesRecipes(recipeProvider, consumer)
addShapelessRecipes(consumer) addShapelessRecipes(consumer)
addOreSmeltingRecipes(consumer) addOreSmeltingRecipes(consumer)
addPainterRecipes(consumer)
} }
addPlatePressRecipes(recipeProvider) addPlatePressRecipes(recipeProvider)

View File

@ -120,6 +120,9 @@ private fun misc(provider: MatteryLanguageProvider) {
gui("help.slot_filters", "Hold CTRL to setup slot filters") gui("help.slot_filters", "Hold CTRL to setup slot filters")
gui("help.slot_charging", "Hold ALT to switch slot charging") gui("help.slot_charging", "Hold ALT to switch slot charging")
gui("needs", "Needs %s")
gui("needs_x", "Needs %s x%d")
misc("needs_no_power", "Requires no power to operate") misc("needs_no_power", "Requires no power to operate")
gui("lock_holo_screen", "Lock contents") gui("lock_holo_screen", "Lock contents")
@ -428,6 +431,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Repairs tools using matter") add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Repairs tools using matter")
add(MBlocks.DEV_CHEST, "Dev Chest") add(MBlocks.DEV_CHEST, "Dev Chest")
add(MBlocks.DEV_CHEST, "desc", "Contains all items present in game") add(MBlocks.DEV_CHEST, "desc", "Contains all items present in game")
add(MBlocks.PAINTER, "Painting Table")
add(MBlocks.FLUID_TANK, "Fluid Tank") add(MBlocks.FLUID_TANK, "Fluid Tank")
add(MBlocks.FLUID_TANK, "named", "Fluid Tank (%s)") add(MBlocks.FLUID_TANK, "named", "Fluid Tank (%s)")

View File

@ -128,6 +128,9 @@ private fun misc(provider: MatteryLanguageProvider) {
gui("help.slot_filters", "Удерживайте CTRL для настройки фильтрации слотов") gui("help.slot_filters", "Удерживайте CTRL для настройки фильтрации слотов")
gui("help.slot_charging", "Удерживайте ALT для переключения зарядки слотов") gui("help.slot_charging", "Удерживайте ALT для переключения зарядки слотов")
gui("needs", "Требуется %s")
gui("needs_x", "Требуется %s x%d")
misc("needs_no_power", "Не требует энергии для работы") misc("needs_no_power", "Не требует энергии для работы")
gui("lock_holo_screen", "Заблокировать содержимое") gui("lock_holo_screen", "Заблокировать содержимое")
@ -430,6 +433,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Чинит инструменты используя материю") add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Чинит инструменты используя материю")
add(MBlocks.DEV_CHEST, "Сундук разработчика") add(MBlocks.DEV_CHEST, "Сундук разработчика")
add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре") add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре")
add(MBlocks.PAINTER, "Стол маляра")
add(MBlocks.FLUID_TANK, "Жидкостный бак") add(MBlocks.FLUID_TANK, "Жидкостный бак")
add(MBlocks.FLUID_TANK, "named", "Жидкостный бак (%s)") add(MBlocks.FLUID_TANK, "named", "Жидкостный бак (%s)")

View File

@ -133,6 +133,7 @@ fun addLootTables(lootTables: LootTables) {
lootTables.tile(MBlocks.ESSENCE_STORAGE) lootTables.tile(MBlocks.ESSENCE_STORAGE)
lootTables.tile(MBlocks.MATTER_RECONSTRUCTOR) lootTables.tile(MBlocks.MATTER_RECONSTRUCTOR)
lootTables.tile(MBlocks.FLUID_TANK) lootTables.tile(MBlocks.FLUID_TANK)
lootTables.tile(MBlocks.PAINTER)
lootTables.tile(MBlocks.ENERGY_SERVO) lootTables.tile(MBlocks.ENERGY_SERVO)
lootTables.tile(MBlocks.ENERGY_COUNTER) lootTables.tile(MBlocks.ENERGY_COUNTER)

View File

@ -433,4 +433,11 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
.row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES) .row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
.unlockedBy(Items.WATER_BUCKET) .unlockedBy(Items.WATER_BUCKET)
.build(consumer) .build(consumer)
MatteryRecipe(MItems.PAINTER, category = machinesCategory)
.row(Items.BRUSH, Items.BUCKET, Items.WATER_BUCKET)
.row(MItemTags.IRON_PLATES, Items.BUCKET, MItemTags.IRON_PLATES)
.row(MItemTags.IRON_PLATES, MItemTags.CRAFTING_TABLES, MItemTags.IRON_PLATES)
.unlockedBy(Tags.Items.DYES)
.build(consumer)
} }

View File

@ -0,0 +1,296 @@
package ru.dbotthepony.mc.otm.datagen.recipes
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.datagen.modLocation
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MRegistry
import java.util.function.Consumer
private val Item.recipeName get() = registryName!!.namespace + "/" + registryName!!.path
private fun generate(consumer: Consumer<FinishedRecipe>, items: Map<out DyeColor?, Item>, amount: Int = 1) {
for ((k1, v1) in items) {
if (k1 == null) continue
for ((k2, v2) in items) {
if (k2 == null || k1 == k2) continue
consumer.accept(PainterRecipe(
modLocation("painter/" + v2.recipeName + "/" + v1.recipeName),
Ingredient.of(v1),
ItemStack(v2),
//if (k1 == DyeColor.WHITE || k2 == DyeColor.BLACK) setOf(k2) else setOf(DyeColor.BLACK, k2)
mapOf(k2 to amount)
).toFinished())
}
}
}
private fun generate(consumer: Consumer<FinishedRecipe>, default: Item, items: Map<out DyeColor?, Item>, amount: Int = 1, cleaning: Boolean = true) {
generate(consumer, items)
if (cleaning)
cleaning(consumer, default, items)
for ((k1, v1) in items) {
if (k1 == null) continue
consumer.accept(PainterRecipe(
modLocation("painter/" + default.recipeName + "/" + v1.recipeName),
Ingredient.of(default),
ItemStack(v1),
mapOf(k1 to amount)
).toFinished())
}
}
private fun cleaning(consumer: Consumer<FinishedRecipe>, to: Item, from: Map<out DyeColor?, Item>) {
for ((k1, v1) in from) {
if (k1 == null) continue
consumer.accept(PainterRecipe(
modLocation("painter/cleaning/" + to.recipeName + "/" + v1.recipeName),
Ingredient.of(v1),
ItemStack(to),
setOf()
).toFinished())
}
}
private fun striped(consumer: Consumer<FinishedRecipe>, name: String, items: List<Pair<Item, Pair<DyeColor, DyeColor>>>, base: Map<DyeColor, Item>) {
for ((stripeItem, colors) in items) {
val (baseColor, stripe) = colors
consumer.accept(PainterRecipe(
modLocation("painter/stripes_$name/${baseColor.getName()}/${stripe.getName()}"),
Ingredient.of(base[baseColor]),
ItemStack(stripeItem),
setOf(stripe)
).toFinished())
}
}
fun addPainterRecipes(consumer: Consumer<FinishedRecipe>) {
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_WOOL,
DyeColor.ORANGE to Items.ORANGE_WOOL,
DyeColor.MAGENTA to Items.MAGENTA_WOOL,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_WOOL,
DyeColor.YELLOW to Items.YELLOW_WOOL,
DyeColor.LIME to Items.LIME_WOOL,
DyeColor.PINK to Items.PINK_WOOL,
DyeColor.GRAY to Items.GRAY_WOOL,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_WOOL,
DyeColor.CYAN to Items.CYAN_WOOL,
DyeColor.PURPLE to Items.PURPLE_WOOL,
DyeColor.BLUE to Items.BLUE_WOOL,
DyeColor.BROWN to Items.BROWN_WOOL,
DyeColor.GREEN to Items.GREEN_WOOL,
DyeColor.RED to Items.RED_WOOL,
DyeColor.BLACK to Items.BLACK_WOOL,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CARPET,
DyeColor.ORANGE to Items.ORANGE_CARPET,
DyeColor.MAGENTA to Items.MAGENTA_CARPET,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CARPET,
DyeColor.YELLOW to Items.YELLOW_CARPET,
DyeColor.LIME to Items.LIME_CARPET,
DyeColor.PINK to Items.PINK_CARPET,
DyeColor.GRAY to Items.GRAY_CARPET,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CARPET,
DyeColor.CYAN to Items.CYAN_CARPET,
DyeColor.PURPLE to Items.PURPLE_CARPET,
DyeColor.BLUE to Items.BLUE_CARPET,
DyeColor.BROWN to Items.BROWN_CARPET,
DyeColor.GREEN to Items.GREEN_CARPET,
DyeColor.RED to Items.RED_CARPET,
DyeColor.BLACK to Items.BLACK_CARPET,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_BED,
DyeColor.ORANGE to Items.ORANGE_BED,
DyeColor.MAGENTA to Items.MAGENTA_BED,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_BED,
DyeColor.YELLOW to Items.YELLOW_BED,
DyeColor.LIME to Items.LIME_BED,
DyeColor.PINK to Items.PINK_BED,
DyeColor.GRAY to Items.GRAY_BED,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_BED,
DyeColor.CYAN to Items.CYAN_BED,
DyeColor.PURPLE to Items.PURPLE_BED,
DyeColor.BLUE to Items.BLUE_BED,
DyeColor.BROWN to Items.BROWN_BED,
DyeColor.GREEN to Items.GREEN_BED,
DyeColor.RED to Items.RED_BED,
DyeColor.BLACK to Items.BLACK_BED,
), 3)
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CANDLE,
DyeColor.ORANGE to Items.ORANGE_CANDLE,
DyeColor.MAGENTA to Items.MAGENTA_CANDLE,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CANDLE,
DyeColor.YELLOW to Items.YELLOW_CANDLE,
DyeColor.LIME to Items.LIME_CANDLE,
DyeColor.PINK to Items.PINK_CANDLE,
DyeColor.GRAY to Items.GRAY_CANDLE,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CANDLE,
DyeColor.CYAN to Items.CYAN_CANDLE,
DyeColor.PURPLE to Items.PURPLE_CANDLE,
DyeColor.BLUE to Items.BLUE_CANDLE,
DyeColor.BROWN to Items.BROWN_CANDLE,
DyeColor.GREEN to Items.GREEN_CANDLE,
DyeColor.RED to Items.RED_CANDLE,
DyeColor.BLACK to Items.BLACK_CANDLE,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CONCRETE,
DyeColor.ORANGE to Items.ORANGE_CONCRETE,
DyeColor.MAGENTA to Items.MAGENTA_CONCRETE,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CONCRETE,
DyeColor.YELLOW to Items.YELLOW_CONCRETE,
DyeColor.LIME to Items.LIME_CONCRETE,
DyeColor.PINK to Items.PINK_CONCRETE,
DyeColor.GRAY to Items.GRAY_CONCRETE,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CONCRETE,
DyeColor.CYAN to Items.CYAN_CONCRETE,
DyeColor.PURPLE to Items.PURPLE_CONCRETE,
DyeColor.BLUE to Items.BLUE_CONCRETE,
DyeColor.BROWN to Items.BROWN_CONCRETE,
DyeColor.GREEN to Items.GREEN_CONCRETE,
DyeColor.RED to Items.RED_CONCRETE,
DyeColor.BLACK to Items.BLACK_CONCRETE,
))
generate(consumer, mapOf(
DyeColor.WHITE to Items.WHITE_CONCRETE_POWDER,
DyeColor.ORANGE to Items.ORANGE_CONCRETE_POWDER,
DyeColor.MAGENTA to Items.MAGENTA_CONCRETE_POWDER,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_CONCRETE_POWDER,
DyeColor.YELLOW to Items.YELLOW_CONCRETE_POWDER,
DyeColor.LIME to Items.LIME_CONCRETE_POWDER,
DyeColor.PINK to Items.PINK_CONCRETE_POWDER,
DyeColor.GRAY to Items.GRAY_CONCRETE_POWDER,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_CONCRETE_POWDER,
DyeColor.CYAN to Items.CYAN_CONCRETE_POWDER,
DyeColor.PURPLE to Items.PURPLE_CONCRETE_POWDER,
DyeColor.BLUE to Items.BLUE_CONCRETE_POWDER,
DyeColor.BROWN to Items.BROWN_CONCRETE_POWDER,
DyeColor.GREEN to Items.GREEN_CONCRETE_POWDER,
DyeColor.RED to Items.RED_CONCRETE_POWDER,
DyeColor.BLACK to Items.BLACK_CONCRETE_POWDER,
))
generate(consumer, MRegistry.CARGO_CRATES.item, MRegistry.CARGO_CRATES.items)
generate(consumer, MRegistry.TRITANIUM_BLOCK.item, MRegistry.TRITANIUM_BLOCK.items)
generate(consumer, MRegistry.TRITANIUM_STAIRS.item, MRegistry.TRITANIUM_STAIRS.items)
generate(consumer, MRegistry.TRITANIUM_SLAB.item, MRegistry.TRITANIUM_SLAB.items)
generate(consumer, MRegistry.TRITANIUM_WALL.item, MRegistry.TRITANIUM_WALL.items)
generate(consumer, Items.TERRACOTTA, mapOf(
DyeColor.WHITE to Items.WHITE_TERRACOTTA,
DyeColor.ORANGE to Items.ORANGE_TERRACOTTA,
DyeColor.MAGENTA to Items.MAGENTA_TERRACOTTA,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_TERRACOTTA,
DyeColor.YELLOW to Items.YELLOW_TERRACOTTA,
DyeColor.LIME to Items.LIME_TERRACOTTA,
DyeColor.PINK to Items.PINK_TERRACOTTA,
DyeColor.GRAY to Items.GRAY_TERRACOTTA,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_TERRACOTTA,
DyeColor.CYAN to Items.CYAN_TERRACOTTA,
DyeColor.PURPLE to Items.PURPLE_TERRACOTTA,
DyeColor.BLUE to Items.BLUE_TERRACOTTA,
DyeColor.BROWN to Items.BROWN_TERRACOTTA,
DyeColor.GREEN to Items.GREEN_TERRACOTTA,
DyeColor.RED to Items.RED_TERRACOTTA,
DyeColor.BLACK to Items.BLACK_TERRACOTTA,
), cleaning = false)
generate(consumer, Items.SHULKER_BOX, mapOf(
DyeColor.WHITE to Items.WHITE_SHULKER_BOX,
DyeColor.ORANGE to Items.ORANGE_SHULKER_BOX,
DyeColor.MAGENTA to Items.MAGENTA_SHULKER_BOX,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_SHULKER_BOX,
DyeColor.YELLOW to Items.YELLOW_SHULKER_BOX,
DyeColor.LIME to Items.LIME_SHULKER_BOX,
DyeColor.PINK to Items.PINK_SHULKER_BOX,
DyeColor.GRAY to Items.GRAY_SHULKER_BOX,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_SHULKER_BOX,
DyeColor.CYAN to Items.CYAN_SHULKER_BOX,
DyeColor.PURPLE to Items.PURPLE_SHULKER_BOX,
DyeColor.BLUE to Items.BLUE_SHULKER_BOX,
DyeColor.BROWN to Items.BROWN_SHULKER_BOX,
DyeColor.GREEN to Items.GREEN_SHULKER_BOX,
DyeColor.RED to Items.RED_SHULKER_BOX,
DyeColor.BLACK to Items.BLACK_SHULKER_BOX,
))
generate(consumer, Items.GLASS, mapOf(
DyeColor.WHITE to Items.WHITE_STAINED_GLASS,
DyeColor.ORANGE to Items.ORANGE_STAINED_GLASS,
DyeColor.MAGENTA to Items.MAGENTA_STAINED_GLASS,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_STAINED_GLASS,
DyeColor.YELLOW to Items.YELLOW_STAINED_GLASS,
DyeColor.LIME to Items.LIME_STAINED_GLASS,
DyeColor.PINK to Items.PINK_STAINED_GLASS,
DyeColor.GRAY to Items.GRAY_STAINED_GLASS,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_STAINED_GLASS,
DyeColor.CYAN to Items.CYAN_STAINED_GLASS,
DyeColor.PURPLE to Items.PURPLE_STAINED_GLASS,
DyeColor.BLUE to Items.BLUE_STAINED_GLASS,
DyeColor.BROWN to Items.BROWN_STAINED_GLASS,
DyeColor.GREEN to Items.GREEN_STAINED_GLASS,
DyeColor.RED to Items.RED_STAINED_GLASS,
DyeColor.BLACK to Items.BLACK_STAINED_GLASS,
))
generate(consumer, Items.GLASS_PANE, mapOf(
DyeColor.WHITE to Items.WHITE_STAINED_GLASS_PANE,
DyeColor.ORANGE to Items.ORANGE_STAINED_GLASS_PANE,
DyeColor.MAGENTA to Items.MAGENTA_STAINED_GLASS_PANE,
DyeColor.LIGHT_BLUE to Items.LIGHT_BLUE_STAINED_GLASS_PANE,
DyeColor.YELLOW to Items.YELLOW_STAINED_GLASS_PANE,
DyeColor.LIME to Items.LIME_STAINED_GLASS_PANE,
DyeColor.PINK to Items.PINK_STAINED_GLASS_PANE,
DyeColor.GRAY to Items.GRAY_STAINED_GLASS_PANE,
DyeColor.LIGHT_GRAY to Items.LIGHT_GRAY_STAINED_GLASS_PANE,
DyeColor.CYAN to Items.CYAN_STAINED_GLASS_PANE,
DyeColor.PURPLE to Items.PURPLE_STAINED_GLASS_PANE,
DyeColor.BLUE to Items.BLUE_STAINED_GLASS_PANE,
DyeColor.BROWN to Items.BROWN_STAINED_GLASS_PANE,
DyeColor.GREEN to Items.GREEN_STAINED_GLASS_PANE,
DyeColor.RED to Items.RED_STAINED_GLASS_PANE,
DyeColor.BLACK to Items.BLACK_STAINED_GLASS_PANE,
))
generate(consumer, MRegistry.INDUSTRIAL_GLASS.item, MRegistry.INDUSTRIAL_GLASS.items)
generate(consumer, MRegistry.INDUSTRIAL_GLASS_PANE.item, MRegistry.INDUSTRIAL_GLASS_PANE.items)
generate(consumer, MRegistry.DECORATIVE_CRATE.item, MRegistry.DECORATIVE_CRATE.items)
generate(consumer, MRegistry.TRITANIUM_PRESSURE_PLATE.item, MRegistry.TRITANIUM_PRESSURE_PLATE.items)
generate(consumer, MItems.TRITANIUM_DOOR[null]!!, MItems.TRITANIUM_DOOR)
generate(consumer, MItems.TRITANIUM_TRAPDOOR[null]!!, MItems.TRITANIUM_TRAPDOOR)
generate(consumer, MRegistry.VENT.item, MRegistry.VENT.items)
generate(consumer, MRegistry.VENT_ALTERNATIVE.item, MRegistry.VENT_ALTERNATIVE.items)
generate(consumer, MItems.CARGO_CRATE_MINECARTS[null]!!, MItems.CARGO_CRATE_MINECARTS)
generate(consumer, MRegistry.UNREFINED_FLOOR_TILES.items)
generate(consumer, MRegistry.FLOOR_TILES.items)
generate(consumer, MRegistry.FLOOR_TILES_SLAB.items)
generate(consumer, MRegistry.FLOOR_TILES_STAIRS.items)
striped(consumer, "full", MRegistry.TRITANIUM_STRIPED_BLOCK.itemsWithColor, MRegistry.TRITANIUM_BLOCK.items)
striped(consumer, "stairs", MRegistry.TRITANIUM_STRIPED_STAIRS.itemsWithColor, MRegistry.TRITANIUM_STAIRS.items)
striped(consumer, "walls", MRegistry.TRITANIUM_STRIPED_WALL.itemsWithColor, MRegistry.TRITANIUM_WALL.items)
striped(consumer, "slabs", MRegistry.TRITANIUM_STRIPED_SLAB.itemsWithColor, MRegistry.TRITANIUM_SLAB.items)
}

View File

@ -145,6 +145,7 @@ fun addTags(tagsProvider: TagsProvider) {
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.values, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.values, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_TRAPDOOR.values, Tiers.IRON) tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_TRAPDOOR.values, Tiers.IRON)
tagsProvider.requiresPickaxe(MBlocks.PAINTER, Tiers.STONE)
tagsProvider.requiresPickaxe(listOf( tagsProvider.requiresPickaxe(listOf(
MBlocks.ANDROID_STATION, MBlocks.ANDROID_STATION,

View File

@ -0,0 +1,197 @@
package ru.dbotthepony.mc.otm.block.entity.tech
import com.google.common.collect.ImmutableList
import net.minecraft.core.BlockPos
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.IntTag
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.entity.MatteryDeviceBlockEntity
import ru.dbotthepony.mc.otm.container.HandlerFilter
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.immutableList
import ru.dbotthepony.mc.otm.core.immutableMap
import ru.dbotthepony.mc.otm.core.nbt.mapPresent
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.menu.tech.PainterMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import java.util.*
class PainterBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryDeviceBlockEntity(MBlockEntities.PAINTER, blockPos, blockState) {
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return PainterMenu(containerID, inventory, this)
}
val dyeInput = MatteryContainer(this::setChangedLight, 1)
private val dyeStored = EnumMap<DyeColor, Int>(DyeColor::class.java)
val dyeStoredView: Map<DyeColor, Int> = Collections.unmodifiableMap(dyeStored)
init {
addDroppableContainer(dyeInput)
savetables.stateful(dyeInput, INVENTORY_KEY)
}
fun takeDyes(dyes: Map<DyeColor, Int>) {
for ((dye, amount) in dyes) {
for (i in 0 until amount) {
mixer(dye).mix(dyeStored)
if (dyeStored(dye) > 0) {
dyeStored[dye] = dyeStored(dye) - 1
}
}
}
setChangedLight()
}
val config = ConfigurableItemHandler(input = dyeInput.handler(object : HandlerFilter {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
val dye = DyeColor.entries.firstOrNull { stack.`is`(it.tag) } ?: return false
return dyeStored(dye) + HUE_PER_ITEM <= MAX_STORAGE
}
override fun modifyInsertCount(slot: Int, stack: ItemStack, existing: ItemStack, simulate: Boolean): Int {
if (!stack.equals(existing, false))
return super.modifyInsertCount(slot, stack, existing, simulate)
val dye = DyeColor.entries.firstOrNull { stack.`is`(it.tag) } ?: return 0
return stack.count.coerceAtMost((MAX_STORAGE - dyeStored(dye)) / HUE_PER_ITEM - existing.count)
}
override fun canExtract(slot: Int, amount: Int, stack: ItemStack): Boolean {
return false
}
}))
fun dyeStored(dye: DyeColor): Int {
return dyeStored[dye]!!
}
init {
for (dye in DyeColor.entries) {
dyeStored[dye] = 0
}
}
override fun saveShared(nbt: CompoundTag) {
super.saveShared(nbt)
nbt["dyes"] = CompoundTag().also {
for ((k, v) in dyeStored) {
it[k.getName()] = v
}
}
}
override fun load(nbt: CompoundTag) {
super.load(nbt)
for (dye in DyeColor.entries) {
dyeStored[dye] = 0
}
nbt.mapPresent("dyes") { it: CompoundTag ->
for (k in it.allKeys) {
dyeStored[DyeColor.entries.firstOrNull { it.getName() == k } ?: continue] = it.getInt(k)
}
}
}
override fun tick() {
super.tick()
val i = dyeInput.iterator()
for (item in i) {
val dye = DyeColor.entries.firstOrNull { item.`is`(it.tag) } ?: continue
val stored = dyeStored(dye)
if (stored + HUE_PER_ITEM <= MAX_STORAGE) {
item.shrink(1)
i.setChanged()
dyeStored[dye] = stored + HUE_PER_ITEM
}
}
}
class Mixer(val color: DyeColor, vararg mixing: ImmutableList<DyeColor>) : Map.Entry<DyeColor, Mixer> {
val mixing: ImmutableList<ImmutableList<DyeColor>> = ImmutableList.copyOf(mixing)
override val key: DyeColor
get() = color
override val value: Mixer
get() = this
private fun mix(input: MutableMap<DyeColor, Int>, seen: MutableSet<DyeColor>, stack: MutableSet<DyeColor>) {
if (input[color]!! > 0 || color in seen || color in stack) return
stack.add(color)
for (ingredients in mixing) {
val copy = EnumMap(input)
ingredients.forEach { mixer(it).mix(copy, seen, stack) }
if (ingredients.all { copy[it]!! > 0 }) {
ingredients.forEach { copy[it] = copy[it]!! - 1 }
copy[color] = ingredients.size
input.putAll(copy)
stack.remove(color)
return
}
}
stack.remove(color)
seen.add(color)
}
fun mix(input: MutableMap<DyeColor, Int>) {
mix(input, EnumSet.noneOf(DyeColor::class.java), EnumSet.noneOf(DyeColor::class.java))
}
fun isAvailable(input: Map<DyeColor, Int>): Boolean {
if (input[color]!! > 0) return true
return EnumMap(input).also(::mix)[color]!! > 0
}
}
companion object {
fun mixer(color: DyeColor): Mixer {
return MIXING[color]!!
}
val MIXING = immutableMap {
put(Mixer(DyeColor.WHITE, immutableList(DyeColor.RED, DyeColor.GREEN, DyeColor.BLUE)))
put(Mixer(DyeColor.LIGHT_GRAY, immutableList(DyeColor.BLACK, DyeColor.WHITE, DyeColor.WHITE)))
put(Mixer(DyeColor.GRAY, immutableList(DyeColor.BLACK, DyeColor.WHITE)))
put(Mixer(DyeColor.ORANGE, immutableList(DyeColor.YELLOW, DyeColor.RED)))
put(Mixer(DyeColor.LIME, immutableList(DyeColor.GREEN, DyeColor.WHITE)))
put(Mixer(DyeColor.LIGHT_BLUE, immutableList(DyeColor.BLUE, DyeColor.WHITE)))
put(Mixer(DyeColor.CYAN, immutableList(DyeColor.BLUE, DyeColor.GREEN)))
put(Mixer(DyeColor.PURPLE, immutableList(DyeColor.BLUE, DyeColor.RED)))
put(Mixer(
DyeColor.MAGENTA,
immutableList(DyeColor.PURPLE, DyeColor.PINK),
immutableList(DyeColor.RED, DyeColor.RED, DyeColor.BLUE, DyeColor.WHITE),
immutableList(DyeColor.PINK, DyeColor.RED, DyeColor.BLUE)
))
put(Mixer(DyeColor.PINK, immutableList(DyeColor.RED, DyeColor.WHITE)))
put(Mixer(DyeColor.RED, immutableList(DyeColor.MAGENTA, DyeColor.YELLOW)))
put(Mixer(DyeColor.GREEN, immutableList(DyeColor.CYAN, DyeColor.YELLOW)))
put(Mixer(DyeColor.BLUE, immutableList(DyeColor.CYAN, DyeColor.MAGENTA)))
put(Mixer(DyeColor.BLACK, immutableList(DyeColor.CYAN, DyeColor.MAGENTA, DyeColor.YELLOW)))
put(Mixer(DyeColor.YELLOW, immutableList(DyeColor.RED, DyeColor.GREEN)))
put(Mixer(DyeColor.BROWN, immutableList(DyeColor.MAGENTA, DyeColor.YELLOW, DyeColor.BLACK)))
}
const val MAX_STORAGE = 256
const val HUE_PER_ITEM = 32
}
}

View File

@ -0,0 +1,22 @@
package ru.dbotthepony.mc.otm.block.tech
import net.minecraft.core.BlockPos
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.EntityBlock
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityTicker
import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.block.RotatableMatteryBlock
import ru.dbotthepony.mc.otm.block.entity.tech.PainterBlockEntity
class PainterBlock : RotatableMatteryBlock(), EntityBlock {
override fun newBlockEntity(p_153215_: BlockPos, p_153216_: BlockState): BlockEntity {
return PainterBlockEntity(p_153215_, p_153216_)
}
override fun <T : BlockEntity?> getTicker(p_153212_: Level, p_153213_: BlockState, p_153214_: BlockEntityType<T>): BlockEntityTicker<T>? {
if (p_153212_.isClientSide) return null
return BlockEntityTicker { p_155253_, p_155254_, p_155255_, p_155256_ -> if (p_155256_ is PainterBlockEntity) p_155256_.tick() }
}
}

View File

@ -3,6 +3,8 @@ package ru.dbotthepony.mc.otm.client.render
import net.minecraft.client.gui.GuiGraphics import net.minecraft.client.gui.GuiGraphics
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.math.RGBAColor import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.systemTime
import kotlin.math.sin
interface IGUIRenderable { interface IGUIRenderable {
/** /**
@ -76,14 +78,14 @@ interface IGUIRenderable {
} }
/** /**
* Locks argument values to default ones and aligns render position to center of render rectangle * Locks argument values to default ones and aligns render position to center of render rectangle (or specified [gravity])
* *
* e.g. for example, if we want [ItemStackIcon] to always render as 16x16 pixels icon, even if required render * e.g. for example, if we want [ItemStackIcon] to always render as 16x16 pixels icon, even if required render
* dimensions are bigger (e.g. 18x18), after calling [fix] on [ItemStackIcon] it will always render as 16x16 icon, * dimensions are bigger (e.g. 18x18), after calling [fix] on [ItemStackIcon] it will always render as 16x16 icon,
* positioned on center of render canvas (e.g. rendering on +0+0 with 18x18 size will put icon at +1+1 and render as 16x16; * positioned on center of render canvas (e.g. rendering on +0+0 with 18x18 size will put icon at +1+1 and render as 16x16;
* rendering on +0+0 with 32x32 canvas will put icon at +8+8 and render as 16x16) * rendering on +0+0 with 32x32 canvas will put icon at +8+8 and render as 16x16)
*/ */
fun fixed(fixedWidth: Boolean = true, fixedHeight: Boolean = true, fixedWinding: Boolean = true): IGUIRenderable { fun fixed(fixedWidth: Boolean = true, fixedHeight: Boolean = true, fixedWinding: Boolean = true, gravity: RenderGravity = RenderGravity.CENTER_CENTER): IGUIRenderable {
if (!fixedHeight && !fixedWidth && !fixedWinding) return this if (!fixedHeight && !fixedWidth && !fixedWinding) return this
return object : IGUIRenderable { return object : IGUIRenderable {
@ -97,11 +99,11 @@ interface IGUIRenderable {
var realY = y var realY = y
if (fixedWidth && width > this.width) { if (fixedWidth && width > this.width) {
realX += (width - this.width) / 2f realX += gravity.repositionX(width, this.width)
} }
if (fixedHeight && height > this.height) { if (fixedHeight && height > this.height) {
realY += (height - this.height) / 2f realY += gravity.repositionY(height, this.height)
} }
this@IGUIRenderable.render(guiGraphics, realX, realY, if (fixedWidth) this.width else width, if (fixedHeight) this.height else height, if (fixedWinding) this.winding else winding, color) this@IGUIRenderable.render(guiGraphics, realX, realY, if (fixedWidth) this.width else width, if (fixedHeight) this.height else height, if (fixedWinding) this.winding else winding, color)
@ -122,22 +124,22 @@ interface IGUIRenderable {
data class ItemStackIcon(private val itemStack: ItemStack, override val width: Float = 16f, override val height: Float = 16f) : IGUIRenderable { data class ItemStackIcon(private val itemStack: ItemStack, override val width: Float = 16f, override val height: Float = 16f) : IGUIRenderable {
override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float, winding: UVWindingOrder, color: RGBAColor) { override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float, winding: UVWindingOrder, color: RGBAColor) {
if (x % 1f == 0f && y % 1f == 0f && width == 16f && height == 16f) { val pose = guiGraphics.pose()
guiGraphics.renderFakeItem(itemStack, x.toInt(), y.toInt())
clearDepth(guiGraphics.pose(), x, y, width, height)
} else {
val pose = guiGraphics.pose()
pose.pushPose() pose.pushPose()
pose.translate(x % 1f, y % 1f, 0f) pose.translate(x, y, 0f)
if (width != 16f || height != 16f) pose.scale(width / 16f, height / 16f, 1f)
pose.scale(width / 16f, height / 16f, 1f)
guiGraphics.renderFakeItem(itemStack, x.toInt(), y.toInt()) guiGraphics.renderFakeItem(itemStack, 0, 0)
pose.popPose() pose.popPose()
clearDepth(pose, x, y, width, height) clearDepth(pose, x, y, width, height)
} }
}
data class FlatRectangleIcon(override val width: Float = 1f, override val height: Float = 1f, val color: RGBAColor) : IGUIRenderable {
override fun render(guiGraphics: GuiGraphics, x: Float, y: Float, width: Float, height: Float, winding: UVWindingOrder, color: RGBAColor) {
guiGraphics.renderRect(x, y, width, height, color = this.color)
} }
} }

View File

@ -1608,7 +1608,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
} }
protected open fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean { protected open fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return true return false
} }
fun mouseScrolled(x: Double, y: Double, scroll: Double): Boolean { fun mouseScrolled(x: Double, y: Double, scroll: Double): Boolean {

View File

@ -0,0 +1,72 @@
package ru.dbotthepony.mc.otm.client.screen.panels.util
import net.minecraft.client.gui.screens.Screen
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
class ScrollableCanvasPanel<out S : Screen>(
screen: S,
parent: EditablePanel<*>,
x: Float = 0f,
y: Float = 0f,
width: Float = 40f,
height: Float = 40f,
slimScrollbar: Boolean = false
) : EditablePanel<S>(screen, parent, x, y, width, height) {
val canvas = object : EditablePanel<S>(screen, this@ScrollableCanvasPanel) {
init {
dock = Dock.FILL
dockRight = 1f
scissor = true
}
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return scrollbar.mouseScrolledInner(x, y, scroll)
}
override fun performLayout() {
super.performLayout()
var y = 0f
var maxHeight = 0f
var x = 0f
for (child in visibleChildren.filter { it.dock == Dock.NONE }) {
if (x > 0f && x + child.width > this.width) {
y += maxHeight
x = 0f
maxHeight = 0f
}
child.x = child.dockLeft + x
child.y = child.dockTop + y
x += child.width + child.dockMargin.horizontal
maxHeight = maxHeight.coerceAtLeast(child.height + child.dockMargin.vertical)
}
updateBounds()
if (getMaxScroll(scrollbar) <= scrollbar.scroll) {
scrollbar.scroll = getMaxScroll(scrollbar)
}
}
}
val scrollbar = AnalogScrollBarPanel(screen, this, maxScroll = ::getMaxScroll, smoothScrollCallback = ::onScrollUpdate, isSlim = slimScrollbar)
init {
scrollbar.dock = Dock.RIGHT
}
override fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
return scrollbar.mouseScrolledInner(x, y, scroll)
}
private fun getMaxScroll(it: AnalogScrollBarPanel<*>): Float {
return (canvas.childrenRectHeight - canvas.height).coerceAtLeast(0f)
}
private fun onScrollUpdate(it: AnalogScrollBarPanel<*>, old: Float, new: Float) {
this.canvas.yOffset = -new
}
}

View File

@ -0,0 +1,152 @@
package ru.dbotthepony.mc.otm.client.screen.tech
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
import net.minecraft.util.RandomSource
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items
import net.minecraftforge.common.Tags
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.block.entity.tech.PainterBlockEntity
import ru.dbotthepony.mc.otm.client.render.FlatRectangleIcon
import ru.dbotthepony.mc.otm.client.render.ItemStackIcon
import ru.dbotthepony.mc.otm.client.render.renderRect
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.Dock
import ru.dbotthepony.mc.otm.client.screen.panels.DockResizeMode
import ru.dbotthepony.mc.otm.client.screen.panels.EditablePanel
import ru.dbotthepony.mc.otm.client.screen.panels.FramePanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.DeviceControls
import ru.dbotthepony.mc.otm.client.screen.panels.button.LargeRectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.button.RectangleButtonPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.slot.SlotPanel
import ru.dbotthepony.mc.otm.client.screen.panels.util.ScrollableCanvasPanel
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.math.RGBAColor
import ru.dbotthepony.mc.otm.menu.tech.PainterMenu
import ru.dbotthepony.mc.otm.registry.MItems
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
inner class Bar(parent: EditablePanel<*>, val dye: DyeColor) : EditablePanel<PainterScreen>(this@PainterScreen, parent, width = 5f) {
init {
dock = Dock.RIGHT
dockLeft = 1f
tooltips.add(TranslatableComponent("item.minecraft.${dye.getName()}_dye"))
tooltips.add(TextComponent(""))
tooltips.add(TextComponent(""))
}
override fun innerRender(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float) {
graphics.renderRect(0f, 0f, width, height, color = RGBAColor.DARK_GRAY)
val color = RGBAColor.rgb(dye.textColor)
graphics.renderRect(0f, 0f, width, height, color = color.copy(alpha = 0.4f))
val multiplier = menu.dyeStoredDirect[dye]!!.toFloat() / PainterBlockEntity.MAX_STORAGE.toFloat()
graphics.renderRect(0f, height * (1f - multiplier), width, height * multiplier, color = color)
tooltips[tooltips.size - 1] = TextComponent("${menu.dyeStoredDirect[dye]} (${(multiplier * 100f).toInt()}%)")
}
}
override fun makeMainFrame(): FramePanel<MatteryScreen<*>> {
val frame = FramePanel(this, 200f, 120f, title)
val strip = EditablePanel(this, frame, width = AbstractSlotPanel.SIZE)
strip.dock = Dock.LEFT
strip.dockRight = 4f
SlotPanel(this, strip, menu.inputSlot).also {
it.dock = Dock.TOP
it.dockTop = 4f
}
EditablePanel(this, frame, width = 6f * DyeColor.entries.size / 2f).also {
it.dock = Dock.RIGHT
it.dockLeft = 4f
EditablePanel(this, it, height = 46f).also {
it.dock = Dock.TOP
for (i in 0 until DyeColor.entries.size / 2) {
Bar(it, DyeColor.entries[i])
}
}
EditablePanel(this, it, height = 46f).also {
it.dock = Dock.BOTTOM
for (i in DyeColor.entries.size / 2 until DyeColor.entries.size) {
Bar(it, DyeColor.entries[i])
}
}
}
SlotPanel(this, strip, menu.outputSlot).also {
it.dock = Dock.BOTTOM
it.dockBottom = 4f
}
SlotPanel(this, strip, menu.dyeSlot).also {
it.dock = Dock.FILL
it.dockResize = DockResizeMode.NONE
it.slotBackgroundEmpty =
ItemStackIcon(ItemStack(ForgeRegistries.ITEMS.tags()!!.getTag(Tags.Items.DYES).getRandomElement(RandomSource.create()).orElse(Items.AIR)), 16f, 16f)
.fixed()
.composeBefore(FlatRectangleIcon(16f, 16f, RGBAColor.rgb(0x8b8b8b).copy(alpha = 0.6f)))
.fixed()
}
val canvas = ScrollableCanvasPanel(this, frame)
canvas.dock = Dock.FILL
val buttons = ArrayList<RectangleButtonPanel<PainterScreen>>()
menu.listeners.addListener {
buttons.forEach { it.remove() }
buttons.clear()
for (recipe in menu.possibleRecipes) {
object : LargeRectangleButtonPanel<PainterScreen>(this@PainterScreen, canvas.canvas, skinElement = ItemStackIcon(recipe.output, 14f, 14f).fixed()) {
init {
buttons.add(this)
dockRight = 1f
dockBottom = 1f
}
override var isDisabled: Boolean
get() = !recipe.canCraft(menu.dyeStoredDirect)
set(value) {}
override fun innerRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
val list = getTooltipFromItem(minecraft!!, recipe.output)
recipe.dyes.forEach {
val (dye, amount) = it
if (amount == 1)
list.add(TranslatableComponent("otm.gui.needs", TranslatableComponent("item.minecraft.${dye.getName()}_dye")))
else if (amount > 1)
list.add(TranslatableComponent("otm.gui.needs_x", TranslatableComponent("item.minecraft.${dye.getName()}_dye"), amount))
}
graphics.renderComponentTooltip(font, list, mouseX.toInt(), mouseY.toInt())
return true
}
override fun onClick(mouseButton: Int) {
menu.selectRecipe.accept(recipe.id)
}
}
}
}
DeviceControls(this, frame, itemConfig = menu.itemConfig)
return frame
}
}

View File

@ -0,0 +1,19 @@
package ru.dbotthepony.mc.otm.compat.jei
import mezz.jei.api.gui.drawable.IDrawable
import net.minecraft.client.gui.GuiGraphics
import ru.dbotthepony.mc.otm.client.render.IGUIRenderable
class IGUIRenderable2IDrawable(val parent: IGUIRenderable) : IDrawable {
override fun getWidth(): Int {
return parent.width.toInt()
}
override fun getHeight(): Int {
return parent.height.toInt()
}
override fun draw(guiGraphics: GuiGraphics, xOffset: Int, yOffset: Int) {
parent.render(guiGraphics, xOffset.toFloat(), yOffset.toFloat())
}
}

View File

@ -70,17 +70,20 @@ class JEIPlugin : IModPlugin {
registration.addRecipeCatalyst(ItemStack(MItems.POWERED_SMOKER), RecipeTypes.SMOKING) registration.addRecipeCatalyst(ItemStack(MItems.POWERED_SMOKER), RecipeTypes.SMOKING)
registration.addRecipeCatalyst(ItemStack(MItems.ExopackUpgrades.CRAFTING_UPGRADE), RecipeTypes.CRAFTING) registration.addRecipeCatalyst(ItemStack(MItems.ExopackUpgrades.CRAFTING_UPGRADE), RecipeTypes.CRAFTING)
registration.addRecipeCatalyst(ItemStack(MItems.PLATE_PRESS), PlatePressRecipeCategory.recipeType) registration.addRecipeCatalyst(ItemStack(MItems.PLATE_PRESS), PlatePressRecipeCategory.recipeType)
registration.addRecipeCatalyst(ItemStack(MItems.PAINTER), PainterRecipeCategory.recipeType)
} }
override fun registerCategories(registration: IRecipeCategoryRegistration) { override fun registerCategories(registration: IRecipeCategoryRegistration) {
helpers = registration.jeiHelpers helpers = registration.jeiHelpers
registration.addRecipeCategories(PlatePressRecipeCategory) registration.addRecipeCategories(PlatePressRecipeCategory)
registration.addRecipeCategories(PainterRecipeCategory)
} }
override fun registerRecipes(registration: IRecipeRegistration) { override fun registerRecipes(registration: IRecipeRegistration) {
val level = minecraft.level ?: throw NullPointerException("No ClientLevel. OLOLOLOLOLOLO") val level = minecraft.level ?: throw NullPointerException("No ClientLevel. OLOLOLOLOLOLO")
registration.addRecipes(PlatePressRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PLATE_PRESS).filter { !it.isIncomplete }) registration.addRecipes(PlatePressRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PLATE_PRESS).filter { !it.isIncomplete })
registration.addRecipes(PainterRecipeCategory.recipeType, level.recipeManager.getAllRecipesFor(MRecipes.PAINTER).filter { !it.isIncomplete })
} }
override fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) { override fun registerRecipeTransferHandlers(registration: IRecipeTransferRegistration) {

View File

@ -0,0 +1,82 @@
package ru.dbotthepony.mc.otm.compat.jei
import mezz.jei.api.constants.VanillaTypes
import mezz.jei.api.gui.builder.IRecipeLayoutBuilder
import mezz.jei.api.gui.drawable.IDrawable
import mezz.jei.api.recipe.IFocusGroup
import mezz.jei.api.recipe.RecipeIngredientRole
import mezz.jei.api.recipe.RecipeType
import mezz.jei.api.recipe.category.IRecipeCategory
import net.minecraft.client.gui.GuiGraphics
import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.render.ItemStackIcon
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.widget.ProgressGaugePanel
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames
object PainterRecipeCategory : IRecipeCategory<PainterRecipe>, IDrawable {
private val type = RecipeType(ResourceLocation(OverdriveThatMatters.MOD_ID, MNames.PAINTER), PainterRecipe::class.java)
override fun getRecipeType(): RecipeType<PainterRecipe> {
return type
}
override fun getTitle(): Component {
return MItems.PAINTER.description
}
override fun getBackground(): IDrawable {
return this
}
override fun getWidth(): Int {
return 120
}
override fun getHeight(): Int {
return 56
}
override fun getIcon(): IDrawable {
return IGUIRenderable2IDrawable(ItemStackIcon(ItemStack(MItems.PAINTER)))
}
override fun setRecipe(builder: IRecipeLayoutBuilder, recipe: PainterRecipe, focuses: IFocusGroup) {
var x = 0
var y = 0
for ((dye, count) in recipe.dyes) {
builder.addSlot(RecipeIngredientRole.INPUT, 1 + x * 18, 1 + y * 18)
.addIngredients(VanillaTypes.ITEM_STACK, Ingredient.of(dye.tag).items.map { it.copyWithCount(count) })
y++
if (y >= 3) {
x++
y = 0
}
}
builder.addSlot(RecipeIngredientRole.INPUT, 50, 22).addIngredients(recipe.input)
builder.addSlot(RecipeIngredientRole.OUTPUT, 100, 22).addIngredients(VanillaTypes.ITEM_STACK, listOf(recipe.output))
}
override fun draw(guiGraphics: GuiGraphics, xOffset: Int, yOffset: Int) {
for (x in 0 .. 1) {
for (y in 0 .. 2) {
AbstractSlotPanel.SLOT_BACKGROUND.render(guiGraphics, xOffset.toFloat() + x * 18f, yOffset.toFloat() + y * 18f)
}
}
AbstractSlotPanel.SLOT_BACKGROUND.render(guiGraphics, xOffset.toFloat() + 49f, yOffset.toFloat() + 21f)
AbstractSlotPanel.SLOT_BACKGROUND.render(guiGraphics, xOffset.toFloat() + 99f, yOffset.toFloat() + 21f)
ProgressGaugePanel.GAUGE_BACKGROUND.render(guiGraphics, xOffset.toFloat() + 73f, yOffset.toFloat() + 22f)
}
}

View File

@ -1,19 +0,0 @@
package ru.dbotthepony.mc.otm.compat.jei
import mezz.jei.api.gui.drawable.IDrawable
import net.minecraft.client.gui.GuiGraphics
import ru.dbotthepony.mc.otm.client.render.sprites.MatterySprite
class SkinDrawable(val element: MatterySprite) : IDrawable {
override fun getWidth(): Int {
return element.width.toInt()
}
override fun getHeight(): Int {
return element.height.toInt()
}
override fun draw(graphics: GuiGraphics, xOffset: Int, yOffset: Int) {
element.render(graphics, xOffset.toFloat(), yOffset.toFloat())
}
}

View File

@ -1,19 +0,0 @@
package ru.dbotthepony.mc.otm.compat.jei
import mezz.jei.api.gui.drawable.IDrawable
import net.minecraft.client.gui.GuiGraphics
import ru.dbotthepony.mc.otm.client.render.sprites.StretchingRectangleElement
class StretchingDrawable(val element: StretchingRectangleElement, val rectWidth: Int, val rectHeight: Int) : IDrawable {
override fun getWidth(): Int {
return rectWidth
}
override fun getHeight(): Int {
return rectHeight
}
override fun draw(graphics: GuiGraphics, xOffset: Int, yOffset: Int) {
element.render(graphics, xOffset.toFloat(), yOffset.toFloat(), rectWidth.toFloat(), rectHeight.toFloat())
}
}

View File

@ -16,20 +16,27 @@ class ContainerHandler @JvmOverloads internal constructor(
return stack return stack
filter.preInsert(slot, stack, simulate) filter.preInsert(slot, stack, simulate)
val localStack = container[slot] val localStack = container[slot]
var amount = filter.modifyInsertCount(slot, stack, localStack, simulate)
if (amount <= 0)
return stack
if (localStack.isEmpty) { if (localStack.isEmpty) {
amount = stack.count.coerceAtMost(container.getMaxStackSize(slot, stack)).coerceAtMost(amount)
if (!simulate) { if (!simulate) {
container.setItem(slot, stack.copyWithCount(stack.count.coerceAtMost(container.getMaxStackSize(slot, stack)))) container.setItem(slot, stack.copyWithCount(amount))
} }
if (stack.count <= container.getMaxStackSize(slot, stack)) { if (stack.count <= amount) {
return ItemStack.EMPTY return ItemStack.EMPTY
} else { } else {
return stack.copyWithCount(container.getMaxStackSize(slot, stack)) return stack.copyWithCount(stack.count - amount)
} }
} else if (localStack.isStackable && container.getMaxStackSize(slot, localStack) > localStack.count && ItemStack.isSameItemSameTags(localStack, stack)) { } else if (localStack.isStackable && container.getMaxStackSize(slot, localStack) > localStack.count && ItemStack.isSameItemSameTags(localStack, stack)) {
val newCount = container.getMaxStackSize(slot, localStack).coerceAtMost(localStack.count + stack.count) val newCount = container.getMaxStackSize(slot, localStack).coerceAtMost(localStack.count + stack.count.coerceAtMost(amount))
val diff = newCount - localStack.count val diff = newCount - localStack.count
if (diff != 0) { if (diff != 0) {
@ -51,12 +58,16 @@ class ContainerHandler @JvmOverloads internal constructor(
if (amount <= 0 || container.isSlotForbiddenForAutomation(slot)) if (amount <= 0 || container.isSlotForbiddenForAutomation(slot))
return ItemStack.EMPTY return ItemStack.EMPTY
filter.preExtract(slot, amount, simulate)
val localStack = container.getItem(slot) val localStack = container.getItem(slot)
if (localStack.isEmpty) return ItemStack.EMPTY if (localStack.isEmpty) return ItemStack.EMPTY
@Suppress("name_shadowing")
val amount = filter.modifyExtractCount(slot, amount, simulate)
if (amount <= 0) return ItemStack.EMPTY
if (!filter.canExtract(slot, amount, localStack)) return ItemStack.EMPTY if (!filter.canExtract(slot, amount, localStack)) return ItemStack.EMPTY
filter.preExtract(slot, amount, simulate)
val minimal = amount.coerceAtMost(localStack.count) val minimal = amount.coerceAtMost(localStack.count)
val copy = localStack.copy() val copy = localStack.copy()
copy.count = minimal copy.count = minimal

View File

@ -19,6 +19,14 @@ interface HandlerFilter {
fun preInsert(slot: Int, stack: ItemStack, simulate: Boolean) {} fun preInsert(slot: Int, stack: ItemStack, simulate: Boolean) {}
fun preExtract(slot: Int, amount: Int, simulate: Boolean) {} fun preExtract(slot: Int, amount: Int, simulate: Boolean) {}
fun modifyInsertCount(slot: Int, stack: ItemStack, existing: ItemStack, simulate: Boolean): Int {
return stack.count
}
fun modifyExtractCount(slot: Int, amount: Int, simulate: Boolean): Int {
return amount
}
fun and(other: HandlerFilter): HandlerFilter { fun and(other: HandlerFilter): HandlerFilter {
return object : HandlerFilter { return object : HandlerFilter {
override fun canInsert(slot: Int, stack: ItemStack): Boolean { override fun canInsert(slot: Int, stack: ItemStack): Boolean {

View File

@ -175,6 +175,13 @@ inline fun <V : Any> immutableList(initializer: Consumer<V>.() -> Unit): Immutab
return builder.build() return builder.build()
} }
fun <V : Any> immutableList(a: V, vararg values: V): ImmutableList<V> {
val builder = ImmutableList.Builder<V>()
builder.add(a)
builder.addAll(values.iterator())
return builder.build()
}
fun <T> IForgeRegistry<T>.getID(value: T): Int { fun <T> IForgeRegistry<T>.getID(value: T): Int {
return (this as ForgeRegistry<T>).getID(value) return (this as ForgeRegistry<T>).getID(value)
} }

View File

@ -5,6 +5,7 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtAccounter import net.minecraft.nbt.NbtAccounter
import net.minecraft.nbt.NbtIo import net.minecraft.nbt.NbtIo
import net.minecraft.network.chat.Component import net.minecraft.network.chat.Component
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.material.Fluid import net.minecraft.world.level.material.Fluid
@ -327,3 +328,12 @@ fun OutputStream.writeBinaryString(input: String) {
writeVarIntLE(bytes.size) writeVarIntLE(bytes.size)
write(bytes) write(bytes)
} }
fun InputStream.readResourceLocation(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): ResourceLocation {
return ResourceLocation(readBinaryString(sizeLimit), readBinaryString(sizeLimit))
}
fun OutputStream.writeResourceLocation(value: ResourceLocation) {
writeBinaryString(value.namespace)
writeBinaryString(value.path)
}

View File

@ -122,6 +122,7 @@ val UUIDValueCodec = StreamCodec({ s, a -> a.accountBytes(8L); UUID(s.readLong()
val VarIntValueCodec = StreamCodec(DataInputStream::readVarIntLE, DataOutputStream::writeVarIntLE) { a, b -> a == b } val VarIntValueCodec = StreamCodec(DataInputStream::readVarIntLE, DataOutputStream::writeVarIntLE) { a, b -> a == b }
val VarLongValueCodec = StreamCodec(DataInputStream::readVarLongLE, DataOutputStream::writeVarLongLE) { a, b -> a == b } val VarLongValueCodec = StreamCodec(DataInputStream::readVarLongLE, DataOutputStream::writeVarLongLE) { a, b -> a == b }
val BinaryStringCodec = StreamCodec(DataInputStream::readBinaryString, DataOutputStream::writeBinaryString) val BinaryStringCodec = StreamCodec(DataInputStream::readBinaryString, DataOutputStream::writeBinaryString)
val ResourceLocationValueCodec = StreamCodec(DataInputStream::readResourceLocation, DataOutputStream::writeResourceLocation)
val RGBCodec: StreamCodec<RGBAColor> = StreamCodec( val RGBCodec: StreamCodec<RGBAColor> = StreamCodec(
{ s, a -> a.accountBytes(12L); RGBAColor(s.readFloat(), s.readFloat(), s.readFloat()) }, { s, a -> a.accountBytes(12L); RGBAColor(s.readFloat(), s.readFloat(), s.readFloat()) },

View File

@ -0,0 +1,119 @@
package ru.dbotthepony.mc.otm.menu.tech
import net.minecraft.world.SimpleContainer
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.block.entity.tech.PainterBlockEntity
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.ISubscriptable
import ru.dbotthepony.mc.otm.core.addAll
import ru.dbotthepony.mc.otm.core.collect.SupplierMap
import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator
import ru.dbotthepony.mc.otm.core.util.ResourceLocationValueCodec
import ru.dbotthepony.mc.otm.menu.MatteryMenu
import ru.dbotthepony.mc.otm.menu.MatterySlot
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.registry.MMenus
import ru.dbotthepony.mc.otm.registry.MRecipes
import java.util.*
import java.util.function.IntConsumer
import kotlin.collections.ArrayList
class PainterMenu(
containerId: Int, inventory: Inventory, tile: PainterBlockEntity? = null
) : MatteryMenu(MMenus.PAINTER, containerId, inventory, tile) {
val dyeStored = DyeColor.entries.associateWith { dye ->
mSynchronizer.ComputedIntField({ tile?.dyeStored(dye) ?: 0 }).also { it.addListener(IntConsumer { rescan() }) }
}
val dyeStoredDirect = SupplierMap(dyeStored)
val itemConfig = ItemConfigPlayerInput(this, tile?.config)
val inputContainer = MatteryContainer(::rescan, 1)
val outputContainer = MatteryContainer(1)
private var lastRecipe: PainterRecipe? = null
var selectedRecipe by mSynchronizer.Field(null, ResourceLocationValueCodec.nullable).also { it.addListener { rescan() } }
val selectRecipe = PlayerInput(ResourceLocationValueCodec) {
selectedRecipe = it
}
val inputSlot = object : MatterySlot(inputContainer, 0) {
override fun mayPlace(itemStack: ItemStack): Boolean {
return super.mayPlace(itemStack) && inventory.player.level().recipeManager.byType(MRecipes.PAINTER).values.any { it.input.test(itemStack) }
}
}
val outputSlot = object : MatterySlot(outputContainer, 0) {
override fun tryRemove(p_150642_: Int, p_150643_: Int, p_150644_: Player): Optional<ItemStack> {
rescan()
return super.tryRemove(p_150642_, p_150643_, p_150644_)
}
override fun onTake(p_150645_: Player, p_150646_: ItemStack) {
if (p_150646_.isNotEmpty) {
lastRecipe?.dyes?.let { tile?.takeDyes(it) }
inputContainer.removeItem(0, 1)
}
super.onTake(p_150645_, p_150646_)
}
override fun mayPlace(itemStack: ItemStack): Boolean {
return false
}
}
val dyeSlot = object : MatterySlot(tile?.dyeInput ?: SimpleContainer(1), 0) {
override fun mayPlace(itemStack: ItemStack): Boolean {
return super.mayPlace(itemStack) && (DyeColor.getColor(itemStack)?.let { dyeStoredDirect[it]!! + PainterBlockEntity.HUE_PER_ITEM <= PainterBlockEntity.MAX_STORAGE } ?: false)
}
}
init {
addSlot(outputSlot)
addSlot(dyeSlot)
addStorageSlot(dyeSlot)
addStorageSlot(inputSlot)
mapQuickMoveToInventory(outputSlot)
mapQuickMoveToInventory(dyeSlot)
addInventorySlots()
}
override fun removed(p_38940_: Player) {
super.removed(p_38940_)
clearContainer(p_38940_, inputContainer)
}
val listeners = ISubscriptable.Impl<Unit>()
val possibleRecipes = ArrayList<PainterRecipe>()
private fun rescan() {
possibleRecipes.clear()
possibleRecipes.addAll(inventory.player.level().recipeManager.byType(MRecipes.PAINTER).values.iterator().filter { it.input.test(inputContainer[0]) })
possibleRecipes.sortWith(CreativeMenuItemComparator.map { it.output.item })
listeners.accept(Unit)
if (tile !is PainterBlockEntity) return
if (inputContainer.isEmpty || selectedRecipe == null) {
outputContainer.clearContent()
} else {
val recipe = inventory.player.level().recipeManager.byType(MRecipes.PAINTER)[selectedRecipe]
if (recipe == null || !recipe.canCraft(dyeStoredDirect) || !recipe.matches(inputContainer, inventory.player.level())) {
outputContainer.clearContent()
} else {
outputContainer[0] = recipe.assemble(inputContainer, inventory.player.level().registryAccess())
lastRecipe = recipe
}
}
}
}

View File

@ -0,0 +1,135 @@
package ru.dbotthepony.mc.otm.recipe
import com.google.common.collect.ImmutableSet
import com.mojang.datafixers.util.Either
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess
import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.resources.ResourceLocation
import net.minecraft.world.Container
import net.minecraft.world.item.DyeColor
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.block.entity.tech.PainterBlockEntity
import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.tagNotNull
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
import ru.dbotthepony.mc.otm.data.CodecList
import ru.dbotthepony.mc.otm.data.IngredientCodec
import ru.dbotthepony.mc.otm.data.PredicatedCodecList
import ru.dbotthepony.mc.otm.data.minRange
import ru.dbotthepony.mc.otm.registry.MRecipes
import java.util.EnumMap
import java.util.function.Predicate
class PainterRecipe(
private val id: ResourceLocation,
val input: Ingredient,
val output: ItemStack,
val dyes: Map<DyeColor, Int>
) : Recipe<Container> {
constructor(
id: ResourceLocation,
input: Ingredient,
output: ItemStack,
dyes: Set<DyeColor>
) : this(id, input, output, dyes.associateWith { 1 })
fun canCraft(storedDyes: Map<DyeColor, Int>): Boolean {
if (isIncomplete) return false
if (dyes.isEmpty() || dyes.values.none { it > 0 }) return true
val copy = EnumMap(storedDyes)
for ((dye, amount) in dyes) {
for (i in 0 until amount) {
PainterBlockEntity.mixer(dye).mix(copy)
if (copy[dye]!! <= 0) return false
copy[dye] = copy[dye]!! - 1
}
}
return true
}
override fun matches(p_44002_: Container, p_44003_: Level): Boolean {
if (isIncomplete) return false
return input.test(p_44002_[0])
}
override fun isIncomplete(): Boolean {
return input.isActuallyEmpty || output.isEmpty
}
override fun getIngredients(): NonNullList<Ingredient> {
return NonNullList.of(Ingredient.EMPTY, input)
}
override fun assemble(p_44001_: Container, p_267165_: RegistryAccess): ItemStack {
return output.copy().also { o ->
p_44001_[0].tag?.let {
if (o.tag == null) {
o.tag = it.copy()
} else {
for (k in it.allKeys)
if (k !in o.tagNotNull)
o.tagNotNull[k] = it[k]!!.copy()
}
}
}
}
override fun canCraftInDimensions(p_43999_: Int, p_44000_: Int): Boolean {
return true
}
override fun isSpecial(): Boolean {
return true
}
override fun getResultItem(p_267052_: RegistryAccess): ItemStack {
return output
}
override fun getId(): ResourceLocation {
return id
}
override fun getSerializer(): RecipeSerializer<*> {
return SERIALIZER
}
override fun getType(): RecipeType<*> {
return MRecipes.PAINTER
}
fun toFinished(): FinishedRecipe {
return SERIALIZER.toFinished(this)
}
companion object {
val SERIALIZER = Codec2RecipeSerializer<PainterRecipe>(
PainterRecipe(ResourceLocation(OverdriveThatMatters.MOD_ID, "empty"), Ingredient.EMPTY, ItemStack.EMPTY, setOf())
) { context ->
RecordCodecBuilder.create {
it.group(
IngredientCodec.fieldOf("input").forGetter(PainterRecipe::input),
ItemStack.CODEC.fieldOf("output").forGetter(PainterRecipe::output),
PredicatedCodecList<Map<DyeColor, Int>>(
DyeColor.CODEC.xmap({ mapOf(it to 1) }, { it.keys.first() }) to Predicate { it.keys.size == 1 && it.values.first() == 1 },
Codec.list(DyeColor.CODEC).xmap({ it.associateWith { 1 } }, { ArrayList(it.keys) }) to Predicate { it.values.all { it == 1 } },
Codec.unboundedMap(DyeColor.CODEC, Codec.INT.minRange(1)) to Predicate { true }
).fieldOf("dyes").forGetter(PainterRecipe::dyes),
).apply(it) { a, b, c -> PainterRecipe(context.invoke(), a, b, c) }
}
}
}
}

View File

@ -1,11 +1,14 @@
package ru.dbotthepony.mc.otm.registry package ru.dbotthepony.mc.otm.registry
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers import net.minecraft.client.renderer.blockentity.BlockEntityRenderers
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraft.world.level.block.entity.BlockEntityType import net.minecraft.world.level.block.entity.BlockEntityType
import net.minecraftforge.eventbus.api.IEventBus import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent
import net.minecraftforge.registries.DeferredRegister import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.block.entity.* import ru.dbotthepony.mc.otm.block.entity.*
import ru.dbotthepony.mc.otm.block.entity.tech.* import ru.dbotthepony.mc.otm.block.entity.tech.*
@ -25,43 +28,49 @@ import ru.dbotthepony.mc.otm.block.entity.tech.EnergyServoBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.GravitationStabilizerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity import ru.dbotthepony.mc.otm.block.entity.tech.PlatePressBlockEntity
import ru.dbotthepony.mc.otm.client.render.blockentity.* import ru.dbotthepony.mc.otm.client.render.blockentity.*
import java.util.function.Supplier
@Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // Type<*> is unused in BlockEntityType.Builder @Suppress("NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS") // Type<*> is unused in BlockEntityType.Builder
object MBlockEntities { object MBlockEntities {
private val registry = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, OverdriveThatMatters.MOD_ID) private val registry = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, OverdriveThatMatters.MOD_ID)
val ANDROID_STATION: BlockEntityType<AndroidStationBlockEntity> by registry.register(MNames.ANDROID_STATION) { BlockEntityType.Builder.of(::AndroidStationBlockEntity, MBlocks.ANDROID_STATION).build(null) } private fun <T : BlockEntity> register(name: String, factory: BlockEntityType.BlockEntitySupplier<T>, vararg blocks: Supplier<Block>): RegistryObject<BlockEntityType<T>> {
val BATTERY_BANK: BlockEntityType<BatteryBankBlockEntity> by registry.register(MNames.BATTERY_BANK) { BlockEntityType.Builder.of(::BatteryBankBlockEntity, MBlocks.BATTERY_BANK).build(null) } return registry.register(name) { BlockEntityType.Builder.of(factory, *blocks.map { it.get() }.toTypedArray()).build(null) }
val MATTER_DECOMPOSER: BlockEntityType<MatterDecomposerBlockEntity> by registry.register(MNames.MATTER_DECOMPOSER) { BlockEntityType.Builder.of(::MatterDecomposerBlockEntity, MBlocks.MATTER_DECOMPOSER).build(null) } }
val MATTER_CAPACITOR_BANK: BlockEntityType<MatterCapacitorBankBlockEntity> by registry.register(MNames.MATTER_CAPACITOR_BANK) { BlockEntityType.Builder.of(::MatterCapacitorBankBlockEntity, MBlocks.MATTER_CAPACITOR_BANK).build(null) }
val MATTER_CABLE: BlockEntityType<MatterCableBlockEntity> by registry.register(MNames.MATTER_CABLE) { BlockEntityType.Builder.of(::MatterCableBlockEntity, MBlocks.MATTER_CABLE).build(null) } val ANDROID_STATION by register(MNames.ANDROID_STATION, ::AndroidStationBlockEntity, MBlocks::ANDROID_STATION)
val STORAGE_CABLE: BlockEntityType<StorageCableBlockEntity> by registry.register(MNames.STORAGE_CABLE) { BlockEntityType.Builder.of(::StorageCableBlockEntity, MBlocks.STORAGE_CABLE).build(null) } val BATTERY_BANK by register(MNames.BATTERY_BANK, ::BatteryBankBlockEntity, MBlocks::BATTERY_BANK)
val PATTERN_STORAGE: BlockEntityType<PatternStorageBlockEntity> by registry.register(MNames.PATTERN_STORAGE) { BlockEntityType.Builder.of(::PatternStorageBlockEntity, MBlocks.PATTERN_STORAGE).build(null) } val MATTER_DECOMPOSER by register(MNames.MATTER_DECOMPOSER, ::MatterDecomposerBlockEntity, MBlocks::MATTER_DECOMPOSER)
val MATTER_SCANNER: BlockEntityType<MatterScannerBlockEntity> by registry.register(MNames.MATTER_SCANNER) { BlockEntityType.Builder.of(::MatterScannerBlockEntity, MBlocks.MATTER_SCANNER).build(null) } val MATTER_CAPACITOR_BANK by register(MNames.MATTER_CAPACITOR_BANK, ::MatterCapacitorBankBlockEntity, MBlocks::MATTER_CAPACITOR_BANK)
val MATTER_PANEL: BlockEntityType<MatterPanelBlockEntity> by registry.register(MNames.MATTER_PANEL) { BlockEntityType.Builder.of(::MatterPanelBlockEntity, MBlocks.MATTER_PANEL).build(null) } val MATTER_CABLE by register(MNames.MATTER_CABLE, ::MatterCableBlockEntity, MBlocks::MATTER_CABLE)
val MATTER_REPLICATOR: BlockEntityType<MatterReplicatorBlockEntity> by registry.register(MNames.MATTER_REPLICATOR) { BlockEntityType.Builder.of(::MatterReplicatorBlockEntity, MBlocks.MATTER_REPLICATOR).build(null) } val STORAGE_CABLE by register(MNames.STORAGE_CABLE, ::StorageCableBlockEntity, MBlocks::STORAGE_CABLE)
val MATTER_BOTTLER: BlockEntityType<MatterBottlerBlockEntity> by registry.register(MNames.MATTER_BOTTLER) { BlockEntityType.Builder.of(::MatterBottlerBlockEntity, MBlocks.MATTER_BOTTLER).build(null) } val PATTERN_STORAGE by register(MNames.PATTERN_STORAGE, ::PatternStorageBlockEntity, MBlocks::PATTERN_STORAGE)
val DRIVE_VIEWER: BlockEntityType<DriveViewerBlockEntity> by registry.register(MNames.DRIVE_VIEWER) { BlockEntityType.Builder.of(::DriveViewerBlockEntity, MBlocks.DRIVE_VIEWER).build(null) } val MATTER_SCANNER by register(MNames.MATTER_SCANNER, ::MatterScannerBlockEntity, MBlocks::MATTER_SCANNER)
val BLACK_HOLE: BlockEntityType<BlackHoleBlockEntity> by registry.register(MNames.BLACK_HOLE) { BlockEntityType.Builder.of(::BlackHoleBlockEntity, MBlocks.BLACK_HOLE).build(null) } val MATTER_PANEL by register(MNames.MATTER_PANEL, ::MatterPanelBlockEntity, MBlocks::MATTER_PANEL)
val CARGO_CRATE: BlockEntityType<CargoCrateBlockEntity> by registry.register(MNames.CARGO_CRATE) { BlockEntityType.Builder.of(::CargoCrateBlockEntity, *MRegistry.CARGO_CRATES.blocks.values.toTypedArray()).build(null) } val MATTER_REPLICATOR by register(MNames.MATTER_REPLICATOR, ::MatterReplicatorBlockEntity, MBlocks::MATTER_REPLICATOR)
val DRIVE_RACK: BlockEntityType<DriveRackBlockEntity> by registry.register(MNames.DRIVE_RACK) { BlockEntityType.Builder.of(::DriveRackBlockEntity, MBlocks.DRIVE_RACK).build(null) } val MATTER_BOTTLER by register(MNames.MATTER_BOTTLER, ::MatterBottlerBlockEntity, MBlocks::MATTER_BOTTLER)
val ITEM_MONITOR: BlockEntityType<ItemMonitorBlockEntity> by registry.register(MNames.ITEM_MONITOR) { BlockEntityType.Builder.of(::ItemMonitorBlockEntity, MBlocks.ITEM_MONITOR).build(null) } val DRIVE_VIEWER by register(MNames.DRIVE_VIEWER, ::DriveViewerBlockEntity, MBlocks::DRIVE_VIEWER)
val ENERGY_COUNTER: BlockEntityType<EnergyCounterBlockEntity> by registry.register(MNames.ENERGY_COUNTER) { BlockEntityType.Builder.of(::EnergyCounterBlockEntity, MBlocks.ENERGY_COUNTER).build(null) } val BLACK_HOLE by register(MNames.BLACK_HOLE, ::BlackHoleBlockEntity, MBlocks::BLACK_HOLE)
val CHEMICAL_GENERATOR: BlockEntityType<ChemicalGeneratorBlockEntity> by registry.register(MNames.CHEMICAL_GENERATOR) { BlockEntityType.Builder.of(::ChemicalGeneratorBlockEntity, MBlocks.CHEMICAL_GENERATOR).build(null) } val CARGO_CRATE by registry.register(MNames.CARGO_CRATE) { BlockEntityType.Builder.of(::CargoCrateBlockEntity, *MRegistry.CARGO_CRATES.blocks.values.toTypedArray()).build(null) }
val PLATE_PRESS: BlockEntityType<PlatePressBlockEntity> by registry.register(MNames.PLATE_PRESS) { BlockEntityType.Builder.of(::PlatePressBlockEntity, MBlocks.PLATE_PRESS).build(null) } val DRIVE_RACK by register(MNames.DRIVE_RACK, ::DriveRackBlockEntity, MBlocks::DRIVE_RACK)
val TWIN_PLATE_PRESS: BlockEntityType<PlatePressBlockEntity> by registry.register(MNames.TWIN_PLATE_PRESS) { BlockEntityType.Builder.of({ a, b -> PlatePressBlockEntity(a, b, true) }, MBlocks.TWIN_PLATE_PRESS).build(null) } val ITEM_MONITOR by register(MNames.ITEM_MONITOR, ::ItemMonitorBlockEntity, MBlocks::ITEM_MONITOR)
val GRAVITATION_STABILIZER: BlockEntityType<GravitationStabilizerBlockEntity> by registry.register(MNames.GRAVITATION_STABILIZER) { BlockEntityType.Builder.of(::GravitationStabilizerBlockEntity, MBlocks.GRAVITATION_STABILIZER).build(null) } val ENERGY_COUNTER by register(MNames.ENERGY_COUNTER, ::EnergyCounterBlockEntity, MBlocks::ENERGY_COUNTER)
val MATTER_RECYCLER: BlockEntityType<MatterRecyclerBlockEntity> by registry.register(MNames.MATTER_RECYCLER) { BlockEntityType.Builder.of(::MatterRecyclerBlockEntity, MBlocks.MATTER_RECYCLER).build(null) } val CHEMICAL_GENERATOR by register(MNames.CHEMICAL_GENERATOR, ::ChemicalGeneratorBlockEntity, MBlocks::CHEMICAL_GENERATOR)
val ENERGY_SERVO: BlockEntityType<EnergyServoBlockEntity> by registry.register(MNames.ENERGY_SERVO) { BlockEntityType.Builder.of(::EnergyServoBlockEntity, MBlocks.ENERGY_SERVO).build(null) } val PLATE_PRESS by register(MNames.PLATE_PRESS, ::PlatePressBlockEntity, MBlocks::PLATE_PRESS)
val COBBLESTONE_GENERATOR: BlockEntityType<CobblerBlockEntity> by registry.register(MNames.COBBLESTONE_GENERATOR) { BlockEntityType.Builder.of(::CobblerBlockEntity, MBlocks.COBBLESTONE_GENERATOR).build(null) } val TWIN_PLATE_PRESS by register(MNames.TWIN_PLATE_PRESS, { a, b -> PlatePressBlockEntity(a, b, true) }, MBlocks::TWIN_PLATE_PRESS)
val ESSENCE_STORAGE: BlockEntityType<EssenceStorageBlockEntity> by registry.register(MNames.ESSENCE_STORAGE) { BlockEntityType.Builder.of(::EssenceStorageBlockEntity, MBlocks.ESSENCE_STORAGE).build(null) } val GRAVITATION_STABILIZER by register(MNames.GRAVITATION_STABILIZER, ::GravitationStabilizerBlockEntity, MBlocks::GRAVITATION_STABILIZER)
val MATTER_RECONSTRUCTOR: BlockEntityType<MatterReconstructorBlockEntity> by registry.register(MNames.MATTER_RECONSTRUCTOR) { BlockEntityType.Builder.of(::MatterReconstructorBlockEntity, MBlocks.MATTER_RECONSTRUCTOR).build(null) } val MATTER_RECYCLER by register(MNames.MATTER_RECYCLER, ::MatterRecyclerBlockEntity, MBlocks::MATTER_RECYCLER)
val FLUID_TANK: BlockEntityType<FluidTankBlockEntity> by registry.register(MNames.FLUID_TANK) { BlockEntityType.Builder.of(::FluidTankBlockEntity, MBlocks.FLUID_TANK).build(null) } val ENERGY_SERVO by register(MNames.ENERGY_SERVO, ::EnergyServoBlockEntity, MBlocks::ENERGY_SERVO)
val ANDROID_CHARGER: BlockEntityType<AndroidChargerBlockEntity> by registry.register(MNames.ANDROID_CHARGER) { BlockEntityType.Builder.of(::AndroidChargerBlockEntity, MBlocks.ANDROID_CHARGER).build(null) } val COBBLESTONE_GENERATOR by register(MNames.COBBLESTONE_GENERATOR, ::CobblerBlockEntity, MBlocks::COBBLESTONE_GENERATOR)
val ANDROID_CHARGER_MIDDLE: BlockEntityType<AndroidChargerMiddleBlockEntity> by registry.register(MNames.ANDROID_CHARGER + "_middle") { BlockEntityType.Builder.of(::AndroidChargerMiddleBlockEntity, MBlocks.ANDROID_CHARGER).build(null) } val ESSENCE_STORAGE by register(MNames.ESSENCE_STORAGE, ::EssenceStorageBlockEntity, MBlocks::ESSENCE_STORAGE)
val ANDROID_CHARGER_TOP: BlockEntityType<AndroidChargerTopBlockEntity> by registry.register(MNames.ANDROID_CHARGER + "_top") { BlockEntityType.Builder.of(::AndroidChargerTopBlockEntity, MBlocks.ANDROID_CHARGER).build(null) } val MATTER_RECONSTRUCTOR by register(MNames.MATTER_RECONSTRUCTOR, ::MatterReconstructorBlockEntity, MBlocks::MATTER_RECONSTRUCTOR)
val INFINITE_WATER_SOURCE: BlockEntityType<InfiniteWaterSourceBlockEntity> by registry.register(MNames.INFINITE_WATER_SOURCE) { BlockEntityType.Builder.of(::InfiniteWaterSourceBlockEntity, MBlocks.INFINITE_WATER_SOURCE).build(null) } val FLUID_TANK by register(MNames.FLUID_TANK, ::FluidTankBlockEntity, MBlocks::FLUID_TANK)
val DEV_CHEST: BlockEntityType<DevChestBlockEntity> by registry.register(MNames.DEV_CHEST) { BlockEntityType.Builder.of(::DevChestBlockEntity, MBlocks.DEV_CHEST).build(null) } val ANDROID_CHARGER by register(MNames.ANDROID_CHARGER, ::AndroidChargerBlockEntity, MBlocks::ANDROID_CHARGER)
val ANDROID_CHARGER_MIDDLE by register(MNames.ANDROID_CHARGER + "_middle", ::AndroidChargerMiddleBlockEntity, MBlocks::ANDROID_CHARGER)
val ANDROID_CHARGER_TOP by register(MNames.ANDROID_CHARGER + "_top", ::AndroidChargerTopBlockEntity, MBlocks::ANDROID_CHARGER)
val INFINITE_WATER_SOURCE by register(MNames.INFINITE_WATER_SOURCE, ::InfiniteWaterSourceBlockEntity, MBlocks::INFINITE_WATER_SOURCE)
val DEV_CHEST by register(MNames.DEV_CHEST, ::DevChestBlockEntity, MBlocks::DEV_CHEST)
val PAINTER by register(MNames.PAINTER, ::PainterBlockEntity, MBlocks::PAINTER)
val POWERED_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_FURNACE).build(null) } val POWERED_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_FURNACE).build(null) }
val POWERED_BLAST_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_BLAST_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_BLAST_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_BLAST_FURNACE).build(null) } val POWERED_BLAST_FURNACE: BlockEntityType<PoweredFurnaceBlockEntity> by registry.register(MNames.POWERED_BLAST_FURNACE) { BlockEntityType.Builder.of({ a, b -> MBlocks.POWERED_BLAST_FURNACE.newBlockEntity(a, b) }, MBlocks.POWERED_BLAST_FURNACE).build(null) }

View File

@ -63,6 +63,7 @@ import ru.dbotthepony.mc.otm.block.storage.StoragePowerSupplierBlock
import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock import ru.dbotthepony.mc.otm.block.tech.AndroidChargerBlock
import ru.dbotthepony.mc.otm.block.tech.CobblerBlock import ru.dbotthepony.mc.otm.block.tech.CobblerBlock
import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock import ru.dbotthepony.mc.otm.block.tech.EssenceStorageBlock
import ru.dbotthepony.mc.otm.block.tech.PainterBlock
import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock import ru.dbotthepony.mc.otm.block.tech.PoweredFurnaceBlock
import ru.dbotthepony.mc.otm.config.MachinesConfig import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
@ -100,6 +101,7 @@ object MBlocks {
val INFINITE_WATER_SOURCE: Block by registry.register(MNames.INFINITE_WATER_SOURCE) { InfiniteWaterSourceBlock() } val INFINITE_WATER_SOURCE: Block by registry.register(MNames.INFINITE_WATER_SOURCE) { InfiniteWaterSourceBlock() }
val ESSENCE_STORAGE: EssenceStorageBlock by registry.register(MNames.ESSENCE_STORAGE) { EssenceStorageBlock() } val ESSENCE_STORAGE: EssenceStorageBlock by registry.register(MNames.ESSENCE_STORAGE) { EssenceStorageBlock() }
val MATTER_RECONSTRUCTOR: MatterReconstructorBlock by registry.register(MNames.MATTER_RECONSTRUCTOR) { MatterReconstructorBlock() } val MATTER_RECONSTRUCTOR: MatterReconstructorBlock by registry.register(MNames.MATTER_RECONSTRUCTOR) { MatterReconstructorBlock() }
val PAINTER: PainterBlock by registry.register(MNames.PAINTER) { PainterBlock() }
val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS) { StorageBusBlock() } val STORAGE_BUS: Block by registry.register(MNames.STORAGE_BUS) { StorageBusBlock() }
val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() } val STORAGE_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() }

View File

@ -151,6 +151,8 @@ object MItems {
} }
} }
val PAINTER: BlockItem by registry.register(MNames.PAINTER) { BlockItem(MBlocks.PAINTER, DEFAULT_PROPERTIES) }
val MACHINES = SupplierList( val MACHINES = SupplierList(
::ANDROID_STATION, ::ANDROID_CHARGER, ::BATTERY_BANK, ::MATTER_DECOMPOSER, ::MATTER_CAPACITOR_BANK, ::MATTER_CABLE, ::PATTERN_STORAGE, ::ANDROID_STATION, ::ANDROID_CHARGER, ::BATTERY_BANK, ::MATTER_DECOMPOSER, ::MATTER_CAPACITOR_BANK, ::MATTER_CABLE, ::PATTERN_STORAGE,
::MATTER_SCANNER, ::MATTER_PANEL, ::MATTER_REPLICATOR, ::MATTER_BOTTLER, ::ENERGY_COUNTER, ::CHEMICAL_GENERATOR, ::MATTER_SCANNER, ::MATTER_PANEL, ::MATTER_REPLICATOR, ::MATTER_BOTTLER, ::ENERGY_COUNTER, ::CHEMICAL_GENERATOR,
@ -158,7 +160,7 @@ object MItems {
::POWERED_SMOKER, ::POWERED_SMOKER,
::STORAGE_BUS, ::STORAGE_IMPORTER, ::STORAGE_EXPORTER, ::DRIVE_VIEWER, ::STORAGE_BUS, ::STORAGE_IMPORTER, ::STORAGE_EXPORTER, ::DRIVE_VIEWER,
::DRIVE_RACK, ::ITEM_MONITOR, ::STORAGE_CABLE, ::STORAGE_POWER_SUPPLIER, ::DRIVE_RACK, ::ITEM_MONITOR, ::STORAGE_CABLE, ::STORAGE_POWER_SUPPLIER,
::ENERGY_SERVO, ::ENERGY_SERVO, ::PAINTER,
::PHANTOM_ATTRACTOR, ::GRAVITATION_STABILIZER, ::COBBLESTONE_GENERATOR, ::INFINITE_WATER_SOURCE, ::PHANTOM_ATTRACTOR, ::GRAVITATION_STABILIZER, ::COBBLESTONE_GENERATOR, ::INFINITE_WATER_SOURCE,
::ESSENCE_STORAGE, ::MATTER_RECONSTRUCTOR ::ESSENCE_STORAGE, ::MATTER_RECONSTRUCTOR
) )

View File

@ -36,6 +36,7 @@ import ru.dbotthepony.mc.otm.client.screen.tech.CobblerScreen
import ru.dbotthepony.mc.otm.client.screen.tech.EnergyCounterScreen import ru.dbotthepony.mc.otm.client.screen.tech.EnergyCounterScreen
import ru.dbotthepony.mc.otm.client.screen.tech.EnergyServoScreen import ru.dbotthepony.mc.otm.client.screen.tech.EnergyServoScreen
import ru.dbotthepony.mc.otm.client.screen.tech.EssenceStorageScreen import ru.dbotthepony.mc.otm.client.screen.tech.EssenceStorageScreen
import ru.dbotthepony.mc.otm.client.screen.tech.PainterScreen
import ru.dbotthepony.mc.otm.client.screen.tech.PlatePressScreen import ru.dbotthepony.mc.otm.client.screen.tech.PlatePressScreen
import ru.dbotthepony.mc.otm.client.screen.tech.PoweredFurnaceScreen import ru.dbotthepony.mc.otm.client.screen.tech.PoweredFurnaceScreen
import ru.dbotthepony.mc.otm.client.screen.tech.TwinPlatePressScreen import ru.dbotthepony.mc.otm.client.screen.tech.TwinPlatePressScreen
@ -66,6 +67,7 @@ import ru.dbotthepony.mc.otm.menu.tech.CobblerMenu
import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu import ru.dbotthepony.mc.otm.menu.tech.EnergyCounterMenu
import ru.dbotthepony.mc.otm.menu.tech.EnergyServoMenu import ru.dbotthepony.mc.otm.menu.tech.EnergyServoMenu
import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu import ru.dbotthepony.mc.otm.menu.tech.EssenceStorageMenu
import ru.dbotthepony.mc.otm.menu.tech.PainterMenu
import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu import ru.dbotthepony.mc.otm.menu.tech.PlatePressMenu
import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu import ru.dbotthepony.mc.otm.menu.tech.PoweredFurnaceMenu
import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu import ru.dbotthepony.mc.otm.menu.tech.TwinPlatePressMenu
@ -100,6 +102,7 @@ object MMenus {
val ESSENCE_STORAGE: MenuType<EssenceStorageMenu> by registry.register(MNames.ESSENCE_STORAGE) { MenuType(::EssenceStorageMenu, FeatureFlags.VANILLA_SET) } val ESSENCE_STORAGE: MenuType<EssenceStorageMenu> by registry.register(MNames.ESSENCE_STORAGE) { MenuType(::EssenceStorageMenu, FeatureFlags.VANILLA_SET) }
val ITEM_REPAIER: MenuType<MatterReconstructorMenu> by registry.register(MNames.MATTER_RECONSTRUCTOR) { MenuType(::MatterReconstructorMenu, FeatureFlags.VANILLA_SET) } val ITEM_REPAIER: MenuType<MatterReconstructorMenu> by registry.register(MNames.MATTER_RECONSTRUCTOR) { MenuType(::MatterReconstructorMenu, FeatureFlags.VANILLA_SET) }
val FLUID_TANK: MenuType<FluidTankMenu> by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) } val FLUID_TANK: MenuType<FluidTankMenu> by registry.register(MNames.FLUID_TANK) { MenuType(::FluidTankMenu, FeatureFlags.VANILLA_SET) }
val PAINTER: MenuType<PainterMenu> by registry.register(MNames.PAINTER) { MenuType(::PainterMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_BUS: MenuType<StorageBusMenu> by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) } val STORAGE_BUS: MenuType<StorageBusMenu> by registry.register(MNames.STORAGE_BUS) { MenuType(::StorageBusMenu, FeatureFlags.VANILLA_SET) }
val STORAGE_IMPORTER_EXPORTER: MenuType<StorageImporterExporterMenu> by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) } val STORAGE_IMPORTER_EXPORTER: MenuType<StorageImporterExporterMenu> by registry.register(MNames.STORAGE_IMPORTER) { MenuType(::StorageImporterExporterMenu, FeatureFlags.VANILLA_SET) }
@ -142,6 +145,7 @@ object MMenus {
MenuScreens.register(ITEM_REPAIER, ::MatterReconstructorScreen) MenuScreens.register(ITEM_REPAIER, ::MatterReconstructorScreen)
MenuScreens.register(FLUID_TANK, ::FluidTankScreen) MenuScreens.register(FLUID_TANK, ::FluidTankScreen)
MenuScreens.register(POWERED_FURNACE, ::PoweredFurnaceScreen) MenuScreens.register(POWERED_FURNACE, ::PoweredFurnaceScreen)
MenuScreens.register(PAINTER, ::PainterScreen)
} }
} }
} }

View File

@ -15,6 +15,7 @@ object MNames {
const val ANDROID_CHARGER = "android_charger" const val ANDROID_CHARGER = "android_charger"
const val INFINITE_WATER_SOURCE = "infinite_water_source" const val INFINITE_WATER_SOURCE = "infinite_water_source"
const val DEV_CHEST = "dev_chest" const val DEV_CHEST = "dev_chest"
const val PAINTER = "painter"
// blocks // blocks
const val ANDROID_STATION = "android_station" const val ANDROID_STATION = "android_station"

View File

@ -10,6 +10,7 @@ import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe
import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe import ru.dbotthepony.mc.otm.recipe.ExplosiveHammerPrimingRecipe
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
@ -36,11 +37,13 @@ object MRecipes {
} }
val PLATE_PRESS by register<PlatePressRecipe>("plate_press") val PLATE_PRESS by register<PlatePressRecipe>("plate_press")
val PAINTER by register<PainterRecipe>("painter")
init { init {
serializers.register("plate_press") { PlatePressRecipe.SERIALIZER } serializers.register("plate_press") { PlatePressRecipe.SERIALIZER }
serializers.register("energy_container") { EnergyContainerRecipe.Companion } serializers.register("energy_container") { EnergyContainerRecipe.Companion }
serializers.register("upgrade") { UpgradeRecipe.Companion } serializers.register("upgrade") { UpgradeRecipe.Companion }
serializers.register("hammer_priming") { ExplosiveHammerPrimingRecipe.Companion } serializers.register("hammer_priming") { ExplosiveHammerPrimingRecipe.Companion }
serializers.register("painter") { PainterRecipe.SERIALIZER }
} }
} }