mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 02:45:13 -04:00
verify skin size
This commit is contained in:
parent
803cdcc552
commit
acb3bd3b02
@ -58,6 +58,9 @@ class RGBA8Buffer(
|
|||||||
|
|
||||||
override fun getRGBA(x: Int, y: Int): Int {
|
override fun getRGBA(x: Int, y: Int): Int {
|
||||||
val stride = stride(x, y)
|
val stride = stride(x, y)
|
||||||
|
if (stride > data.capacity()) {
|
||||||
|
throw IllegalArgumentException("Can not access pixel at ($x,$y), exceeds size: $size")
|
||||||
|
}
|
||||||
return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or (this[stride + 3] shl 0)
|
return (this[stride + 0] shl 24) or (this[stride + 1] shl 16) or (this[stride + 2] shl 8) or (this[stride + 3] shl 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,6 +24,9 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.array.TextureArray
|
|||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.data.MipmapTextureData
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.data.MipmapTextureData
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.data.buffer.TextureBuffer
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.data.buffer.TextureBuffer
|
||||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.readTexture
|
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.readTexture
|
||||||
|
import de.bixilon.minosoft.util.logging.Log
|
||||||
|
import de.bixilon.minosoft.util.logging.LogLevels
|
||||||
|
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
@ -70,7 +73,14 @@ abstract class DynamicTextureArray(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun DynamicTexture.load(index: Int, creator: () -> TextureBuffer) {
|
private fun DynamicTexture.load(index: Int, creator: () -> TextureBuffer) {
|
||||||
val buffer = creator.invoke()
|
val buffer = try {
|
||||||
|
creator.invoke()
|
||||||
|
} catch (error: Throwable) {
|
||||||
|
Log.log(LogMessageType.RENDERING, LogLevels.WARN) { "Could not load dynamic texture (index=$index, identifier=${this.identifier}): $error" }
|
||||||
|
error.printStackTrace()
|
||||||
|
this.state = DynamicTextureState.ERROR
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
this.data = MipmapTextureData(buffer, mipmaps)
|
this.data = MipmapTextureData(buffer, mipmaps)
|
||||||
if (Thread.currentThread() == context.thread) {
|
if (Thread.currentThread() == context.thread) {
|
||||||
@ -147,7 +157,7 @@ abstract class DynamicTextureArray(
|
|||||||
for ((index, reference) in textures.withIndex()) {
|
for ((index, reference) in textures.withIndex()) {
|
||||||
if (reference == null) continue
|
if (reference == null) continue
|
||||||
val texture = reference.get()
|
val texture = reference.get()
|
||||||
if (texture != null) continue // not gced yet, keep it for now
|
if (texture != null && texture.state != DynamicTextureState.ERROR) continue // not gced yet, keep it for now
|
||||||
textures[index] = null
|
textures[index] = null
|
||||||
}
|
}
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
|
@ -17,6 +17,7 @@ enum class DynamicTextureState {
|
|||||||
WAITING,
|
WAITING,
|
||||||
LOADING,
|
LOADING,
|
||||||
LOADED,
|
LOADED,
|
||||||
|
ERROR,
|
||||||
|
|
||||||
@Deprecated("unrechable", level = DeprecationLevel.ERROR)
|
@Deprecated("unrechable", level = DeprecationLevel.ERROR)
|
||||||
UNLOADED,
|
UNLOADED,
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Minosoft
|
||||||
|
* Copyright (C) 2020-2023 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.system.base.texture.skin
|
||||||
|
|
||||||
|
class IllegalSkinError(message: String? = null) : Exception(message)
|
@ -30,13 +30,13 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY_INSTANCE
|
|||||||
import java.io.ByteArrayInputStream
|
import java.io.ByteArrayInputStream
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class SkinManager(private val textureManager: TextureManager) {
|
class SkinManager(private val textures: TextureManager) {
|
||||||
lateinit var default: DefaultSkinProvider
|
lateinit var default: DefaultSkinProvider
|
||||||
private set
|
private set
|
||||||
private var skin: PlayerSkin? = null
|
private var skin: PlayerSkin? = null
|
||||||
|
|
||||||
fun initialize(account: Account, assets: AssetsManager) {
|
fun initialize(account: Account, assets: AssetsManager) {
|
||||||
default = DefaultSkinProvider(this.textureManager.dynamic, assets)
|
default = DefaultSkinProvider(this.textures.dynamic, assets)
|
||||||
default.initialize()
|
default.initialize()
|
||||||
skin = getSkin(account.uuid, account.properties, fetch = true, async = false)
|
skin = getSkin(account.uuid, account.properties, fetch = true, async = false)
|
||||||
}
|
}
|
||||||
@ -57,7 +57,7 @@ class SkinManager(private val textureManager: TextureManager) {
|
|||||||
|
|
||||||
private fun getSkin(uuid: UUID, properties: PlayerProperties?, async: Boolean = true): PlayerSkin? {
|
private fun getSkin(uuid: UUID, properties: PlayerProperties?, async: Boolean = true): PlayerSkin? {
|
||||||
val texture = properties?.textures?.skin ?: return default[uuid]
|
val texture = properties?.textures?.skin ?: return default[uuid]
|
||||||
return PlayerSkin(textureManager.dynamic.push(texture.getHash(), async) { texture.read().readSkin() }, default[uuid]?.texture, texture.metadata.model)
|
return PlayerSkin(textures.dynamic.push(texture.getHash(), async) { texture.read().readSkin() }, default[uuid]?.texture, texture.metadata.model)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSkin(player: PlayerEntity, properties: PlayerProperties? = null, fetch: Boolean = true, async: Boolean = true): PlayerSkin? {
|
fun getSkin(player: PlayerEntity, properties: PlayerProperties? = null, fetch: Boolean = true, async: Boolean = true): PlayerSkin? {
|
||||||
@ -76,16 +76,22 @@ class SkinManager(private val textureManager: TextureManager) {
|
|||||||
|
|
||||||
private fun ByteArray.readSkin(): TextureBuffer {
|
private fun ByteArray.readSkin(): TextureBuffer {
|
||||||
val data = ByteArrayInputStream(this).readTexture()
|
val data = ByteArrayInputStream(this).readTexture()
|
||||||
if (data.size.y != 32) return data
|
if (data.size.x != 64) throw IllegalSkinError("Width of skin must be 64 pixels: ${data.size}")
|
||||||
|
return when (data.size.y) {
|
||||||
|
32 -> {
|
||||||
|
// <1.8 legacy skin
|
||||||
|
val next = RGBA8Buffer(Vec2i(64))
|
||||||
|
next.put(data, Vec2i.EMPTY_INSTANCE, Vec2i.EMPTY_INSTANCE, data.size)
|
||||||
|
|
||||||
val next = RGBA8Buffer(Vec2i(64))
|
next.put(next, Vec2i(0, 16), Vec2i(16, 48), Vec2i(16, 16))// leg [0, 16][16,16] to left leg [16, 48]
|
||||||
next.put(data, Vec2i.EMPTY_INSTANCE, Vec2i.EMPTY_INSTANCE, data.size)
|
next.put(next, Vec2i(40, 16), Vec2i(32, 48), Vec2i(16, 16)) // arm [40, 16] to left arm [32, 48]
|
||||||
|
|
||||||
next.put(next, Vec2i(0, 16), Vec2i(16, 48), Vec2i(16, 16))// leg [0, 16][16,16] to left leg [16, 48]
|
// TODO: flip every texture part
|
||||||
next.put(next, Vec2i(40, 16), Vec2i(32, 48), Vec2i(16, 16)) // arm [40, 16] to left arm [32, 48]
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: flip every texture part
|
64 -> data // skin
|
||||||
|
else -> throw IllegalSkinError("Can not detect skin format: ${data.size}")
|
||||||
return next
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user