Revert "DBot — Сегодня, в 7:53"

This reverts commit 8abb4e1598.

Revert "бакпорт изменений curios под смачный пердёж"

This reverts commit 1cbf73cdfd.

Revert "помогите"

This reverts commit b97e18ca5f.

Revert "DBotThePony — Сегодня, в 17:11"

This reverts commit 0da87980f7.

Revert "android health bar + 1px wider energy bar"

This reverts commit cbaf89d4a7.

Revert "Resolve conflicts between 1.19.3 code and 1.19.2 code"

This reverts commit 006cbc75e3.

Revert "Add missing import"

This reverts commit 275e340243.

Revert "Multi packet mattery registry sync"

This reverts commit 3dcaed64cd.

Revert "Increase (de)compress buffer sizes"

This reverts commit 04a5e87fec.

Revert "Compress matter registry packet"

This reverts commit 36c14be025.

Revert "Payload may not be larger than 1048576 bytes"

This reverts commit 26a064fbe2.
This commit is contained in:
DBotThePony 2024-01-01 23:05:36 +07:00
parent 8abb4e1598
commit 036de121c7
Signed by: DBot
GPG Key ID: DCC23B5715498507
14 changed files with 53 additions and 684 deletions

View File

@ -321,6 +321,7 @@ repositories {
url = uri("https://maven.dbotthepony.ru")
content {
includeGroup("top.theillusivec4.curios")
includeGroup("yalter.mousetweaks")
includeGroup("mekanism")
includeGroup("lain.mods.cos")
@ -356,14 +357,6 @@ repositories {
}
}
maven {
url = uri("https://maven.theillusivec4.top/")
content {
includeGroup("top.theillusivec4.curios")
}
}
// mavenCentral()
}

View File

@ -19,7 +19,7 @@ mixin_version=0.8.5
jei_version=11.3.0.262
jupiter_version=5.8.2
mekanism_version=10.3.5.homebaked
curios_version=5.1.4.1
curios_version=5.1.1.0
cosmetic_armor_reworked_version=v1
jade_id=4010505
configured_id=4011355

View File

@ -34,7 +34,6 @@ import ru.dbotthepony.mc.otm.client.model.GravitationStabilizerModel;
import ru.dbotthepony.mc.otm.client.model.TritaniumArmorModel;
import ru.dbotthepony.mc.otm.client.render.ShockwaveRenderer;
import ru.dbotthepony.mc.otm.client.render.WidgetAtlasHolder;
import ru.dbotthepony.mc.otm.compat.curios.CuriosCompatKt;
import ru.dbotthepony.mc.otm.compat.mekanism.QIOKt;
import ru.dbotthepony.mc.otm.compat.mekanism.TooltipsKt;
import ru.dbotthepony.mc.otm.core.Decimal;
@ -198,10 +197,6 @@ public final class OverdriveThatMatters {
EVENT_BUS.addGenericListener(BlockEntity.class, EventPriority.NORMAL, QIOKt::attachCapabilities);
}
if (ModList.get().isLoaded("curios")) {
EVENT_BUS.addListener(EventPriority.NORMAL, CuriosCompatKt::onCuriosSlotModifiersUpdated);
}
OreGen.INSTANCE.register();
}

View File

