Compress matter registry packet

# Conflicts:
#	src/main/kotlin/ru/dbotthepony/mc/otm/core/Ext.kt
#	src/main/kotlin/ru/dbotthepony/mc/otm/matter/IMatterValue.kt
#	src/main/kotlin/ru/dbotthepony/mc/otm/matter/MatterManager.kt
This commit is contained in:
DBotThePony 2023-03-03 21:24:25 +07:00
parent 26a064fbe2
commit 36c14be025
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 169 additions and 11 deletions

View File

@ -28,6 +28,9 @@ import net.minecraftforge.items.IItemHandler
import net.minecraftforge.registries.ForgeRegistries import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.ForgeRegistry import net.minecraftforge.registries.ForgeRegistry
import net.minecraftforge.registries.IForgeRegistry import net.minecraftforge.registries.IForgeRegistry
import ru.dbotthepony.mc.otm.core.util.readInt
import java.io.InputStream
import java.io.OutputStream
import java.lang.ref.Reference import java.lang.ref.Reference
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.math.BigInteger import java.math.BigInteger
@ -344,6 +347,10 @@ fun FriendlyByteBuf.readItemType(): Item? {
return ForgeRegistries.ITEMS.getValue(readInt()) return ForgeRegistries.ITEMS.getValue(readInt())
} }
fun InputStream.readItemType(): Item? {
return ForgeRegistries.ITEMS.getValue(readInt())
}
operator fun <T : Comparable<T>> StateHolder<*, *>.get(property: Property<T>): T { operator fun <T : Comparable<T>> StateHolder<*, *>.get(property: Property<T>): T {
return getValue(property) return getValue(property)
} }

View File

