paint and remove armor dye in painting table
This commit is contained in:
parent
6c9058e72d
commit
94e1ce6d8e
@ -10,6 +10,7 @@ import net.minecraft.world.item.crafting.Ingredient
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.stream
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.recipe.PainterArmorDyeRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
@ -283,4 +284,9 @@ fun addPainterRecipes(consumer: RecipeOutput) {
|
||||
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)
|
||||
|
||||
for (color in DyeColor.entries) {
|
||||
consumer.accept(PainterArmorDyeRecipe(mapOf(color to 1)).toFinished(modLocation("painter/armor_dye_" + color.getName().lowercase())))
|
||||
}
|
||||
consumer.accept(PainterArmorDyeRecipe(mapOf(null to 15)).toFinished(modLocation("painter/armor_clear_dye")))
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.core.map
|
||||
import ru.dbotthepony.mc.otm.core.math.RGBAColor
|
||||
import ru.dbotthepony.mc.otm.core.util.CreativeMenuItemComparator
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
|
||||
|
||||
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
|
||||
private inner class Bar(parent: EditablePanel<*>, val dye: DyeColor?) : EditablePanel<PainterScreen>(this@PainterScreen, parent, width = 5f) {
|
||||
@ -130,8 +131,19 @@ class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) :
|
||||
buttons.forEach { it.remove() }
|
||||
buttons.clear()
|
||||
|
||||
for (recipe in menu.possibleRecipes.sortedWith(CreativeMenuItemComparator.map { it.value.output.item })) {
|
||||
object : LargeRectangleButtonPanel<PainterScreen>(this@PainterScreen, canvas.canvas, icon = ItemStackIcon(recipe.value.output, 14f, 14f).fixed()) {
|
||||
val recipes = menu.possibleRecipes
|
||||
.filter { !it.value.ingredients.isEmpty() }
|
||||
.sortedWith(CreativeMenuItemComparator.map { it.value.getOutput(menu.inputContainer).item })
|
||||
.plus(
|
||||
menu.possibleRecipes
|
||||
.filter { it.value.ingredients.isEmpty() }
|
||||
.sortedBy { it.id }
|
||||
)
|
||||
|
||||
for (recipe in recipes) {
|
||||
val recipeOutput = recipe.value.getOutput(menu.inputContainer)
|
||||
|
||||
object : LargeRectangleButtonPanel<PainterScreen>(this@PainterScreen, canvas.canvas, icon = ItemStackIcon(recipeOutput, 14f, 14f).fixed()) {
|
||||
init {
|
||||
buttons.add(this)
|
||||
dockRight = 1f
|
||||
@ -143,7 +155,7 @@ class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) :
|
||||
set(value) {}
|
||||
|
||||
override fun innerRenderTooltips(graphics: GuiGraphics, mouseX: Float, mouseY: Float, partialTick: Float): Boolean {
|
||||
val list = getTooltipFromItem(minecraft!!, recipe.value.output)
|
||||
val list = getTooltipFromItem(minecraft!!, recipeOutput)
|
||||
|
||||
recipe.value.dyes.forEach {
|
||||
val (dye, amount) = it
|
||||
|
@ -3,8 +3,7 @@ package ru.dbotthepony.mc.otm.menu.decorative
|
||||
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 net.minecraft.world.item.*
|
||||
import net.minecraft.world.item.crafting.RecipeHolder
|
||||
import net.minecraft.world.level.material.Fluids
|
||||
import net.minecraftforge.common.capabilities.ForgeCapabilities
|
||||
@ -17,19 +16,14 @@ 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.collect.find
|
||||
import ru.dbotthepony.mc.otm.core.collect.maybe
|
||||
import ru.dbotthepony.mc.otm.core.ifPresentK
|
||||
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.isClientThread
|
||||
import ru.dbotthepony.mc.otm.menu.MatteryMenu
|
||||
import ru.dbotthepony.mc.otm.menu.MatterySlot
|
||||
import ru.dbotthepony.mc.otm.menu.input.BooleanInputWithFeedback
|
||||
import ru.dbotthepony.mc.otm.menu.input.ItemConfigPlayerInput
|
||||
import ru.dbotthepony.mc.otm.recipe.PainterRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.AbstractPainterRecipe
|
||||
import ru.dbotthepony.mc.otm.registry.MMenus
|
||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||
import java.util.*
|
||||
@ -48,7 +42,7 @@ class PainterMenu(
|
||||
|
||||
val inputContainer = MatteryContainer(::rescan, 1)
|
||||
val outputContainer = MatteryContainer(1)
|
||||
private var lastRecipe: RecipeHolder<PainterRecipe>? = null
|
||||
private var lastRecipe: RecipeHolder<out AbstractPainterRecipe>? = null
|
||||
var selectedRecipe by mSynchronizer.Field(null, ResourceLocationValueCodec.nullable).also { it.addListener { rescan() } }
|
||||
|
||||
val isBulk = BooleanInputWithFeedback(this, tile?.let { it::isBulk })
|
||||
@ -59,6 +53,10 @@ class PainterMenu(
|
||||
|
||||
val inputSlot = object : MatterySlot(inputContainer, 0) {
|
||||
override fun mayPlace(itemStack: ItemStack): Boolean {
|
||||
if (!itemStack.isEmpty && itemStack.item is DyeableArmorItem) {
|
||||
return super.mayPlace(itemStack)
|
||||
}
|
||||
|
||||
return super.mayPlace(itemStack) && inventory.player.level().recipeManager.byType(MRecipes.PAINTER).values.any { it.value.input.test(itemStack) }
|
||||
}
|
||||
}
|
||||
@ -126,18 +124,24 @@ class PainterMenu(
|
||||
}
|
||||
|
||||
val listeners = ISubscriptable.Impl<Unit>()
|
||||
val possibleRecipes = ArrayList<RecipeHolder<PainterRecipe>>()
|
||||
val possibleRecipes = ArrayList<RecipeHolder<out AbstractPainterRecipe>>()
|
||||
|
||||
private fun rescan() {
|
||||
possibleRecipes.clear()
|
||||
possibleRecipes.addAll(inventory.player.level().recipeManager.byType(MRecipes.PAINTER).values.iterator().filter { it.value.input.test(inputContainer[0]) })
|
||||
|
||||
if (!inputContainer[0].isEmpty && inputContainer[0].item is DyeableArmorItem) {
|
||||
possibleRecipes.addAll(inventory.player.level().recipeManager.byType(MRecipes.PAINTER_ARMOR_DYE).values)
|
||||
}
|
||||
|
||||
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]
|
||||
// val recipe = inventory.player.level().recipeManager.byType(MRecipes.PAINTER)[selectedRecipe]
|
||||
val recipe = inventory.player.level().recipeManager.byKey(selectedRecipe).get() as RecipeHolder<AbstractPainterRecipe>?
|
||||
|
||||
if (recipe == null || !recipe.value.canCraft(dyeStoredDirect) || !recipe.value.matches(inputContainer, inventory.player.level())) {
|
||||
outputContainer.clearContent()
|
||||
|
@ -1,6 +1,5 @@
|
||||
package ru.dbotthepony.mc.otm.recipe
|
||||
|
||||
import com.google.common.collect.ImmutableMap
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder
|
||||
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap
|
||||
@ -12,8 +11,7 @@ import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.StringRepresentable
|
||||
import net.minecraft.world.Container
|
||||
import net.minecraft.world.item.DyeColor
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.*
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.item.crafting.Recipe
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||
@ -29,24 +27,15 @@ import ru.dbotthepony.mc.otm.data.PredicatedCodecList
|
||||
import ru.dbotthepony.mc.otm.data.minRange
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRecipes
|
||||
import java.util.EnumMap
|
||||
import java.util.function.Predicate
|
||||
import java.util.stream.Collector
|
||||
import java.util.stream.Collectors
|
||||
|
||||
class PainterRecipe(
|
||||
val input: Ingredient,
|
||||
val output: ItemStack,
|
||||
abstract class AbstractPainterRecipe(
|
||||
dyes: Map<out DyeColor?, Int>
|
||||
) : Recipe<Container> {
|
||||
constructor(
|
||||
input: Ingredient,
|
||||
output: ItemStack,
|
||||
dyes: Set<DyeColor?>
|
||||
) : this(input, output, Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
|
||||
val dyes: Object2IntMap<DyeColor?> = Object2IntMaps.unmodifiable(Object2IntArrayMap(dyes))
|
||||
|
||||
override fun getToastSymbol(): ItemStack = ItemStack(MItems.PAINTER)
|
||||
|
||||
fun canCraft(storedDyes: Map<out DyeColor?, Int>): Boolean {
|
||||
if (isIncomplete) return false
|
||||
if (dyes.isEmpty() || dyes.values.none { it > 0 }) return true
|
||||
@ -63,6 +52,52 @@ class PainterRecipe(
|
||||
return true
|
||||
}
|
||||
|
||||
override fun canCraftInDimensions(p_43999_: Int, p_44000_: Int): Boolean = true
|
||||
|
||||
override fun isSpecial(): Boolean = true
|
||||
|
||||
open fun getOutput(container: Container): ItemStack {
|
||||
if (container.isEmpty) return ItemStack.EMPTY
|
||||
|
||||
return container[0].copy()
|
||||
}
|
||||
|
||||
enum class DyeColorWrapper(private val refName: String, val key: DyeColor?) : StringRepresentable {
|
||||
WHITE("white", DyeColor.WHITE),
|
||||
ORANGE("orange", DyeColor.ORANGE),
|
||||
MAGENTA("magenta", DyeColor.MAGENTA),
|
||||
LIGHT_BLUE("light_blue", DyeColor.LIGHT_BLUE),
|
||||
YELLOW("yellow", DyeColor.YELLOW),
|
||||
LIME("lime", DyeColor.LIME),
|
||||
PINK("pink", DyeColor.PINK),
|
||||
GRAY("gray", DyeColor.GRAY),
|
||||
LIGHT_GRAY("light_gray", DyeColor.LIGHT_GRAY),
|
||||
CYAN("cyan", DyeColor.CYAN),
|
||||
PURPLE("purple", DyeColor.PURPLE),
|
||||
BLUE("blue", DyeColor.BLUE),
|
||||
BROWN("brown", DyeColor.BROWN),
|
||||
GREEN("green", DyeColor.GREEN),
|
||||
RED("red", DyeColor.RED),
|
||||
BLACK("black", DyeColor.BLACK),
|
||||
WATER("water", null);
|
||||
|
||||
override fun getSerializedName(): String {
|
||||
return refName
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class PainterRecipe(
|
||||
val input: Ingredient,
|
||||
val output: ItemStack,
|
||||
dyes: Map<out DyeColor?, Int>
|
||||
) : AbstractPainterRecipe(dyes) {
|
||||
constructor(
|
||||
input: Ingredient,
|
||||
output: ItemStack,
|
||||
dyes: Set<DyeColor?>
|
||||
) : this(input, output, Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
|
||||
override fun matches(p_44002_: Container, p_44003_: Level): Boolean {
|
||||
if (isIncomplete) return false
|
||||
return input.test(p_44002_[0])
|
||||
@ -90,14 +125,6 @@ class PainterRecipe(
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@ -110,36 +137,12 @@ class PainterRecipe(
|
||||
return MRecipes.PAINTER
|
||||
}
|
||||
|
||||
override fun getToastSymbol(): ItemStack {
|
||||
return ItemStack(MItems.PAINTER)
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this, id)
|
||||
}
|
||||
|
||||
private enum class DyeColorWrapper(val refName: String, val key: DyeColor?) : StringRepresentable {
|
||||
WHITE("white", DyeColor.WHITE),
|
||||
ORANGE("orange", DyeColor.ORANGE),
|
||||
MAGENTA("magenta", DyeColor.MAGENTA),
|
||||
LIGHT_BLUE("light_blue", DyeColor.LIGHT_BLUE),
|
||||
YELLOW("yellow", DyeColor.YELLOW),
|
||||
LIME("lime", DyeColor.LIME),
|
||||
PINK("pink", DyeColor.PINK),
|
||||
GRAY("gray", DyeColor.GRAY),
|
||||
LIGHT_GRAY("light_gray", DyeColor.LIGHT_GRAY),
|
||||
CYAN("cyan", DyeColor.CYAN),
|
||||
PURPLE("purple", DyeColor.PURPLE),
|
||||
BLUE("blue", DyeColor.BLUE),
|
||||
BROWN("brown", DyeColor.BROWN),
|
||||
GREEN("green", DyeColor.GREEN),
|
||||
RED("red", DyeColor.RED),
|
||||
BLACK("black", DyeColor.BLACK),
|
||||
WATER("water", null);
|
||||
|
||||
override fun getSerializedName(): String {
|
||||
return refName
|
||||
}
|
||||
override fun getOutput(container: Container): ItemStack {
|
||||
return this.output
|
||||
}
|
||||
|
||||
companion object {
|
||||
@ -160,3 +163,75 @@ class PainterRecipe(
|
||||
}
|
||||
}
|
||||
}
|
||||
class PainterArmorDyeRecipe(
|
||||
dyes: Map<out DyeColor?, Int>
|
||||
) : AbstractPainterRecipe(dyes) {
|
||||
constructor(
|
||||
dyes: Set<DyeColor?>
|
||||
) : this(Object2IntArrayMap<DyeColor?>().also { map -> dyes.forEach { map[it] = 1 } })
|
||||
|
||||
override fun matches(contaier: Container, level: Level): Boolean {
|
||||
if (this.isIncomplete) return false
|
||||
val stack = contaier[0]
|
||||
|
||||
return (!stack.isEmpty && stack.item is DyeableArmorItem)
|
||||
}
|
||||
|
||||
override fun assemble(container: Container, registry: RegistryAccess): ItemStack {
|
||||
var output = container[0].copy()
|
||||
|
||||
dyes.forEach { entry ->
|
||||
if (entry.key == null) {
|
||||
(output.item as DyeableLeatherItem).clearColor(output)
|
||||
} else {
|
||||
output = DyeableLeatherItem.dyeArmor(output.copy(), listOf(DyeItem.byColor(entry.key!!)))
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
override fun getResultItem(registry: RegistryAccess): ItemStack = ItemStack.EMPTY
|
||||
|
||||
override fun getSerializer(): RecipeSerializer<*> = SERIALIZER
|
||||
|
||||
override fun getType(): RecipeType<*> = MRecipes.PAINTER_ARMOR_DYE
|
||||
|
||||
override fun isIncomplete(): Boolean = dyes.isEmpty()
|
||||
|
||||
fun toFinished(id: ResourceLocation): FinishedRecipe {
|
||||
return SERIALIZER.toFinished(this, id)
|
||||
}
|
||||
|
||||
override fun getOutput(container: Container): ItemStack {
|
||||
if (container.isEmpty) return ItemStack.EMPTY
|
||||
|
||||
var output = container[0].copy()
|
||||
|
||||
dyes.forEach { entry ->
|
||||
if (entry.key == null) {
|
||||
(output.item as DyeableLeatherItem).clearColor(output)
|
||||
} else {
|
||||
output = DyeableLeatherItem.dyeArmor(output.copy(), listOf(DyeItem.byColor(entry.key!!)))
|
||||
}
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val wrapperCodec = StringRepresentable.fromEnum(DyeColorWrapper::values)
|
||||
|
||||
val SERIALIZER = Codec2RecipeSerializer<PainterArmorDyeRecipe> { _ ->
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
PredicatedCodecList<Map<DyeColorWrapper, Int>>(
|
||||
wrapperCodec.xmap({ mapOf(it to 1) }, { it.keys.first() }) to Predicate { it.keys.size == 1 && it.values.first() == 1 },
|
||||
Codec.list(wrapperCodec).xmap({ it.associateWith { 1 } }, { ArrayList(it.keys) }) to Predicate { it.values.all { it == 1 } },
|
||||
Codec.unboundedMap(wrapperCodec, Codec.INT.minRange(1)) to Predicate { true }
|
||||
).fieldOf("dyes").xmap({ it.mapKeys { it.key.key } }, { it.mapKeys { k -> DyeColorWrapper.entries.first { k.key == it.key } } }).forGetter(PainterArmorDyeRecipe::dyes),
|
||||
).apply(it, ::PainterArmorDyeRecipe)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ object MRecipes {
|
||||
|
||||
val PLATE_PRESS by register<PlatePressRecipe>("plate_press")
|
||||
val PAINTER by register<PainterRecipe>("painter")
|
||||
val PAINTER_ARMOR_DYE by register<PainterArmorDyeRecipe>("painter_armor_dye")
|
||||
val MATTER_ENTANGLER by register<IMatterEntanglerRecipe>("matter_entangler")
|
||||
val MICROWAVE by register<MicrowaveRecipe>("microwave")
|
||||
|
||||
@ -43,6 +44,7 @@ object MRecipes {
|
||||
serializers.register("upgrade") { UpgradeRecipe.CODEC }
|
||||
serializers.register("hammer_priming") { ExplosiveHammerPrimingRecipe.CODEC }
|
||||
serializers.register("painter") { PainterRecipe.SERIALIZER }
|
||||
serializers.register("painter_armor_dye") { PainterArmorDyeRecipe.SERIALIZER }
|
||||
serializers.register("matter_entangler") { MatterEntanglerRecipe.SERIALIZER }
|
||||
serializers.register("matter_entangler_energetic") { MatterEntanglerRecipe.ENERGY_SERIALIZER }
|
||||
serializers.register("matter_entangler_matter") { MatterEntanglerRecipe.MATTER_SERIALIZER }
|
||||
|
Loading…
Reference in New Issue
Block a user