mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 10:25:06 -04:00
rewrite PlayInByteBuffer in kotlin
This commit is contained in:
parent
6f4096b42b
commit
ddd51401d6
@ -14,7 +14,7 @@ package de.bixilon.minosoft.data.mappings.recipes
|
||||
|
||||
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||
|
||||
data class Ingredient(val itemStacks: Array<ItemStack>) {
|
||||
data class Ingredient(val itemStacks: Array<ItemStack?>) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
@ -92,7 +92,7 @@ class PacketJoinGame(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
if (buffer.versionId < ProtocolVersions.V_20W21A) {
|
||||
dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readInt())
|
||||
} else {
|
||||
val dimensionCodec = buffer.readNBT()
|
||||
val dimensionCodec = buffer.readNBT()!!
|
||||
dimensions = parseDimensionCodec(dimensionCodec, buffer.versionId)
|
||||
if (buffer.versionId < ProtocolVersions.V_1_16_2_PRE3) {
|
||||
dimension = dimensions[buffer.readResourceLocation()]!!
|
||||
|
@ -70,12 +70,11 @@ open class InByteBuffer {
|
||||
return bytes[pointer++]
|
||||
}
|
||||
|
||||
fun readByteArray(length: Int = readVarInt()): ByteArray {
|
||||
open fun readByteArray(length: Int = readVarInt()): ByteArray {
|
||||
check(length <= bytes.size) { "Trying to allocate to much memory!" }
|
||||
val array = ByteArray(length)
|
||||
for (i in 0 until length) {
|
||||
array[i] = readByte()
|
||||
}
|
||||
System.arraycopy(bytes, pointer, array, 0, length)
|
||||
pointer += length
|
||||
return array
|
||||
}
|
||||
|
||||
|
@ -1,231 +0,0 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.protocol.protocol;
|
||||
|
||||
import de.bixilon.minosoft.data.entities.meta.EntityMetaData;
|
||||
import de.bixilon.minosoft.data.inventory.ItemStack;
|
||||
import de.bixilon.minosoft.data.mappings.biomes.Biome;
|
||||
import de.bixilon.minosoft.data.mappings.particle.Particle;
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.BlockParticleData;
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.DustParticleData;
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.ItemParticleData;
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.ParticleData;
|
||||
import de.bixilon.minosoft.data.mappings.recipes.Ingredient;
|
||||
import de.bixilon.minosoft.data.text.ChatComponent;
|
||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection;
|
||||
import de.bixilon.minosoft.util.nbt.tag.CompoundTag;
|
||||
import de.bixilon.minosoft.util.nbt.tag.NBTTag;
|
||||
import glm_.vec3.Vec3i;
|
||||
|
||||
import static de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*;
|
||||
|
||||
public class PlayInByteBuffer extends InByteBuffer {
|
||||
private final PlayConnection connection;
|
||||
private final int versionId;
|
||||
|
||||
public PlayInByteBuffer(byte[] bytes, PlayConnection connection) {
|
||||
super(bytes, connection);
|
||||
this.connection = connection;
|
||||
this.versionId = connection.getVersion().getVersionId();
|
||||
}
|
||||
|
||||
public PlayInByteBuffer(PlayInByteBuffer buffer) {
|
||||
super(buffer);
|
||||
this.connection = buffer.getConnection();
|
||||
this.versionId = this.connection.getVersion().getVersionId();
|
||||
}
|
||||
|
||||
public byte[] readByteArray() {
|
||||
int count;
|
||||
if (this.versionId < V_14W21A) {
|
||||
count = readUnsignedShort();
|
||||
} else {
|
||||
count = readVarInt();
|
||||
}
|
||||
return readByteArray(count);
|
||||
}
|
||||
|
||||
|
||||
public Vec3i readBlockPosition() {
|
||||
// ToDo: protocol id 7
|
||||
long raw = readLong();
|
||||
int x = (int) (raw >> 38);
|
||||
if (this.versionId < V_18W43A) {
|
||||
int y = (int) ((raw >> 26) & 0xFFF);
|
||||
int z = (int) (raw << 38 >> 38);
|
||||
return new Vec3i(x, y, z);
|
||||
}
|
||||
int y = (int) (raw << 52 >> 52);
|
||||
int z = (int) (raw << 26 >> 38);
|
||||
return new Vec3i(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChatComponent readChatComponent() {
|
||||
return ChatComponent.Companion.valueOf(this.connection.getVersion().getLocaleManager(), null, readString());
|
||||
}
|
||||
|
||||
public ParticleData readParticle() {
|
||||
Particle type = this.connection.getMapping().getParticleRegistry().get(readVarInt());
|
||||
return readParticleData(type);
|
||||
}
|
||||
|
||||
public ParticleData readParticleData(Particle type) {
|
||||
if (this.versionId < V_17W45A) {
|
||||
// old particle format
|
||||
return switch (type.getResourceLocation().getFull()) {
|
||||
case "minecraft:iconcrack" -> new ItemParticleData(new ItemStack(this.connection.getMapping().getItemRegistry().get((readVarInt() << 16) | readVarInt()), this.connection.getVersion()), type);
|
||||
case "minecraft:blockcrack", "minecraft:blockdust", "minecraft:falling_dust" -> new BlockParticleData(this.connection.getMapping().getBlockState(readVarInt() << 4), type);
|
||||
default -> new ParticleData(type);
|
||||
};
|
||||
}
|
||||
return switch (type.getResourceLocation().getFull()) {
|
||||
case "minecraft:block", "minecraft:falling_dust" -> new BlockParticleData(this.connection.getMapping().getBlockState(readVarInt()), type);
|
||||
case "minecraft:dust" -> new DustParticleData(readFloat(), readFloat(), readFloat(), readFloat(), type);
|
||||
case "minecraft:item" -> new ItemParticleData(readItemStack(), type);
|
||||
default -> new ParticleData(type);
|
||||
};
|
||||
}
|
||||
|
||||
public NBTTag readNBT() {
|
||||
return readNBT(this.versionId < V_14W28B);
|
||||
}
|
||||
|
||||
public ItemStack readItemStack() {
|
||||
if (this.versionId < V_1_13_2_PRE1) {
|
||||
short id = readShort();
|
||||
if (id == -1) {
|
||||
return null;
|
||||
}
|
||||
byte count = readByte();
|
||||
short metaData = 0;
|
||||
|
||||
if (this.versionId < ProtocolDefinition.FLATTING_VERSION_ID) {
|
||||
metaData = readShort();
|
||||
}
|
||||
CompoundTag nbt = (CompoundTag) readNBT(this.versionId < V_14W28B);
|
||||
return new ItemStack(this.connection.getVersion(), this.connection.getMapping().getItemRegistry().get((id << 16) | metaData), count, metaData, nbt);
|
||||
}
|
||||
if (readBoolean()) {
|
||||
return new ItemStack(this.connection.getVersion(), this.connection.getMapping().getItemRegistry().get(readVarInt()), readByte(), (CompoundTag) readNBT());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public Biome[] readBiomeArray() {
|
||||
int length = 0;
|
||||
if (this.versionId >= V_20W28A) {
|
||||
length = readVarInt();
|
||||
} else if (this.versionId >= V_19W36A) {
|
||||
length = 1024;
|
||||
}
|
||||
if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) {
|
||||
throw new IllegalArgumentException("Trying to allocate to much memory");
|
||||
}
|
||||
|
||||
Biome[] ret = new Biome[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
int biomeId;
|
||||
|
||||
if (this.versionId >= V_20W28A) {
|
||||
biomeId = readVarInt();
|
||||
} else {
|
||||
biomeId = readInt();
|
||||
}
|
||||
ret[i] = this.connection.getMapping().getBiomeRegistry().get(biomeId);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public int getVersionId() {
|
||||
return this.versionId;
|
||||
}
|
||||
|
||||
public EntityMetaData readMetaData() {
|
||||
EntityMetaData metaData = new EntityMetaData(this.connection);
|
||||
EntityMetaData.MetaDataHashMap sets = metaData.getSets();
|
||||
|
||||
if (this.versionId < V_15W31A) { // ToDo: This version was 48, but this one does not exist!
|
||||
int item = readUnsignedByte();
|
||||
while (item != 0x7F) {
|
||||
byte index = (byte) (item & 0x1F);
|
||||
EntityMetaData.EntityMetaDataDataTypes type = this.connection.getMapping().getEntityMetaDataDataDataTypesRegistry().get((item & 0xFF) >> 5);
|
||||
sets.put((int) index, metaData.getData(type, this));
|
||||
item = readByte();
|
||||
}
|
||||
} else {
|
||||
int index = readUnsignedByte();
|
||||
while (index != 0xFF) {
|
||||
int id;
|
||||
if (this.versionId < V_1_9_1_PRE1) {
|
||||
id = readUnsignedByte();
|
||||
} else {
|
||||
id = readVarInt();
|
||||
}
|
||||
EntityMetaData.EntityMetaDataDataTypes type = this.connection.getMapping().getEntityMetaDataDataDataTypesRegistry().get(id);
|
||||
if (type == null) {
|
||||
throw new IllegalStateException("Can not get meta data index for id " + id);
|
||||
}
|
||||
sets.put(index, metaData.getData(type, this));
|
||||
index = readUnsignedByte();
|
||||
}
|
||||
}
|
||||
return metaData;
|
||||
}
|
||||
|
||||
public Ingredient readIngredient() {
|
||||
return new Ingredient(readItemStackArray());
|
||||
}
|
||||
|
||||
public Ingredient[] readIngredientArray(int length) {
|
||||
if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) {
|
||||
throw new IllegalArgumentException("Trying to allocate to much memory");
|
||||
}
|
||||
Ingredient[] ret = new Ingredient[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
ret[i] = readIngredient();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public Ingredient[] readIngredientArray() {
|
||||
return readIngredientArray(readVarInt());
|
||||
}
|
||||
|
||||
public ItemStack[] readItemStackArray(int length) {
|
||||
if (length > ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) {
|
||||
throw new IllegalArgumentException("Trying to allocate to much memory");
|
||||
}
|
||||
ItemStack[] res = new ItemStack[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
res[i] = readItemStack();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
public ItemStack[] readItemStackArray() {
|
||||
return readItemStackArray(readVarInt());
|
||||
}
|
||||
|
||||
public PlayConnection getConnection() {
|
||||
return this.connection;
|
||||
}
|
||||
|
||||
public int readEntityId() {
|
||||
if (this.versionId < V_14W04A) {
|
||||
return readInt();
|
||||
}
|
||||
return readVarInt();
|
||||
}
|
||||
}
|
@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 Moritz Zwerger
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
package de.bixilon.minosoft.protocol.protocol
|
||||
|
||||
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
||||
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||
import de.bixilon.minosoft.data.mappings.biomes.Biome
|
||||
import de.bixilon.minosoft.data.mappings.particle.Particle
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.BlockParticleData
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.DustParticleData
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.ItemParticleData
|
||||
import de.bixilon.minosoft.data.mappings.particle.data.ParticleData
|
||||
import de.bixilon.minosoft.data.mappings.recipes.Ingredient
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.data.text.ChatComponent.Companion.valueOf
|
||||
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.*
|
||||
import de.bixilon.minosoft.util.nbt.tag.CompoundTag
|
||||
import de.bixilon.minosoft.util.nbt.tag.NBTTag
|
||||
import glm_.vec3.Vec3i
|
||||
|
||||
|
||||
class PlayInByteBuffer : InByteBuffer {
|
||||
val connection: PlayConnection
|
||||
val versionId: Int
|
||||
|
||||
constructor(bytes: ByteArray, connection: PlayConnection) : super(bytes, connection) {
|
||||
this.connection = connection
|
||||
versionId = connection.version.versionId
|
||||
}
|
||||
|
||||
constructor(buffer: PlayInByteBuffer) : super(buffer) {
|
||||
connection = buffer.connection
|
||||
versionId = connection.version.versionId
|
||||
}
|
||||
|
||||
fun readByteArray(): ByteArray {
|
||||
val length: Int = if (versionId < V_14W21A) {
|
||||
readUnsignedShort()
|
||||
} else {
|
||||
readVarInt()
|
||||
}
|
||||
return super.readByteArray(length)
|
||||
}
|
||||
|
||||
|
||||
fun readBlockPosition(): Vec3i {
|
||||
// ToDo: protocol id 7
|
||||
val raw = readLong()
|
||||
val x = raw shr 38
|
||||
val y: Long
|
||||
val z: Long
|
||||
if (versionId < V_18W43A) {
|
||||
y = raw shr 26 and 0xFFF
|
||||
z = raw shl 38 shr 38
|
||||
} else {
|
||||
y = raw shl 52 shr 52
|
||||
z = raw shl 26 shr 38
|
||||
}
|
||||
return Vec3i(x, y, z)
|
||||
}
|
||||
|
||||
override fun readChatComponent(): ChatComponent {
|
||||
return valueOf(connection.version.localeManager, null, readString())
|
||||
}
|
||||
|
||||
fun readParticle(): ParticleData {
|
||||
val type = connection.mapping.particleRegistry.get(readVarInt())
|
||||
return readParticleData(type)
|
||||
}
|
||||
|
||||
fun readParticleData(type: Particle): ParticleData {
|
||||
// ToDo: Replace with dynamic particle type calling
|
||||
if (this.versionId < V_17W45A) {
|
||||
return when (type.resourceLocation.full) {
|
||||
"minecraft:iconcrack" -> ItemParticleData(ItemStack(item = connection.mapping.itemRegistry.get(readVarInt() shl 16 or readVarInt()), connection.version), type)
|
||||
"minecraft:blockcrack", "minecraft:blockdust", "minecraft:falling_dust" -> BlockParticleData(connection.mapping.getBlockState(readVarInt() shl 4), type) // ToDo: What about meta data?
|
||||
else -> ParticleData(type)
|
||||
}
|
||||
}
|
||||
|
||||
return when (type.resourceLocation.full) {
|
||||
"minecraft:block", "minecraft:falling_dust" -> BlockParticleData(connection.mapping.getBlockState(readVarInt()), type)
|
||||
"minecraft:dust" -> DustParticleData(readFloat(), readFloat(), readFloat(), readFloat(), type)
|
||||
"minecraft:item" -> ItemParticleData(readItemStack(), type)
|
||||
else -> ParticleData(type)
|
||||
}
|
||||
}
|
||||
|
||||
fun readNBT(): NBTTag? {
|
||||
return readNBT(versionId < V_14W28B)
|
||||
}
|
||||
|
||||
fun readItemStack(): ItemStack? {
|
||||
if (versionId < V_1_13_2_PRE1) {
|
||||
val id = readShort().toInt()
|
||||
if (id == -1) {
|
||||
return null
|
||||
}
|
||||
val count = readByte()
|
||||
var metaData = 0
|
||||
if (connection.version.isFlattened()) {
|
||||
metaData = readUnsignedShort()
|
||||
}
|
||||
val nbt = readNBT(versionId < V_14W28B) as CompoundTag?
|
||||
return ItemStack(connection.version, connection.mapping.itemRegistry.get(id shl 16 or metaData), count, metaData, nbt)
|
||||
}
|
||||
|
||||
return if (readBoolean()) {
|
||||
ItemStack(connection.version, connection.mapping.itemRegistry.get(readVarInt()), readByte().toInt(), readNBT() as CompoundTag?)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun readItemStackArray(length: Int = readVarInt()): Array<ItemStack?> {
|
||||
return readArray(length) { readItemStack() }
|
||||
}
|
||||
|
||||
fun readBiomeArray(): Array<Biome> {
|
||||
val length = when {
|
||||
versionId >= V_20W28A -> {
|
||||
readVarInt()
|
||||
}
|
||||
versionId >= V_19W36A -> {
|
||||
1024
|
||||
}
|
||||
else -> {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
check(length <= ProtocolDefinition.PROTOCOL_PACKET_MAX_SIZE) { "Trying to allocate to much memory" }
|
||||
|
||||
val ret: MutableList<Biome> = mutableListOf()
|
||||
for (i in 0 until length) {
|
||||
val biomeId: Int = if (versionId >= V_20W28A) {
|
||||
readVarInt()
|
||||
} else {
|
||||
readInt()
|
||||
}
|
||||
ret.add(i, connection.mapping.biomeRegistry.get(biomeId))
|
||||
}
|
||||
return ret.toTypedArray()
|
||||
}
|
||||
|
||||
fun readMetaData(): EntityMetaData {
|
||||
val metaData = EntityMetaData(connection)
|
||||
val sets = metaData.sets
|
||||
if (versionId < V_15W31A) { // ToDo: This version was 48, but this one does not exist!
|
||||
var item = readUnsignedByte()
|
||||
while (item != 0x7F) {
|
||||
val index = item and 0x1F
|
||||
val type = connection.mapping.entityMetaDataDataDataTypesRegistry.get(item and 0xFF shr 5)!!
|
||||
sets[index] = metaData.getData(type, this)!!
|
||||
item = readUnsignedByte()
|
||||
}
|
||||
} else {
|
||||
var index = readUnsignedByte()
|
||||
while (index != 0xFF) {
|
||||
val id: Int = if (versionId < V_1_9_1_PRE1) {
|
||||
readUnsignedByte()
|
||||
} else {
|
||||
readVarInt()
|
||||
}
|
||||
val type = connection.mapping.entityMetaDataDataDataTypesRegistry.get(id) ?: error("Can not get meta data index for id $id")
|
||||
sets[index] = metaData.getData(type, this)!!
|
||||
index = readUnsignedByte()
|
||||
}
|
||||
}
|
||||
return metaData
|
||||
}
|
||||
|
||||
fun readIngredient(): Ingredient {
|
||||
return Ingredient(readItemStackArray())
|
||||
}
|
||||
|
||||
@Deprecated(message = "Legacy only", replaceWith = ReplaceWith("readIngredientArray(readVarInt())"))
|
||||
fun readIngredientArray(): Array<Ingredient> {
|
||||
return readIngredientArray(readVarInt())
|
||||
}
|
||||
|
||||
fun readIngredientArray(length: Int = readVarInt()): Array<Ingredient> {
|
||||
return readArray(length) { readIngredient() }
|
||||
}
|
||||
|
||||
fun readEntityId(): Int {
|
||||
return if (versionId < V_14W04A) {
|
||||
readInt()
|
||||
} else {
|
||||
readVarInt()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user