@ -262,3 +262,24 @@ fun FriendlyByteBuf.readBinaryComponent(): Component {
fun FriendlyByteBuf.writeBinaryComponent(component: Component) { fun FriendlyByteBuf.writeBinaryComponent(component: Component) {
writeJson(Component.Serializer.toJsonTree(component)) writeJson(Component.Serializer.toJsonTree(component))
} }
fun <S : OutputStream, V> S.writeCollection(collection: Collection<V>, writer: S.(V) -> Unit) {
writeVarIntLE(collection.size)
for (value in collection) {
writer(this, value)
}
}
fun <S : InputStream, V, C : MutableCollection<V>> S.readCollection(reader: S.() -> V, factory: (Int) -> C): C {
val size = readVarIntLE()
val collection = factory.invoke(size)
for (i in 0 until size) {
collection.add(reader(this))
}
return collection
}
fun <S : InputStream, V> S.readCollection(reader: S.() -> V) = readCollection(reader, ::ArrayList)

View File

@ -4,6 +4,10 @@ import net.minecraft.network.FriendlyByteBuf
import ru.dbotthepony.mc.otm.core.Decimal import ru.dbotthepony.mc.otm.core.Decimal
import ru.dbotthepony.mc.otm.core.readDecimal import ru.dbotthepony.mc.otm.core.readDecimal
import ru.dbotthepony.mc.otm.core.writeDecimal import ru.dbotthepony.mc.otm.core.writeDecimal
import ru.dbotthepony.mc.otm.core.util.readDouble
import ru.dbotthepony.mc.otm.core.util.writeDouble
import java.io.InputStream
import java.io.OutputStream
interface IMatterValue : Comparable<IMatterValue> { interface IMatterValue : Comparable<IMatterValue> {
val matter: Decimal val matter: Decimal
@ -51,6 +55,11 @@ fun FriendlyByteBuf.writeMatterValue(value: IMatterValue) {
writeDouble(value.complexity) writeDouble(value.complexity)
} }
fun OutputStream.writeMatterValue(value: IMatterValue) {
writeDecimal(value.matter)
writeDouble(value.complexity)
}
fun FriendlyByteBuf.readMatterValue(): IMatterValue { fun FriendlyByteBuf.readMatterValue(): IMatterValue {
val matter = readDecimal() val matter = readDecimal()
val complexity = readDouble() val complexity = readDouble()
@ -62,6 +71,17 @@ fun FriendlyByteBuf.readMatterValue(): IMatterValue {
} }
} }
fun InputStream.readMatterValue(): IMatterValue {
val matter = readDecimal()
val complexity = readDouble()
if (matter.isZero && complexity == 0.0) {
return IMatterValue.Companion
} else {
return MatterValue(matter, complexity)
}
}
data class MatterValue( data class MatterValue(
override val matter: Decimal, override val matter: Decimal,
override val complexity: Double override val complexity: Double

View File

@ -11,6 +11,8 @@ import com.google.gson.JsonSyntaxException
import com.mojang.blaze3d.platform.InputConstants import com.mojang.blaze3d.platform.InputConstants
import com.mojang.brigadier.arguments.StringArgumentType import com.mojang.brigadier.arguments.StringArgumentType
import com.mojang.brigadier.context.CommandContext import com.mojang.brigadier.context.CommandContext
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.Object2BooleanFunction import it.unimi.dsi.fastutil.objects.Object2BooleanFunction
import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap import it.unimi.dsi.fastutil.objects.Object2BooleanOpenHashMap
import it.unimi.dsi.fastutil.objects.Reference2BooleanFunction import it.unimi.dsi.fastutil.objects.Reference2BooleanFunction
@ -78,17 +80,23 @@ import ru.dbotthepony.mc.otm.core.readItemType
import ru.dbotthepony.mc.otm.core.registryName import ru.dbotthepony.mc.otm.core.registryName
import ru.dbotthepony.mc.otm.core.stream import ru.dbotthepony.mc.otm.core.stream
import ru.dbotthepony.mc.otm.core.util.readBinaryComponent import ru.dbotthepony.mc.otm.core.util.readBinaryComponent
import ru.dbotthepony.mc.otm.core.util.readCollection
import ru.dbotthepony.mc.otm.core.util.writeBinaryComponent import ru.dbotthepony.mc.otm.core.util.writeBinaryComponent
import ru.dbotthepony.mc.otm.core.writeItemType import ru.dbotthepony.mc.otm.core.util.writeCollection
import ru.dbotthepony.mc.otm.network.MatteryPacket import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
import ru.dbotthepony.mc.otm.registry.RegistryDelegate import ru.dbotthepony.mc.otm.registry.RegistryDelegate
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.File import java.io.File
import java.io.OutputStream
import java.math.BigInteger import java.math.BigInteger
import java.util.* import java.util.*
import java.util.function.Supplier import java.util.function.Supplier
import java.util.stream.Stream import java.util.stream.Stream
import java.util.zip.Deflater
import java.util.zip.Inflater
import kotlin.ConcurrentModificationException import kotlin.ConcurrentModificationException
import kotlin.collections.ArrayDeque import kotlin.collections.ArrayDeque
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@ -1088,7 +1096,6 @@ object MatterManager {
fun tooltipEvent(event: ItemTooltipEvent) { fun tooltipEvent(event: ItemTooltipEvent) {
val window = minecraft.window.window val window = minecraft.window.window
if (InputConstants.isKeyDown(window, GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(window, GLFW.GLFW_KEY_RIGHT_SHIFT)) { if (InputConstants.isKeyDown(window, GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(window, GLFW.GLFW_KEY_RIGHT_SHIFT)) {
val matter = get(event.itemStack, accountForStackSize = false) val matter = get(event.itemStack, accountForStackSize = false)
@ -1397,12 +1404,70 @@ object MatterManager {
val time = SystemTime() val time = SystemTime()
val result = SyncPacket( val bbytes = ByteArray(buff.readableBytes())
buff.readMap(FriendlyByteBuf::readItemType, FriendlyByteBuf::readMatterValue), buff.readBytes(bbytes)
buff.readMap(FriendlyByteBuf::readItemType) { self -> self.readCollection(::ArrayList, FriendlyByteBuf::readBinaryComponent) }
)
LOGGER.debug("Reading matter registry packet took ${time.millis}ms") val chunks = ArrayList<ByteArray>()
var size = 0
val inflater = Inflater()
inflater.setInput(bbytes)
while (!inflater.finished()) {
val chunk = ByteArray(4096)
val inflated = inflater.inflate(chunk)
if (inflated == 0) {
break
} else {
size += inflated
if (size >= 1 shl 24 /* 16 MiB */) {
throw IndexOutOfBoundsException("Pipe Bomb")
}
if (inflated == 4096) {
chunks.add(chunk)
} else {
chunks.add(chunk.copyOfRange(0, inflated))
}
}
}
val spliced = ByteArray(size)
var pointer = 0
for (chunk in chunks) {
for (i in chunk.indices) {
spliced[pointer++] = chunk[i]
}
}
val stream = FastByteArrayInputStream(spliced)
val data = DataInputStream(stream)
val valuesSize = data.readInt()
val values = Reference2ObjectOpenHashMap<Item, IMatterValue>(valuesSize)
val comments = Reference2ObjectOpenHashMap<Item, ArrayList<Component>>()
for (i in 0 until valuesSize) {
val type = data.readItemType()
check(values.put(type, data.readMatterValue()) == null) { "Duplicate item type $type" }
if (data.read() > 0) {
comments[type] = data.readCollection { readBinaryComponent()!! }
}
}
val commentsSize = data.readInt()
for (i in 0 until commentsSize) {
val type = data.readItemType()
check(comments.put(type, data.readCollection { readBinaryComponent()!! }) == null) { "Duplicate commentary item type $type" }
}
val result = SyncPacket(values, comments)
LOGGER.debug("Reading matter registry packet took ${time.millis}ms (${bbytes.size} bytes compressed, $size bytes total)")
return result return result
} }
@ -1413,9 +1478,54 @@ object MatterManager {
) : MatteryPacket { ) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) { override fun write(buff: FriendlyByteBuf) {
val time = SystemTime() val time = SystemTime()
buff.writeMap(values, FriendlyByteBuf::writeItemType, FriendlyByteBuf::writeMatterValue)
buff.writeMap(comments, FriendlyByteBuf::writeItemType) { self, value -> self.writeCollection(value, FriendlyByteBuf::writeBinaryComponent) } val stream = FastByteArrayOutputStream()
LOGGER.debug("Encoding matter registry packet took ${time.millis}ms, written total ${buff.writerIndex() - 1} bytes") val data = DataOutputStream(stream)
var commentsSize = comments.size
data.writeInt(values.size)
for ((k, v) in values) {
data.writeInt(ForgeRegistries.ITEMS.getID(k))
data.writeMatterValue(v)
val comment = comments[k]
if (comment != null) {
commentsSize--
data.write(1)
data.writeCollection(comment, OutputStream::writeBinaryComponent)
} else {
data.write(0)
}
}
data.writeInt(commentsSize)
for ((k, v) in comments) {
if (!values.containsKey(k)) {
data.writeInt(ForgeRegistries.ITEMS.getID(k))
data.writeCollection(v, OutputStream::writeBinaryComponent)
}
}
val deflater = Deflater(5)
deflater.setInput(stream.array, 0, stream.length)
deflater.finish()
val bytes = ByteArray(4096)
while (true) {
val written = deflater.deflate(bytes)
if (written == 0) {
break
} else {
buff.writeBytes(bytes, 0, written)
}
}
LOGGER.debug("Encoding matter registry packet took ${time.millis}ms, (${stream.length} bytes total, ${buff.writerIndex() - 1} bytes compressed)")
} }
override fun play(context: Supplier<NetworkEvent.Context>) { override fun play(context: Supplier<NetworkEvent.Context>) {
@ -1430,7 +1540,7 @@ object MatterManager {
commentary.clear() commentary.clear()
for ((k, v) in comments) { for ((k, v) in comments) {
commentary[k] = ArrayList<Component>(v.size).also { it.addAll(v) } commentary[k] = ArrayList(v)
} }
LOGGER.debug("Updating matter registry from packet took ${time.millis}ms") LOGGER.debug("Updating matter registry from packet took ${time.millis}ms")