Painter table
This commit is contained in:
parent
615912de8b
commit
61b83d5f5a
@ -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.addShapelessRecipes
|
||||
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.addTags
|
||||
import ru.dbotthepony.mc.otm.matter.MatterDataProvider
|
||||
@ -562,6 +563,7 @@ object DataGen {
|
||||
addDecorativesRecipes(recipeProvider, consumer)
|
||||
addShapelessRecipes(consumer)
|
||||
addOreSmeltingRecipes(consumer)
|
||||
addPainterRecipes(consumer)
|
||||
}
|
||||
|
||||
addPlatePressRecipes(recipeProvider)
|
||||
|
@ -120,6 +120,9 @@ private fun misc(provider: MatteryLanguageProvider) {
|
||||
gui("help.slot_filters", "Hold CTRL to setup slot filters")
|
||||
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")
|
||||
|
||||
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.DEV_CHEST, "Dev Chest")
|
||||
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, "named", "Fluid Tank (%s)")
|
||||
|
@ -128,6 +128,9 @@ private fun misc(provider: MatteryLanguageProvider) {
|
||||
gui("help.slot_filters", "Удерживайте CTRL для настройки фильтрации слотов")
|
||||
gui("help.slot_charging", "Удерживайте ALT для переключения зарядки слотов")
|
||||
|
||||
gui("needs", "Требуется %s")
|
||||
gui("needs_x", "Требуется %s x%d")
|
||||
|
||||
misc("needs_no_power", "Не требует энергии для работы")
|
||||
|
||||
gui("lock_holo_screen", "Заблокировать содержимое")
|
||||
@ -430,6 +433,7 @@ private fun blocks(provider: MatteryLanguageProvider) {
|
||||
add(MBlocks.MATTER_RECONSTRUCTOR, "desc", "Чинит инструменты используя материю")
|
||||
add(MBlocks.DEV_CHEST, "Сундук разработчика")
|
||||
add(MBlocks.DEV_CHEST, "desc", "Хранит все предметы, которые есть в игре")
|
||||
add(MBlocks.PAINTER, "Стол маляра")
|
||||
|
||||
add(MBlocks.FLUID_TANK, "Жидкостный бак")
|
||||
add(MBlocks.FLUID_TANK, "named", "Жидкостный бак (%s)")
|
||||
|
@ -133,6 +133,7 @@ fun addLootTables(lootTables: LootTables) {
|
||||
lootTables.tile(MBlocks.ESSENCE_STORAGE)
|
||||
lootTables.tile(MBlocks.MATTER_RECONSTRUCTOR)
|
||||
lootTables.tile(MBlocks.FLUID_TANK)
|
||||
lootTables.tile(MBlocks.PAINTER)
|
||||
|
||||
lootTables.tile(MBlocks.ENERGY_SERVO)
|
||||
lootTables.tile(MBlocks.ENERGY_COUNTER)
|
||||
|
@ -433,4 +433,11 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
|
||||
.row(MItemTags.IRON_PLATES, MItemTags.IRON_PLATES, MItemTags.IRON_PLATES)
|
||||
.unlockedBy(Items.WATER_BUCKET)
|
||||
.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)
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
@ -145,6 +145,7 @@ fun addTags(tagsProvider: TagsProvider) {
|
||||
|
||||
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_DOOR.values, Tiers.IRON)
|
||||
tagsProvider.requiresPickaxe(MBlocks.TRITANIUM_TRAPDOOR.values, Tiers.IRON)
|
||||
tagsProvider.requiresPickaxe(MBlocks.PAINTER, Tiers.STONE)
|
||||
|
||||
tagsProvider.requiresPickaxe(listOf(
|
||||
MBlocks.ANDROID_STATION,
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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() }
|
||||
}
|
||||
}
|
@ -3,6 +3,8 @@ package ru.dbotthepony.mc.otm.client.render
|
||||
import net.minecraft.client.gui.GuiGraphics
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import ru.dbotthepony.mc.otm.core.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.systemTime
|
||||
import kotlin.math.sin
|
||||
|
||||
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
|
||||
* 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;
|
||||
* 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
|
||||
|
||||
return object : IGUIRenderable {
|
||||
@ -97,11 +99,11 @@ interface IGUIRenderable {
|
||||
var realY = y
|
||||
|
||||
if (fixedWidth && width > this.width) {
|
||||
realX += (width - this.width) / 2f
|
||||
realX += gravity.repositionX(width, this.width)
|
||||
}
|
||||
|
||||
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)
|
||||
@ -122,22 +124,22 @@ interface 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) {
|
||||
if (x % 1f == 0f && y % 1f == 0f && width == 16f && height == 16f) {
|
||||
guiGraphics.renderFakeItem(itemStack, x.toInt(), y.toInt())
|
||||
clearDepth(guiGraphics.pose(), x, y, width, height)
|
||||
} else {
|
||||
val pose = guiGraphics.pose()
|
||||
|
||||
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)
|
||||
|
||||
guiGraphics.renderFakeItem(itemStack, x.toInt(), y.toInt())
|
||||
guiGraphics.renderFakeItem(itemStack, 0, 0)
|
||||
pose.popPose()
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -1608,7 +1608,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
}
|
||||
|
||||
protected open fun mouseScrolledInner(x: Double, y: Double, scroll: Double): Boolean {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
fun mouseScrolled(x: Double, y: Double, scroll: Double): Boolean {
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
@ -70,17 +70,20 @@ class JEIPlugin : IModPlugin {
|
||||
registration.addRecipeCatalyst(ItemStack(MItems.POWERED_SMOKER), RecipeTypes.SMOKING)
|
||||
registration.addRecipeCatalyst(ItemStack(MItems.ExopackUpgrades.CRAFTING_UPGRADE), RecipeTypes.CRAFTING)
|
||||
registration.addRecipeCatalyst(ItemStack(MItems.PLATE_PRESS), PlatePressRecipeCategory.recipeType)
|
||||
registration.addRecipeCatalyst(ItemStack(MItems.PAINTER), PainterRecipeCategory.recipeType)
|
||||
}
|
||||
|
||||
override fun registerCategories(registration: IRecipeCategoryRegistration) {
|
||||
helpers = registration.jeiHelpers
|
||||
registration.addRecipeCategories(PlatePressRecipeCategory)
|
||||
registration.addRecipeCategories(PainterRecipeCategory)
|
||||
}
|
||||
|
||||
override fun registerRecipes(registration: IRecipeRegistration) {
|
||||
val level = minecraft.level ?: throw NullPointerException("No ClientLevel. OLOLOLOLOLOLO")
|
||||
|
||||
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) {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
@ -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())
|
||||
}
|
||||
}
|
@ -16,20 +16,27 @@ class ContainerHandler @JvmOverloads internal constructor(
|
||||
return stack
|
||||
|
||||
filter.preInsert(slot, stack, simulate)
|
||||
|
||||
val localStack = container[slot]
|
||||
var amount = filter.modifyInsertCount(slot, stack, localStack, simulate)
|
||||
|
||||
if (amount <= 0)
|
||||
return stack
|
||||
|
||||
if (localStack.isEmpty) {
|
||||
amount = stack.count.coerceAtMost(container.getMaxStackSize(slot, stack)).coerceAtMost(amount)
|
||||
|
||||
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
|
||||
} 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)) {
|
||||
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
|
||||
|
||||
if (diff != 0) {
|
||||
@ -51,12 +58,16 @@ class ContainerHandler @JvmOverloads internal constructor(
|
||||
if (amount <= 0 || container.isSlotForbiddenForAutomation(slot))
|
||||
return ItemStack.EMPTY
|
||||
|
||||
filter.preExtract(slot, amount, simulate)
|
||||
|
||||
val localStack = container.getItem(slot)
|
||||
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
|
||||
|
||||
filter.preExtract(slot, amount, simulate)
|
||||
|
||||
val minimal = amount.coerceAtMost(localStack.count)
|
||||
val copy = localStack.copy()
|
||||
copy.count = minimal
|
||||
|
@ -19,6 +19,14 @@ interface HandlerFilter {
|
||||
fun preInsert(slot: Int, stack: ItemStack, 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 {
|
||||
return object : HandlerFilter {
|
||||
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
|
||||
|
@ -175,6 +175,13 @@ inline fun <V : Any> immutableList(initializer: Consumer<V>.() -> Unit): Immutab
|
||||
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 {
|
||||
return (this as ForgeRegistry<T>).getID(value)
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.nbt.NbtAccounter
|
||||
import net.minecraft.nbt.NbtIo
|
||||
import net.minecraft.network.chat.Component
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.item.Item
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.level.material.Fluid
|
||||
@ -327,3 +328,12 @@ fun OutputStream.writeBinaryString(input: String) {
|
||||
writeVarIntLE(bytes.size)
|
||||
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)
|
||||
}
|
||||
|
@ -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 VarLongValueCodec = StreamCodec(DataInputStream::readVarLongLE, DataOutputStream::writeVarLongLE) { a, b -> a == b }
|
||||
val BinaryStringCodec = StreamCodec(DataInputStream::readBinaryString, DataOutputStream::writeBinaryString)
|
||||
val ResourceLocationValueCodec = StreamCodec(DataInputStream::readResourceLocation, DataOutputStream::writeResourceLocation)
|
||||
|
||||
val RGBCodec: StreamCodec<RGBAColor> = StreamCodec(
|
||||
{ s, a -> a.accountBytes(12L); RGBAColor(s.readFloat(), s.readFloat(), s.readFloat()) },
|
||||
|
119
src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PainterMenu.kt
Normal file
119
src/main/kotlin/ru/dbotthepony/mc/otm/menu/tech/PainterMenu.kt
Normal 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
135
src/main/kotlin/ru/dbotthepony/mc/otm/recipe/PainterRecipe.kt
Normal file
135
src/main/kotlin/ru/dbotthepony/mc/otm/recipe/PainterRecipe.kt
Normal 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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,11 +1,14 @@
|
||||
package ru.dbotthepony.mc.otm.registry
|
||||
|
||||
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.minecraftforge.eventbus.api.IEventBus
|
||||
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent
|
||||
import net.minecraftforge.registries.DeferredRegister
|
||||
import net.minecraftforge.registries.ForgeRegistries
|
||||
import net.minecraftforge.registries.RegistryObject
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.block.entity.*
|
||||
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.PlatePressBlockEntity
|
||||
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
|
||||
object MBlockEntities {
|
||||
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) }
|
||||
val BATTERY_BANK: BlockEntityType<BatteryBankBlockEntity> by registry.register(MNames.BATTERY_BANK) { BlockEntityType.Builder.of(::BatteryBankBlockEntity, MBlocks.BATTERY_BANK).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 STORAGE_CABLE: BlockEntityType<StorageCableBlockEntity> by registry.register(MNames.STORAGE_CABLE) { BlockEntityType.Builder.of(::StorageCableBlockEntity, MBlocks.STORAGE_CABLE).build(null) }
|
||||
val PATTERN_STORAGE: BlockEntityType<PatternStorageBlockEntity> by registry.register(MNames.PATTERN_STORAGE) { BlockEntityType.Builder.of(::PatternStorageBlockEntity, MBlocks.PATTERN_STORAGE).build(null) }
|
||||
val MATTER_SCANNER: BlockEntityType<MatterScannerBlockEntity> by registry.register(MNames.MATTER_SCANNER) { BlockEntityType.Builder.of(::MatterScannerBlockEntity, MBlocks.MATTER_SCANNER).build(null) }
|
||||
val MATTER_PANEL: BlockEntityType<MatterPanelBlockEntity> by registry.register(MNames.MATTER_PANEL) { BlockEntityType.Builder.of(::MatterPanelBlockEntity, MBlocks.MATTER_PANEL).build(null) }
|
||||
val MATTER_REPLICATOR: BlockEntityType<MatterReplicatorBlockEntity> by registry.register(MNames.MATTER_REPLICATOR) { BlockEntityType.Builder.of(::MatterReplicatorBlockEntity, MBlocks.MATTER_REPLICATOR).build(null) }
|
||||
val MATTER_BOTTLER: BlockEntityType<MatterBottlerBlockEntity> by registry.register(MNames.MATTER_BOTTLER) { BlockEntityType.Builder.of(::MatterBottlerBlockEntity, MBlocks.MATTER_BOTTLER).build(null) }
|
||||
val DRIVE_VIEWER: BlockEntityType<DriveViewerBlockEntity> by registry.register(MNames.DRIVE_VIEWER) { BlockEntityType.Builder.of(::DriveViewerBlockEntity, MBlocks.DRIVE_VIEWER).build(null) }
|
||||
val BLACK_HOLE: BlockEntityType<BlackHoleBlockEntity> by registry.register(MNames.BLACK_HOLE) { BlockEntityType.Builder.of(::BlackHoleBlockEntity, MBlocks.BLACK_HOLE).build(null) }
|
||||
val CARGO_CRATE: BlockEntityType<CargoCrateBlockEntity> by registry.register(MNames.CARGO_CRATE) { BlockEntityType.Builder.of(::CargoCrateBlockEntity, *MRegistry.CARGO_CRATES.blocks.values.toTypedArray()).build(null) }
|
||||
val DRIVE_RACK: BlockEntityType<DriveRackBlockEntity> by registry.register(MNames.DRIVE_RACK) { BlockEntityType.Builder.of(::DriveRackBlockEntity, MBlocks.DRIVE_RACK).build(null) }
|
||||
val ITEM_MONITOR: BlockEntityType<ItemMonitorBlockEntity> by registry.register(MNames.ITEM_MONITOR) { BlockEntityType.Builder.of(::ItemMonitorBlockEntity, MBlocks.ITEM_MONITOR).build(null) }
|
||||
val ENERGY_COUNTER: BlockEntityType<EnergyCounterBlockEntity> by registry.register(MNames.ENERGY_COUNTER) { BlockEntityType.Builder.of(::EnergyCounterBlockEntity, MBlocks.ENERGY_COUNTER).build(null) }
|
||||
val CHEMICAL_GENERATOR: BlockEntityType<ChemicalGeneratorBlockEntity> by registry.register(MNames.CHEMICAL_GENERATOR) { BlockEntityType.Builder.of(::ChemicalGeneratorBlockEntity, MBlocks.CHEMICAL_GENERATOR).build(null) }
|
||||
val PLATE_PRESS: BlockEntityType<PlatePressBlockEntity> by registry.register(MNames.PLATE_PRESS) { BlockEntityType.Builder.of(::PlatePressBlockEntity, MBlocks.PLATE_PRESS).build(null) }
|
||||
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 GRAVITATION_STABILIZER: BlockEntityType<GravitationStabilizerBlockEntity> by registry.register(MNames.GRAVITATION_STABILIZER) { BlockEntityType.Builder.of(::GravitationStabilizerBlockEntity, MBlocks.GRAVITATION_STABILIZER).build(null) }
|
||||
val MATTER_RECYCLER: BlockEntityType<MatterRecyclerBlockEntity> by registry.register(MNames.MATTER_RECYCLER) { BlockEntityType.Builder.of(::MatterRecyclerBlockEntity, MBlocks.MATTER_RECYCLER).build(null) }
|
||||
val ENERGY_SERVO: BlockEntityType<EnergyServoBlockEntity> by registry.register(MNames.ENERGY_SERVO) { BlockEntityType.Builder.of(::EnergyServoBlockEntity, MBlocks.ENERGY_SERVO).build(null) }
|
||||
val COBBLESTONE_GENERATOR: BlockEntityType<CobblerBlockEntity> by registry.register(MNames.COBBLESTONE_GENERATOR) { BlockEntityType.Builder.of(::CobblerBlockEntity, MBlocks.COBBLESTONE_GENERATOR).build(null) }
|
||||
val ESSENCE_STORAGE: BlockEntityType<EssenceStorageBlockEntity> by registry.register(MNames.ESSENCE_STORAGE) { BlockEntityType.Builder.of(::EssenceStorageBlockEntity, MBlocks.ESSENCE_STORAGE).build(null) }
|
||||
val MATTER_RECONSTRUCTOR: BlockEntityType<MatterReconstructorBlockEntity> by registry.register(MNames.MATTER_RECONSTRUCTOR) { BlockEntityType.Builder.of(::MatterReconstructorBlockEntity, MBlocks.MATTER_RECONSTRUCTOR).build(null) }
|
||||
val FLUID_TANK: BlockEntityType<FluidTankBlockEntity> by registry.register(MNames.FLUID_TANK) { BlockEntityType.Builder.of(::FluidTankBlockEntity, MBlocks.FLUID_TANK).build(null) }
|
||||
val ANDROID_CHARGER: BlockEntityType<AndroidChargerBlockEntity> by registry.register(MNames.ANDROID_CHARGER) { BlockEntityType.Builder.of(::AndroidChargerBlockEntity, MBlocks.ANDROID_CHARGER).build(null) }
|
||||
val ANDROID_CHARGER_MIDDLE: BlockEntityType<AndroidChargerMiddleBlockEntity> by registry.register(MNames.ANDROID_CHARGER + "_middle") { BlockEntityType.Builder.of(::AndroidChargerMiddleBlockEntity, MBlocks.ANDROID_CHARGER).build(null) }
|
||||
val ANDROID_CHARGER_TOP: BlockEntityType<AndroidChargerTopBlockEntity> by registry.register(MNames.ANDROID_CHARGER + "_top") { BlockEntityType.Builder.of(::AndroidChargerTopBlockEntity, MBlocks.ANDROID_CHARGER).build(null) }
|
||||
val INFINITE_WATER_SOURCE: BlockEntityType<InfiniteWaterSourceBlockEntity> by registry.register(MNames.INFINITE_WATER_SOURCE) { BlockEntityType.Builder.of(::InfiniteWaterSourceBlockEntity, MBlocks.INFINITE_WATER_SOURCE).build(null) }
|
||||
val DEV_CHEST: BlockEntityType<DevChestBlockEntity> by registry.register(MNames.DEV_CHEST) { BlockEntityType.Builder.of(::DevChestBlockEntity, MBlocks.DEV_CHEST).build(null) }
|
||||
private fun <T : BlockEntity> register(name: String, factory: BlockEntityType.BlockEntitySupplier<T>, vararg blocks: Supplier<Block>): RegistryObject<BlockEntityType<T>> {
|
||||
return registry.register(name) { BlockEntityType.Builder.of(factory, *blocks.map { it.get() }.toTypedArray()).build(null) }
|
||||
}
|
||||
|
||||
val ANDROID_STATION by register(MNames.ANDROID_STATION, ::AndroidStationBlockEntity, MBlocks::ANDROID_STATION)
|
||||
val BATTERY_BANK by register(MNames.BATTERY_BANK, ::BatteryBankBlockEntity, MBlocks::BATTERY_BANK)
|
||||
val MATTER_DECOMPOSER by register(MNames.MATTER_DECOMPOSER, ::MatterDecomposerBlockEntity, MBlocks::MATTER_DECOMPOSER)
|
||||
val MATTER_CAPACITOR_BANK by register(MNames.MATTER_CAPACITOR_BANK, ::MatterCapacitorBankBlockEntity, MBlocks::MATTER_CAPACITOR_BANK)
|
||||
val MATTER_CABLE by register(MNames.MATTER_CABLE, ::MatterCableBlockEntity, MBlocks::MATTER_CABLE)
|
||||
val STORAGE_CABLE by register(MNames.STORAGE_CABLE, ::StorageCableBlockEntity, MBlocks::STORAGE_CABLE)
|
||||
val PATTERN_STORAGE by register(MNames.PATTERN_STORAGE, ::PatternStorageBlockEntity, MBlocks::PATTERN_STORAGE)
|
||||
val MATTER_SCANNER by register(MNames.MATTER_SCANNER, ::MatterScannerBlockEntity, MBlocks::MATTER_SCANNER)
|
||||
val MATTER_PANEL by register(MNames.MATTER_PANEL, ::MatterPanelBlockEntity, MBlocks::MATTER_PANEL)
|
||||
val MATTER_REPLICATOR by register(MNames.MATTER_REPLICATOR, ::MatterReplicatorBlockEntity, MBlocks::MATTER_REPLICATOR)
|
||||
val MATTER_BOTTLER by register(MNames.MATTER_BOTTLER, ::MatterBottlerBlockEntity, MBlocks::MATTER_BOTTLER)
|
||||
val DRIVE_VIEWER by register(MNames.DRIVE_VIEWER, ::DriveViewerBlockEntity, MBlocks::DRIVE_VIEWER)
|
||||
val BLACK_HOLE by register(MNames.BLACK_HOLE, ::BlackHoleBlockEntity, MBlocks::BLACK_HOLE)
|
||||
val CARGO_CRATE by registry.register(MNames.CARGO_CRATE) { BlockEntityType.Builder.of(::CargoCrateBlockEntity, *MRegistry.CARGO_CRATES.blocks.values.toTypedArray()).build(null) }
|
||||
val DRIVE_RACK by register(MNames.DRIVE_RACK, ::DriveRackBlockEntity, MBlocks::DRIVE_RACK)
|
||||
val ITEM_MONITOR by register(MNames.ITEM_MONITOR, ::ItemMonitorBlockEntity, MBlocks::ITEM_MONITOR)
|
||||
val ENERGY_COUNTER by register(MNames.ENERGY_COUNTER, ::EnergyCounterBlockEntity, MBlocks::ENERGY_COUNTER)
|
||||
val CHEMICAL_GENERATOR by register(MNames.CHEMICAL_GENERATOR, ::ChemicalGeneratorBlockEntity, MBlocks::CHEMICAL_GENERATOR)
|
||||
val PLATE_PRESS by register(MNames.PLATE_PRESS, ::PlatePressBlockEntity, MBlocks::PLATE_PRESS)
|
||||
val TWIN_PLATE_PRESS by register(MNames.TWIN_PLATE_PRESS, { a, b -> PlatePressBlockEntity(a, b, true) }, MBlocks::TWIN_PLATE_PRESS)
|
||||
val GRAVITATION_STABILIZER by register(MNames.GRAVITATION_STABILIZER, ::GravitationStabilizerBlockEntity, MBlocks::GRAVITATION_STABILIZER)
|
||||
val MATTER_RECYCLER by register(MNames.MATTER_RECYCLER, ::MatterRecyclerBlockEntity, MBlocks::MATTER_RECYCLER)
|
||||
val ENERGY_SERVO by register(MNames.ENERGY_SERVO, ::EnergyServoBlockEntity, MBlocks::ENERGY_SERVO)
|
||||
val COBBLESTONE_GENERATOR by register(MNames.COBBLESTONE_GENERATOR, ::CobblerBlockEntity, MBlocks::COBBLESTONE_GENERATOR)
|
||||
val ESSENCE_STORAGE by register(MNames.ESSENCE_STORAGE, ::EssenceStorageBlockEntity, MBlocks::ESSENCE_STORAGE)
|
||||
val MATTER_RECONSTRUCTOR by register(MNames.MATTER_RECONSTRUCTOR, ::MatterReconstructorBlockEntity, MBlocks::MATTER_RECONSTRUCTOR)
|
||||
val FLUID_TANK by register(MNames.FLUID_TANK, ::FluidTankBlockEntity, MBlocks::FLUID_TANK)
|
||||
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_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) }
|
||||
|
@ -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.CobblerBlock
|
||||
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.config.MachinesConfig
|
||||
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 ESSENCE_STORAGE: EssenceStorageBlock by registry.register(MNames.ESSENCE_STORAGE) { EssenceStorageBlock() }
|
||||
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_IMPORTER: Block by registry.register(MNames.STORAGE_IMPORTER) { StorageImporterBlock() }
|
||||
|
@ -151,6 +151,8 @@ object MItems {
|
||||
}
|
||||
}
|
||||
|
||||
val PAINTER: BlockItem by registry.register(MNames.PAINTER) { BlockItem(MBlocks.PAINTER, DEFAULT_PROPERTIES) }
|
||||
|
||||
val MACHINES = SupplierList(
|
||||
::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,
|
||||
@ -158,7 +160,7 @@ object MItems {
|
||||
::POWERED_SMOKER,
|
||||
::STORAGE_BUS, ::STORAGE_IMPORTER, ::STORAGE_EXPORTER, ::DRIVE_VIEWER,
|
||||
::DRIVE_RACK, ::ITEM_MONITOR, ::STORAGE_CABLE, ::STORAGE_POWER_SUPPLIER,
|
||||
::ENERGY_SERVO,
|
||||
::ENERGY_SERVO, ::PAINTER,
|
||||
::PHANTOM_ATTRACTOR, ::GRAVITATION_STABILIZER, ::COBBLESTONE_GENERATOR, ::INFINITE_WATER_SOURCE,
|
||||
::ESSENCE_STORAGE, ::MATTER_RECONSTRUCTOR
|
||||
)
|
||||
|
@ -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.EnergyServoScreen
|
||||
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.PoweredFurnaceScreen
|
||||
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.EnergyServoMenu
|
||||
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.PoweredFurnaceMenu
|
||||
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 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 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_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(FLUID_TANK, ::FluidTankScreen)
|
||||
MenuScreens.register(POWERED_FURNACE, ::PoweredFurnaceScreen)
|
||||
MenuScreens.register(PAINTER, ::PainterScreen)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@ object MNames {
|
||||
const val ANDROID_CHARGER = "android_charger"
|
||||
const val INFINITE_WATER_SOURCE = "infinite_water_source"
|
||||
const val DEV_CHEST = "dev_chest"
|
||||
const val PAINTER = "painter"
|
||||
|
||||
// blocks
|
||||
const val ANDROID_STATION = "android_station"
|
||||
|
@ -10,6 +10,7 @@ import net.minecraftforge.registries.RegistryObject
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe
|
||||
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.UpgradeRecipe
|
||||
|
||||
@ -36,11 +37,13 @@ object MRecipes {
|
||||
}
|
||||
|
||||
val PLATE_PRESS by register<PlatePressRecipe>("plate_press")
|
||||
val PAINTER by register<PainterRecipe>("painter")
|
||||
|
||||
init {
|
||||
serializers.register("plate_press") { PlatePressRecipe.SERIALIZER }
|
||||
serializers.register("energy_container") { EnergyContainerRecipe.Companion }
|
||||
serializers.register("upgrade") { UpgradeRecipe.Companion }
|
||||
serializers.register("hammer_priming") { ExplosiveHammerPrimingRecipe.Companion }
|
||||
serializers.register("painter") { PainterRecipe.SERIALIZER }
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user