Skip to content

Commit

Permalink
Merge pull request #565 from ValkyrienSkies/feature/phys-entity-tracking
Browse files Browse the repository at this point in the history
Feature/phys entity tracking
  • Loading branch information
StewStrong authored Aug 25, 2023
2 parents 96a8332 + 7b9a49b commit c4fb3ff
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 44 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import net.minecraft.resources.ResourceLocation
import net.minecraft.world.inventory.InventoryMenu
import net.minecraft.world.level.block.RenderShape.INVISIBLE
import net.minecraft.world.level.block.RenderShape.MODEL
import org.valkyrienskies.core.impl.game.ships.ShipObjectClientWorld
import org.valkyrienskies.mod.common.IShipObjectWorldClientProvider
import org.valkyrienskies.mod.common.ValkyrienSkiesMod
import org.valkyrienskies.mod.common.entity.VSPhysicsEntity
import org.valkyrienskies.mod.common.util.toMinecraft
Expand All @@ -33,9 +35,25 @@ class VSPhysicsEntityRenderer(context: EntityRendererProvider.Context) : EntityR
) {
return
}

val renderTransform = fallingBlockEntity.getRenderTransform(
((Minecraft.getInstance() as IShipObjectWorldClientProvider).shipObjectWorld as ShipObjectClientWorld)
) ?: return

val expectedX = fallingBlockEntity.xo + (fallingBlockEntity.x - fallingBlockEntity.xo) * partialTick
val expectedY = fallingBlockEntity.yo + (fallingBlockEntity.y - fallingBlockEntity.yo) * partialTick
val expectedZ = fallingBlockEntity.zo + (fallingBlockEntity.z - fallingBlockEntity.zo) * partialTick

// Replace the default transform applied by mc with these offsets
val offsetX = renderTransform.positionInWorld.x() - expectedX
val offsetY = renderTransform.positionInWorld.y() - expectedY
val offsetZ = renderTransform.positionInWorld.z() - expectedZ

poseStack.pushPose()
val blockPos = BlockPos(fallingBlockEntity.x, fallingBlockEntity.boundingBox.maxY, fallingBlockEntity.z)
poseStack.mulPose(fallingBlockEntity.getRenderRotation(partialTick).toMinecraft())

poseStack.translate(offsetX, offsetY, offsetZ)
poseStack.mulPose(renderTransform.shipToWorldRotation.toMinecraft())
poseStack.translate(-0.5, -0.5, -0.5)
val blockRenderDispatcher = Minecraft.getInstance().blockRenderer
blockRenderDispatcher.modelRenderer.tesselateBlock(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import net.minecraft.world.entity.EntityType
import net.minecraft.world.level.Level
import net.minecraft.world.level.entity.EntityInLevelCallback
import org.joml.Matrix3d
import org.joml.Quaternionf
import org.joml.Quaternionfc
import org.joml.Vector3d
import org.joml.Vector3dc
import org.valkyrienskies.core.api.ships.properties.ShipId
Expand All @@ -27,6 +25,7 @@ import org.valkyrienskies.core.apigame.physics.VSSphereCollisionShapeData
import org.valkyrienskies.core.apigame.world.ServerShipWorldCore
import org.valkyrienskies.core.impl.game.ShipTeleportDataImpl
import org.valkyrienskies.core.impl.game.ships.ShipInertiaDataImpl
import org.valkyrienskies.core.impl.game.ships.ShipObjectClientWorld
import org.valkyrienskies.core.impl.game.ships.ShipObjectServerWorld
import org.valkyrienskies.core.impl.game.ships.ShipTransformImpl
import org.valkyrienskies.core.impl.util.serialization.VSJacksonUtil
Expand All @@ -43,19 +42,9 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En
// The physics entity, transient, only exists server side after this entity has been added to a world
private var physicsEntityServer: PhysicsEntityServer? = null

private var lastTickRotation: Quaternionfc? = null
private var rotation: Quaternionfc? = null

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)
}

