Item repairer recipe
This commit is contained in:
parent
d1978d7e04
commit
66140d33a2
@ -8,12 +8,14 @@ import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.Items
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
|
||||
import ru.dbotthepony.mc.otm.registry.MBlocks
|
||||
import ru.dbotthepony.mc.otm.registry.MItemTags
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
import ru.dbotthepony.mc.otm.registry.MRegistry
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.datagen.modLocation
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
||||
import java.util.function.Consumer
|
||||
|
||||
fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
|
||||
@ -295,4 +297,15 @@ fun addCraftingTableRecipes(consumer: Consumer<FinishedRecipe>) {
|
||||
.rowB(Tags.Items.RODS_WOODEN)
|
||||
.rowB(Tags.Items.RODS_WOODEN)
|
||||
.build(consumer)
|
||||
|
||||
MatteryRecipe(MItems.ITEM_REPAIRER, category = machinesCategory)
|
||||
.setUpgradeSource(MItems.MATTER_REPLICATOR)
|
||||
.addUpgradeOps(
|
||||
UpgradeRecipe.Indirect("BlockEntityTag.${MatteryBlockEntity.ENERGY_KEY}", "BlockEntityTag.energy"),
|
||||
UpgradeRecipe.Indirect("BlockEntityTag.${MatteryBlockEntity.MATTER_STORAGE_KEY}", "BlockEntityTag.matter"),
|
||||
)
|
||||
.row(MItemTags.ADVANCED_CIRCUIT, Tags.Items.GEMS_EMERALD, MItemTags.ADVANCED_CIRCUIT)
|
||||
.row(MItems.ELECTRIC_PARTS, MItems.MATTER_REPLICATOR, MItems.ELECTRIC_PARTS)
|
||||
.row(MItems.ELECTROMAGNET, MItems.ELECTROMAGNET, MItems.ELECTROMAGNET)
|
||||
.build(consumer)
|
||||
}
|
||||
|
@ -1,13 +1,11 @@
|
||||
|
||||
package ru.dbotthepony.mc.otm.datagen.recipes
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.gson.JsonObject
|
||||
import net.minecraft.advancements.CriterionTriggerInstance
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.data.recipes.RecipeBuilder
|
||||
import net.minecraft.data.recipes.RecipeCategory
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.tags.TagKey
|
||||
import net.minecraft.world.item.Item
|
||||
@ -15,8 +13,11 @@ import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||
import net.minecraft.world.level.ItemLike
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
import ru.dbotthepony.mc.otm.core.collect.JsonArrayCollector
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe
|
||||
import java.util.function.Consumer
|
||||
|
||||
private interface RecipeCell {
|
||||
@ -116,7 +117,7 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: Reci
|
||||
}
|
||||
}
|
||||
|
||||
fun build(consumer: Consumer<FinishedRecipe>, name: String? = null) {
|
||||
private fun buildRegular(): ShapedRecipeBuilder {
|
||||
if (index == 0) {
|
||||
throw NoSuchElementException("No recipe rows were defined")
|
||||
}
|
||||
@ -140,15 +141,62 @@ class MatteryRecipe(val result: ItemLike, val count: Int = 1, val category: Reci
|
||||
builder.unlockedBy(a, b)
|
||||
}
|
||||
|
||||
return builder
|
||||
}
|
||||
|
||||
private var source: ResourceLocation? = null
|
||||
private val copyPaths = ArrayList<UpgradeRecipe.Op>()
|
||||
|
||||
fun setUpgradeSource(source: ResourceLocation): MatteryRecipe {
|
||||
this.source = source
|
||||
return this
|
||||
}
|
||||
|
||||
fun setUpgradeSource(source: ItemLike): MatteryRecipe {
|
||||
this.source = source.asItem().registryName!!
|
||||
return this
|
||||
}
|
||||
|
||||
fun addUpgradeOps(vararg operations: UpgradeRecipe.Op): MatteryRecipe {
|
||||
for (op in operations) copyPaths.add(op)
|
||||
return this
|
||||
}
|
||||
|
||||
private fun filter(consumer: Consumer<FinishedRecipe>): Consumer<FinishedRecipe> {
|
||||
if (source != null) {
|
||||
check(copyPaths.isNotEmpty()) { "Defined upgrade recipe without nbt migration operations" }
|
||||
|
||||
return Consumer {
|
||||
consumer.accept(object : FinishedRecipe by it {
|
||||
override fun serializeRecipeData(pJson: JsonObject) {
|
||||
it.serializeRecipeData(pJson)
|
||||
|
||||
pJson["copyPaths"] = copyPaths.stream().map { it.serialize() }.collect(JsonArrayCollector)
|
||||
pJson["source"] = source!!.toString()
|
||||
}
|
||||
|
||||
override fun getType(): RecipeSerializer<*> {
|
||||
return UpgradeRecipe.Companion
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return consumer
|
||||
}
|
||||
|
||||
fun build(consumer: Consumer<FinishedRecipe>, name: String? = null) {
|
||||
val builder = buildRegular()
|
||||
|
||||
if (name != null) {
|
||||
builder.save(consumer, ResourceLocation(OverdriveThatMatters.MOD_ID,
|
||||
builder.save(filter(consumer), ResourceLocation(OverdriveThatMatters.MOD_ID,
|
||||
if (result.asItem().registryName!!.namespace == OverdriveThatMatters.MOD_ID)
|
||||
"${result.asItem().registryName!!.path}_$name"
|
||||
else
|
||||
"${result.asItem().registryName!!.namespace}_${result.asItem().registryName!!.path}_$name"
|
||||
))
|
||||
} else {
|
||||
builder.save(consumer)
|
||||
builder.save(filter(consumer))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters;
|
||||
import ru.dbotthepony.mc.otm.recipe.EnergyContainerRecipe;
|
||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipe;
|
||||
import ru.dbotthepony.mc.otm.recipe.PlatePressRecipeFactory;
|
||||
import ru.dbotthepony.mc.otm.recipe.UpgradeRecipe;
|
||||
|
||||
public class MRecipes {
|
||||
public static class MatteryRecipeType<T extends Recipe<?>> implements RecipeType<T> {
|
||||
@ -28,6 +29,7 @@ public class MRecipes {
|
||||
|
||||
public static final MatteryRecipeType<PlatePressRecipe> PLATE_PRESS = new MatteryRecipeType<>(OverdriveThatMatters.loc(MNames.PLATE_PRESS));
|
||||
public static final MatteryRecipeType<PlatePressRecipe> ENERGY_CONTAINER = new MatteryRecipeType<>(OverdriveThatMatters.loc("energy_container"));
|
||||
public static final MatteryRecipeType<PlatePressRecipe> UPGRADE = new MatteryRecipeType<>(OverdriveThatMatters.loc("upgrade"));
|
||||
|
||||
private static final DeferredRegister<RecipeSerializer<?>> serializerRegistry = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, OverdriveThatMatters.MOD_ID);
|
||||
private static final DeferredRegister<RecipeType<?>> typeRegistry = DeferredRegister.create(ForgeRegistries.RECIPE_TYPES, OverdriveThatMatters.MOD_ID);
|
||||
@ -35,8 +37,11 @@ public class MRecipes {
|
||||
static {
|
||||
serializerRegistry.register(MNames.PLATE_PRESS, () -> PlatePressRecipeFactory.INSTANCE);
|
||||
serializerRegistry.register(ENERGY_CONTAINER.name.getPath(), () -> EnergyContainerRecipe.Companion);
|
||||
serializerRegistry.register(UPGRADE.name.getPath(), () -> UpgradeRecipe.Companion);
|
||||
|
||||
typeRegistry.register(MNames.PLATE_PRESS, () -> PLATE_PRESS);
|
||||
typeRegistry.register(ENERGY_CONTAINER.name.getPath(), () -> ENERGY_CONTAINER);
|
||||
typeRegistry.register(UPGRADE.name.getPath(), () -> UPGRADE);
|
||||
}
|
||||
|
||||
public static void register(IEventBus bus) {
|
||||
|
@ -0,0 +1,31 @@
|
||||
package ru.dbotthepony.mc.otm.core.collect
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import java.util.function.BiConsumer
|
||||
import java.util.function.BinaryOperator
|
||||
import java.util.function.Function
|
||||
import java.util.function.Supplier
|
||||
import java.util.stream.Collector
|
||||
|
||||
object JsonArrayCollector : Collector<JsonElement, JsonArray, JsonArray> {
|
||||
override fun supplier(): Supplier<JsonArray> {
|
||||
return Supplier { JsonArray() }
|
||||
}
|
||||
|
||||
override fun accumulator(): BiConsumer<JsonArray, JsonElement> {
|
||||
return BiConsumer { t, u -> t.add(u) }
|
||||
}
|
||||
|
||||
override fun combiner(): BinaryOperator<JsonArray> {
|
||||
return BinaryOperator { t, u -> t.addAll(u); t }
|
||||
}
|
||||
|
||||
override fun finisher(): Function<JsonArray, JsonArray> {
|
||||
return Function.identity()
|
||||
}
|
||||
|
||||
override fun characteristics(): Set<Collector.Characteristics> {
|
||||
return setOf(Collector.Characteristics.IDENTITY_FINISH)
|
||||
}
|
||||
}
|
@ -17,14 +17,14 @@ import ru.dbotthepony.mc.otm.container.stream
|
||||
import ru.dbotthepony.mc.otm.core.filterNotNull
|
||||
|
||||
class EnergyContainerRecipe(
|
||||
p_44153_: ResourceLocation,
|
||||
p_44154_: String,
|
||||
id: ResourceLocation,
|
||||
group: String,
|
||||
category: CraftingBookCategory,
|
||||
p_44155_: Int,
|
||||
p_44156_: Int,
|
||||
p_44157_: NonNullList<Ingredient>,
|
||||
p_44158_: ItemStack,
|
||||
) : ShapedRecipe(p_44153_, p_44154_, category, p_44155_, p_44156_, p_44157_, p_44158_) {
|
||||
width: Int,
|
||||
height: Int,
|
||||
ingredients: NonNullList<Ingredient>,
|
||||
result: ItemStack,
|
||||
) : ShapedRecipe(id, group, category, width, height, ingredients, result) {
|
||||
constructor(parent: ShapedRecipe) : this(parent.id, parent.group, parent.category(), parent.width, parent.height, parent.ingredients, parent.resultItem)
|
||||
|
||||
override fun assemble(container: CraftingContainer): ItemStack {
|
||||
@ -53,25 +53,25 @@ class EnergyContainerRecipe(
|
||||
return itemStack
|
||||
}
|
||||
|
||||
override fun matches(p_44002_: CraftingContainer, p_44003_: Level): Boolean {
|
||||
return super.matches(p_44002_, p_44003_) && !p_44002_.stream().anyMatch { it.isDamaged }
|
||||
override fun matches(container: CraftingContainer, level: Level): Boolean {
|
||||
return super.matches(container, level) && !container.stream().anyMatch { it.isDamaged }
|
||||
}
|
||||
|
||||
override fun getSerializer(): RecipeSerializer<*> {
|
||||
override fun getSerializer(): RecipeSerializer<EnergyContainerRecipe> {
|
||||
return Companion
|
||||
}
|
||||
|
||||
companion object : RecipeSerializer<EnergyContainerRecipe> {
|
||||
override fun fromJson(p_44103_: ResourceLocation, p_44104_: JsonObject): EnergyContainerRecipe {
|
||||
return EnergyContainerRecipe(Serializer.SHAPED_RECIPE.fromJson(p_44103_, p_44104_))
|
||||
override fun fromJson(id: ResourceLocation, data: JsonObject): EnergyContainerRecipe {
|
||||
return EnergyContainerRecipe(Serializer.SHAPED_RECIPE.fromJson(id, data))
|
||||
}
|
||||
|
||||
override fun fromNetwork(p_44105_: ResourceLocation, p_44106_: FriendlyByteBuf): EnergyContainerRecipe? {
|
||||
return Serializer.SHAPED_RECIPE.fromNetwork(p_44105_, p_44106_)?.let(::EnergyContainerRecipe)
|
||||
override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): EnergyContainerRecipe? {
|
||||
return Serializer.SHAPED_RECIPE.fromNetwork(id, data)?.let(::EnergyContainerRecipe)
|
||||
}
|
||||
|
||||
override fun toNetwork(p_44101_: FriendlyByteBuf, p_44102_: EnergyContainerRecipe) {
|
||||
Serializer.SHAPED_RECIPE.toNetwork(p_44101_, p_44102_)
|
||||
override fun toNetwork(buff: FriendlyByteBuf, value: EnergyContainerRecipe) {
|
||||
Serializer.SHAPED_RECIPE.toNetwork(buff, value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
205
src/main/kotlin/ru/dbotthepony/mc/otm/recipe/UpgradeRecipe.kt
Normal file
205
src/main/kotlin/ru/dbotthepony/mc/otm/recipe/UpgradeRecipe.kt
Normal file
@ -0,0 +1,205 @@
|
||||
package ru.dbotthepony.mc.otm.recipe
|
||||
|
||||
import com.google.common.collect.ImmutableList
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonPrimitive
|
||||
import net.minecraft.core.NonNullList
|
||||
import net.minecraft.nbt.CompoundTag
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.util.GsonHelper
|
||||
import net.minecraft.world.inventory.CraftingContainer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
import net.minecraft.world.item.crafting.CraftingBookCategory
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
import net.minecraft.world.item.crafting.RecipeSerializer
|
||||
import net.minecraft.world.item.crafting.ShapedRecipe
|
||||
import ru.dbotthepony.mc.otm.container.stream
|
||||
import ru.dbotthepony.mc.otm.core.nbt.set
|
||||
import ru.dbotthepony.mc.otm.core.registryName
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.core.tagNotNull
|
||||
import ru.dbotthepony.mc.otm.core.util.readJson
|
||||
import ru.dbotthepony.mc.otm.core.util.writeJson
|
||||
import ru.dbotthepony.mc.otm.data.stream
|
||||
import java.util.stream.Stream
|
||||
|
||||
class UpgradeRecipe(
|
||||
id: ResourceLocation,
|
||||
group: String,
|
||||
category: CraftingBookCategory,
|
||||
width: Int,
|
||||
height: Int,
|
||||
ingredients: NonNullList<Ingredient>,
|
||||
result: ItemStack,
|
||||
copyPaths: Stream<Op>,
|
||||
val source: ResourceLocation,
|
||||
) : ShapedRecipe(id, group, category, width, height, ingredients, result) {
|
||||
constructor(parent: ShapedRecipe, copyPaths: Stream<Op>, source: ResourceLocation) : this(parent.id, parent.group, parent.category(), parent.width, parent.height, parent.ingredients, parent.resultItem, copyPaths, source)
|
||||
|
||||
enum class OpType {
|
||||
DIRECT {
|
||||
override fun deserialize(obj: JsonObject): Op {
|
||||
return Direct(GsonHelper.getAsString(obj, "path"))
|
||||
}
|
||||
}, INDIRECT {
|
||||
override fun deserialize(obj: JsonObject): Op {
|
||||
return Indirect(GsonHelper.getAsString(obj, "source"), GsonHelper.getAsString(obj, "destination"))
|
||||
}
|
||||
};
|
||||
|
||||
abstract fun deserialize(obj: JsonObject): Op
|
||||
}
|
||||
|
||||
interface Op {
|
||||
val type: OpType
|
||||
fun apply(source: CompoundTag, destination: CompoundTag)
|
||||
fun serialize(json: JsonObject)
|
||||
|
||||
fun serialize(): JsonObject {
|
||||
return JsonObject().also {
|
||||
it["type"] = JsonPrimitive(type.name)
|
||||
serialize(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Direct(val path: String) : Op {
|
||||
private val split = path.split('.')
|
||||
override val type: OpType
|
||||
get() = OpType.DIRECT
|
||||
|
||||
override fun serialize(json: JsonObject) {
|
||||
json["path"] = JsonPrimitive("path")
|
||||
}
|
||||
|
||||
override fun apply(source: CompoundTag, destination: CompoundTag) {
|
||||
var a = source
|
||||
var b = destination
|
||||
|
||||
for (i in 0 until split.size - 1) {
|
||||
val value = split[i]
|
||||
|
||||
if (value !in a) {
|
||||
a[value] = CompoundTag()
|
||||
}
|
||||
|
||||
if (value !in b) {
|
||||
b[value] = CompoundTag()
|
||||
}
|
||||
|
||||
a = a[value] as CompoundTag
|
||||
b = b[value] as CompoundTag
|
||||
}
|
||||
|
||||
val value = split.last()
|
||||
|
||||
if (value in a) {
|
||||
b[value] = a[value]!!.copy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data class Indirect(val pathSource: String, val pathDestination: String) : Op {
|
||||
private val splitSource = pathSource.split('.')
|
||||
private val splitDestination = pathDestination.split('.')
|
||||
|
||||
override val type: OpType
|
||||
get() = OpType.INDIRECT
|
||||
|
||||
override fun serialize(json: JsonObject) {
|
||||
json["source"] = JsonPrimitive(pathSource)
|
||||
json["destination"] = JsonPrimitive(pathDestination)
|
||||
}
|
||||
|
||||
override fun apply(source: CompoundTag, destination: CompoundTag) {
|
||||
var a = source
|
||||
var b = destination
|
||||
|
||||
for (i in 0 until splitSource.size - 1) {
|
||||
val value = splitSource[i]
|
||||
|
||||
if (value !in a) {
|
||||
a[value] = CompoundTag()
|
||||
}
|
||||
|
||||
a = a[value] as CompoundTag
|
||||
}
|
||||
|
||||
for (i in 0 until splitDestination.size - 1) {
|
||||
val value = splitDestination[i]
|
||||
|
||||
if (value !in b) {
|
||||
b[value] = CompoundTag()
|
||||
}
|
||||
|
||||
b = b[value] as CompoundTag
|
||||
}
|
||||
|
||||
val valueA = splitSource.last()
|
||||
val valueB = splitDestination.last()
|
||||
|
||||
if (valueA in a) {
|
||||
b[valueB] = a[valueA]!!.copy()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val copyPaths: ImmutableList<Op> = copyPaths.collect(ImmutableList.toImmutableList())
|
||||
|
||||
override fun assemble(pInv: CraftingContainer): ItemStack {
|
||||
val result = super.assemble(pInv)
|
||||
|
||||
if (result.isEmpty) {
|
||||
return result
|
||||
}
|
||||
|
||||
val sources = pInv.stream().filter { !it.isEmpty && it.item.registryName == source }.toList()
|
||||
|
||||
if (sources.size != 1) {
|
||||
return ItemStack.EMPTY
|
||||
}
|
||||
|
||||
val source = sources.first()
|
||||
|
||||
for (op in copyPaths) {
|
||||
op.apply(source.tagNotNull, result.tagNotNull)
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getSerializer(): RecipeSerializer<UpgradeRecipe> {
|
||||
return Companion
|
||||
}
|
||||
|
||||
companion object : RecipeSerializer<UpgradeRecipe> {
|
||||
fun deserializeOp(json: JsonObject): Op {
|
||||
return OpType.valueOf(GsonHelper.getAsString(json, "type")).deserialize(json)
|
||||
}
|
||||
|
||||
override fun fromJson(id: ResourceLocation, data: JsonObject): UpgradeRecipe {
|
||||
return UpgradeRecipe(
|
||||
Serializer.SHAPED_RECIPE.fromJson(id, data),
|
||||
GsonHelper.getAsJsonArray(data, "copyPaths").stream().map { deserializeOp(it as JsonObject) },
|
||||
ResourceLocation(GsonHelper.getAsString(data, "source"))
|
||||
)
|
||||
}
|
||||
|
||||
override fun fromNetwork(id: ResourceLocation, buff: FriendlyByteBuf): UpgradeRecipe? {
|
||||
val recipe = Serializer.SHAPED_RECIPE.fromNetwork(id, buff) ?: return null
|
||||
|
||||
return UpgradeRecipe(
|
||||
recipe,
|
||||
buff.readCollection({ ArrayList<Op>(it) }, { deserializeOp(it.readJson() as JsonObject) }).stream(),
|
||||
buff.readResourceLocation()
|
||||
)
|
||||
}
|
||||
|
||||
override fun toNetwork(buff: FriendlyByteBuf, value: UpgradeRecipe) {
|
||||
Serializer.SHAPED_RECIPE.toNetwork(buff, value)
|
||||
buff.writeCollection(value.copyPaths) { it, v -> it.writeJson(v.serialize()) }
|
||||
buff.writeResourceLocation(value.source)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user