mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-12 17:07:55 -04:00
fix nbt writing, item picking, ItemStack: fix enchantment nbt generation
This commit is contained in:
parent
0a9091b73b
commit
b3da8b1185
@ -20,6 +20,7 @@ import glm_.vec3.Vec3i
|
|||||||
abstract class BlockEntity(
|
abstract class BlockEntity(
|
||||||
val connection: PlayConnection,
|
val connection: PlayConnection,
|
||||||
) {
|
) {
|
||||||
|
open val nbt: Map<String, Any> = mapOf()
|
||||||
|
|
||||||
open fun updateNBT(nbt: Map<String, Any>) = Unit
|
open fun updateNBT(nbt: Map<String, Any>) = Unit
|
||||||
|
|
||||||
|
@ -240,10 +240,11 @@ class ItemStack(
|
|||||||
nbt[HIDE_FLAGS_TAG] = hideFlags
|
nbt[HIDE_FLAGS_TAG] = hideFlags
|
||||||
}
|
}
|
||||||
if (enchantments.isNotEmpty()) {
|
if (enchantments.isNotEmpty()) {
|
||||||
|
val connection = connection!!
|
||||||
val enchantmentList: MutableList<Map<String, Any>> = mutableListOf()
|
val enchantmentList: MutableList<Map<String, Any>> = mutableListOf()
|
||||||
for ((enchantment, level) in enchantments) {
|
for ((enchantment, level) in enchantments) {
|
||||||
val enchantmentTag: MutableMap<String, Any> = mutableMapOf()
|
val enchantmentTag: MutableMap<String, Any> = mutableMapOf()
|
||||||
enchantmentTag[ENCHANTMENT_ID_TAG] = if (connection!!.version.isFlattened()) {
|
enchantmentTag[ENCHANTMENT_ID_TAG] = if (connection.version.isFlattened()) {
|
||||||
enchantment.resourceLocation.full
|
enchantment.resourceLocation.full
|
||||||
} else {
|
} else {
|
||||||
connection.registries.enchantmentRegistry.getId(enchantment)
|
connection.registries.enchantmentRegistry.getId(enchantment)
|
||||||
@ -254,8 +255,9 @@ class ItemStack(
|
|||||||
} else {
|
} else {
|
||||||
level.toShort()
|
level.toShort()
|
||||||
}
|
}
|
||||||
|
enchantmentList += enchantmentTag
|
||||||
}
|
}
|
||||||
if (connection!!.version.isFlattened()) {
|
if (connection.version.isFlattened()) {
|
||||||
nbt[ENCHANTMENT_FLATTENING_TAG] = enchantmentList
|
nbt[ENCHANTMENT_FLATTENING_TAG] = enchantmentList
|
||||||
} else {
|
} else {
|
||||||
nbt[ENCHANTMENT_PRE_FLATTENING_TAG] = enchantmentList
|
nbt[ENCHANTMENT_PRE_FLATTENING_TAG] = enchantmentList
|
||||||
|
@ -17,7 +17,7 @@ data class Abilities(
|
|||||||
var isInvulnerable: Boolean = false,
|
var isInvulnerable: Boolean = false,
|
||||||
var isFlying: Boolean = false,
|
var isFlying: Boolean = false,
|
||||||
var canFly: Boolean = false,
|
var canFly: Boolean = false,
|
||||||
var canInstantBreak: Boolean = false, // ToDo: This is the check if we are in creative mode, but no exactly sure...
|
var creative: Boolean = false, // ToDo: This is the check if we are in creative mode, but no exactly sure...
|
||||||
|
|
||||||
var flyingSpeed: Double = 0.05,
|
var flyingSpeed: Double = 0.05,
|
||||||
var walkingSpeed: Double = 0.1,
|
var walkingSpeed: Double = 0.1,
|
||||||
|
@ -198,7 +198,6 @@ class LocalPlayerEntity(
|
|||||||
val swimHeight: Double
|
val swimHeight: Double
|
||||||
get() = (eyeHeight < 0.4).decide(0.0, 0.4)
|
get() = (eyeHeight < 0.4).decide(0.0, 0.4)
|
||||||
|
|
||||||
|
|
||||||
val reachDistance: Double
|
val reachDistance: Double
|
||||||
get() = (gamemode == Gamemodes.CREATIVE).decide(5.0, 4.5)
|
get() = (gamemode == Gamemodes.CREATIVE).decide(5.0, 4.5)
|
||||||
|
|
||||||
|
@ -19,12 +19,14 @@ import de.bixilon.minosoft.data.entities.EntityRotation
|
|||||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||||
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
import de.bixilon.minosoft.data.entities.meta.EntityMetaData
|
||||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||||
|
import de.bixilon.minosoft.data.registries.items.SpawnEggItem
|
||||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer
|
import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer
|
||||||
import de.bixilon.minosoft.data.registries.registries.registry.Translatable
|
import de.bixilon.minosoft.data.registries.registries.registry.Translatable
|
||||||
import de.bixilon.minosoft.datafixer.EntityAttributeFixer.fix
|
import de.bixilon.minosoft.datafixer.EntityAttributeFixer.fix
|
||||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||||
|
import de.bixilon.minosoft.util.KUtil.nullCast
|
||||||
import de.bixilon.minosoft.util.KUtil.toBoolean
|
import de.bixilon.minosoft.util.KUtil.toBoolean
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
@ -41,8 +43,10 @@ data class EntityType(
|
|||||||
val fireImmune: Boolean,
|
val fireImmune: Boolean,
|
||||||
val attributes: Map<ResourceLocation, Double>,
|
val attributes: Map<ResourceLocation, Double>,
|
||||||
val factory: EntityFactory<out Entity>,
|
val factory: EntityFactory<out Entity>,
|
||||||
|
val spawnEgg: SpawnEggItem?,
|
||||||
) : RegistryItem(), Translatable {
|
) : RegistryItem(), Translatable {
|
||||||
|
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return resourceLocation.toString()
|
return resourceLocation.toString()
|
||||||
}
|
}
|
||||||
@ -83,6 +87,7 @@ data class EntityType(
|
|||||||
sizeFixed = data["size_fixed"]?.toBoolean() ?: false,
|
sizeFixed = data["size_fixed"]?.toBoolean() ?: false,
|
||||||
attributes = attributes.toMap(),
|
attributes = attributes.toMap(),
|
||||||
factory = DefaultEntityFactories[resourceLocation] ?: error("Can not find entity factory for $resourceLocation"),
|
factory = DefaultEntityFactories[resourceLocation] ?: error("Can not find entity factory for $resourceLocation"),
|
||||||
|
spawnEgg = registries.itemRegistry[data["spawn_egg_item"]]?.nullCast(), // ToDo: Not yet in PixLyzer
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,7 +40,7 @@ class PlayerInventory(connection: PlayConnection) : Container(
|
|||||||
|
|
||||||
fun getHotbarSlot(hotbarSlot: Int = connection.player.selectedHotbarSlot): ItemStack? {
|
fun getHotbarSlot(hotbarSlot: Int = connection.player.selectedHotbarSlot): ItemStack? {
|
||||||
check(hotbarSlot in 0..HOTBAR_SLOTS) { "Hotbar slot out of bounds!" }
|
check(hotbarSlot in 0..HOTBAR_SLOTS) { "Hotbar slot out of bounds!" }
|
||||||
return slots[hotbarSlot + HOTBAR_OFFSET] // ToDo
|
return slots[hotbarSlot + HOTBAR_OFFSET]
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun get(slot: InventorySlots.EquipmentSlots): ItemStack? {
|
operator fun get(slot: InventorySlots.EquipmentSlots): ItemStack? {
|
||||||
|
@ -23,6 +23,7 @@ import de.bixilon.minosoft.protocol.protocol.PacketTypes.C2S
|
|||||||
import de.bixilon.minosoft.protocol.protocol.PacketTypes.S2C
|
import de.bixilon.minosoft.protocol.protocol.PacketTypes.S2C
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.protocol.protocol.ProtocolStates
|
import de.bixilon.minosoft.protocol.protocol.ProtocolStates
|
||||||
|
import de.bixilon.minosoft.protocol.protocol.ProtocolVersions.V_15W31A
|
||||||
import de.bixilon.minosoft.util.CountUpAndDownLatch
|
import de.bixilon.minosoft.util.CountUpAndDownLatch
|
||||||
import de.bixilon.minosoft.util.KUtil.decide
|
import de.bixilon.minosoft.util.KUtil.decide
|
||||||
import de.bixilon.minosoft.util.logging.Log
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
@ -152,4 +153,6 @@ data class Version(
|
|||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
return name
|
return name
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val hasOffhand = versionId >= V_15W31A
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,7 @@ class LeftClickHandler(
|
|||||||
val canStartBreaking = currentTime - breakSent >= ProtocolDefinition.TICK_TIME
|
val canStartBreaking = currentTime - breakSent >= ProtocolDefinition.TICK_TIME
|
||||||
|
|
||||||
|
|
||||||
val canInstantBreak = connection.player.baseAbilities.canInstantBreak || connection.player.gamemode == Gamemodes.CREATIVE
|
val canInstantBreak = connection.player.baseAbilities.creative || connection.player.gamemode == Gamemodes.CREATIVE
|
||||||
|
|
||||||
if (canInstantBreak) {
|
if (canInstantBreak) {
|
||||||
if (!canStartBreaking) {
|
if (!canStartBreaking) {
|
||||||
|
@ -35,8 +35,8 @@ class HotbarInteractionHandler(
|
|||||||
val renderWindow: RenderWindow,
|
val renderWindow: RenderWindow,
|
||||||
) {
|
) {
|
||||||
private val connection = renderWindow.connection
|
private val connection = renderWindow.connection
|
||||||
private val slotLimiter = RateLimiter()
|
val slotLimiter = RateLimiter()
|
||||||
private val swapLimiter = RateLimiter(dependencies = synchronizedSetOf(slotLimiter)) // we don't want to swap wrong items
|
val swapLimiter = RateLimiter(dependencies = synchronizedSetOf(slotLimiter)) // we don't want to swap wrong items
|
||||||
|
|
||||||
private var currentScrollOffset = 0.0
|
private var currentScrollOffset = 0.0
|
||||||
|
|
||||||
@ -54,7 +54,7 @@ class HotbarInteractionHandler(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun swapItems() {
|
fun swapItems() {
|
||||||
if (connection.player.gamemode == Gamemodes.SPECTATOR) {
|
if (!connection.version.hasOffhand || connection.player.gamemode == Gamemodes.SPECTATOR) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val inventory = connection.player.inventory
|
val inventory = connection.player.inventory
|
||||||
@ -62,6 +62,7 @@ class HotbarInteractionHandler(
|
|||||||
val off = inventory[InventorySlots.EquipmentSlots.OFF_HAND]
|
val off = inventory[InventorySlots.EquipmentSlots.OFF_HAND]
|
||||||
|
|
||||||
if (main == null && off == null) {
|
if (main == null && off == null) {
|
||||||
|
// ToDo: Forbid swap if both are equals?
|
||||||
// both are air, we can't swap
|
// both are air, we can't swap
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -19,12 +19,15 @@ class InteractionManager(
|
|||||||
val renderWindow: RenderWindow,
|
val renderWindow: RenderWindow,
|
||||||
) {
|
) {
|
||||||
val hotbar = HotbarInteractionHandler(renderWindow)
|
val hotbar = HotbarInteractionHandler(renderWindow)
|
||||||
|
val pick = ItemPickInteractionHandler(renderWindow, this)
|
||||||
|
|
||||||
fun init() {
|
fun init() {
|
||||||
hotbar.init()
|
hotbar.init()
|
||||||
|
pick.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun draw(delta: Double) {
|
fun draw(delta: Double) {
|
||||||
hotbar.draw(delta)
|
hotbar.draw(delta)
|
||||||
|
pick.draw(delta)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
* 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.gui.rendering.input.interaction
|
||||||
|
|
||||||
|
import de.bixilon.minosoft.config.key.KeyAction
|
||||||
|
import de.bixilon.minosoft.config.key.KeyBinding
|
||||||
|
import de.bixilon.minosoft.config.key.KeyCodes
|
||||||
|
import de.bixilon.minosoft.data.inventory.InventorySlots
|
||||||
|
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||||
|
import de.bixilon.minosoft.data.registries.other.containers.PlayerInventory
|
||||||
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
|
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||||
|
import de.bixilon.minosoft.gui.rendering.input.camera.hit.EntityRaycastHit
|
||||||
|
import de.bixilon.minosoft.protocol.RateLimiter
|
||||||
|
import de.bixilon.minosoft.protocol.packets.c2s.play.ItemStackCreateC2SP
|
||||||
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
|
|
||||||
|
class ItemPickInteractionHandler(
|
||||||
|
val renderWindow: RenderWindow,
|
||||||
|
val interactionManager: InteractionManager,
|
||||||
|
) {
|
||||||
|
private val connection = renderWindow.connection
|
||||||
|
val rateLimiter = RateLimiter()
|
||||||
|
|
||||||
|
|
||||||
|
fun init() {
|
||||||
|
renderWindow.inputHandler.registerKeyCallback("minosoft:pick_item".toResourceLocation(), KeyBinding(
|
||||||
|
mutableMapOf(
|
||||||
|
KeyAction.PRESS to mutableSetOf(KeyCodes.MOUSE_BUTTON_MIDDLE),
|
||||||
|
),
|
||||||
|
)) {
|
||||||
|
pickItem(true) // ToDo: Combination for not copying nbt
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun pickItem(copyNBT: Boolean) {
|
||||||
|
if (!connection.player.baseAbilities.creative) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val raycast = renderWindow.inputHandler.camera.target ?: return
|
||||||
|
|
||||||
|
if (raycast.distance > connection.player.reachDistance) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val itemStack: ItemStack?
|
||||||
|
|
||||||
|
when (raycast) {
|
||||||
|
is BlockRaycastHit -> {
|
||||||
|
itemStack = ItemStack(raycast.blockState.block.item!!, connection, 1)
|
||||||
|
|
||||||
|
if (copyNBT) {
|
||||||
|
val blockEntity = connection.world.getBlockEntity(raycast.blockPosition)
|
||||||
|
blockEntity?.nbt?.let { itemStack.nbt.putAll(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
is EntityRaycastHit -> {
|
||||||
|
val entity = raycast.entity
|
||||||
|
itemStack = entity.entityType.spawnEgg?.let { ItemStack(it, connection) } ?: let {
|
||||||
|
entity.equipment[InventorySlots.EquipmentSlots.MAIN_HAND]?.copy()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> {
|
||||||
|
itemStack = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemStack == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for (i in 0 until PlayerInventory.HOTBAR_SLOTS) {
|
||||||
|
val slot = connection.player.inventory.getHotbarSlot(i) ?: continue
|
||||||
|
if (slot != itemStack) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
interactionManager.hotbar.selectSlot(i)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val selectedSlot = connection.player.selectedHotbarSlot + PlayerInventory.HOTBAR_OFFSET
|
||||||
|
|
||||||
|
rateLimiter += { connection.sendPacket(ItemStackCreateC2SP(selectedSlot, itemStack)) }
|
||||||
|
connection.player.inventory[selectedSlot] = itemStack
|
||||||
|
}
|
||||||
|
|
||||||
|
fun draw(delta: Double) {
|
||||||
|
rateLimiter.work()
|
||||||
|
}
|
||||||
|
}
|
@ -75,7 +75,7 @@ class AudioPlayer(
|
|||||||
|
|
||||||
|
|
||||||
private fun preloadSounds() {
|
private fun preloadSounds() {
|
||||||
Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Preloading sounds..." }
|
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Preloading sounds..." }
|
||||||
if (SoundConstants.DISABLE_PRELOADING) {
|
if (SoundConstants.DISABLE_PRELOADING) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ class AudioPlayer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun loadSounds() {
|
private fun loadSounds() {
|
||||||
Log.log(LogMessageType.RENDERING_LOADING, LogLevels.VERBOSE) { "Loading sounds.json" }
|
Log.log(LogMessageType.AUDIO_LOADING, LogLevels.VERBOSE) { "Loading sounds.json" }
|
||||||
val data = connection.assetsManager.readJsonAsset(SOUNDS_INDEX_FILE)
|
val data = connection.assetsManager.readJsonAsset(SOUNDS_INDEX_FILE)
|
||||||
|
|
||||||
for ((soundEventResourceLocation, json) in data) {
|
for ((soundEventResourceLocation, json) in data) {
|
||||||
|
@ -55,7 +55,7 @@ class PlayerAbilitiesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
|||||||
abilities.isInvulnerable = isInvulnerable
|
abilities.isInvulnerable = isInvulnerable
|
||||||
abilities.isFlying = isFlying
|
abilities.isFlying = isFlying
|
||||||
abilities.canFly = canFly
|
abilities.canFly = canFly
|
||||||
abilities.canInstantBreak = canInstantBuild
|
abilities.creative = canInstantBuild
|
||||||
|
|
||||||
abilities.flyingSpeed = flyingSpeed
|
abilities.flyingSpeed = flyingSpeed
|
||||||
abilities.walkingSpeed = walkingSpeed
|
abilities.walkingSpeed = walkingSpeed
|
||||||
|
@ -154,18 +154,18 @@ open class OutByteBuffer(open val connection: Connection? = null) {
|
|||||||
writeByte(type.ordinal)
|
writeByte(type.ordinal)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun writeNBT(nbt: Any?, compressed: Boolean) {
|
fun writeNBT(nbt: Any?, compressed: Boolean = false) {
|
||||||
if (compressed) {
|
if (compressed) {
|
||||||
TODO("Can not write compressed NBT yet!")
|
TODO("Can not write compressed NBT yet!")
|
||||||
}
|
}
|
||||||
if (nbt is Collection<*> && nbt.isEmpty()) {
|
|
||||||
return writeNBTTag(null)
|
|
||||||
}
|
|
||||||
if (nbt is Map<*, *>) {
|
if (nbt is Map<*, *>) {
|
||||||
if (nbt.isEmpty()) {
|
if (nbt.isEmpty()) {
|
||||||
return writeNBTTag(null)
|
return writeNBTTag(null)
|
||||||
}
|
}
|
||||||
|
writeNBTTagType(NBTTagTypes.COMPOUND)
|
||||||
writeShort(0) // Length of compound tag name
|
writeShort(0) // Length of compound tag name
|
||||||
|
writeNBTTag(nbt, false)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
writeNBTTag(nbt)
|
writeNBTTag(nbt)
|
||||||
}
|
}
|
||||||
@ -203,13 +203,12 @@ open class OutByteBuffer(open val connection: Connection? = null) {
|
|||||||
writeUnprefixedByteArray(bytes)
|
writeUnprefixedByteArray(bytes)
|
||||||
}
|
}
|
||||||
is Collection<*> -> {
|
is Collection<*> -> {
|
||||||
val collectionType: NBTTagTypes = if (tag.isEmpty()) {
|
this.writeNBTTagType(if (tag.isEmpty()) {
|
||||||
NBTTagTypes.END
|
NBTTagTypes.END
|
||||||
} else {
|
} else {
|
||||||
tag.iterator().next().type
|
tag.iterator().next().type
|
||||||
}
|
})
|
||||||
this.writeNBTTagType(collectionType)
|
|
||||||
// write Type
|
|
||||||
writeInt(tag.size)
|
writeInt(tag.size)
|
||||||
|
|
||||||
for (element in tag) {
|
for (element in tag) {
|
||||||
@ -217,22 +216,16 @@ open class OutByteBuffer(open val connection: Connection? = null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
is Map<*, *> -> {
|
is Map<*, *> -> {
|
||||||
val size = tag.size
|
|
||||||
var index = 0
|
|
||||||
for ((key, value) in tag) {
|
for ((key, value) in tag) {
|
||||||
val valueType = value.type
|
val valueType = value.type
|
||||||
if (valueType == NBTTagTypes.END) {
|
if (valueType == NBTTagTypes.END) {
|
||||||
break
|
error("NBT does not support null as value in a compound tag!")
|
||||||
}
|
}
|
||||||
this.writeNBTTagType(valueType)
|
this.writeNBTTagType(valueType)
|
||||||
writeNBTTag(key?.toString() ?: "", false)
|
writeNBTTag(key?.toString() ?: "", false)
|
||||||
writeNBTTag(value, true)
|
writeNBTTag(value, false)
|
||||||
index++
|
|
||||||
}
|
}
|
||||||
if (index - 1 != size) {
|
this.writeNBTTagType(NBTTagTypes.END)
|
||||||
error("NBT does not support null as value in a compound tag!")
|
|
||||||
}
|
|
||||||
writeNBTTagType(NBTTagTypes.END)
|
|
||||||
}
|
}
|
||||||
is IntArray -> {
|
is IntArray -> {
|
||||||
writeInt(tag.size)
|
writeInt(tag.size)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user