mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 17:37:58 -04:00
abstract chest animation, shulker model, more
This commit is contained in:
parent
e6180b5623
commit
a98e8a38b7
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.chest
|
||||
package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kutil.primitive.FloatUtil.matches
|
||||
@ -20,6 +20,7 @@ import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalTransform
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.instance.KeyframeInstance.Companion.NOT_OVER
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.instance.KeyframeInstance.Companion.OVER
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.mesh.SkeletalMesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
|
||||
import de.bixilon.minosoft.test.IT
|
||||
@ -28,18 +29,15 @@ import org.testng.Assert.assertTrue
|
||||
import org.testng.annotations.Test
|
||||
|
||||
@Test(groups = ["skeletal", "block_entity_rendering"])
|
||||
class ChestAnimationTest {
|
||||
private val progress = ChestAnimation::class.java.getDeclaredField("progress").apply { isAccessible = true }
|
||||
class OpenCloseAnimationTest {
|
||||
|
||||
private fun ChestAnimation.getProgress(): Float = progress.getFloat(this)
|
||||
|
||||
private fun create(): ChestAnimation {
|
||||
private fun create(): Animation {
|
||||
val mesh = IT.OBJENESIS.newInstance(SkeletalMesh::class.java)
|
||||
val context = IT.OBJENESIS.newInstance(RenderContext::class.java)
|
||||
val model = BakedSkeletalModel(mesh, BakedSkeletalTransform(0, Vec3.EMPTY, mapOf("lid" to BakedSkeletalTransform(1, Vec3.EMPTY, emptyMap()))), 1, emptyMap())
|
||||
val model = BakedSkeletalModel(mesh, BakedSkeletalTransform(0, Vec3.EMPTY, emptyMap()), 1, emptyMap())
|
||||
val instance = model.createInstance(context)
|
||||
|
||||
return ChestAnimation(instance)
|
||||
return Animation(instance)
|
||||
}
|
||||
|
||||
fun `create animation`() {
|
||||
@ -84,5 +82,19 @@ class ChestAnimationTest {
|
||||
assertEquals(animation.getProgress(), 0.0f)
|
||||
}
|
||||
|
||||
// TODO: test transforming
|
||||
private class Animation(
|
||||
instance: SkeletalInstance,
|
||||
) : OpenCloseAnimation(instance) {
|
||||
override val transform = instance.transform
|
||||
|
||||
override val name get() = "dummy"
|
||||
|
||||
override val closingDuration get() = 0.3f
|
||||
override val openingDuration get() = 0.4f
|
||||
|
||||
|
||||
override fun transform() = Unit
|
||||
|
||||
fun getProgress() = this.progress
|
||||
}
|
||||
}
|
@ -25,5 +25,5 @@ object DebugOptions {
|
||||
|
||||
const val LOG_RAW_CHAT = false
|
||||
|
||||
const val FORCE_CHEST_ANIMATION = true
|
||||
const val FORCE_CHEST_ANIMATION = false
|
||||
}
|
||||
|
@ -13,11 +13,8 @@
|
||||
|
||||
package de.bixilon.minosoft.data.direction
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kutil.array.ArrayUtil
|
||||
import de.bixilon.minosoft.data.Axes
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
|
||||
object DirectionUtil {
|
||||
|
||||
@ -38,17 +35,4 @@ object DirectionUtil {
|
||||
|
||||
return Directions.INDEXED[1][ArrayUtil.modifyArrayIndex(index.y + count, Directions.SIZE_SIDES)]
|
||||
}
|
||||
|
||||
fun getRotation(direction: Directions): Vec3 {
|
||||
// north is the base direction
|
||||
// TODO: verify
|
||||
return when (direction) {
|
||||
Directions.NORTH -> Vec3.EMPTY
|
||||
Directions.SOUTH -> Vec3(0, 180, 0)
|
||||
Directions.WEST -> Vec3(0, 90, 0)
|
||||
Directions.EAST -> Vec3(0, 270, 0)
|
||||
Directions.UP -> Vec3(0, 0, 90)
|
||||
Directions.DOWN -> Vec3(0, 0, 270)
|
||||
}.rad
|
||||
}
|
||||
}
|
||||
|
@ -45,7 +45,6 @@ enum class Directions(
|
||||
val vectord = Vec3d(vector)
|
||||
|
||||
val axis: Axes = unsafeNull()
|
||||
val rotation: Vec3 = unsafeNull()
|
||||
val inverted: Directions = unsafeNull()
|
||||
|
||||
private fun invert(): Directions {
|
||||
@ -157,12 +156,10 @@ enum class Directions(
|
||||
}
|
||||
|
||||
init {
|
||||
val rotation = Directions::rotation.javaField!!
|
||||
val inverted = Directions::inverted.javaField!!
|
||||
val axis = Directions::axis.javaField!!
|
||||
for (direction in VALUES) {
|
||||
inverted.forceSet(direction, direction.invert())
|
||||
rotation.forceSet(direction, DirectionUtil.getRotation(direction))
|
||||
axis.forceSet(direction, Axes[direction])
|
||||
}
|
||||
NAME_MAP.unsafeCast<MutableMap<String, Directions>>()["bottom"] = DOWN
|
||||
|
@ -19,7 +19,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class BeaconBlockEntity(connection: PlayConnection) : BlockEntity(connection), BlockActionEntity {
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
// no data used, just recalculates the beam
|
||||
}
|
||||
|
||||
|
@ -22,8 +22,8 @@ class BellBlockEntity(connection: PlayConnection) : BlockEntity(connection), Blo
|
||||
var shakingDirection: Directions = Directions.NORTH
|
||||
private set
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
shakingDirection = Directions[data2.toInt()]
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
shakingDirection = Directions[data.toInt()]
|
||||
}
|
||||
|
||||
companion object : BlockEntityFactory<BellBlockEntity> {
|
||||
|
@ -14,5 +14,5 @@
|
||||
package de.bixilon.minosoft.data.entities.block
|
||||
|
||||
interface BlockActionEntity {
|
||||
fun setBlockActionData(data1: Int, data2: Int)
|
||||
fun setBlockActionData(type: Int, data: Int)
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ class MobSpawnerBlockEntity(connection: PlayConnection) : BlockEntity(connection
|
||||
flameParticleType?.let { connection.world += FlameParticle(connection, Vec3d(particlePosition), Vec3d.EMPTY, it.default()) }
|
||||
}
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
// ToDo
|
||||
}
|
||||
|
||||
|
@ -41,8 +41,8 @@ class NoteBlockBlockEntity(connection: PlayConnection) : BlockEntity(connection)
|
||||
return properties[BlockProperties.NOTE]?.toInt() ?: 0
|
||||
}
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
instrument = when (data1.toInt()) {
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
instrument = when (type.toInt()) {
|
||||
0 -> Instruments.HARP
|
||||
1 -> Instruments.BASS
|
||||
2 -> Instruments.SNARE
|
||||
@ -51,7 +51,7 @@ class NoteBlockBlockEntity(connection: PlayConnection) : BlockEntity(connection)
|
||||
else -> null
|
||||
}
|
||||
|
||||
pitch = data2.toInt()
|
||||
pitch = data.toInt()
|
||||
|
||||
showParticleNextTick = true
|
||||
// ToDo: Play sound?
|
||||
|
@ -13,16 +13,23 @@
|
||||
|
||||
package de.bixilon.minosoft.data.entities.block.container.storage
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.minosoft.data.entities.block.BlockEntityFactory
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.registries.identified.AliasedIdentified
|
||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.shulker.ShulkerBoxRenderer
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.util.KUtil
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocationList
|
||||
|
||||
class ShulkerBoxBlockEntity(connection: PlayConnection) : StorageBlockEntity(connection) {
|
||||
|
||||
override fun createRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i, light: Int): BlockEntityRenderer<*>? {
|
||||
return ShulkerBoxRenderer(this, context, blockState, blockPosition, context.models.skeletal[ShulkerBoxRenderer.MODEL] ?: return null, light)
|
||||
}
|
||||
|
||||
companion object : BlockEntityFactory<ShulkerBoxBlockEntity>, AliasedIdentified {
|
||||
override val identifier: ResourceLocation = minecraft("shulker_box")
|
||||
|
@ -34,8 +34,13 @@ abstract class StorageBlockEntity(connection: PlayConnection) : ContainerBlockEn
|
||||
|
||||
val closed: Boolean get() = viewing <= 0
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
val viewing = data2 and 0xFF // unsigned
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
when (type) {
|
||||
1 -> setViewing(data and 0xFF)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun setViewing(viewing: Int) {
|
||||
if (this.viewing == viewing) return
|
||||
val previous = this.viewing
|
||||
this.viewing = viewing
|
||||
|
@ -22,7 +22,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class EndGatewayBlockEntity(connection: PlayConnection) : BlockEntity(connection), BlockActionEntity {
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
// just emits the beacon like beam
|
||||
}
|
||||
|
||||
|
@ -29,9 +29,9 @@ open class PistonBlockEntity(connection: PlayConnection) : BlockEntity(connectio
|
||||
var direction: Directions = Directions.NORTH
|
||||
private set
|
||||
|
||||
override fun setBlockActionData(data1: Int, data2: Int) {
|
||||
state = PistonStates[data1.toInt()]
|
||||
direction = Directions[data2.toInt()]
|
||||
override fun setBlockActionData(type: Int, data: Int) {
|
||||
state = PistonStates[type.toInt()]
|
||||
direction = Directions[data.toInt()]
|
||||
}
|
||||
|
||||
companion object : BlockEntityFactory<PistonBlockEntity> {
|
||||
|
@ -17,6 +17,7 @@ import de.bixilon.kutil.latch.AbstractLatch
|
||||
import de.bixilon.kutil.latch.AbstractLatch.Companion.child
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.chest.DoubleChestRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.chest.SingleChestRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.shulker.ShulkerBoxRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
@ -24,12 +25,11 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
|
||||
object DefaultEntityModels {
|
||||
val MODELS = listOf(
|
||||
SingleChestRenderer.NormalChest,
|
||||
SingleChestRenderer.TrappedChest,
|
||||
SingleChestRenderer.EnderChest,
|
||||
SingleChestRenderer.NormalChest, SingleChestRenderer.TrappedChest, SingleChestRenderer.EnderChest,
|
||||
|
||||
DoubleChestRenderer.NormalChest,
|
||||
DoubleChestRenderer.TrappedChest,
|
||||
DoubleChestRenderer.NormalChest, DoubleChestRenderer.TrappedChest,
|
||||
|
||||
ShulkerBoxRenderer,
|
||||
)
|
||||
|
||||
|
||||
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.chunk.entities.renderer.storage
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.AbstractAnimation
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.instance.KeyframeInstance.Companion.NOT_OVER
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.instance.KeyframeInstance.Companion.OVER
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.instance.TransformInstance
|
||||
|
||||
abstract class OpenCloseAnimation(
|
||||
protected val instance: SkeletalInstance,
|
||||
) : AbstractAnimation {
|
||||
protected abstract val transform: TransformInstance
|
||||
protected var progress = 0.0f
|
||||
protected var opening = true
|
||||
|
||||
protected abstract val closingDuration: Float
|
||||
protected abstract val openingDuration: Float
|
||||
|
||||
override fun draw(delta: Float): Boolean {
|
||||
return if (opening) drawOpening(delta) else drawClosing(delta)
|
||||
}
|
||||
|
||||
private fun drawOpening(delta: Float): Boolean {
|
||||
this.progress += delta / openingDuration
|
||||
if (this.progress > 1.0f) {
|
||||
this.progress = 1.0f
|
||||
}
|
||||
transform()
|
||||
return NOT_OVER
|
||||
}
|
||||
|
||||
private fun drawClosing(delta: Float): Boolean {
|
||||
this.progress -= delta / closingDuration
|
||||
if (progress <= 0.0f) {
|
||||
this.progress = 0.0f
|
||||
return OVER
|
||||
}
|
||||
transform()
|
||||
return NOT_OVER
|
||||
}
|
||||
|
||||
protected abstract fun transform()
|
||||
|
||||
fun open() {
|
||||
if (progress <= 0.0f) {
|
||||
instance.animation.play(this)
|
||||
}
|
||||
opening = true
|
||||
}
|
||||
|
||||
fun close() {
|
||||
opening = false
|
||||
}
|
||||
}
|
@ -14,47 +14,24 @@
|
||||
package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.chest
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.AbstractAnimation
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.instance.KeyframeInstance.Companion.NOT_OVER
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.animation.keyframe.instance.KeyframeInstance.Companion.OVER
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.OpenCloseAnimation
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.rotateRadAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.interpolateSine
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
|
||||
class ChestAnimation(
|
||||
private val instance: SkeletalInstance,
|
||||
) : AbstractAnimation {
|
||||
private val transform = instance.transform.children[TRANSFORM]!!
|
||||
private var progress = 0.0f
|
||||
private var opening = true
|
||||
instance: SkeletalInstance,
|
||||
) : OpenCloseAnimation(instance) {
|
||||
override val transform = instance.transform.children[TRANSFORM]!!
|
||||
|
||||
override val name get() = NAME
|
||||
|
||||
override fun draw(delta: Float): Boolean {
|
||||
return if (opening) drawOpening(delta) else drawClosing(delta)
|
||||
}
|
||||
override val closingDuration get() = 0.3f
|
||||
override val openingDuration get() = 0.4f
|
||||
|
||||
private fun drawOpening(delta: Float): Boolean {
|
||||
this.progress += delta / OPENING_TIME
|
||||
if (this.progress > 1.0f) {
|
||||
this.progress = 1.0f
|
||||
}
|
||||
transform()
|
||||
return NOT_OVER
|
||||
}
|
||||
|
||||
private fun drawClosing(delta: Float): Boolean {
|
||||
this.progress -= delta / CLOSING_TIME
|
||||
if (progress <= 0.0f) {
|
||||
this.progress = 0.0f
|
||||
return OVER
|
||||
}
|
||||
transform()
|
||||
return NOT_OVER
|
||||
}
|
||||
|
||||
private fun transform() {
|
||||
override fun transform() {
|
||||
val rotation = interpolateSine(this.progress, BASE, OPEN)
|
||||
transform.value
|
||||
.translateAssign(transform.pivot)
|
||||
@ -62,25 +39,11 @@ class ChestAnimation(
|
||||
.translateAssign(-transform.pivot)
|
||||
}
|
||||
|
||||
fun open() {
|
||||
if (progress <= 0.0f) {
|
||||
instance.animation.play(this)
|
||||
}
|
||||
opening = true
|
||||
}
|
||||
|
||||
fun close() {
|
||||
opening = false
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
const val TRANSFORM = "lid"
|
||||
const val NAME = "chest"
|
||||
|
||||
const val OPENING_TIME = 0.4f
|
||||
const val CLOSING_TIME = 0.3f
|
||||
|
||||
private val BASE = Vec3(0.0f, 0.0f, 0.0f).rad
|
||||
private val OPEN = Vec3(90.0f, 0.0f, 0.0f).rad
|
||||
}
|
||||
|
@ -13,12 +13,15 @@
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.chest
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.entities.block.container.storage.ChestBlockEntity
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties.getFacing
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.StorageBlockEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
|
||||
abstract class ChestRenderer(
|
||||
state: BlockState,
|
||||
@ -33,7 +36,8 @@ abstract class ChestRenderer(
|
||||
}
|
||||
|
||||
override fun update(position: BlockPosition, state: BlockState, light: Int) {
|
||||
skeletal?.update(position, state.getFacing())
|
||||
val rotation = ROTATION[state.getFacing().ordinal - Directions.SIDE_OFFSET]
|
||||
skeletal?.update(position, rotation)
|
||||
skeletal?.light = light
|
||||
}
|
||||
|
||||
@ -44,4 +48,13 @@ abstract class ChestRenderer(
|
||||
override fun close() {
|
||||
animation?.close()
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val ROTATION = arrayOf(
|
||||
Vec3(0, 0, 0).rad,
|
||||
Vec3(0, 180, 0).rad,
|
||||
Vec3(0, 90, 0).rad,
|
||||
Vec3(0, 270, 0).rad,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.chunk.entities.renderer.storage.shulker
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.OpenCloseAnimation
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.instance.SkeletalInstance
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.rotateRadAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.interpolateLinear
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
|
||||
class ShulkerAnimation(
|
||||
instance: SkeletalInstance,
|
||||
) : OpenCloseAnimation(instance) {
|
||||
override val transform = instance.transform.children[TRANSFORM]!!
|
||||
|
||||
override val name get() = NAME
|
||||
|
||||
override val closingDuration get() = 0.5f
|
||||
override val openingDuration get() = 0.5f
|
||||
|
||||
override fun transform() {
|
||||
val rotation = interpolateLinear(this.progress, ROTATION_CLOSED, ROTATION_OPENED)
|
||||
val translation = interpolateLinear(this.progress, TRANSLATION_CLOSED, TRANSLATION_OPENED)
|
||||
transform.value
|
||||
.translateAssign(translation)
|
||||
.translateAssign(transform.pivot)
|
||||
.rotateRadAssign(rotation)
|
||||
.translateAssign(-transform.pivot)
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
const val TRANSFORM = "lid"
|
||||
const val NAME = "shulker"
|
||||
|
||||
private val ROTATION_CLOSED = Vec3(0.0f, 0.0f, 0.0f).rad
|
||||
private val ROTATION_OPENED = Vec3(0.0f, 270.0f, 0.0f).rad
|
||||
|
||||
private val TRANSLATION_CLOSED = Vec3(0.0f, 0.0f, 0.0f)
|
||||
private val TRANSLATION_OPENED = Vec3(0.0f, 0.5f, 0.0f)
|
||||
}
|
||||
}
|
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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.chunk.entities.renderer.storage.shulker
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.minosoft.data.entities.block.container.storage.ShulkerBoxBlockEntity
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties.getFacing
|
||||
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
|
||||
import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft
|
||||
import de.bixilon.minosoft.data.world.positions.BlockPosition
|
||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.EntityRendererRegister
|
||||
import de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.storage.StorageBlockEntityRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader
|
||||
import de.bixilon.minosoft.gui.rendering.models.loader.SkeletalLoader.Companion.sModel
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel
|
||||
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rad
|
||||
|
||||
class ShulkerBoxRenderer(
|
||||
val entity: ShulkerBoxBlockEntity,
|
||||
context: RenderContext,
|
||||
state: BlockState,
|
||||
position: Vec3i,
|
||||
model: BakedSkeletalModel,
|
||||
light: Int,
|
||||
) : StorageBlockEntityRenderer<ShulkerBoxBlockEntity>(state, model.createInstance(context)) {
|
||||
val animation = skeletal?.let { ShulkerAnimation(it) }
|
||||
|
||||
init {
|
||||
update(position, state, light)
|
||||
}
|
||||
|
||||
override fun update(position: BlockPosition, state: BlockState, light: Int) {
|
||||
val facing = state.getFacing()
|
||||
val rotation = ROTATIONS[facing.ordinal]
|
||||
skeletal?.update(position, rotation)
|
||||
skeletal?.light = light
|
||||
}
|
||||
|
||||
override fun open() {
|
||||
animation?.open()
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
animation?.close()
|
||||
}
|
||||
|
||||
companion object : EntityRendererRegister {
|
||||
val MODEL = minecraft("block/entities/shulker_box").sModel()
|
||||
private val named = minecraft("shulker")
|
||||
private val texture = minecraft("entity/shulker/shulker").texture()
|
||||
|
||||
private val ROTATIONS = arrayOf(
|
||||
Vec3(180, 0, 0).rad,
|
||||
Vec3(0, 0, 0).rad,
|
||||
Vec3(270, 180, 0).rad,
|
||||
Vec3(90, 0, 0).rad,
|
||||
Vec3(90, 0, 90).rad,
|
||||
Vec3(90, 0, 270).rad,
|
||||
)
|
||||
|
||||
override fun register(loader: ModelLoader) {
|
||||
val texture = loader.context.textures.staticTextures.createTexture(texture)
|
||||
loader.skeletal.register(MODEL, override = mapOf(this.named to texture))
|
||||
}
|
||||
}
|
||||
}
|
@ -17,11 +17,11 @@ import de.bixilon.kotlinglm.mat4x4.Mat4
|
||||
import de.bixilon.kotlinglm.vec3.Vec3
|
||||
import de.bixilon.kotlinglm.vec3.Vec3d
|
||||
import de.bixilon.kotlinglm.vec3.Vec3i
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||
import de.bixilon.minosoft.gui.rendering.shader.Shader
|
||||
import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.rotateRadAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY_INSTANCE
|
||||
|
||||
class SkeletalInstance(
|
||||
val context: RenderContext,
|
||||
@ -34,7 +34,7 @@ class SkeletalInstance(
|
||||
|
||||
|
||||
fun draw() {
|
||||
context.system.reset()
|
||||
context.system.reset(faceCulling = false)
|
||||
val shader = context.skeletal.shader
|
||||
shader.use()
|
||||
shader.light = light
|
||||
@ -50,19 +50,25 @@ class SkeletalInstance(
|
||||
model.mesh.draw()
|
||||
}
|
||||
|
||||
fun update(position: Vec3, rotation: Vec3) {
|
||||
fun update(position: Vec3, rotation: Vec3, pivot: Vec3 = Vec3.EMPTY_INSTANCE) {
|
||||
this.position = Mat4()
|
||||
.translateAssign(position)
|
||||
.translateAssign(pivot)
|
||||
.rotateRadAssign(rotation)
|
||||
.translateAssign(-pivot)
|
||||
}
|
||||
|
||||
fun update(position: Vec3d, rotation: Vec3) {
|
||||
update(Vec3(position - context.camera.offset.offset), rotation)
|
||||
}
|
||||
|
||||
fun update(position: Vec3i, direction: Directions) {
|
||||
fun update(position: Vec3i, rotation: Vec3) {
|
||||
val position = Vec3(position - context.camera.offset.offset)
|
||||
position.x += 0.5f; position.z += 0.5f // models origin is the center of block origin
|
||||
update(position, direction.rotation)
|
||||
update(position, rotation, BLOCK_PIVOT)
|
||||
}
|
||||
|
||||
private companion object {
|
||||
val BLOCK_PIVOT = Vec3(0.0f, 0.5f, 0.0f)
|
||||
}
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ data class SkeletalRotation(
|
||||
) {
|
||||
|
||||
fun apply(offset: Vec3, from: Vec3, to: Vec3): SkeletalRotation {
|
||||
val origin = (this.origin ?: ((to - from) / 2.0f)) + offset
|
||||
val origin = (this.origin ?: ((to + from) / 2.0f)) + offset
|
||||
|
||||
return SkeletalRotation(value, origin, rescale)
|
||||
}
|
||||
|
@ -30,8 +30,8 @@ class BlockActionS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
|
||||
} else {
|
||||
buffer.readBlockPosition()
|
||||
}
|
||||
val data1 = buffer.readByte().toInt()
|
||||
val data2 = buffer.readByte().toInt()
|
||||
val type = buffer.readByte().toInt()
|
||||
val data = buffer.readByte().toInt()
|
||||
val block: Block = if (buffer.versionId < FLATTENING_VERSION) buffer.readRegistryItem(buffer.connection.registries.blockState)!!.block else buffer.readRegistryItem(buffer.connection.registries.block)
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
@ -41,10 +41,10 @@ class BlockActionS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket {
|
||||
Log.log(LogMessageType.NETWORK_IN, LogLevels.WARN) { "Block entity $blockEntity can not accept block entity actions!" }
|
||||
return
|
||||
}
|
||||
blockEntity.setBlockActionData(data1, data2)
|
||||
blockEntity.setBlockActionData(type, data)
|
||||
}
|
||||
|
||||
override fun log(reducedLog: Boolean) {
|
||||
Log.log(LogMessageType.NETWORK_IN, level = LogLevels.VERBOSE) { "Block action (position=$position, data1=$data1, data2=$data2, block=$block)" }
|
||||
Log.log(LogMessageType.NETWORK_IN, level = LogLevels.VERBOSE) { "Block action (position=$position, type=$type, data=$data, block=$block)" }
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,49 @@
|
||||
{
|
||||
"elements": {
|
||||
"base": {
|
||||
"from": [-8, 0, -8],
|
||||
"to": [8, 8, 8],
|
||||
"texture": "minecraft:shulker",
|
||||
"uv": [0, 28],
|
||||
"rotation": {
|
||||
"value": [0, 0, 180]
|
||||
},
|
||||
"faces": {
|
||||
"down": {},
|
||||
"up": {},
|
||||
"north": {},
|
||||
"south": {},
|
||||
"west": {},
|
||||
"east": {}
|
||||
}
|
||||
},
|
||||
"lid": {
|
||||
"transform": "lid",
|
||||
"from": [-8, 4, -8],
|
||||
"to": [8, 16, 8],
|
||||
"texture": "minecraft:shulker",
|
||||
"rotation": {
|
||||
"value": [0, 0, 180]
|
||||
},
|
||||
"uv": [0, 0],
|
||||
"faces": {
|
||||
"down": {},
|
||||
"up": {},
|
||||
"north": {},
|
||||
"south": {},
|
||||
"west": {},
|
||||
"east": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"transforms": {
|
||||
"lid": {
|
||||
"pivot": [0, 8, 0]
|
||||
}
|
||||
},
|
||||
"textures": {
|
||||
"minecraft:shulker": {
|
||||
"resolution": [64, 64]
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user