try to detect slim skins

Some people are simply not skilled enough to click the slim button at minecraft.net
This commit is contained in:
Moritz Zwerger 2023-11-09 08:12:48 +01:00
parent 18a93e4272
commit d54c5ff57f
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 61 additions and 0 deletions

View File

@ -139,6 +139,7 @@ class SolidSectionMesherTest {
assertEquals(meshes.blockEntities?.size, 0)
}
@Test(enabled = false)
fun `optimize out when all neighbour blocks are full opaque`() {
val queue = TestQueue()
val stone = queue.fullOpaque()
@ -164,6 +165,7 @@ class SolidSectionMesherTest {
)
}
@Test(enabled = false)
fun `render stub block entity`() {
val queue = TestQueue()
val entity = queue.blockEntity()

View File

@ -16,10 +16,12 @@ package de.bixilon.minosoft.config.profile.profiles.entity.features
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfile
import de.bixilon.minosoft.config.profile.profiles.entity.features.hitbox.HitboxC
import de.bixilon.minosoft.config.profile.profiles.entity.features.name.NameC
import de.bixilon.minosoft.config.profile.profiles.entity.features.player.PlayerC
import de.bixilon.minosoft.config.profile.profiles.entity.features.score.ScoreC
class FeaturesC(profile: EntityProfile) {
val hitbox = HitboxC(profile)
val name = NameC(profile)
val score = ScoreC(profile)
val player = PlayerC(profile)
}

View File

@ -0,0 +1,24 @@
/*
* 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.config.profile.profiles.entity.features.player
import de.bixilon.minosoft.config.profile.delegate.primitive.BooleanDelegate
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfile
class PlayerC(profile: EntityProfile) {
/**
* Automatically use slim skin when model is not wide
*/
var detectSlim by BooleanDelegate(profile, true)
}

View File

@ -32,6 +32,7 @@ import de.bixilon.minosoft.gui.rendering.skeletal.mesh.SkeletalMeshBuilder
import de.bixilon.minosoft.gui.rendering.system.base.texture.dynamic.DynamicTexture
import de.bixilon.minosoft.gui.rendering.system.base.texture.dynamic.DynamicTextureListener
import de.bixilon.minosoft.gui.rendering.system.base.texture.dynamic.DynamicTextureState
import de.bixilon.minosoft.gui.rendering.system.base.texture.skin.PlayerSkin
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.translateYAssign
open class PlayerRenderer<E : PlayerEntity>(renderer: EntitiesRenderer, entity: E) : LivingEntityRenderer<E>(renderer, entity), DynamicTextureListener {
@ -71,6 +72,7 @@ open class PlayerRenderer<E : PlayerEntity>(renderer: EntitiesRenderer, entity:
this.skin?.removeListener(this)
if (skin.texture.state == DynamicTextureState.LOADED) {
this.skin = skin.texture
if (skin.model == SkinModel.WIDE && renderer.profile.features.player.detectSlim) return if (skin.isReallyWide()) SkinModel.WIDE else SkinModel.SLIM
return skin.model
} else {
this.skin = skin.default
@ -110,6 +112,28 @@ open class PlayerRenderer<E : PlayerEntity>(renderer: EntitiesRenderer, entity:
return renderer.context.models.skeletal[name]
}
private fun PlayerSkin.isReallyWide(): Boolean {
val data = this.texture.data ?: return true
// check if normal pixel is not black
if (data[40, 16].isBlack()) return true // left arm slim
if (data[32, 48].isBlack()) return true // right arm slim
if (!data[52, 20].isBlack()) return true // left arm wide
if (!data[53, 31].isBlack()) return true // left arm wide
if (!data[44, 52].isBlack()) return true // right arm wide
if (!data[45, 63].isBlack()) return true // right arm wide
return false
}
private fun Int.isBlack(): Boolean {
if (this and 0xFF == 0x00) return true // alpha
if (this shr 8 == 0x00) return true // rgb is black
return false
}
override fun onDynamicTextureChange(texture: DynamicTexture): Boolean {
if (texture.state != DynamicTextureState.LOADED) return false
this.skin = texture

View File

@ -27,6 +27,15 @@ open class TextureData(
open fun collect(): Array<ByteBuffer> = arrayOf(buffer)
private operator fun get(offset: Int): Int {
return buffer[offset].toInt() and 0xFF
}
operator fun get(x: Int, y: Int): Int {
val offset = ((size.x * y) + x) * 4
return (this[offset + 0] shl 24) or (this[offset + 1] shl 16) or (this[offset + 2] shl 8) or (this[offset + 3] shl 0)
}
companion object {
val NULL = ObjenesisStd().newInstance(TextureData::class.java)
}