package ru.dbotthepony.kstarbound.io import it.unimi.dsi.fastutil.bytes.ByteArrayList import ru.dbotthepony.kommons.io.readBinaryString import ru.dbotthepony.kommons.util.IStruct2d import ru.dbotthepony.kommons.util.IStruct2i import ru.dbotthepony.kommons.io.readDouble import ru.dbotthepony.kommons.io.readFloat import ru.dbotthepony.kommons.io.readLong import ru.dbotthepony.kommons.io.readSignedVarInt import ru.dbotthepony.kommons.io.readVector2d import ru.dbotthepony.kommons.io.readVector2f import ru.dbotthepony.kommons.io.writeDouble import ru.dbotthepony.kommons.io.writeFloat import ru.dbotthepony.kommons.io.writeLong import ru.dbotthepony.kommons.io.writeSignedVarInt import ru.dbotthepony.kommons.io.writeStruct2d import ru.dbotthepony.kommons.io.writeStruct2f import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.util.AABB import ru.dbotthepony.kommons.util.KOptional import ru.dbotthepony.kommons.vector.Vector2d import ru.dbotthepony.kommons.vector.Vector2i import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.world.ChunkPos import java.io.DataInput import java.io.DataOutput import java.io.IOException import java.io.InputStream import java.io.OutputStream import java.io.RandomAccessFile import java.util.* import java.util.function.IntConsumer import java.util.function.IntSupplier import kotlin.collections.ArrayList fun InputStream.readByteChar(): Char { return read().toChar() } fun InputStream.readHeader(header: String) { for ((i, char) in header.withIndex()) { val read = readByteChar() if (read != char) { throw IllegalArgumentException("Malformed header at byte $i: expected $char (${char.code}) got $read (${char.code})") } } } fun InputStream.readChunkPos(): ChunkPos { return ChunkPos(readSignedVarInt(), readSignedVarInt()) } fun OutputStream.writeColor(color: RGBAColor) { writeFloat(color.red) writeFloat(color.green) writeFloat(color.blue) writeFloat(color.alpha) } fun InputStream.readColor(): RGBAColor { return RGBAColor(readFloat(), readFloat(), readFloat(), readFloat()) } fun InputStream.readInternedString(): String = Starbound.STRINGS.intern(readBinaryString()) fun InputStream.readAABBLegacy(): AABB { val mins = readVector2f() val maxs = readVector2f() return AABB(mins.toDoubleVector(), maxs.toDoubleVector()) } fun InputStream.readAABBLegacyOptional(): KOptional { val mins = readVector2f() val maxs = readVector2f() // what the fuck are you doing?! if ( mins.x == Float.MAX_VALUE && mins.y == Float.MAX_VALUE && maxs.x == -Float.MAX_VALUE && maxs.y == -Float.MAX_VALUE ) { return KOptional() } return KOptional(AABB(mins.toDoubleVector(), maxs.toDoubleVector())) } fun InputStream.readAABB(): AABB { return AABB(readVector2d(), readVector2d()) } fun OutputStream.writeAABBLegacy(value: AABB) { writeStruct2f(value.mins.toFloatVector()) writeStruct2f(value.maxs.toFloatVector()) } fun OutputStream.writeAABBLegacyOptional(value: KOptional) { value.ifPresent { writeStruct2f(it.mins.toFloatVector()) writeStruct2f(it.maxs.toFloatVector()) }.ifNotPresent { writeFloat(Float.MAX_VALUE) writeFloat(Float.MAX_VALUE) writeFloat(-Float.MAX_VALUE) writeFloat(-Float.MAX_VALUE) } } fun OutputStream.writeAABB(value: AABB) { writeStruct2d(value.mins) writeStruct2d(value.maxs) }