diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt b/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt index 83461ccc8..3339af1ce 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/client/VSPhysicsEntityRenderer.kt @@ -19,7 +19,7 @@ import java.util.Random class VSPhysicsEntityRenderer(context: EntityRendererProvider.Context) : EntityRenderer(context) { override fun render( - fallingBlockEntity: VSPhysicsEntity, f: Float, g: Float, poseStack: PoseStack, + fallingBlockEntity: VSPhysicsEntity, f: Float, partialTick: Float, poseStack: PoseStack, multiBufferSource: MultiBufferSource, i: Int ) { val blockState = ValkyrienSkiesMod.TEST_SPHERE.defaultBlockState() @@ -35,7 +35,7 @@ class VSPhysicsEntityRenderer(context: EntityRendererProvider.Context) : EntityR } poseStack.pushPose() val blockPos = BlockPos(fallingBlockEntity.x, fallingBlockEntity.boundingBox.maxY, fallingBlockEntity.z) - poseStack.mulPose(fallingBlockEntity.rotation.toMinecraft()) + poseStack.mulPose(fallingBlockEntity.getRenderRotation(partialTick).toMinecraft()) poseStack.translate(-0.5, -0.5, -0.5) val blockRenderDispatcher = Minecraft.getInstance().blockRenderer blockRenderDispatcher.modelRenderer.tesselateBlock( @@ -45,7 +45,7 @@ class VSPhysicsEntityRenderer(context: EntityRendererProvider.Context) : EntityR ), false, Random(), blockState.getSeed(BlockPos.ZERO), OverlayTexture.NO_OVERLAY ) poseStack.popPose() - super.render(fallingBlockEntity, f, g, poseStack, multiBufferSource, i) + super.render(fallingBlockEntity, f, partialTick, poseStack, multiBufferSource, i) } override fun getTextureLocation(entity: VSPhysicsEntity): ResourceLocation { diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestSphereBlock.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestSphereBlock.kt new file mode 100644 index 000000000..cfdb38ac8 --- /dev/null +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/block/TestSphereBlock.kt @@ -0,0 +1,28 @@ +package org.valkyrienskies.mod.common.block + +import net.minecraft.core.BlockPos +import net.minecraft.world.level.BlockGetter +import net.minecraft.world.level.block.Block +import net.minecraft.world.level.block.state.BlockState +import net.minecraft.world.level.material.Material +import net.minecraft.world.phys.shapes.CollisionContext +import net.minecraft.world.phys.shapes.Shapes +import net.minecraft.world.phys.shapes.VoxelShape + +object TestSphereBlock : Block(Properties.of(Material.STONE)) { + override fun getVisualShape( + blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos?, collisionContext: CollisionContext? + ): VoxelShape { + return Shapes.empty() + } + + override fun getShadeBrightness(blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos?): Float { + return 1.0f + } + + override fun propagatesSkylightDown( + blockState: BlockState?, blockGetter: BlockGetter?, blockPos: BlockPos? + ): Boolean { + return true + } +} diff --git a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt index d0e7bbfcb..c7279eb88 100644 --- a/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt +++ b/common/src/main/kotlin/org/valkyrienskies/mod/common/entity/VSPhysicsEntity.kt @@ -29,6 +29,7 @@ import org.valkyrienskies.core.impl.game.ships.ShipInertiaDataImpl import org.valkyrienskies.core.impl.util.serialization.VSJacksonUtil import org.valkyrienskies.mod.common.dimensionId import org.valkyrienskies.mod.common.shipObjectWorld +import org.valkyrienskies.mod.common.util.toJOML import org.valkyrienskies.mod.common.util.toMinecraft class VSPhysicsEntity(type: EntityType, level: Level) : Entity(type, level) { @@ -38,10 +39,14 @@ class VSPhysicsEntity(type: EntityType, level: Level) : Entity( // The physics entity, transient, only exists server side after this entity has been added to a world private var physicsEntityServer: PhysicsEntityServer? = null - private var clientPos: Vector3dc? = null - private var clientRotation: Quaternionfc? = null + private var lastTickRotation: Quaternionfc? = null + private var rotation: Quaternionfc? = null - val rotation: Quaternionfc + private var lerpPos: Vector3dc? = null + private var lerpRot: Quaternionfc? = null + private var lerpSteps = 0 + + private val serverRotation: Quaternionfc get() { val rotationRaw = entityData.get(ROTATION_DATA) return Quaternionf().rotateXYZ(rotationRaw.x, rotationRaw.y, rotationRaw.z) @@ -52,22 +57,76 @@ class VSPhysicsEntity(type: EntityType, level: Level) : Entity( throw IllegalStateException("Cannot define physicsEntityData, its already defined!") } this.physicsEntityData = physicsEntityData + if (!this.level.isClientSide) { + var defaultRot = Rotations(0.0f, 0.0f, 0.0f) + if (!this.level.isClientSide) { + val eulerAngles = physicsEntityData.transform.shipToWorldRotation.getEulerAnglesXYZ(Vector3d()) + defaultRot = Rotations(eulerAngles.x.toFloat(), eulerAngles.y.toFloat(), eulerAngles.z.toFloat()) + } + this.entityData.set(ROTATION_DATA, defaultRot) + } + lastTickRotation = Quaternionf(physicsEntityData.transform.shipToWorldRotation) + rotation = lastTickRotation } override fun tick() { + if (lerpPos == null) { + lerpPos = position().toJOML() + lerpRot = serverRotation + rotation = serverRotation + } + lastTickRotation = rotation if (!this.level.isClientSide) { val physicsEntityServerCopy = physicsEntityServer if (physicsEntityServerCopy != null) { - this.setPos(physicsEntityServerCopy.shipTransform.positionInWorld.toMinecraft()) - val eulerAngles = physicsEntityServerCopy.shipTransform.shipToWorldRotation.getEulerAnglesXYZ(Vector3d()) + val transform = physicsEntityServerCopy.shipTransform + this.setPos(transform.positionInWorld.toMinecraft()) + val eulerAngles = transform.shipToWorldRotation.getEulerAnglesXYZ(Vector3d()) this.entityData.set( ROTATION_DATA, Rotations(eulerAngles.x.toFloat(), eulerAngles.y.toFloat(), eulerAngles.z.toFloat()) ) + rotation = Quaternionf(transform.shipToWorldRotation) + this.physicsEntityData!!.transform = transform } + } else { + tickLerp() } super.tick() } + override fun lerpTo(d: Double, e: Double, f: Double, g: Float, h: Float, i: Int, bl: Boolean) { + this.lerpPos = Vector3d(d, e, f) + this.lerpRot = serverRotation + this.lerpSteps = CLIENT_INTERP_STEPS + } + + private fun tickLerp() { + if (this.lerpSteps <= 0) { + return + } else if (this.lerpSteps == 1) { + setPos(lerpPos!!.x(), lerpPos!!.y(), lerpPos!!.z()) + rotation = lerpRot + lerpSteps = 0 + return + } + + val d: Double = this.x + (this.lerpPos!!.x() - this.x) / this.lerpSteps.toDouble() + val e: Double = this.y + (this.lerpPos!!.y() - this.y) / this.lerpSteps.toDouble() + val f: Double = this.z + (this.lerpPos!!.z() - this.z) / this.lerpSteps.toDouble() + + rotation = rotation!!.slerp(this.lerpRot, (1.0 - (1.0 / this.lerpSteps.toDouble())).toFloat(), Quaternionf()) + + --this.lerpSteps + this.setPos(d, e, f) + } + + fun getRenderRotation(partialTick: Float): Quaternionfc { + if (lastTickRotation == null) { + return serverRotation + } + return lastTickRotation!!.slerp(rotation!!, partialTick, Quaternionf()) + } + override fun defineSynchedData() { entityData.define(ROTATION_DATA, Rotations(0.0f, 0.0f, 0.0f)) } @@ -127,8 +186,18 @@ class VSPhysicsEntity(type: EntityType, level: Level) : Entity( } } + override fun shouldRenderAtSqrDistance(d: Double): Boolean { + var e = this.boundingBox.size + if (java.lang.Double.isNaN(e)) { + e = 1.0 + } + e *= 1024.0 + return d < e * e + } + companion object { private const val PHYS_DATA_NBT_KEY = "phys_entity_data" + private const val CLIENT_INTERP_STEPS = 3 private val ROTATION_DATA: EntityDataAccessor = SynchedEntityData.defineId(VSPhysicsEntity::class.java, EntityDataSerializers.ROTATIONS) diff --git a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt index 7b432e8fa..5ae9cea1f 100644 --- a/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt +++ b/fabric/src/main/kotlin/org/valkyrienskies/mod/fabric/common/ValkyrienSkiesModFabric.kt @@ -23,8 +23,6 @@ import net.minecraft.world.item.BlockItem import net.minecraft.world.item.CreativeModeTab import net.minecraft.world.item.Item.Properties import net.minecraft.world.level.block.Block -import net.minecraft.world.level.block.state.BlockBehaviour -import net.minecraft.world.level.material.Material import org.valkyrienskies.core.apigame.VSCoreFactory import org.valkyrienskies.mod.client.EmptyRenderer import org.valkyrienskies.mod.client.VSPhysicsEntityRenderer @@ -32,6 +30,7 @@ import org.valkyrienskies.mod.common.ValkyrienSkiesMod import org.valkyrienskies.mod.common.block.TestChairBlock import org.valkyrienskies.mod.common.block.TestFlapBlock import org.valkyrienskies.mod.common.block.TestHingeBlock +import org.valkyrienskies.mod.common.block.TestSphereBlock import org.valkyrienskies.mod.common.block.TestWingBlock import org.valkyrienskies.mod.common.blockentity.TestHingeBlockEntity import org.valkyrienskies.mod.common.command.VSCommands @@ -63,7 +62,7 @@ class ValkyrienSkiesModFabric : ModInitializer { ValkyrienSkiesMod.TEST_HINGE = TestHingeBlock ValkyrienSkiesMod.TEST_FLAP = TestFlapBlock ValkyrienSkiesMod.TEST_WING = TestWingBlock - ValkyrienSkiesMod.TEST_SPHERE = Block(BlockBehaviour.Properties.of(Material.STONE)) + ValkyrienSkiesMod.TEST_SPHERE = TestSphereBlock ValkyrienSkiesMod.SHIP_CREATOR_ITEM = ShipCreatorItem( Properties().tab(CreativeModeTab.TAB_MISC), { 1.0 }, @@ -88,6 +87,7 @@ class ValkyrienSkiesModFabric : ModInitializer { MobCategory.MISC ).sized(.3f, .3f) .updateInterval(1) + .clientTrackingRange(10) .build(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "vs_physics_entity").toString()) ValkyrienSkiesMod.TEST_HINGE_BLOCK_ENTITY_TYPE = diff --git a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt index dfea1eede..1906df862 100644 --- a/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt +++ b/forge/src/main/kotlin/org/valkyrienskies/mod/forge/common/ValkyrienSkiesModForge.kt @@ -1,6 +1,7 @@ package org.valkyrienskies.mod.forge.common -import net.minecraft.commands.Commands.CommandSelection.* +import net.minecraft.commands.Commands.CommandSelection.ALL +import net.minecraft.commands.Commands.CommandSelection.INTEGRATED import net.minecraft.resources.ResourceLocation import net.minecraft.world.entity.EntityType import net.minecraft.world.entity.MobCategory @@ -10,14 +11,12 @@ import net.minecraft.world.item.Item import net.minecraft.world.item.Item.Properties import net.minecraft.world.level.block.Block import net.minecraft.world.level.block.entity.BlockEntityType -import net.minecraft.world.level.block.state.BlockBehaviour -import net.minecraft.world.level.material.Material import net.minecraftforge.client.ClientRegistry import net.minecraftforge.client.ConfigGuiHandler.ConfigGuiFactory import net.minecraftforge.client.event.EntityRenderersEvent import net.minecraftforge.event.AddReloadListenerEvent -import net.minecraftforge.event.TagsUpdatedEvent import net.minecraftforge.event.RegisterCommandsEvent +import net.minecraftforge.event.TagsUpdatedEvent import net.minecraftforge.fml.ModLoadingContext import net.minecraftforge.fml.common.Mod import net.minecraftforge.fml.common.Mod.EventBusSubscriber.Bus @@ -36,6 +35,7 @@ import org.valkyrienskies.mod.common.ValkyrienSkiesMod import org.valkyrienskies.mod.common.block.TestChairBlock import org.valkyrienskies.mod.common.block.TestFlapBlock import org.valkyrienskies.mod.common.block.TestHingeBlock +import org.valkyrienskies.mod.common.block.TestSphereBlock import org.valkyrienskies.mod.common.block.TestWingBlock import org.valkyrienskies.mod.common.blockentity.TestHingeBlockEntity import org.valkyrienskies.mod.common.command.VSCommands @@ -113,7 +113,7 @@ class ValkyrienSkiesModForge { TEST_HINGE_REGISTRY = registerBlockAndItem("test_hinge") { TestHingeBlock } TEST_FLAP_REGISTRY = registerBlockAndItem("test_flap") { TestFlapBlock } TEST_WING_REGISTRY = registerBlockAndItem("test_wing") { TestWingBlock } - TEST_SPHERE_REGISTRY = registerBlockAndItem("test_sphere") { Block(BlockBehaviour.Properties.of(Material.STONE)) } + TEST_SPHERE_REGISTRY = registerBlockAndItem("test_sphere") { TestSphereBlock } SHIP_CREATOR_ITEM_REGISTRY = ITEMS.register("ship_creator") { ShipCreatorItem(Properties().tab(CreativeModeTab.TAB_MISC), @@ -150,6 +150,7 @@ class ValkyrienSkiesModForge { MobCategory.MISC ).sized(.3f, .3f) .setUpdateInterval(1) + .clientTrackingRange(10) .build(ResourceLocation(ValkyrienSkiesMod.MOD_ID, "vs_physics_entity").toString()) }