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.ForgeRegistry
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.WeakReference
import java.math.BigInteger
@ -344,6 +347,10 @@ fun FriendlyByteBuf.readItemType(): Item? {
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 {
return getValue(property)
}

View File

@ -262,3 +262,24 @@ fun FriendlyByteBuf.readBinaryComponent(): Component {
fun FriendlyByteBuf.writeBinaryComponent(component: 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.readDecimal
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> {
val matter: Decimal
@ -51,6 +55,11 @@ fun FriendlyByteBuf.writeMatterValue(value: IMatterValue) {
writeDouble(value.complexity)
}
fun OutputStream.writeMatterValue(value: IMatterValue) {
writeDecimal(value.matter)
writeDouble(value.complexity)
}
fun FriendlyByteBuf.readMatterValue(): IMatterValue {
val matter = readDecimal()
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(
override val matter: Decimal,
override val complexity: Double

View File

@ -11,6 +11,8 @@ import com.google.gson.JsonSyntaxException
import com.mojang.blaze3d.platform.InputConstants
import com.mojang.brigadier.arguments.StringArgumentType
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.Object2BooleanOpenHashMap
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.stream
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.writeItemType
import ru.dbotthepony.mc.otm.core.util.writeCollection
import ru.dbotthepony.mc.otm.network.MatteryPacket
import ru.dbotthepony.mc.otm.network.RegistryNetworkChannel
import ru.dbotthepony.mc.otm.registry.RegistryDelegate
import ru.dbotthepony.mc.otm.storage.ItemStackWrapper
import java.io.DataInputStream
import java.io.DataOutputStream
import java.io.File
import java.io.OutputStream
import java.math.BigInteger
import java.util.*
import java.util.function.Supplier
import java.util.stream.Stream
import java.util.zip.Deflater
import java.util.zip.Inflater
import kotlin.ConcurrentModificationException
import kotlin.collections.ArrayDeque
import kotlin.collections.ArrayList
@ -1088,7 +1096,6 @@ object MatterManager {
fun tooltipEvent(event: ItemTooltipEvent) {
val window = minecraft.window.window
if (InputConstants.isKeyDown(window, GLFW.GLFW_KEY_LEFT_SHIFT) || InputConstants.isKeyDown(window, GLFW.GLFW_KEY_RIGHT_SHIFT)) {
val matter = get(event.itemStack, accountForStackSize = false)
@ -1397,12 +1404,70 @@ object MatterManager {
val time = SystemTime()
val result = SyncPacket(
buff.readMap(FriendlyByteBuf::readItemType, FriendlyByteBuf::readMatterValue),
buff.readMap(FriendlyByteBuf::readItemType) { self -> self.readCollection(::ArrayList, FriendlyByteBuf::readBinaryComponent) }
)
val bbytes = ByteArray(buff.readableBytes())
buff.readBytes(bbytes)
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
}
@ -1413,9 +1478,54 @@ object MatterManager {
) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
val time = SystemTime()
buff.writeMap(values, FriendlyByteBuf::writeItemType, FriendlyByteBuf::writeMatterValue)
buff.writeMap(comments, FriendlyByteBuf::writeItemType) { self, value -> self.writeCollection(value, FriendlyByteBuf::writeBinaryComponent) }
LOGGER.debug("Encoding matter registry packet took ${time.millis}ms, written total ${buff.writerIndex() - 1} bytes")
val stream = FastByteArrayOutputStream()
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>) {
@ -1430,7 +1540,7 @@ object MatterManager {
commentary.clear()
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")