apply correct client velocity for other entities (like falling block, item)

This commit is contained in:
Bixilon 2021-06-23 20:55:16 +02:00
parent 26b21d3404
commit b6e46a3913
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
4 changed files with 143 additions and 98 deletions

View File

@ -20,6 +20,7 @@ import de.bixilon.minosoft.data.entities.meta.EntityMetaData
import de.bixilon.minosoft.data.inventory.InventorySlots.EquipmentSlots
import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.physics.PhysicsEntity
import de.bixilon.minosoft.data.player.LocalPlayerEntity
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.effects.StatusEffect
import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttribute
@ -34,8 +35,11 @@ import de.bixilon.minosoft.gui.rendering.input.camera.EntityPositionInfo
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.advanced.block.BlockDustParticle
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty
import de.bixilon.minosoft.gui.rendering.util.VecUtil.floor
import de.bixilon.minosoft.gui.rendering.util.VecUtil.horizontal
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkPosition
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.synchronizedMapOf
@ -77,6 +81,11 @@ abstract class Entity(
override var velocity: Vec3d = Vec3d.EMPTY
var movementMultiplier = Vec3d.EMPTY // ToDo: Used in cobwebs, etc
protected open var velocityMultiplier: Double = 1.0
protected var horizontalCollision = false
protected var verticalCollision = false
protected var fallDistance = 0.0
protected open val hasCollisions = true
@ -358,6 +367,102 @@ abstract class Entity(
return entityType.toString()
}
fun fall(deltaY: Double) {
if (onGround) {
// ToDo: On block landing (particles, sounds, etc)
this.fallDistance = 0.0
return
}
this.fallDistance = this.fallDistance - deltaY
}
fun move(delta: Vec3d) {
if (!hasCollisions) {
forceMove(delta)
return
}
var movement = Vec3d(delta)
// ToDo: Check for piston movement
if (!movementMultiplier.empty) {
movement = movement * movementMultiplier
movementMultiplier = Vec3d.EMPTY
velocity = Vec3d.EMPTY
}
if (this is LocalPlayerEntity) {
movement = connection.collisionDetector.sneak(this, movement)
}
val collisionMovement = connection.collisionDetector.collide(null, movement, aabb, true)
forceMove(collisionMovement)
horizontalCollision = collisionMovement.x != movement.x || collisionMovement.z != movement.z
verticalCollision = collisionMovement.y != movement.y
this.onGround = verticalCollision && movement.y < 0.0f
fall(collisionMovement.y)
var velocityChanged = false
if (movement.y != collisionMovement.y) {
if (movement.y < 0.0 && collisionMovement.y != 0.0) {
val landingPosition = belowBlockPosition
val landingBlockState = connection.world[belowBlockPosition]
val previousVelocity = Vec3d(velocity)
landingBlockState?.block?.onEntityLand(connection, this, landingPosition, landingBlockState)
velocityChanged = velocity != previousVelocity
}
if (!velocityChanged) {
velocity.y = 0.0
}
}
if (!velocityChanged) {
if (movement.x != collisionMovement.x) {
velocity.x = 0.0
}
if (movement.z != collisionMovement.z) {
velocity.z = 0.0
}
}
if (onGround && canStep) {
// ToDo: Play step sound
}
// ToDo: Check for move effect
// block collision handling
val aabb = aabb.shrink(0.001)
for (blockPosition in aabb.blockPositions) {
val chunk = connection.world[blockPosition.chunkPosition] ?: continue
val blockState = chunk[blockPosition.inChunkPosition] ?: continue
blockState.block.onEntityCollision(connection, this, blockState, blockPosition)
}
val velocityMultiplier = velocityMultiplier
velocity.x *= velocityMultiplier
velocity.z *= velocityMultiplier
}
protected fun applyGravity(force: Boolean = false) {
if (hasGravity) {
velocity.y += -0.04
}
}
companion object {
private val BELOW_POSITION_MINUS = Vec3(0, 0.20000000298023224f, 0)
}

View File

@ -38,6 +38,16 @@ class FallingBlock(connection: PlayConnection, entityType: EntityType, position:
blockState = connection.registries.blockStateRegistry[data]
}
override fun realTick() {
super.realTick()
applyGravity()
move(velocity)
velocity = velocity * 0.98
}
companion object : EntityFactory<FallingBlock> {
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("falling_block")

View File

@ -20,8 +20,10 @@ import de.bixilon.minosoft.data.inventory.ItemStack
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.entities.EntityFactory
import de.bixilon.minosoft.data.registries.entities.EntityType
import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import glm_.vec3.Vec3d
import glm_.vec3.Vec3i
class ItemEntity(connection: PlayConnection, entityType: EntityType, position: Vec3d, rotation: EntityRotation) : Entity(connection, entityType, position, rotation) {
@ -30,6 +32,30 @@ class ItemEntity(connection: PlayConnection, entityType: EntityType, position: V
get() = entityMetaData.sets.getItemStack(EntityMetaDataFields.ITEM_ITEM)
override fun realTick() {
super.realTick()
when {
// ToDo: Apply water and lava "bouncing"
hasGravity -> applyGravity()
}
if (!onGround || !velocity.empty) {
move(velocity)
var movement = 0.98
if (onGround) {
movement = (connection.world[Vec3i(positionInfo.blockPosition.x, position.y - 1.0, position.z)]?.block?.friction ?: 1.0) * 0.98
}
velocity = velocity * Vec3d(movement, 0.98, movement)
if (onGround && velocity.y < 0.0) {
velocity.y *= -0.5
}
}
}
companion object : EntityFactory<ItemEntity> {
override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("item")

View File

@ -49,9 +49,7 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.assign
import de.bixilon.minosoft.gui.rendering.util.VecUtil.blockPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.clearZero
import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty
import de.bixilon.minosoft.gui.rendering.util.VecUtil.get
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.packets.c2s.play.*
@ -114,13 +112,8 @@ class LocalPlayerEntity(
private val walkingSpeed: Double
get() = getAttributeValue(DefaultStatusEffectAttributeNames.GENERIC_MOVEMENT_SPEED, baseAbilities.walkingSpeed)
private var horizontalCollision = false
private var verticalCollision = false
var dirtyVelocity = false
var jumpingCoolDown = 0
var isJumping = false
var fallDistance = 0.0
private var lastFovMultiplier = 1.0
private var currentFovMultiplier = 1.0
@ -174,7 +167,8 @@ class LocalPlayerEntity(
return DefaultBlockTags.CLIMBABLE.contains(blockState.block.resourceLocation)
}
private val velocityMultiplier: Double
override var velocityMultiplier: Double
set(value) {}
get() {
if (isFlyingWithElytra || baseAbilities.isFlying) {
return 1.0
@ -194,7 +188,6 @@ class LocalPlayerEntity(
}
}
return blockStateBelow.block.velocityMultiplier
}
private val jumpVelocityMultiplier: Double
@ -292,94 +285,6 @@ class LocalPlayerEntity(
return Vec3d(velocity.x * cos - velocity.z * sin, velocity.y, velocity.z * cos + velocity.x * sin)
}
fun fall(deltaY: Double) {
if (onGround) {
// ToDo: On block landing (particles, sounds, etc)
this.fallDistance = 0.0
return
}
this.fallDistance = this.fallDistance - deltaY
}
fun move(delta: Vec3d) {
if (!hasCollisions) {
forceMove(delta)
return
}
var movement = Vec3d(delta)
// ToDo: Check for piston movement
if (!movementMultiplier.empty) {
movement = movement * movementMultiplier
movementMultiplier = Vec3d.EMPTY
velocity = Vec3d.EMPTY
}
movement = connection.collisionDetector.sneak(this, movement)
val collisionMovement = connection.collisionDetector.collide(null, movement, aabb, true)
forceMove(collisionMovement)
horizontalCollision = collisionMovement.x != movement.x || collisionMovement.z != movement.z
verticalCollision = collisionMovement.y != movement.y
this.onGround = verticalCollision && movement.y < 0.0f
fall(collisionMovement.y)
var velocityChanged = false
if (movement.y != collisionMovement.y) {
if (movement.y < 0.0 && collisionMovement.y != 0.0) {
val landingPosition = belowBlockPosition
val landingBlockState = connection.world[belowBlockPosition]
val previousVelocity = Vec3d(velocity)
landingBlockState?.block?.onEntityLand(connection, this, landingPosition, landingBlockState)
velocityChanged = velocity != previousVelocity
}
if (!velocityChanged) {
velocity.y = 0.0
}
}
if (!velocityChanged) {
if (movement.x != collisionMovement.x) {
velocity.x = 0.0
}
if (movement.z != collisionMovement.z) {
velocity.z = 0.0
}
}
if (onGround && canStep) {
// ToDo: Play step sound
}
// ToDo: Check for move effect
// block collision handling
val aabb = aabb.shrink(0.001)
for (blockPosition in aabb.blockPositions) {
val chunk = connection.world[blockPosition.chunkPosition] ?: continue
val blockState = chunk[blockPosition.inChunkPosition] ?: continue
blockState.block.onEntityCollision(connection, this, blockState, blockPosition)
}
val velocityMultiplier = velocityMultiplier
velocity.x *= velocityMultiplier
velocity.z *= velocityMultiplier
}
private fun applyClimbingSpeed(velocity: Vec3d): Vec3d {
if (!isClimbing) {
@ -574,7 +479,6 @@ class LocalPlayerEntity(
val yawRad = rotation.headYaw.rad
this.velocity = this.velocity + Vec3(-(yawRad.sin * 0.2f), 0.0f, yawRad.cos * 0.2f)
}
dirtyVelocity = true
}
private fun pushOutOfBlocks(x: Double, z: Double) {