entity raycasting

This commit is contained in:
Bixilon 2021-07-08 00:02:32 +02:00
parent 9a70922138
commit f81e6e116a
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
4 changed files with 60 additions and 12 deletions

View File

@ -27,6 +27,9 @@ import glm_.vec3.Vec3t
class VoxelShape(private val aabbs: MutableList<AABB> = mutableListOf()) : Iterable<AABB> { class VoxelShape(private val aabbs: MutableList<AABB> = mutableListOf()) : Iterable<AABB> {
constructor(vararg aabbs: AABB) : this(aabbs.toMutableList())
constructor(data: Any, aabbs: List<AABB>) : this() { constructor(data: Any, aabbs: List<AABB>) : this() {
when (data) { when (data) {
is JsonArray -> { is JsonArray -> {

View File

@ -14,6 +14,7 @@
package de.bixilon.minosoft.gui.rendering.input package de.bixilon.minosoft.gui.rendering.input
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.player.Hands import de.bixilon.minosoft.data.player.Hands
import de.bixilon.minosoft.data.registries.blocks.BlockUsages import de.bixilon.minosoft.data.registries.blocks.BlockUsages
import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderConstants
@ -50,8 +51,25 @@ class RightClickHandler(
if (raycastHit.distance > RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) { if (raycastHit.distance > RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) {
return return
} }
fun sendInteractionPacket() {
connection.sendPacket(BlockPlaceC2SP(
position = raycastHit.blockPosition,
direction = raycastHit.hitDirection,
cursorPosition = Vec3(raycastHit.hitPosition),
item = connection.player.inventory.getHotbarSlot(),
hand = Hands.MAIN_HAND,
insideBlock = false, // ToDo
))
}
val itemInHand = connection.player.inventory.getHotbarSlot() val itemInHand = connection.player.inventory.getHotbarSlot()
if (connection.player.gamemode == Gamemodes.SPECTATOR) {
sendInteractionPacket()
return
}
val usage = if (connection.player.isSneaking) { val usage = if (connection.player.isSneaking) {
BlockUsages.PASS BlockUsages.PASS
} else { } else {
@ -70,14 +88,7 @@ class RightClickHandler(
if (usage == BlockUsages.SUCCESS) { if (usage == BlockUsages.SUCCESS) {
connection.sendPacket(ArmSwingC2SP(Hands.MAIN_HAND)) connection.sendPacket(ArmSwingC2SP(Hands.MAIN_HAND))
} }
connection.sendPacket(BlockPlaceC2SP( sendInteractionPacket()
position = raycastHit.blockPosition,
direction = raycastHit.hitDirection,
cursorPosition = Vec3(raycastHit.hitPosition),
item = connection.player.inventory.getHotbarSlot(),
hand = Hands.MAIN_HAND,
insideBlock = false, // ToDo
))
} }
BlockUsages.PASS -> { BlockUsages.PASS -> {
// use item or place block // use item or place block

View File

@ -17,6 +17,7 @@ import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.entities.EntityRotation
import de.bixilon.minosoft.data.player.LocalPlayerEntity import de.bixilon.minosoft.data.player.LocalPlayerEntity
import de.bixilon.minosoft.data.registries.VoxelShape
import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
import de.bixilon.minosoft.data.text.ChatColors import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderConstants
@ -37,6 +38,7 @@ import de.bixilon.minosoft.modding.event.CallbackEventInvoker
import de.bixilon.minosoft.protocol.network.connection.PlayConnection import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockBreakC2SP import de.bixilon.minosoft.protocol.packets.c2s.play.BlockBreakC2SP
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.KUtil.decide
import de.bixilon.minosoft.util.Previous import de.bixilon.minosoft.util.Previous
import glm_.func.cos import glm_.func.cos
import glm_.func.rad import glm_.func.rad
@ -277,9 +279,30 @@ class Camera(
entityTarget = raycast(eyePosition, cameraFront, blocks = false, fluids = false, entities = true) as EntityRaycastHit? entityTarget = raycast(eyePosition, cameraFront, blocks = false, fluids = false, entities = true) as EntityRaycastHit?
} }
private fun raycastEntity(origin: Vec3d, direction: Vec3d): EntityRaycastHit? {
var currentHit: EntityRaycastHit? = null
for (entity in connection.world.entities) {
if (entity is LocalPlayerEntity) {
continue
}
val hit = VoxelShape(entity.cameraAABB).raycast(origin, direction)
if (!hit.hit) {
continue
}
if ((currentHit?.distance ?: Double.MAX_VALUE) < hit.distance) {
continue
}
currentHit = EntityRaycastHit(origin + direction * hit.distance, hit.distance, hit.direction, entity)
}
return currentHit
}
private fun raycast(origin: Vec3d, direction: Vec3d, blocks: Boolean, fluids: Boolean, entities: Boolean): RaycastHit? { private fun raycast(origin: Vec3d, direction: Vec3d, blocks: Boolean, fluids: Boolean, entities: Boolean): RaycastHit? {
if (!blocks && !fluids && entities) { if (!blocks && !fluids && entities) {
return null // ToDo: Raycast entities // only raycast entities
return raycastEntity(origin, direction)
} }
val currentPosition = Vec3d(origin) val currentPosition = Vec3d(origin)
@ -287,6 +310,7 @@ class Camera(
return (origin - currentPosition).length() return (origin - currentPosition).length()
} }
var hit: RaycastHit? = null
for (i in 0..RAYCAST_MAX_STEPS) { for (i in 0..RAYCAST_MAX_STEPS) {
val blockPosition = currentPosition.floor val blockPosition = currentPosition.floor
val blockState = connection.world[blockPosition] val blockState = connection.world[blockPosition]
@ -305,7 +329,7 @@ class Camera(
if (!fluids) { if (!fluids) {
continue continue
} }
return FluidRaycastHit( hit = FluidRaycastHit(
currentPosition, currentPosition,
distance, distance,
voxelShapeRaycastResult.direction, voxelShapeRaycastResult.direction,
@ -313,23 +337,32 @@ class Camera(
blockPosition, blockPosition,
blockState.block.fluid, blockState.block.fluid,
) )
break
} }
if (!blocks) { if (!blocks) {
continue continue
} }
return BlockRaycastHit( hit = BlockRaycastHit(
currentPosition, currentPosition,
distance, distance,
voxelShapeRaycastResult.direction, voxelShapeRaycastResult.direction,
blockState, blockState,
blockPosition, blockPosition,
) )
break
} else { } else {
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001) currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
} }
} }
return null
if (entities) {
val entityRaycastHit = raycastEntity(origin, direction) ?: return hit
hit ?: return null
return (entityRaycastHit.distance < hit.distance).decide(entityRaycastHit, hit)
}
return hit
} }
companion object { companion object {

View File

@ -48,4 +48,5 @@ class Previous<T>(value: T, private val interpolator: ((previous: Previous<T>, d
fun interpolate(): T { fun interpolate(): T {
return interpolator!!(this, (System.currentTimeMillis() - lastChangeTime)) return interpolator!!(this, (System.currentTimeMillis() - lastChangeTime))
} }
} }