Some minor changes for 1.21

This commit is contained in:
DBotThePony 2024-07-01 20:02:32 +07:00
parent 0a4468fcdd
commit 91835905a3
Signed by: DBot
GPG Key ID: DCC23B5715498507
14 changed files with 174 additions and 125 deletions

View File

@ -3,7 +3,6 @@ package ru.dbotthepony.mc.otm.capability;
import net.minecraftforge.common.capabilities.CapabilityManager; import net.minecraftforge.common.capabilities.CapabilityManager;
import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.CapabilityToken; import net.minecraftforge.common.capabilities.CapabilityToken;
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import ru.dbotthepony.mc.otm.block.entity.cable.EnergyCableBlockEntity; import ru.dbotthepony.mc.otm.block.entity.cable.EnergyCableBlockEntity;
import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive; import ru.dbotthepony.mc.otm.capability.drive.IMatteryDrive;
@ -66,16 +65,4 @@ public class MatteryCapability {
@Nonnull @Nonnull
@NotNull @NotNull
public static final Capability<IMatteryUpgrade> UPGRADE = CapabilityManager.get(new CapabilityToken<>() {}); public static final Capability<IMatteryUpgrade> UPGRADE = CapabilityManager.get(new CapabilityToken<>() {});
public static void register(RegisterCapabilitiesEvent event) {
event.register(IMatteryEnergyStorage.class);
event.register(MatteryPlayerCapability.class);
event.register(IMatterStorage.class);
event.register(MatterNode.class);
event.register(IPatternStorage.class);
event.register(IReplicationTaskProvider.class);
event.register(IMatteryDrive.class);
event.register(StorageNode.class);
event.register(IMatteryUpgrade.class);
}
} }

View File

@ -22,6 +22,7 @@ import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.screen.MatteryScreen import ru.dbotthepony.mc.otm.client.screen.MatteryScreen
import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel import ru.dbotthepony.mc.otm.client.screen.panels.slot.AbstractSlotPanel
import ru.dbotthepony.mc.otm.client.screen.widget.FluidGaugePanel import ru.dbotthepony.mc.otm.client.screen.widget.FluidGaugePanel
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.filterIsInstance import ru.dbotthepony.mc.otm.core.collect.filterIsInstance
import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.map

View File

