More backporting
This commit is contained in:
parent
f16483d7c0
commit
3c5ea937a5
@ -531,7 +531,7 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
|
||||
super.onJobTick(status)
|
||||
|
||||
if (isExopackVisible && ply.level().random.nextFloat() <= 0.05f) {
|
||||
MatteryPlayerNetworkChannel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with(ply as ServerPlayer), ExopackSmokePacket(ply.uuid))
|
||||
MatteryPlayerNetworkChannel.send(PacketDistributor.TRACKING_ENTITY_AND_SELF.with { ply as ServerPlayer }, ExopackSmokePacket(ply.uuid))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -564,7 +564,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
||||
return super.mouseReleased(p_97812_, p_97813_, p_97814_)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollY: Double): Boolean {
|
||||
for (panel in panels) {
|
||||
if (panel.mouseScrolledChecked(mouseX, mouseY, scrollY)) {
|
||||
return true
|
||||
@ -647,7 +647,7 @@ abstract class MatteryScreen<T : MatteryMenu>(menu: T, inventory: Inventory, tit
|
||||
val mouseYf = mouseY.toFloat()
|
||||
|
||||
// dark background
|
||||
this.renderBackground(graphics, mouseX, mouseY, partialTick)
|
||||
this.renderBackground(graphics)
|
||||
|
||||
super.hoveredSlot = null
|
||||
var hovered = false
|
||||
|
@ -32,6 +32,7 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
|
||||
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.core.value
|
||||
import ru.dbotthepony.mc.otm.menu.decorative.PainterMenu
|
||||
|
||||
class PainterScreen(menu: PainterMenu, inventory: Inventory, title: Component) : MatteryScreen<PainterMenu>(menu, inventory, title) {
|
||||
|
@ -108,7 +108,7 @@ open class EditablePanel<out S : Screen> @JvmOverloads constructor(
|
||||
return this@EditablePanel.mouseDragged(p_94740_, p_94741_, p_94742_, p_94743_, p_94744_)
|
||||
}
|
||||
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollX: Double, scrollY: Double): Boolean {
|
||||
override fun mouseScrolled(mouseX: Double, mouseY: Double, scrollY: Double): Boolean {
|
||||
return this@EditablePanel.mouseScrolled(mouseX, mouseY, scrollY)
|
||||
}
|
||||
|
||||
|
@ -8,9 +8,6 @@ import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.Unpooled
|
||||
import net.minecraft.advancements.AdvancementHolder
|
||||
import net.minecraft.data.recipes.FinishedRecipe
|
||||
import net.minecraft.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
@ -24,15 +21,7 @@ import ru.dbotthepony.mc.otm.core.util.readBinaryJsonWithCodecIndirect
|
||||
import ru.dbotthepony.mc.otm.core.util.writeBinaryJsonWithCodec
|
||||
import kotlin.collections.ArrayDeque
|
||||
import kotlin.concurrent.getOrSet
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
* 1.20.2: Mojang FINALLY moved json IO of recipes to codecs
|
||||
*
|
||||
* ...but they forgot to do the same for Networking them, Ingredient does not have codec for network.
|
||||
*
|
||||
* Mojang.... Mojang never changes.
|
||||
*/
|
||||
class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
val empty: S?,
|
||||
codec: (Codec2RecipeSerializer<S>.Context) -> Codec<S>,
|
||||
@ -40,45 +29,15 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
constructor(supplier: (Codec2RecipeSerializer<S>.Context) -> Codec<S>) : this(null, supplier)
|
||||
|
||||
private class CurrentContext {
|
||||
val idStack = ArrayDeque<ResourceLocation>()
|
||||
var isNetwork = 0
|
||||
}
|
||||
|
||||
inner class Context {
|
||||
val id: ResourceLocation
|
||||
get() = checkNotNull(context.idStack.lastOrNull()) { "Not currently deserializing recipe" }
|
||||
|
||||
val ingredients: Codec<Ingredient> get() = ActualIngredientCodec
|
||||
|
||||
fun <P : Recipe<*>> wrap(serializer: RecipeSerializer<P>): Codec<P> {
|
||||
return object : Codec<P> {
|
||||
override fun <T : Any?> encode(input: P, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
if (context.isNetwork > 0) {
|
||||
val parent = Unpooled.buffer()
|
||||
val buff = FriendlyByteBuf(parent)
|
||||
serializer.toNetwork(buff, input)
|
||||
return DataResult.success(ops.createByteList(parent.nioBuffer()))
|
||||
} else {
|
||||
return serializer.codec().encode(input, ops, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
override fun <T : Any?> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<P, T>> {
|
||||
if (context.isNetwork > 0) {
|
||||
return ops.getByteBuffer(input).flatMap {
|
||||
val parent = Unpooled.buffer()
|
||||
val buff = FriendlyByteBuf(parent)
|
||||
parent.writeBytes(it)
|
||||
parent.setIndex(0, 0)
|
||||
val read = serializer.fromNetwork(buff)
|
||||
|
||||
if (read == null)
|
||||
DataResult.error { "Unable to read parent recipe from network" }
|
||||
else
|
||||
DataResult.success(Pair(read, ops.empty()))
|
||||
}
|
||||
} else {
|
||||
return serializer.codec().decode(ops, input)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val codec = codec.invoke(Context())
|
||||
@ -97,30 +56,45 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
}
|
||||
}
|
||||
|
||||
override fun codec(): Codec<S> {
|
||||
return this
|
||||
override fun fromJson(id: ResourceLocation, data: JsonObject): S {
|
||||
try {
|
||||
context.idStack.addLast(id)
|
||||
|
||||
return decode(JsonOps.INSTANCE, data).get().map(
|
||||
{ it.first },
|
||||
{ empty ?: throw JsonSyntaxException("Failed to deserialize recipe from JSON: ${it.message()}") }
|
||||
)
|
||||
} finally {
|
||||
context.idStack.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun fromNetwork(data: FriendlyByteBuf): S? {
|
||||
override fun fromNetwork(id: ResourceLocation, data: FriendlyByteBuf): S? {
|
||||
try {
|
||||
context.idStack.addLast(id)
|
||||
context.isNetwork++
|
||||
|
||||
return data.readBinaryJsonWithCodecIndirect(this)
|
||||
.resultOrPartial { LOGGER.error("Failed to read recipe from network: $it") }.orElse(null)
|
||||
.resultOrPartial { LOGGER.error("Failed to read recipe $id from network: $it") }.orElse(null)
|
||||
} finally {
|
||||
context.isNetwork--
|
||||
context.idStack.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
override fun toNetwork(data: FriendlyByteBuf, recipe: S) {
|
||||
try {
|
||||
context.idStack.addLast(recipe.id)
|
||||
context.isNetwork++
|
||||
|
||||
data.writeBinaryJsonWithCodec(this, recipe)
|
||||
} finally {
|
||||
context.isNetwork--
|
||||
context.idStack.removeLast()
|
||||
}
|
||||
}
|
||||
|
||||
fun toFinished(recipe: S, id: ResourceLocation): FinishedRecipe {
|
||||
fun toFinished(recipe: S): FinishedRecipe {
|
||||
return object : FinishedRecipe {
|
||||
override fun serializeRecipeData(p_125967_: JsonObject) {
|
||||
encode(recipe, JsonOps.INSTANCE, p_125967_).get().map(
|
||||
@ -137,15 +111,19 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
)
|
||||
}
|
||||
|
||||
override fun id(): ResourceLocation {
|
||||
return id
|
||||
override fun getId(): ResourceLocation {
|
||||
return recipe.id
|
||||
}
|
||||
|
||||
override fun type(): RecipeSerializer<*> {
|
||||
override fun getType(): RecipeSerializer<*> {
|
||||
return this@Codec2RecipeSerializer
|
||||
}
|
||||
|
||||
override fun advancement(): AdvancementHolder? {
|
||||
override fun serializeAdvancement(): JsonObject? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun getAdvancementId(): ResourceLocation? {
|
||||
return null
|
||||
}
|
||||
}
|
||||
@ -156,7 +134,7 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
return if (context.isNetwork > 0) {
|
||||
networkIngredientCodec.encode(input, ops, prefix)
|
||||
} else {
|
||||
Ingredient.CODEC.encode(input, ops, prefix)
|
||||
IngredientCodec.encode(input, ops, prefix)
|
||||
}
|
||||
}
|
||||
|
||||
@ -164,7 +142,7 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
return if (context.isNetwork > 0) {
|
||||
networkIngredientCodec.decode(ops, input)
|
||||
} else {
|
||||
Ingredient.CODEC.decode(ops, input)
|
||||
IngredientCodec.decode(ops, input)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -178,14 +156,8 @@ class Codec2RecipeSerializer<S : Recipe<*>>(
|
||||
* since RecipeSerializers are expected to be stateless. [Codec2RecipeSerializer], however, is stateful (threading PoV).
|
||||
* To make it stateless, [ThreadLocal] is used.
|
||||
*/
|
||||
private val context by object : ThreadLocal<CurrentContext>() {
|
||||
override fun initialValue(): CurrentContext {
|
||||
return CurrentContext()
|
||||
}
|
||||
}
|
||||
private val contextHolder = ThreadLocal<CurrentContext>()
|
||||
private val context: CurrentContext
|
||||
get() = contextHolder.getOrSet { CurrentContext() }
|
||||
}
|
||||
}
|
||||
|
||||
private operator fun <T> ThreadLocal<T>.getValue(companion: Codec2RecipeSerializer.Companion, property: KProperty<*>): T {
|
||||
return get()
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package ru.dbotthepony.mc.otm.data
|
||||
|
||||
import com.google.gson.JsonSyntaxException
|
||||
import com.mojang.datafixers.util.Pair
|
||||
import com.mojang.serialization.Codec
|
||||
import com.mojang.serialization.DataResult
|
||||
import com.mojang.serialization.DynamicOps
|
||||
import com.mojang.serialization.JsonOps
|
||||
import net.minecraft.world.item.crafting.Ingredient
|
||||
|
||||
object IngredientCodec : Codec<Ingredient> {
|
||||
override fun <T : Any> encode(input: Ingredient, ops: DynamicOps<T>, prefix: T): DataResult<T> {
|
||||
return DataResult.success(JsonOps.INSTANCE.convertTo(ops, input.toJson()))
|
||||
}
|
||||
|
||||
override fun <T : Any> decode(ops: DynamicOps<T>, input: T): DataResult<Pair<Ingredient, T>> {
|
||||
try {
|
||||
return DataResult.success(Pair(Ingredient.fromJson(ops.convertTo(JsonOps.INSTANCE, input)), ops.empty()))
|
||||
} catch (err: JsonSyntaxException) {
|
||||
return DataResult.error { "Error decoding Ingredient: ${err.message}" }
|
||||
}
|
||||
}
|
||||
}
|
@ -5,12 +5,11 @@ import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.server.level.ServerPlayer
|
||||
import net.minecraft.world.entity.Entity
|
||||
import net.minecraft.world.entity.player.Player
|
||||
import net.minecraftforge.event.network.CustomPayloadEvent
|
||||
import net.minecraftforge.network.Channel
|
||||
import net.minecraftforge.network.ChannelBuilder
|
||||
import net.minecraftforge.network.NetworkDirection
|
||||
import net.minecraftforge.network.NetworkEvent
|
||||
import net.minecraftforge.network.NetworkRegistry
|
||||
import net.minecraftforge.network.PacketDistributor
|
||||
import net.minecraftforge.network.SimpleChannel
|
||||
import net.minecraftforge.network.simple.SimpleChannel
|
||||
import org.apache.logging.log4j.LogManager
|
||||
import ru.dbotthepony.mc.otm.NULLABLE_MINECRAFT_SERVER
|
||||
import ru.dbotthepony.mc.otm.OverdriveThatMatters
|
||||
@ -20,6 +19,7 @@ import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.locks.LockSupport
|
||||
import java.util.function.BiConsumer
|
||||
import java.util.function.Function
|
||||
import java.util.function.Supplier
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
class MNetworkContext(val sender: ServerPlayer?, packetHandled: GetterSetter<Boolean>, private val enqueuer: (Runnable) -> CompletableFuture<*>) {
|
||||
@ -36,23 +36,20 @@ interface MatteryPacket {
|
||||
}
|
||||
|
||||
abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
val channel: SimpleChannel = ChannelBuilder
|
||||
.named(ResourceLocation(OverdriveThatMatters.MOD_ID, name))
|
||||
.acceptedVersions(Channel.VersionTest.exact(version))
|
||||
.networkProtocolVersion(version)
|
||||
.simpleChannel()
|
||||
val channel: SimpleChannel = NetworkRegistry
|
||||
.newSimpleChannel(ResourceLocation(OverdriveThatMatters.MOD_ID, name), version::toString, String::equals, String::equals)
|
||||
|
||||
fun sendToServer(packet: Any) = channel.send(packet, PacketDistributor.SERVER.noArg())
|
||||
fun sendToServer(packet: Any) = channel.send(PacketDistributor.SERVER.noArg(), packet)
|
||||
|
||||
fun send(ply: Player, packet: Any) {
|
||||
if (ply is ServerPlayer) {
|
||||
queue.add(Task(channel, PacketDistributor.PLAYER.with(ply), packet))
|
||||
queue.add(Task(channel, PacketDistributor.PLAYER.with { ply }, packet))
|
||||
}
|
||||
}
|
||||
|
||||
fun sendNow(ply: Player, packet: Any) {
|
||||
if (ply is ServerPlayer) {
|
||||
channel.send(packet, PacketDistributor.PLAYER.with(ply))
|
||||
channel.send(PacketDistributor.PLAYER.with { ply }, packet)
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +58,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
return
|
||||
}
|
||||
|
||||
queue.add(Task(channel, PacketDistributor.TRACKING_ENTITY.with(entity), packet))
|
||||
queue.add(Task(channel, PacketDistributor.TRACKING_ENTITY.with { entity }, packet))
|
||||
}
|
||||
|
||||
fun sendTrackingAndSelf(entity: Entity, packet: Any) {
|
||||
@ -69,7 +66,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
return
|
||||
}
|
||||
|
||||
queue.add(Task(channel, PacketDistributor.TRACKING_ENTITY_AND_SELF.with(entity), packet))
|
||||
queue.add(Task(channel, PacketDistributor.TRACKING_ENTITY_AND_SELF.with { entity }, packet))
|
||||
}
|
||||
|
||||
fun send(distributor: PacketDistributor.PacketTarget, packet: Any) {
|
||||
@ -77,7 +74,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
}
|
||||
|
||||
fun sendNow(distributor: PacketDistributor.PacketTarget, packet: Any) {
|
||||
channel.send(packet, distributor)
|
||||
channel.send(distributor, packet)
|
||||
}
|
||||
|
||||
private var nextNetworkPacketID = 0
|
||||
@ -94,8 +91,8 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
throw IndexOutOfBoundsException("Network message ID overflow!")
|
||||
}
|
||||
|
||||
val builder = channel.messageBuilder(packetClass, direction)
|
||||
val bridgeHandler = BiConsumer<T, CustomPayloadEvent.Context> { a, b -> handler(a, MNetworkContext(b.sender, GetterSetter.of({ b.packetHandled }, { b.packetHandled = it }), b::enqueueWork)) }
|
||||
val builder = channel.messageBuilder(packetClass, nextNetworkPacketID++)
|
||||
val bridgeHandler = BiConsumer<T, Supplier<NetworkEvent.Context>> { a, b -> handler(a, MNetworkContext(b.get().sender, GetterSetter.of({ b.get().packetHandled }, { b.get().packetHandled = it }), b.get()::enqueueWork)) }
|
||||
|
||||
if (handleOnMainThread) {
|
||||
builder.consumerMainThread(bridgeHandler)
|
||||
@ -154,7 +151,7 @@ abstract class MatteryNetworkChannel(val version: Int, val name: String) {
|
||||
LockSupport.park()
|
||||
} else {
|
||||
try {
|
||||
task.channel.send(task.packet, task.target)
|
||||
task.channel.send(task.target, task.packet)
|
||||
} catch(err: Throwable) {
|
||||
logger.error("Error executing network dispatcher task", err)
|
||||
}
|
||||
|
@ -1,12 +1,8 @@
|
||||
package ru.dbotthepony.mc.otm.recipe
|
||||
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonSyntaxException
|
||||
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.network.FriendlyByteBuf
|
||||
import net.minecraft.resources.ResourceLocation
|
||||
import net.minecraft.world.inventory.CraftingContainer
|
||||
import net.minecraft.world.item.ItemStack
|
||||
@ -19,12 +15,15 @@ import net.minecraftforge.common.Tags
|
||||
import ru.dbotthepony.mc.otm.container.util.stream
|
||||
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
|
||||
import ru.dbotthepony.mc.otm.core.isNotEmpty
|
||||
import ru.dbotthepony.mc.otm.core.set
|
||||
import ru.dbotthepony.mc.otm.data.Codec2RecipeSerializer
|
||||
import ru.dbotthepony.mc.otm.item.tool.ExplosiveHammerItem
|
||||
import ru.dbotthepony.mc.otm.registry.MItems
|
||||
|
||||
class ExplosiveHammerPrimingRecipe(val payload: Ingredient) : CraftingRecipe {
|
||||
class ExplosiveHammerPrimingRecipe(val payload: Ingredient, val id: ResourceLocation) : CraftingRecipe {
|
||||
override fun getId(): ResourceLocation {
|
||||
return id
|
||||
}
|
||||
|
||||
override fun isIncomplete(): Boolean {
|
||||
return payload.isActuallyEmpty
|
||||
}
|
||||
@ -70,14 +69,14 @@ class ExplosiveHammerPrimingRecipe(val payload: Ingredient) : CraftingRecipe {
|
||||
return NonNullList.of(Ingredient.of(), Ingredient.of(MItems.EXPLOSIVE_HAMMER), Ingredient.of(Tags.Items.GUNPOWDER), payload)
|
||||
}
|
||||
|
||||
fun toFinished(id: ResourceLocation) = CODEC.toFinished(this, id)
|
||||
fun toFinished() = CODEC.toFinished(this)
|
||||
|
||||
companion object {
|
||||
val CODEC = Codec2RecipeSerializer<ExplosiveHammerPrimingRecipe> { p ->
|
||||
RecordCodecBuilder.create {
|
||||
it.group(
|
||||
p.ingredients.fieldOf("payload").forGetter(ExplosiveHammerPrimingRecipe::payload)
|
||||
).apply(it, ::ExplosiveHammerPrimingRecipe)
|
||||
).apply(it) { a -> ExplosiveHammerPrimingRecipe(a, p.id) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user