diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt index 9f3a48fae..e9bed62c0 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt @@ -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) } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/item/FallingBlock.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/item/FallingBlock.kt index 37c18a4e2..30116d76f 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/item/FallingBlock.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/item/FallingBlock.kt @@ -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 { override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("falling_block") diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/item/ItemEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/item/ItemEntity.kt index a52d7f5bd..a8b228c9f 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/item/ItemEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/item/ItemEntity.kt @@ -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 { override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("item") diff --git a/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt b/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt index 0d866a3dc..3251f973e 100644 --- a/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt @@ -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) {