@ -22,10 +22,6 @@ object ClientConfig {
.comment("Allow to scroll Exopack inventory in non OTM inventories when hovering just over inventory slots, not only scrollbar")
.define("exopackFreeScroll", true)
var ANDROID_HEALTH_HUD: Boolean by specBuilder
.comment("Replace hearts with health bar on HUD when you are an android")
.define("ANDROID_HEALTH_HUD", true)
init {
spec = specBuilder.build()
}

View File

@ -18,17 +18,14 @@ import ru.dbotthepony.mc.otm.triggers.NanobotsArmorTrigger
import kotlin.math.roundToInt
class NanobotsArmorFeature(android: MatteryPlayerCapability) : AndroidFeature(AndroidFeatures.NANOBOTS_ARMOR, android) {
var strength by synchronizer.int(
setter = setter@{
value, access, _ -> access.write(value.coerceIn(0 .. 3))
}
)
var strength: Int = 0
set(value) { field = value.coerceIn(0 .. 3) }
var speed: Int = 0
set(value) { field = value.coerceIn(0 .. 3) }
private var ticksPassed = 0
var layers by synchronizer.int()
private var layers = 0
override fun tickServer() {
if (layers < strength + 1 && android.androidEnergy.extractEnergyInnerExact(ENERGY_PER_LAYER, true).isPositive) {

View File

@ -165,10 +165,6 @@ class MatteryPlayerCapability(val ply: Player) : ICapabilityProvider, INBTSerial
return _exoPackMenu!!
}
fun recreateExoPackMenu() {
_exoPackMenu = ExoPackInventoryMenu(this)
}
private var shouldSendIteration = false
var iteration = 0
private set

View File

@ -17,9 +17,7 @@ import net.minecraftforge.client.event.RenderLevelStageEvent
import net.minecraftforge.client.event.ScreenEvent
import net.minecraftforge.client.gui.overlay.ForgeGui
import net.minecraftforge.client.gui.overlay.GuiOverlayManager
import ru.dbotthepony.mc.otm.ClientConfig
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.android.feature.NanobotsArmorFeature
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
@ -28,29 +26,17 @@ import ru.dbotthepony.mc.otm.client.render.*
import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.registry.AndroidFeatures
import java.util.*
import kotlin.math.ceil
object MatteryGUI {
private val BARS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "player_bars"), 81f, 36f)
private val BARS = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "player_bars"), 80f, 36f)
val CHARGE = BARS.subElement(height = 9f)
val CHARGE_BG = BARS.subElement(y = 9f, height = 9f)
val CHARGE_HUNGER = BARS.subElement(y = 18f, height = 9f)
val CHARGE_HUNGER_BG = BARS.subElement(y = 27f, height = 9f)
private val BARS_HP = AtlasSkinElement(ResourceLocation(OverdriveThatMatters.MOD_ID, "player_bars_health"), 81f, 63f)
val HEALTH = BARS_HP.subElement(height = 9f)
val HEALTH_BG = BARS_HP.subElement(y = 9f, height = 9f)
val HEALTH_BG_NANOBOTS = BARS_HP.subElement(y = 18f, height = 9f)
val HEALTH_POISON = BARS_HP.subElement(y = 27f, height = 9f)
val HEALTH_WITHER = BARS_HP.subElement(y = 36f, height = 9f)
val HEALTH_ABSORB = BARS_HP.subElement(y = 45f, height = 9f)
val HEALTH_FROZEN = BARS_HP.subElement(y = 54f, height = 9f)
private var originalBedButtonX = -1
private var originalBedButtonY = -1
@ -113,10 +99,6 @@ object MatteryGUI {
GuiOverlayManager.findOverlay(ResourceLocation("minecraft", "air_level"))
}
private val PLAYER_HEALTH_ELEMENT by lazy {
GuiOverlayManager.findOverlay(ResourceLocation("minecraft", "player_health"))
}
var iteration = 0
var showIterationUntil = 0L
var showIterationUntilFade = 0L
@ -195,7 +177,7 @@ object MatteryGUI {
showIteration(event)
}
private fun renderFoodAndAir(event: RenderGuiOverlayEvent.Pre) {
fun onLayerRenderEvent(event: RenderGuiOverlayEvent.Pre) {
if (event.overlay != FOOD_LEVEL_ELEMENT && event.overlay != AIR_LEVEL_ELEMENT) {
return
}
@ -226,8 +208,6 @@ object MatteryGUI {
return
}
if (!gui.shouldDrawSurvivalElements()) return
var level: Float
if (mattery.androidEnergy.maxBatteryLevel.isZero) {
@ -248,14 +228,14 @@ object MatteryGUI {
val top: Int = height - gui.rightHeight
gui.rightHeight += 10
val leftPadding = ceil(level * 80f - 0.5f)
val leftPadding = ceil(level * 79f - 0.5f)
if (ply.hasEffect(MobEffects.HUNGER)) {
CHARGE_HUNGER_BG.render(event.poseStack, left.toFloat(), top.toFloat())
CHARGE_HUNGER.renderPartial(event.poseStack, left.toFloat() - leftPadding + 80f, top.toFloat(), width = leftPadding)
CHARGE_HUNGER.renderPartial(event.poseStack, left.toFloat() - leftPadding + 79f, top.toFloat(), width = leftPadding)
} else {
CHARGE_BG.render(event.poseStack, left.toFloat(), top.toFloat())
CHARGE.renderPartial(event.poseStack, left.toFloat() - leftPadding + 80f, top.toFloat(), width = leftPadding)
CHARGE.renderPartial(event.poseStack, left.toFloat() - leftPadding + 79f, top.toFloat(), width = leftPadding)
}
val formattedPower = mattery.androidEnergy.batteryLevel.formatPower()
@ -269,95 +249,4 @@ object MatteryGUI {
event.poseStack.popPose()
}
}
private fun getSpriteForPlayer(player: Player): SubSkinElement {
if (player.hasEffect(MobEffects.POISON)) {
return HEALTH_POISON
} else if (player.hasEffect(MobEffects.WITHER)) {
return HEALTH_WITHER
} else if (player.isFullyFrozen()) {
return HEALTH_FROZEN
}
return HEALTH
}
private fun getHealthColorForPlayer(player: Player): Int {
if (player.hasEffect(MobEffects.POISON)) {
return RGBAColor.DARK_GREEN.toInt()
} else if (player.hasEffect(MobEffects.WITHER)) {
return RGBAColor.WHITE.toInt()
} else if (player.isFullyFrozen()) {
return RGBAColor.AQUA.toInt()
}
return RGBAColor.RED.toInt()
} // можно вынести в конфиг, но для этого нужен селектор цвета
private fun renderPlayerHealth(event: RenderGuiOverlayEvent.Pre) {
if (!ClientConfig.ANDROID_HEALTH_HUD) return
val ply: LocalPlayer = minecraft.player ?: return
var mattery = ply.matteryPlayer
if (!ply.isAlive && mattery == null) {
mattery = lastState
}
val gui = minecraft.gui as? ForgeGui ?: return
if (mattery != null && mattery.isAndroid) {
event.isCanceled = true
lastState = mattery
if (!gui.shouldDrawSurvivalElements()) return
val level: Float = (ply.health / ply.maxHealth).coerceIn(0.0f .. 1.0f)
val levelAbsorb: Float = (ply.absorptionAmount / ply.maxHealth).coerceIn(0.0f .. 1.0f)
gui.setupOverlayRenderState(true, false)
RenderSystem.setShaderColor(1.0f, 1.0f, 1.0f, 1.0f)
val width = event.window.guiScaledWidth
val height = event.window.guiScaledHeight
val left = width / 2 - 10 - 81
val top: Int = height - gui.leftHeight
gui.leftHeight += 10
HEALTH_BG.render(event.poseStack, left.toFloat(), top.toFloat())
if (mattery.hasFeature(AndroidFeatures.NANOBOTS_ARMOR)) {
val featArmor = mattery.getFeature(AndroidFeatures.NANOBOTS_ARMOR) as NanobotsArmorFeature
val levelArmor: Float = (featArmor.layers.toFloat() / (featArmor.strength + 1).toFloat()).coerceIn(0.0f .. 1.0f)
HEALTH_BG_NANOBOTS.renderPartial(event.poseStack, left.toFloat(), top.toFloat(), width = ceil(levelArmor * 81f))
}
getSpriteForPlayer(ply).renderPartial(event.poseStack, left.toFloat(), top.toFloat(), width = ceil(level * 80f - 0.5f))
if (levelAbsorb > 0) {
HEALTH_ABSORB.renderPartial(event.poseStack, left.toFloat(), top.toFloat(), width = ceil(levelAbsorb * 80f - 0.5f))
}
var formattedHealth = "%d/%d".format(ply.health.toInt(), ply.maxHealth.toInt())
if (ply.absorptionAmount > 0)
formattedHealth = "%d+%d/%d".format(ply.health.toInt(), ply.absorptionAmount.toInt(), ply.maxHealth.toInt())
event.poseStack.pushPose()
event.poseStack.scale(0.5f, 0.5f, 0.5f)
minecraft.font.drawAligned(event.poseStack, formattedHealth, TextAlign.CENTER_RIGHT, (left - 1f) * 2f, (top + 5.5f) * 2f, RGBAColor.BLACK.toInt())
minecraft.font.drawAligned(event.poseStack, formattedHealth, TextAlign.CENTER_RIGHT, (left - 2f) * 2f, (top + 4.5f) * 2f, getHealthColorForPlayer(ply))
event.poseStack.popPose()
}
}
fun onLayerRenderEvent(event: RenderGuiOverlayEvent.Pre) {
if (event.overlay == FOOD_LEVEL_ELEMENT || event.overlay == AIR_LEVEL_ELEMENT) {
renderFoodAndAir(event)
} else if (event.overlay == PLAYER_HEALTH_ELEMENT) {
renderPlayerHealth(event)
}
}
}

View File

@ -6,26 +6,20 @@ import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.ItemStack
import net.minecraftforge.fml.ModList
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.container.awareStream
import ru.dbotthepony.mc.otm.container.stream
import ru.dbotthepony.mc.otm.core.AwareItemStack
import ru.dbotthepony.mc.otm.core.orNull
import top.theillusivec4.curios.api.CuriosApi
import top.theillusivec4.curios.api.event.SlotModifiersUpdatedEvent
import top.theillusivec4.curios.common.inventory.CosmeticCurioSlot
import top.theillusivec4.curios.common.inventory.CurioSlot
import java.util.*
import java.util.stream.Stream
val isCuriosLoaded by lazy {
ModList.get().isLoaded(CuriosApi.MODID)
}
fun onCuriosSlotModifiersUpdated(event: SlotModifiersUpdatedEvent) {
check(isCuriosLoaded) { "Curios is not loaded!" }
event.entity.matteryPlayer?.recreateExoPackMenu()
}
private fun Player.getCuriosSlotsImpl(): Collection<Pair<Slot, Slot?>> {
val handler = getCapability(MatteryCapability.CURIOS_INVENTORY).orNull() ?: return listOf()
@ -34,9 +28,9 @@ private fun Player.getCuriosSlotsImpl(): Collection<Pair<Slot, Slot?>> {
val sortedIdentifiers = ArrayList<String>(handler.curios.keys.size)
sortedIdentifiers.addAll(handler.curios.keys)
//if (handler.curios !is LinkedHashMap) {
// sortedIdentifiers.sort()
//}
if (handler.curios !is LinkedHashMap) {
sortedIdentifiers.sort()
}
for (identifier in sortedIdentifiers) {
val curio = handler.curios[identifier]!!
@ -75,7 +69,7 @@ val Player.curiosSlots: Collection<Pair<Slot, Slot?>> get() {
private fun Player.curiosStreamImpl(includeCosmetics: Boolean): Stream<out ItemStack> {
val handler = getCapability(MatteryCapability.CURIOS_INVENTORY).orNull() ?: return Stream.empty()
val result = ArrayList<Stream<out ItemStack>>()
val result = LinkedList<Stream<out ItemStack>>()
for ((identifier, curio) in handler.curios) {
result.add(curio.stacks.stream())
@ -85,7 +79,7 @@ private fun Player.curiosStreamImpl(includeCosmetics: Boolean): Stream<out ItemS
}
}
return result.stream().flatMap { it }
return Streams.concat(*result.toTypedArray())
}
fun Player.curiosStream(includeCosmetics: Boolean = true): Stream<out ItemStack> {
@ -99,7 +93,7 @@ fun Player.curiosStream(includeCosmetics: Boolean = true): Stream<out ItemStack>
private fun Player.curiosAwareStreamImpl(includeCosmetics: Boolean): Stream<out AwareItemStack> {
val handler = getCapability(MatteryCapability.CURIOS_INVENTORY).orNull() ?: return Stream.empty()
val result = ArrayList<Stream<out AwareItemStack>>()
val result = LinkedList<Stream<out AwareItemStack>>()
for ((identifier, curio) in handler.curios) {
result.add(curio.stacks.awareStream())

View File

@ -28,8 +28,8 @@ import net.minecraftforge.items.IItemHandler
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.ForgeRegistry
import net.minecraftforge.registries.IForgeRegistry
import java.io.InputStream
import java.lang.ref.Reference
import java.lang.ref.WeakReference
import java.math.BigInteger
import java.util.Arrays
import java.util.Spliterators
@ -344,10 +344,6 @@ 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

@ -1,310 +0,0 @@
package ru.dbotthepony.mc.otm.core.util
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import com.google.gson.JsonParseException
import com.google.gson.JsonPrimitive
import com.google.gson.JsonSyntaxException
import io.netty.buffer.ByteBufInputStream
import io.netty.buffer.ByteBufOutputStream
import io.netty.handler.codec.EncoderException
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.NbtAccounter
import net.minecraft.nbt.NbtIo
import net.minecraft.network.FriendlyByteBuf
import net.minecraft.network.chat.Component
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraftforge.registries.ForgeRegistries
import net.minecraftforge.registries.ForgeRegistry
import ru.dbotthepony.mc.otm.core.readDouble
import ru.dbotthepony.mc.otm.core.readInt
import ru.dbotthepony.mc.otm.core.readVarIntLE
import ru.dbotthepony.mc.otm.core.readVarLongLE
import ru.dbotthepony.mc.otm.core.writeDouble
import ru.dbotthepony.mc.otm.core.writeInt
import ru.dbotthepony.mc.otm.core.writeVarIntLE
import ru.dbotthepony.mc.otm.core.writeVarLongLE
import java.io.*
import java.math.BigDecimal
import java.math.BigInteger
import kotlin.math.absoluteValue
// But seriously, Mojang, why would you need to derive from ByteBuf directly, when you can implement
// your own InputStream and OutputStream, since ByteBuf is meant to be operated on most time like a stream anyway?
// netty ByteBuf -> netty ByteBufInputStream -> Minecraft FriendlyInputStream
fun OutputStream.writeNbt(value: CompoundTag) {
try {
NbtIo.write(value, if (this is DataOutputStream) this else DataOutputStream(this))
} catch (ioexception: IOException) {
throw EncoderException(ioexception)
}
}
fun InputStream.readBinaryString(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): String {
val size = readVarIntLE()
require(size >= 0) { "Negative payload size: $size" }
sizeLimit.accountBytes(size.toLong())
val bytes = ByteArray(size)
read(bytes)
return bytes.decodeToString()
}
fun OutputStream.writeBinaryString(input: String) {
val bytes = input.encodeToByteArray()
writeVarIntLE(bytes.size)
write(bytes)
}
fun InputStream.readNbt(accounter: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): CompoundTag {
return try {
NbtIo.read(if (this is DataInputStream) this else DataInputStream(this), accounter)
} catch (ioexception: IOException) {
throw EncoderException(ioexception)
}
}
fun OutputStream.writeItem(itemStack: ItemStack, limitedTag: Boolean = true) {
if (itemStack.isEmpty) {
write(0)
} else {
write(1)
val id = (ForgeRegistries.ITEMS as ForgeRegistry<Item>).getID(itemStack.item)
writeInt(id)
writeInt(itemStack.count)
var compoundtag: CompoundTag? = null
if (itemStack.item.isDamageable(itemStack) || itemStack.item.shouldOverrideMultiplayerNbt()) {
compoundtag = if (limitedTag) itemStack.shareTag else itemStack.tag
}
write(if (compoundtag != null) 1 else 0)
if (compoundtag != null) {
writeNbt(compoundtag)
}
}
}
private fun NbtAccounter.accountBytes(bytes: Long) = accountBits(bytes * 8L)
fun InputStream.readItem(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): ItemStack {
sizeLimit.accountBytes(1L)
if (read() == 0) {
return ItemStack.EMPTY
}
sizeLimit.accountBytes(9L)
val item = (ForgeRegistries.ITEMS as ForgeRegistry<Item>).getValue(readInt())
val itemStack = ItemStack(item, readInt())
if (read() != 0) {
itemStack.readShareTag(readNbt(sizeLimit))
}
return itemStack
}
fun OutputStream.writeBigDecimal(value: BigDecimal) {
writeInt(value.scale())
val bytes = value.unscaledValue().toByteArray()
writeVarIntLE(bytes.size)
write(bytes)
}
fun InputStream.readBigDecimal(sizeLimit: NbtAccounter = NbtAccounter(512L)): BigDecimal {
val scale = readInt()
val size = readVarIntLE()
require(size >= 0) { "Negative payload size: $size" }
sizeLimit.accountBytes(size.toLong() + 4L)
val bytes = ByteArray(size)
read(bytes)
return BigDecimal(BigInteger(bytes), scale)
}
private const val TYPE_NULL = 0x01
private const val TYPE_DOUBLE = 0x02
private const val TYPE_BOOLEAN = 0x03
private const val TYPE_INT = 0x04
private const val TYPE_STRING = 0x05
private const val TYPE_ARRAY = 0x06
private const val TYPE_OBJECT = 0x07
private fun fixSignedInt(read: Long): Long {
val sign = read and 0x1L
@Suppress("name_shadowing")
val read = read ushr 1
if (sign == 1L) {
return -read - 1L
} else {
return read
}
}
/**
* Writes binary json to stream in Starbound Object Notation format
*
* just copy pasted this code from my another project because i was lazy
*/
fun OutputStream.writeJson(element: JsonElement) {
if (element is JsonObject) {
write(TYPE_OBJECT)
writeVarIntLE(element.size())
for ((k, v) in element.entrySet()) {
writeBinaryString(k)
writeJson(v)
}
} else if (element is JsonArray) {
write(TYPE_ARRAY)
writeVarIntLE(element.size())
for (v in element) {
writeJson(v)
}
} else if (element is JsonPrimitive) {
if (element.isNumber) {
val num = element.asNumber
if (num is Int || num is Long) {
write(TYPE_INT)
var int = num.toLong()
if (int < 0) {
int = int.absoluteValue.shl(1).or(1)
} else {
int.shl(1)
}
writeVarLongLE(int)
} else if (num is Float || num is Double) {
write(TYPE_DOUBLE)
writeDouble(num.toDouble())
} else {
throw IllegalArgumentException("Unknown number type: ${num::class.qualifiedName}")
}
} else if (element.isString) {
write(TYPE_STRING)
writeBinaryString(element.asString)
} else if (element.isBoolean) {
write(TYPE_BOOLEAN)
write(if (element.asBoolean) 1 else 0)
} else {
write(TYPE_NULL)
}
} else {
throw IllegalArgumentException("Unknown element type: ${element::class.qualifiedName}")
}
}
/**
* Reads binary json from stream in Starbound Object Notation format
*
* just copy pasted this code from my another project because i was lazy
*/
fun InputStream.readJson(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18 /* 256 KiB */)): JsonElement {
sizeLimit.accountBytes(1L)
return when (val id = read()) {
TYPE_NULL -> JsonNull.INSTANCE
TYPE_DOUBLE -> {
sizeLimit.accountBytes(8L)
JsonPrimitive(readDouble())
}
TYPE_BOOLEAN -> {
sizeLimit.accountBytes(1L)
JsonPrimitive(read() > 1)
}
TYPE_INT -> JsonPrimitive(fixSignedInt(readVarLongLE()))
TYPE_STRING -> JsonPrimitive(readBinaryString(sizeLimit))
TYPE_ARRAY -> {
val values = readVarIntLE()
if (values == 0) return JsonArray()
if (values < 0) throw JsonSyntaxException("Tried to read json array with $values elements in it")
val build = JsonArray(values)
for (i in 0 until values) build.add(readJson(sizeLimit))
return build
}
TYPE_OBJECT -> {
val values = readVarIntLE()
if (values == 0) return JsonObject()
if (values < 0) throw JsonSyntaxException("Tried to read json object with $values elements in it")
val build = JsonObject()
for (i in 0 until values) {
val key: String
try {
key = readBinaryString(sizeLimit)
} catch(err: Throwable) {
throw JsonSyntaxException("Reading json object at $i", err)
}
try {
build.add(key, readJson(sizeLimit))
} catch(err: Throwable) {
throw JsonSyntaxException("Reading json object at $i with name $key", err)
}
}
return build
}
else -> throw JsonParseException("Unknown element type $id")
}
}
fun InputStream.readBinaryComponent(): Component? {
return Component.Serializer.fromJson(readJson())
}
fun OutputStream.writeBinaryComponent(component: Component) {
writeJson(Component.Serializer.toJsonTree(component))
}
fun FriendlyByteBuf.readJson(sizeLimit: NbtAccounter = NbtAccounter(1L shl 18)): JsonElement {
return ByteBufInputStream(this).readJson(sizeLimit)
}
fun FriendlyByteBuf.writeJson(value: JsonElement) {
ByteBufOutputStream(this).writeJson(value)
}
fun FriendlyByteBuf.readBinaryComponent(): Component {
return Component.Serializer.fromJson(readJson()) ?: throw NullPointerException("Received null 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

@ -3,11 +3,7 @@ package ru.dbotthepony.mc.otm.matter
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.readDouble
import ru.dbotthepony.mc.otm.core.writeDecimal
import ru.dbotthepony.mc.otm.core.writeDouble
import java.io.InputStream
import java.io.OutputStream
interface IMatterValue : Comparable<IMatterValue> {
val matter: Decimal
@ -55,11 +51,6 @@ 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()
@ -71,17 +62,6 @@ 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,8 +11,6 @@ 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
@ -72,7 +70,6 @@ import ru.dbotthepony.mc.otm.core.formatMatter
import ru.dbotthepony.mc.otm.core.formatMatterFull
import ru.dbotthepony.mc.otm.core.formatSiComponent
import ru.dbotthepony.mc.otm.core.formatTickDuration
import ru.dbotthepony.mc.otm.core.getID
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.isActuallyEmpty
import ru.dbotthepony.mc.otm.core.isZero
@ -80,24 +77,16 @@ import ru.dbotthepony.mc.otm.core.orNull
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.util.writeCollection
import ru.dbotthepony.mc.otm.core.writeItemType
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
@ -479,7 +468,7 @@ object MatterManager {
val ignoreDamageables = data["ignore_damageables"]?.asBoolean ?: false
val allowBacktrack = data["allow_backtrack"]?.asBoolean ?: true
var stream = server.recipeManager.byType(findRecipeType).values.stream().filter { !it.isIncomplete }
var stream = server.recipeManager.byType(findRecipeType).values.parallelStream().filter { !it.isIncomplete }
if (ignoreDamageables) {
stream = stream.filter { it.ingredients.stream().flatMap { it.items.stream() }.noneMatch { it.isDamageableItem } }
@ -1097,6 +1086,7 @@ 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)
@ -1376,7 +1366,7 @@ object MatterManager {
matterValues[item] = value
}
syncRegistry(PacketDistributor.ALL.noArg())
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), SyncPacket(matterValues, commentary))
}
fun onDataPackSync(event: OnDatapackSyncEvent) {
@ -1384,9 +1374,9 @@ object MatterManager {
return
if (event.player == null) {
syncRegistry(PacketDistributor.ALL.noArg())
RegistryNetworkChannel.send(PacketDistributor.ALL.noArg(), SyncPacket(matterValues, commentary))
} else {
syncRegistry(PacketDistributor.PLAYER.with { event.player ?: throw ConcurrentModificationException() })
RegistryNetworkChannel.send(PacketDistributor.PLAYER.with { event.player ?: throw ConcurrentModificationException() }, SyncPacket(matterValues, commentary))
}
}
@ -1400,195 +1390,48 @@ object MatterManager {
return matterValues[value] ?: IMatterValue.Companion
}
private val receivedPackets = ArrayList<SyncPacket>()
private fun syncRegistry(distributor: PacketDistributor.PacketTarget) {
val time = SystemTime()
val stream = FastByteArrayOutputStream()
val data = DataOutputStream(stream)
var commentsSize = commentary.size
data.writeInt(matterValues.size)
for ((k, v) in matterValues) {
data.writeInt(ForgeRegistries.ITEMS.getID(k))
data.writeMatterValue(v)
val comment = commentary[k]
if (comment != null) {
commentsSize--
data.write(1)
data.writeCollection(comment, OutputStream::writeBinaryComponent)
} else {
data.write(0)
}
}
data.writeInt(commentsSize)
for ((k, v) in commentary) {
if (!matterValues.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 chunks = ArrayList<SyncPacket>()
var totalSize = 0
var first = true
while (true) {
val bytes = ByteArray(2 shl 20 - 1024)
val written = deflater.deflate(bytes)
if (written == 0) {
break
} else {
totalSize += written
chunks.add(SyncPacket(bytes, written, if (first) { first = false; FIRST } else NORMAL))
}
}
if (chunks.size == 1) {
chunks[0].mode = FIRST_AND_LAST
} else if(chunks.size > 1) {
chunks.last().mode = LAST
}
LOGGER.debug("Encoding matter registry packet took ${time.millis}ms, (${stream.length} bytes total, $totalSize bytes compressed)")
for (chunk in chunks) {
RegistryNetworkChannel.send(distributor, chunk)
}
}
private fun playRegistryPackets() {
val time = SystemTime()
var totalCompressedSize = 0
for (chunk in receivedPackets) {
totalCompressedSize += chunk.length
}
if (totalCompressedSize == 0) {
return // what.
}
val compressed = ByteArray(totalCompressedSize)
var pointer = 0
for (chunk in receivedPackets) {
for (i in 0 until chunk.length) {
compressed[pointer++] = chunk.payload[i]
}
}
receivedPackets.clear()
val chunks = ArrayList<ByteArray>()
var size = 0
val inflater = Inflater()
inflater.setInput(compressed)
while (!inflater.finished()) {
val chunk = ByteArray(2 shl 16)
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 == 2 shl 16) {
chunks.add(chunk)
} else {
chunks.add(chunk.copyOfRange(0, inflated))
}
}
}
val spliced = ByteArray(size)
var pointer2 = 0
for (chunk in chunks) {
for (i in chunk.indices) {
spliced[pointer2++] = chunk[i]
}
}
val stream = FastByteArrayInputStream(spliced)
val data = DataInputStream(stream)
val valuesSize = data.readInt()
matterValues.clear()
commentary.clear()
for (i in 0 until valuesSize) {
val type = data.readItemType()
check(matterValues.put(type, data.readMatterValue()) == null) { "Duplicate item type $type" }
if (data.read() > 0) {
commentary[type] = data.readCollection { readBinaryComponent()!! }
}
}
val commentsSize = data.readInt()
for (i in 0 until commentsSize) {
val type = data.readItemType()
check(commentary.put(type, data.readCollection { readBinaryComponent()!! }) == null) { "Duplicate commentary item type $type" }
}
LOGGER.debug("Decoding matter registry packets took ${time.millis}ms ($totalCompressedSize bytes compressed, $size bytes total)")
}
fun readSyncPacket(buff: FriendlyByteBuf): SyncPacket {
LOGGER.info("Received matter registry packet, ${buff.readableBytes()} bytes in size")
val mode = buff.readByte()
val bytes = ByteArray(buff.readableBytes())
buff.readBytes(bytes)
return SyncPacket(bytes, bytes.size, mode.toInt())
val time = SystemTime()
val result = SyncPacket(
buff.readMap(FriendlyByteBuf::readItemType, FriendlyByteBuf::readMatterValue),
buff.readMap(FriendlyByteBuf::readItemType) { self -> self.readCollection(::ArrayList, FriendlyByteBuf::readComponent) }
)
LOGGER.debug("Reading matter registry packet took ${time.millis}ms")
return result
}
private const val FIRST = 0
private const val NORMAL = 1
private const val LAST = 2
private const val FIRST_AND_LAST = 3
class SyncPacket(val payload: ByteArray, val length: Int, var mode: Int) : MatteryPacket {
class SyncPacket(
val values: Map<Item, IMatterValue>,
val comments: Map<Item, Collection<Component>>
) : MatteryPacket {
override fun write(buff: FriendlyByteBuf) {
buff.writeByte(mode)
buff.writeBytes(payload, 0, length)
val time = SystemTime()
buff.writeMap(values, FriendlyByteBuf::writeItemType, FriendlyByteBuf::writeMatterValue)
buff.writeMap(comments, FriendlyByteBuf::writeItemType) { self, value -> self.writeCollection(value, FriendlyByteBuf::writeComponent) }
LOGGER.debug("Encoding matter registry packet took ${time.millis}ms, written total ${buff.writerIndex() - 1} bytes")
}
override fun play(context: Supplier<NetworkEvent.Context>) {
if (SERVER_IS_LIVE)
return // singleplayer or LAN host
if (mode == FIRST) {
receivedPackets.clear()
receivedPackets.add(this)
} else if (mode == LAST) {
receivedPackets.add(this)
playRegistryPackets()
} else if (mode == FIRST_AND_LAST) {
receivedPackets.clear()
receivedPackets.add(this)
playRegistryPackets()
} else {
receivedPackets.add(this)
val time = SystemTime()
matterValues.clear()
matterValues.putAll(values)
commentary.clear()
for ((k, v) in comments) {
commentary[k] = ArrayList<Component>(v.size).also { it.addAll(v) }
}
LOGGER.debug("Updating matter registry from packet took ${time.millis}ms")
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 B

After

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 367 B