fun setPhysicsEntityData(physicsEntityData: PhysicsEntityData) {
if (this.physicsEntityData != null) {
throw IllegalStateException("Cannot define physicsEntityData, its already defined!")
Expand All @@ -67,29 +56,20 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En
val eulerAngles = physicsEntityData.transform.shipToWorldRotation.getEulerAnglesXYZ(Vector3d())
defaultRot = Rotations(eulerAngles.x.toFloat(), eulerAngles.y.toFloat(), eulerAngles.z.toFloat())
}
this.entityData.set(ROTATION_DATA, defaultRot)
this.entityData.set(SHIP_ID_DATA, physicsEntityData.shipId.toString())
}
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) {
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
}
this.tryCheckInsideBlocks()
Expand All @@ -101,7 +81,6 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En

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
}

Expand All @@ -110,7 +89,6 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En
return
} else if (this.lerpSteps == 1) {
setPos(lerpPos!!.x(), lerpPos!!.y(), lerpPos!!.z())
rotation = lerpRot
lerpSteps = 0
return
}
Expand All @@ -119,26 +97,22 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En
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()

if (rotation != null) {
rotation = rotation!!.slerp(this.lerpRot, (1.0 - (1.0 / this.lerpSteps.toDouble())).toFloat(), Quaternionf())
} else {
rotation = serverRotation
lastTickRotation = rotation
}

--this.lerpSteps
this.setPos(d, e, f)
}

fun getRenderRotation(partialTick: Float): Quaternionfc {
if (lastTickRotation == null) {
return serverRotation
fun getRenderTransform(shipObjectClientWorld: ShipObjectClientWorld): ShipTransform? {
val shipIdString = entityData.get(SHIP_ID_DATA)
if (shipIdString == "") {
return null
}
return lastTickRotation!!.slerp(rotation!!, partialTick, Quaternionf())
val shipIdLong = shipIdString.toLong()
val physEntityClient = shipObjectClientWorld.physicsEntities[shipIdLong]
return physEntityClient?.renderTransform
}

override fun defineSynchedData() {
entityData.define(ROTATION_DATA, Rotations(0.0f, 0.0f, 0.0f))
entityData.define(SHIP_ID_DATA, "")
}

override fun readAdditionalSaveData(compoundTag: CompoundTag) {
Expand Down Expand Up @@ -221,11 +195,7 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En
val physicsEntityServerCopy = physicsEntityServer
if (physicsEntityServerCopy != null) {
val newPos = Vector3d(d, e, f)
this.entityData.set(
ROTATION_DATA, Rotations(0.0f, 0.0f, 0.0f)
)
val teleportData = ShipTeleportDataImpl(newPos = newPos)
rotation = Quaternionf()
(this.level.shipObjectWorld as ShipObjectServerWorld).teleportPhysicsEntity(this.physicsEntityServer!!, teleportData)
} else {
physicsEntityData!!.transform = ShipTransformImpl.create(
Expand All @@ -250,8 +220,9 @@ open class VSPhysicsEntity(type: EntityType<VSPhysicsEntity>, level: Level) : En
private const val PHYS_DATA_NBT_KEY = "phys_entity_data"
private const val CLIENT_INTERP_STEPS = 3

private val ROTATION_DATA: EntityDataAccessor<Rotations> =
SynchedEntityData.defineId(VSPhysicsEntity::class.java, EntityDataSerializers.ROTATIONS)
// Use string because there is no LONG serializer by default SMH my head!
private val SHIP_ID_DATA: EntityDataAccessor<String> =
SynchedEntityData.defineId(VSPhysicsEntity::class.java, EntityDataSerializers.STRING)

private fun getMapper(): ObjectMapper {
return VSJacksonUtil.defaultMapper
Expand Down
2 changes: 1 addition & 1 deletion vs-core

0 comments on commit c4fb3ff

Please sign in to comment.