@ -4,12 +4,13 @@ import it.unimi.dsi.fastutil.ints.IntIterable
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.RecipeInput
import ru.dbotthepony.mc.otm.container.util.IContainerSlot import ru.dbotthepony.mc.otm.container.util.IContainerSlot
import ru.dbotthepony.mc.otm.core.collect.filter import ru.dbotthepony.mc.otm.core.collect.filter
import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.isNotEmpty import ru.dbotthepony.mc.otm.core.isNotEmpty
interface IMatteryContainer : IContainer, Iterable<ItemStack> { interface IMatteryContainer : IContainer, RecipeInput, Iterable<ItemStack> {
fun getSlotFilter(slot: Int): Item? fun getSlotFilter(slot: Int): Item?
/** /**
@ -19,8 +20,13 @@ interface IMatteryContainer : IContainer, Iterable<ItemStack> {
return false return false
} }
override fun isEmpty(): Boolean
fun setChanged(slot: Int) fun setChanged(slot: Int)
override fun size(): Int {
return containerSize
}
/** /**
* Iterates over non-empty itemstacks of this container * Iterates over non-empty itemstacks of this container
*/ */
@ -105,7 +111,7 @@ interface IMatteryContainer : IContainer, Iterable<ItemStack> {
if ( if (
(ignoreFilters || !isSlotForbiddenForAutomation(slot)) && (ignoreFilters || !isSlotForbiddenForAutomation(slot)) &&
ItemStack.isSameItemSameTags(getItem(slot), stack) && ItemStack.isSameItemSameComponents(getItem(slot), stack) &&
(ignoreFilters || !filterPass && !hasSlotFilter(slot) || filterPass && hasSlotFilter(slot) && testSlotFilter(slot, stack)) (ignoreFilters || !filterPass && !hasSlotFilter(slot) || filterPass && hasSlotFilter(slot) && testSlotFilter(slot, stack))
) { ) {
val slotStack = getItem(slot) val slotStack = getItem(slot)

View File

@ -1,14 +1,18 @@
package ru.dbotthepony.mc.otm.container package ru.dbotthepony.mc.otm.container
import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import it.unimi.dsi.fastutil.ints.IntArrayList import it.unimi.dsi.fastutil.ints.IntArrayList
import it.unimi.dsi.fastutil.ints.IntComparators import it.unimi.dsi.fastutil.ints.IntComparators
import it.unimi.dsi.fastutil.ints.IntSpliterator import it.unimi.dsi.fastutil.ints.IntSpliterator
import it.unimi.dsi.fastutil.objects.ObjectSpliterators import it.unimi.dsi.fastutil.objects.ObjectSpliterators
import net.minecraft.core.HolderLookup
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.nbt.CompoundTag import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag import net.minecraft.nbt.ListTag
import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.Container import net.minecraft.world.Container
@ -19,6 +23,7 @@ import net.minecraft.world.item.Item
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraftforge.common.util.INBTSerializable import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.collect.ListenableMap import ru.dbotthepony.kommons.collect.ListenableMap
import ru.dbotthepony.kommons.io.DelegateSyncher import ru.dbotthepony.kommons.io.DelegateSyncher
import ru.dbotthepony.kommons.io.VarIntValueCodec import ru.dbotthepony.kommons.io.VarIntValueCodec
@ -34,6 +39,7 @@ import ru.dbotthepony.mc.otm.core.nbt.map
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.util.ItemValueCodec import ru.dbotthepony.mc.otm.core.util.ItemValueCodec
import ru.dbotthepony.mc.otm.data.minRange
import java.util.* import java.util.*
import java.util.function.Consumer import java.util.function.Consumer
import java.util.function.Predicate import java.util.function.Predicate
@ -184,58 +190,43 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I
protected open fun startedIgnoringUpdates() {} protected open fun startedIgnoringUpdates() {}
protected open fun stoppedIgnoringUpdates() {} protected open fun stoppedIgnoringUpdates() {}
private fun deserializeNBT(tag: CompoundTag) { private data class SerializedItem(val item: ItemStack, val slot: Int) {
// нам не интересен размер companion object {
tag.map("items") { it: ListTag -> val CODEC: Codec<SerializedItem> = RecordCodecBuilder.create {
deserializeNBT(it) it.group(
} ItemStack.CODEC.fieldOf("item").forGetter { it.item },
Codec.INT.minRange(0).fieldOf("slot").forGetter { it.slot },
tag.map("filters") { it: ListTag -> ).apply(it, ::SerializedItem)
val map = filterSynchronizer?.delegate
for (i in 0 until it.size.coerceAtMost(size)) {
val nbt = it[i] as CompoundTag
val index = nbt.getInt("slotIndex")
filters[index] = ForgeRegistries.ITEMS.getValue(ResourceLocation.tryParse(nbt.getString("filter")) ?: continue)
if (filters[index] != null) {
map?.put(index, filters[index]!!)
} }
} }
} }
setChanged() private data class SerializedFilter(val item: Item, val slot: Int) {
} companion object {
val CODEC: Codec<SerializedFilter> = RecordCodecBuilder.create {
private fun deserializeNBT(tag: ListTag) { it.group(
if (tag.all { (it as CompoundTag).contains("slotIndex") }) { ForgeRegistries.ITEMS.codec.fieldOf("item").forGetter { it.item },
val freeSlots = IntAVLTreeSet() Codec.INT.minRange(0).fieldOf("slot").forGetter { it.slot },
).apply(it, ::SerializedFilter)
for (i in 0 until size)
freeSlots.add(i)
for (i in 0 until tag.size.coerceAtMost(size)) {
val nbt = tag[i] as CompoundTag
var slotID = nbt.getInt("slotIndex")
if (freeSlots.remove(slotID)) {
slots[slotID] = ItemStack.of(nbt)
} else if (freeSlots.isEmpty()) {
break
} else {
slotID = freeSlots.firstInt()
freeSlots.remove(slotID)
slots[slotID] = ItemStack.of(nbt)
}
}
} else {
for (i in 0 until tag.size.coerceAtMost(size)) {
slots[i] = ItemStack.of(tag[i] as CompoundTag)
} }
} }
} }
override fun deserializeNBT(tag: Tag?) { private data class SerializedState(
val items: List<SerializedItem>,
val filters: List<SerializedFilter>
) {
companion object {
val CODEC: Codec<SerializedState> = RecordCodecBuilder.create {
it.group(
Codec.list(SerializedItem.CODEC).fieldOf("items").forGetter { it.items },
Codec.list(SerializedFilter.CODEC).fieldOf("filters").forGetter { it.filters },
).apply(it, ::SerializedState)
}
}
}
override fun deserializeNBT(registries: HolderLookup.Provider, tag: Tag?) {
Arrays.fill(slots, ItemStack.EMPTY) Arrays.fill(slots, ItemStack.EMPTY)
Arrays.fill(filters, null) Arrays.fill(filters, null)
nonEmptyFlags.clear() nonEmptyFlags.clear()
@ -243,14 +234,37 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I
filterSynchronizer?.delegate?.clear() filterSynchronizer?.delegate?.clear()
when (tag) { if (tag != null) {
is CompoundTag -> deserializeNBT(tag) SerializedState.CODEC.parse(registries.createSerializationContext(NbtOps.INSTANCE), tag)
is ListTag -> { .resultOrPartial { LOGGER.error("Error deserializing container: $it") }
deserializeNBT(tag) .ifPresent {
setChanged() val freeSlots = IntAVLTreeSet()
for (i in 0 until size)
freeSlots.add(i)
for ((item, slotID) in it.items) {
if (item.isEmpty)
continue
if (freeSlots.remove(slotID)) {
slots[slotID] = item
} else if (freeSlots.isEmpty()) {
break
} else {
val slotID = freeSlots.firstInt()
freeSlots.remove(slotID)
slots[slotID] = item
}
} }
else -> setChanged() val map = filterSynchronizer?.delegate
for ((item, index) in it.filters) {
filters[index] = item
map?.put(index, item)
}
}
} }
} }
@ -274,12 +288,13 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I
listener.setChanged(slot, new, old) listener.setChanged(slot, new, old)
} }
override fun serializeNBT(): CompoundTag { override fun serializeNBT(registries: HolderLookup.Provider): CompoundTag {
return CompoundTag().also { return CompoundTag().also {
it["items"] = ListTag().also { it["items"] = ListTag().also {
for ((i, item) in slots.withIndex()) { for ((i, item) in slots.withIndex()) {
if (!item.isEmpty) { if (!item.isEmpty) {
it.add(item.serializeNBT().also { it.add(item.save(registries).also {
it as CompoundTag
it["slotIndex"] = i it["slotIndex"] = i
}) })
} }
@ -311,7 +326,7 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I
operator fun contains(other: ItemStack): Boolean { operator fun contains(other: ItemStack): Boolean {
for (i in 0 until size) { for (i in 0 until size) {
if (ItemStack.isSameItemSameTags(this[i], other)) { if (ItemStack.isSameItemSameComponents(this[i], other)) {
return true return true
} }
} }
@ -399,7 +414,7 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I
} }
final override fun setChanged(slot: Int) { final override fun setChanged(slot: Int) {
if (!slots[slot].equals(trackedSlots[slot], false)) { if (!ItemStack.isSameItemSameComponents(slots[slot], trackedSlots[slot])) {
trackedSlots[slot] = slots[slot].copy() trackedSlots[slot] = slots[slot].copy()
updateEmptyFlag(slot) updateEmptyFlag(slot)
changeset++ changeset++
@ -567,4 +582,8 @@ open class MatteryContainer(var listener: ContainerListener, private val size: I
fun stream(): Stream<ItemStack> { fun stream(): Stream<ItemStack> {
return StreamSupport.stream(spliterator(), false) return StreamSupport.stream(spliterator(), false)
} }
companion object {
private val LOGGER = LogManager.getLogger()
}
} }

View File

@ -24,7 +24,9 @@ import net.minecraft.world.entity.Entity
import net.minecraft.world.item.Item import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Items import net.minecraft.world.item.Items
import net.minecraft.world.item.crafting.CraftingInput
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.RecipeInput
import net.minecraft.world.level.BlockGetter import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import net.minecraft.world.level.LevelAccessor import net.minecraft.world.level.LevelAccessor
@ -72,6 +74,10 @@ import java.util.stream.Stream
import java.util.stream.StreamSupport import java.util.stream.StreamSupport
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
operator fun RecipeInput.get(index: Int): ItemStack = getItem(index)
operator fun CraftingInput.get(x: Int, y: Int): ItemStack = getItem(x, y)
operator fun CraftingInput.get(x: Int, y: Int, flop: Boolean): ItemStack = if (flop) getItem(x, y) else getItem(width() - x - 1, y)
fun FriendlyByteBuf.writeBigInteger(value: BigInteger) { fun FriendlyByteBuf.writeBigInteger(value: BigInteger) {
writeByteArray(value.toByteArray()) writeByteArray(value.toByteArray())
} }
@ -142,8 +148,6 @@ inline fun <T> LazyOptional<T>.ifPresentK(lambda: (T) -> Unit) {
} }
} }
val ItemStack.tagNotNull: CompoundTag get() = orCreateTag
inline val FluidStack.isNotEmpty get() = !isEmpty inline val FluidStack.isNotEmpty get() = !isEmpty
inline val ItemStack.isNotEmpty get() = !isEmpty inline val ItemStack.isNotEmpty get() = !isEmpty

View File

@ -2,7 +2,9 @@ package ru.dbotthepony.mc.otm.core
import com.google.gson.JsonElement import com.google.gson.JsonElement
import com.google.gson.JsonSyntaxException import com.google.gson.JsonSyntaxException
import com.mojang.datafixers.util.Either
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.DataResult
import com.mojang.serialization.JsonOps import com.mojang.serialization.JsonOps
import net.minecraft.core.Holder import net.minecraft.core.Holder
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
@ -11,7 +13,7 @@ import net.minecraft.nbt.NbtOps
import net.minecraft.nbt.Tag import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.MutableComponent import net.minecraft.network.chat.MutableComponent
import net.minecraft.network.chat.contents.LiteralContents import net.minecraft.network.chat.contents.PlainTextContents
import net.minecraft.network.chat.contents.TranslatableContents import net.minecraft.network.chat.contents.TranslatableContents
import net.minecraft.resources.ResourceKey import net.minecraft.resources.ResourceKey
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
@ -26,38 +28,39 @@ import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.IForgeRegistry import net.minecraftforge.registries.IForgeRegistry
import ru.dbotthepony.mc.otm.core.util.readBinaryJson import ru.dbotthepony.mc.otm.core.util.readBinaryJson
import ru.dbotthepony.mc.otm.core.util.writeBinaryJson import ru.dbotthepony.mc.otm.core.util.writeBinaryJson
import kotlin.jvm.optionals.getOrNull
// because doing it inline is ugly // because doing it inline is ugly
fun <V : Any> Codec<V>.fromJson(value: JsonElement): V? { fun <V : Any> Codec<V>.fromJson(value: JsonElement): V? {
return decode(JsonOps.INSTANCE, value).get().map({ left -> left.first }, { null }) return decode(JsonOps.INSTANCE, value).result().map { left -> left.first }.getOrNull()
} }
fun <V : Any> Codec<V>.fromJsonStrict(value: JsonElement): V { fun <V : Any> Codec<V>.fromJsonStrict(value: JsonElement): V {
return decode(JsonOps.INSTANCE, value).get().map({ left -> left.first }, { throw JsonSyntaxException("Error decoding element: ${it.message()}") }) return decode(JsonOps.INSTANCE, value).get({ left -> left.first }, { throw JsonSyntaxException("Error decoding element: ${it.message()}") })
} }
fun <V : Any> Codec<V>.toJson(value: V, prefix: JsonElement = JsonOps.INSTANCE.empty()): JsonElement? { fun <V : Any> Codec<V>.toJson(value: V, prefix: JsonElement = JsonOps.INSTANCE.empty()): JsonElement? {
return encode(value, JsonOps.INSTANCE, prefix).get().map({ it }, { null }) return encode(value, JsonOps.INSTANCE, prefix).getOrNull { it }
} }
fun <V : Any> Codec<V>.toJsonStrict(value: V, prefix: JsonElement = JsonOps.INSTANCE.empty()): JsonElement { fun <V : Any> Codec<V>.toJsonStrict(value: V, prefix: JsonElement = JsonOps.INSTANCE.empty()): JsonElement {
return encode(value, JsonOps.INSTANCE, prefix).get().map({ it }, { throw RuntimeException("Error encoding element: ${it.message()}") }) return encode(value, JsonOps.INSTANCE, prefix).get({ it }, { throw RuntimeException("Error encoding element: ${it.message()}") })
} }
fun <V : Any> Codec<V>.fromNbt(value: Tag): V? { fun <V : Any> Codec<V>.fromNbt(value: Tag): V? {
return decode(NbtOps.INSTANCE, value).get().map({ left -> left.first }, { null }) return decode(NbtOps.INSTANCE, value).getOrNull { left -> left.first }
} }
fun <V : Any> Codec<V>.fromNbtStrict(value: Tag): V { fun <V : Any> Codec<V>.fromNbtStrict(value: Tag): V {
return decode(NbtOps.INSTANCE, value).get().map({ left -> left.first }, { throw RuntimeException("Error decoding element: ${it.message()}") }) return decode(NbtOps.INSTANCE, value).get({ left -> left.first }, { throw RuntimeException("Error decoding element: ${it.message()}") })
} }
fun <V : Any> Codec<V>.toNbt(value: V, prefix: Tag = NbtOps.INSTANCE.empty()): Tag? { fun <V : Any> Codec<V>.toNbt(value: V, prefix: Tag = NbtOps.INSTANCE.empty()): Tag? {
return encode(value, NbtOps.INSTANCE, prefix).get().map({ it }, { null }) return encode(value, NbtOps.INSTANCE, prefix).getOrNull { it }
} }
fun <V : Any> Codec<V>.toNbtStrict(value: V, prefix: Tag = NbtOps.INSTANCE.empty()): Tag { fun <V : Any> Codec<V>.toNbtStrict(value: V, prefix: Tag = NbtOps.INSTANCE.empty()): Tag {
return encode(value, NbtOps.INSTANCE, prefix).get().map({ it }, { throw RuntimeException("Error encoding element: ${it.message()}") }) return encode(value, NbtOps.INSTANCE, prefix).get({ it }, { throw RuntimeException("Error encoding element: ${it.message()}") })
} }
fun <V : Any> Codec<V>.toNetwork(buff: FriendlyByteBuf, value: V) { fun <V : Any> Codec<V>.toNetwork(buff: FriendlyByteBuf, value: V) {
@ -70,7 +73,7 @@ fun <V : Any> Codec<V>.fromNetwork(buff: FriendlyByteBuf): V {
// 1.19 being 1.19 // 1.19 being 1.19
fun TranslatableComponent(key: String, vararg values: Any): MutableComponent = MutableComponent.create(TranslatableContents(key, null, values)) fun TranslatableComponent(key: String, vararg values: Any): MutableComponent = MutableComponent.create(TranslatableContents(key, null, values))
fun TextComponent(value: String): MutableComponent = MutableComponent.create(LiteralContents(value)) fun TextComponent(value: String): MutableComponent = MutableComponent.create(PlainTextContents.create(value))
fun <T> IForgeRegistry<T>.getKeyNullable(value: T): ResourceLocation? { fun <T> IForgeRegistry<T>.getKeyNullable(value: T): ResourceLocation? {
val key = getResourceKey(value) val key = getResourceKey(value)
@ -100,3 +103,15 @@ inline val DamageSource.isFire get() = `is`(DamageTypeTags.IS_FIRE)
fun RegistryAccess.damageType(key: ResourceKey<DamageType>): Holder<DamageType> { fun RegistryAccess.damageType(key: ResourceKey<DamageType>): Holder<DamageType> {
return registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(key) return registryOrThrow(Registries.DAMAGE_TYPE).getHolderOrThrow(key)
} }
// 1.21
fun ResourceLocation(namespace: String, path: String) = ResourceLocation.fromNamespaceAndPath(namespace, path)
// mojang hello?
fun <IN, OUT> DataResult<IN>.get(map: (IN) -> OUT, orThrow: (DataResult.Error<IN>) -> Nothing): OUT {
return result().map(map).orElseGet { orThrow(error().get()) }
}
fun <IN, OUT> DataResult<IN>.getOrNull(map: (IN) -> OUT): OUT? {
return result().map(map).orElse(null)
}

View File

@ -14,9 +14,13 @@ import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.block.decorative.FluidTankBlock import ru.dbotthepony.mc.otm.block.decorative.FluidTankBlock
import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.FluidTankBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.fluid.BlockMatteryFluidHandler import ru.dbotthepony.mc.otm.capability.fluid.BlockMatteryFluidHandler
import ru.dbotthepony.mc.otm.capability.fluidLevel import ru.dbotthepony.mc.otm.capability.fluidLevel
import ru.dbotthepony.mc.otm.client.render.blockentity.FluidTankRenderer import ru.dbotthepony.mc.otm.client.render.blockentity.FluidTankRenderer
import ru.dbotthepony.mc.otm.config.MachinesConfig
import ru.dbotthepony.mc.otm.core.TooltipList import ru.dbotthepony.mc.otm.core.TooltipList
import ru.dbotthepony.mc.otm.core.TranslatableComponent import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.ifPresentK import ru.dbotthepony.mc.otm.core.ifPresentK

View File

@ -5,12 +5,13 @@ import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.Recipe import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeInput
import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeSerializer
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
// passthrough all default methods to fix Kotlin bug related to implementation delegation not properly working on Java interfaces // passthrough all default methods to fix Kotlin bug related to implementation delegation not properly working on Java interfaces
// https://youtrack.jetbrains.com/issue/KT-55080/Change-the-behavior-of-inheritance-delegation-to-delegates-implementing-Java-interfaces-with-default-methods // https://youtrack.jetbrains.com/issue/KT-55080/Change-the-behavior-of-inheritance-delegation-to-delegates-implementing-Java-interfaces-with-default-methods
interface IMatteryRecipe<C : Container> : Recipe<C> { interface IMatteryRecipe<C : RecipeInput> : Recipe<C> {
override fun getRemainingItems(p_44004_: C): NonNullList<ItemStack> { override fun getRemainingItems(p_44004_: C): NonNullList<ItemStack> {
return super.getRemainingItems(p_44004_) return super.getRemainingItems(p_44004_)
} }

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.recipe
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.world.inventory.CraftingContainer import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.crafting.CraftingInput
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.get
@ -9,12 +10,13 @@ import ru.dbotthepony.mc.otm.core.collect.allEqual
import ru.dbotthepony.mc.otm.core.collect.any import ru.dbotthepony.mc.otm.core.collect.any
import ru.dbotthepony.mc.otm.core.collect.flatMap import ru.dbotthepony.mc.otm.core.collect.flatMap
import ru.dbotthepony.mc.otm.core.collect.map import ru.dbotthepony.mc.otm.core.collect.map
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.isNotEmpty import ru.dbotthepony.mc.otm.core.isNotEmpty
import ru.dbotthepony.mc.otm.core.util.countingLazy import ru.dbotthepony.mc.otm.core.util.countingLazy
import java.util.function.Predicate import java.util.function.Predicate
interface IIngredientMatrix : Predicate<CraftingContainer>, Iterable<Ingredient> { interface IIngredientMatrix : Predicate<CraftingInput>, Iterable<Ingredient> {
val width: Int val width: Int
val height: Int val height: Int
val isEmpty: Boolean val isEmpty: Boolean
@ -52,8 +54,8 @@ interface IIngredientMatrix : Predicate<CraftingContainer>, Iterable<Ingredient>
return result return result
} }
fun test(t: CraftingContainer, fromColumn: Int, fromRow: Int, flop: Boolean): Boolean { fun test(t: CraftingInput, fromColumn: Int, fromRow: Int, flop: Boolean): Boolean {
if (t.width - fromColumn < width || t.height - fromRow < height) if (t.width() - fromColumn < width || t.height() - fromRow < height)
return false return false
for (column in 0 until width) for (column in 0 until width)
@ -64,8 +66,8 @@ interface IIngredientMatrix : Predicate<CraftingContainer>, Iterable<Ingredient>
return true return true
} }
fun preemptiveTest(t: CraftingContainer, fromColumn: Int, fromRow: Int, flop: Boolean): Boolean { fun preemptiveTest(t: CraftingInput, fromColumn: Int, fromRow: Int, flop: Boolean): Boolean {
if (t.width - fromColumn < width || t.height - fromRow < height) if (t.width() - fromColumn < width || t.height() - fromRow < height)
return false return false
for (column in 0 until width) { for (column in 0 until width) {
@ -82,24 +84,24 @@ interface IIngredientMatrix : Predicate<CraftingContainer>, Iterable<Ingredient>
return true return true
} }
override fun test(t: CraftingContainer): Boolean { override fun test(t: CraftingInput): Boolean {
if (t.width < width || t.height < height) if (t.width() < width || t.height() < height)
return false return false
for (column in 0 .. t.width - width) for (column in 0 .. t.width() - width)
for (row in 0 .. t.height - height) for (row in 0 .. t.height() - height)
if (test(t, column, row, false) || test(t, column, row, true)) if (test(t, column, row, false) || test(t, column, row, true))
return true return true
return false return false
} }
fun preemptiveTest(t: CraftingContainer): Boolean { fun preemptiveTest(t: CraftingInput): Boolean {
if (t.width < width || t.height < height) if (t.width() < width || t.height() < height)
return false return false
for (column in 0 .. t.width - width) for (column in 0 .. t.width() - width)
for (row in 0 .. t.height - height) for (row in 0 .. t.height() - height)
if (preemptiveTest(t, column, row, false) || preemptiveTest(t, column, row, true)) if (preemptiveTest(t, column, row, false) || preemptiveTest(t, column, row, true))
return true return true

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.recipe
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
import net.minecraft.core.UUIDUtil import net.minecraft.core.UUIDUtil
@ -9,6 +10,7 @@ import net.minecraft.data.recipes.FinishedRecipe
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.CraftingContainer import net.minecraft.world.inventory.CraftingContainer
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.CraftingInput
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.item.crafting.RecipeType
@ -31,14 +33,14 @@ import java.util.Optional
import java.util.UUID import java.util.UUID
import kotlin.jvm.optionals.getOrElse import kotlin.jvm.optionals.getOrElse
interface IMatterEntanglerRecipe : IMatteryRecipe<CraftingContainer> { interface IMatterEntanglerRecipe : IMatteryRecipe<CraftingInput> {
val matter: Decimal val matter: Decimal
val ticks: Double val ticks: Double
val ingredients: IIngredientMatrix val ingredients: IIngredientMatrix
val result: ItemStack val result: ItemStack
val experience: Float val experience: Float
fun preemptivelyMatches(container: CraftingContainer, level: Level): Boolean fun preemptivelyMatches(container: CraftingInput, level: Level): Boolean
} }
open class MatterEntanglerRecipe( open class MatterEntanglerRecipe(
@ -50,17 +52,17 @@ open class MatterEntanglerRecipe(
val uuidKey: String = "uuid", val uuidKey: String = "uuid",
val fixedUuid: Optional<UUID> = Optional.empty() val fixedUuid: Optional<UUID> = Optional.empty()
) : IMatterEntanglerRecipe { ) : IMatterEntanglerRecipe {
override fun matches(container: CraftingContainer, level: Level): Boolean { override fun matches(container: CraftingInput, level: Level): Boolean {
if (isIncomplete) return false if (isIncomplete) return false
return ingredients.test(container) return ingredients.test(container)
} }
override fun preemptivelyMatches(container: CraftingContainer, level: Level): Boolean { override fun preemptivelyMatches(container: CraftingInput, level: Level): Boolean {
if (isIncomplete) return false if (isIncomplete) return false
return ingredients.preemptiveTest(container) return ingredients.preemptiveTest(container)
} }
override fun assemble(container: CraftingContainer, registry: RegistryAccess): ItemStack { override fun assemble(container: CraftingInput, registry: HolderLookup.Provider): ItemStack {
return result.copy().also { return result.copy().also {
it.tagNotNull[uuidKey] = fixedUuid.getOrElse { UUID.randomUUID() } it.tagNotNull[uuidKey] = fixedUuid.getOrElse { UUID.randomUUID() }
} }
@ -106,9 +108,9 @@ open class MatterEntanglerRecipe(
fun matter() = Matter(this) fun matter() = Matter(this)
open class Energy(val parent: MatterEntanglerRecipe) : IMatterEntanglerRecipe by parent { open class Energy(val parent: MatterEntanglerRecipe) : IMatterEntanglerRecipe by parent {
override fun assemble(container: CraftingContainer, registry: RegistryAccess): ItemStack { override fun assemble(container: CraftingInput, registry: HolderLookup.Provider): ItemStack {
return parent.assemble(container, registry).also { result -> return parent.assemble(container, registry).also { result ->
container.iterator().map { it.matteryEnergy }.filterNotNull().forEach { container.items().iterator().map { it.matteryEnergy }.filterNotNull().forEach {
result.matteryEnergy!!.batteryLevel += it.batteryLevel result.matteryEnergy!!.batteryLevel += it.batteryLevel
} }
} }
@ -124,9 +126,9 @@ open class MatterEntanglerRecipe(
} }
open class Matter(val parent: MatterEntanglerRecipe) : IMatterEntanglerRecipe by parent { open class Matter(val parent: MatterEntanglerRecipe) : IMatterEntanglerRecipe by parent {
override fun assemble(container: CraftingContainer, registry: RegistryAccess): ItemStack { override fun assemble(container: CraftingInput, registry: HolderLookup.Provider): ItemStack {
return parent.assemble(container, registry).also { result -> return parent.assemble(container, registry).also { result ->
container.iterator().map { it.matter }.filterNotNull().forEach { container.items().iterator().map { it.matter }.filterNotNull().forEach {
result.matter!!.storedMatter += it.storedMatter result.matter!!.storedMatter += it.storedMatter
} }
} }

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.recipe
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.FinishedRecipe
@ -16,6 +17,7 @@ import net.minecraft.world.item.crafting.*
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
@ -29,15 +31,15 @@ abstract class MatteryCookingRecipe(
val count: Int = 1, val count: Int = 1,
val workTime: Int = 200, val workTime: Int = 200,
val experience: FloatProvider = ConstantFloat.ZERO val experience: FloatProvider = ConstantFloat.ZERO
) : Recipe<Container> { ) : Recipe<RecipeInput> {
override fun matches(container: Container, level: Level): Boolean { override fun matches(container: RecipeInput, level: Level): Boolean {
if (isIncomplete) if (isIncomplete)
return false return false
return input.test(container[0]) return input.test(container[0])
} }
fun matches(container: Container, slot: Int): Boolean { fun matches(container: RecipeInput, slot: Int): Boolean {
if (isIncomplete) if (isIncomplete)
return false return false
@ -63,11 +65,11 @@ abstract class MatteryCookingRecipe(
override fun isIncomplete(): Boolean = input.isActuallyEmpty || output.isActuallyEmpty override fun isIncomplete(): Boolean = input.isActuallyEmpty || output.isActuallyEmpty
override fun assemble(container: Container, registry: RegistryAccess): ItemStack = outputStack.copy() override fun assemble(container: RecipeInput, registry: HolderLookup.Provider): ItemStack = outputStack.copy()
override fun canCraftInDimensions(width: Int, height: Int): Boolean = true override fun canCraftInDimensions(width: Int, height: Int): Boolean = true
override fun getResultItem(registry: RegistryAccess): ItemStack = outputStack override fun getResultItem(registry: HolderLookup.Provider): ItemStack = outputStack
abstract fun toFinished(id: ResourceLocation): FinishedRecipe abstract fun toFinished(id: ResourceLocation): FinishedRecipe
} }

View File

@ -6,6 +6,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap import it.unimi.dsi.fastutil.objects.Object2IntArrayMap
import it.unimi.dsi.fastutil.objects.Object2IntMap import it.unimi.dsi.fastutil.objects.Object2IntMap
import it.unimi.dsi.fastutil.objects.Object2IntMaps import it.unimi.dsi.fastutil.objects.Object2IntMaps
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
import net.minecraft.data.recipes.FinishedRecipe import net.minecraft.data.recipes.FinishedRecipe
@ -14,12 +15,13 @@ import net.minecraft.util.StringRepresentable
import net.minecraft.world.Container import net.minecraft.world.Container
import net.minecraft.world.item.* import net.minecraft.world.item.*
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.Recipe import net.minecraft.world.item.crafting.RecipeInput
import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity import ru.dbotthepony.mc.otm.block.entity.decorative.PainterBlockEntity
import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.nbt.set import ru.dbotthepony.mc.otm.core.nbt.set
import ru.dbotthepony.mc.otm.core.tagNotNull import ru.dbotthepony.mc.otm.core.tagNotNull
@ -32,12 +34,12 @@ import java.util.function.Predicate
abstract class AbstractPainterRecipe( abstract class AbstractPainterRecipe(
dyes: Map<out DyeColor?, Int> dyes: Map<out DyeColor?, Int>
) : IMatteryRecipe<Container> { ) : IMatteryRecipe<RecipeInput> {
val dyes: Object2IntMap<DyeColor?> = Object2IntMaps.unmodifiable(Object2IntArrayMap(dyes)) val dyes: Object2IntMap<DyeColor?> = Object2IntMaps.unmodifiable(Object2IntArrayMap(dyes))
abstract fun matches(value: ItemStack): Boolean abstract fun matches(value: ItemStack): Boolean
override fun matches(contaier: Container, level: Level): Boolean { override fun matches(contaier: RecipeInput, level: Level): Boolean {
return !isIncomplete && matches(contaier[0]) return !isIncomplete && matches(contaier[0])
} }
@ -128,7 +130,7 @@ class PainterRecipe(
return NonNullList.of(Ingredient.EMPTY, input) return NonNullList.of(Ingredient.EMPTY, input)
} }
override fun assemble(p_44001_: Container, p_267165_: RegistryAccess): ItemStack { override fun assemble(p_44001_: RecipeInput, registries: HolderLookup.Provider): ItemStack {
return output.copy().also { o -> return output.copy().also { o ->
p_44001_[0].tag?.let { p_44001_[0].tag?.let {
if (o.tag == null) { if (o.tag == null) {
@ -142,7 +144,7 @@ class PainterRecipe(
} }
} }
override fun getResultItem(p_267052_: RegistryAccess): ItemStack { override fun getResultItem(registries: HolderLookup.Provider): ItemStack {
return output return output
} }
@ -185,7 +187,7 @@ class PainterArmorDyeRecipe(
return !isIncomplete && value.item is DyeableArmorItem return !isIncomplete && value.item is DyeableArmorItem
} }
override fun assemble(container: Container, registry: RegistryAccess): ItemStack { override fun assemble(container: RecipeInput, registry: HolderLookup.Provider): ItemStack {
var output = container[0].copy() var output = container[0].copy()
dyes.forEach { entry -> dyes.forEach { entry ->
@ -199,7 +201,7 @@ class PainterArmorDyeRecipe(
return output return output
} }
override fun getResultItem(registry: RegistryAccess): ItemStack = ItemStack.EMPTY override fun getResultItem(registry: HolderLookup.Provider): ItemStack = ItemStack.EMPTY
override fun getSerializer(): RecipeSerializer<*> = SERIALIZER override fun getSerializer(): RecipeSerializer<*> = SERIALIZER

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.recipe
import com.mojang.serialization.Codec import com.mojang.serialization.Codec
import com.mojang.serialization.codecs.RecordCodecBuilder import com.mojang.serialization.codecs.RecordCodecBuilder
import net.minecraft.core.HolderLookup
import net.minecraft.core.NonNullList import net.minecraft.core.NonNullList
import net.minecraft.core.RegistryAccess import net.minecraft.core.RegistryAccess
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
@ -11,11 +12,13 @@ import net.minecraft.world.Container
import net.minecraft.world.item.ItemStack import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.crafting.Ingredient import net.minecraft.world.item.crafting.Ingredient
import net.minecraft.world.item.crafting.Recipe import net.minecraft.world.item.crafting.Recipe
import net.minecraft.world.item.crafting.RecipeInput
import net.minecraft.world.item.crafting.RecipeSerializer import net.minecraft.world.item.crafting.RecipeSerializer
import net.minecraft.world.item.crafting.RecipeType import net.minecraft.world.item.crafting.RecipeType
import net.minecraft.world.level.Level import net.minecraft.world.level.Level
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.container.get import ru.dbotthepony.mc.otm.container.get
import ru.dbotthepony.mc.otm.core.get
import ru.dbotthepony.mc.otm.core.isActuallyEmpty import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.registry.MRecipes import ru.dbotthepony.mc.otm.registry.MRecipes
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
@ -29,8 +32,8 @@ class PlatePressRecipe(
val count: Int = 1, val count: Int = 1,
val workTime: Int = 200, val workTime: Int = 200,
val experience: FloatProvider = ConstantFloat.ZERO val experience: FloatProvider = ConstantFloat.ZERO
) : Recipe<Container> { ) : Recipe<RecipeInput> {
override fun matches(container: Container, p_44003_: Level): Boolean { override fun matches(container: RecipeInput, p_44003_: Level): Boolean {
if (isIncomplete) if (isIncomplete)
return false return false
@ -65,9 +68,9 @@ class PlatePressRecipe(
return input.isActuallyEmpty || output.isActuallyEmpty return input.isActuallyEmpty || output.isActuallyEmpty
} }
override fun assemble(p_44001_: Container, registry: RegistryAccess): ItemStack = outputStack.copy() override fun assemble(p_44001_: RecipeInput, registry: HolderLookup.Provider): ItemStack = outputStack.copy()
override fun canCraftInDimensions(p_43999_: Int, p_44000_: Int) = true override fun canCraftInDimensions(p_43999_: Int, p_44000_: Int) = true
override fun getResultItem(registry: RegistryAccess): ItemStack = outputStack override fun getResultItem(registry: HolderLookup.Provider): ItemStack = outputStack
override fun getSerializer(): RecipeSerializer<*> { override fun getSerializer(): RecipeSerializer<*> {
return SERIALIZER return SERIALIZER

View File

@ -8,6 +8,7 @@ import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.RegistryObject import net.minecraftforge.registries.RegistryObject
import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.ResourceLocation
import ru.dbotthepony.mc.otm.recipe.* import ru.dbotthepony.mc.otm.recipe.*
@Suppress("SameParameterValue") @Suppress("SameParameterValue")