mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 10:55:01 -04:00
Merge branch 'work/camera' into 'master'
Refactor camera See merge request bixilon/minosoft!37
This commit is contained in:
commit
543dda505a
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,4 +1,4 @@
|
||||
target/
|
||||
/target/
|
||||
out/
|
||||
.idea/
|
||||
*.iml
|
||||
|
@ -5,17 +5,3 @@ There is a config file located in:
|
||||
* Windows: `%AppData%\Minosoft`
|
||||
* MacOS: `"~/Library/Application Support/Minosoft"`
|
||||
* Linux (and all others): `~\Minosoft`
|
||||
|
||||
|
||||
- Profiles
|
||||
- Select profile per server
|
||||
- Config reloading
|
||||
- From disk
|
||||
- In eros
|
||||
- Per key combination
|
||||
- Migration
|
||||
- Automatic saving (periodic, per event, maybe use delegates?)
|
||||
- Config editor
|
||||
- Config value checker
|
||||
- Change event, batch those, apply event
|
||||
- Multiple config files (e.g. eros, key combinations, particles, accounts, log, audio, blocks, entities, hit boxes, world, network, assets, physics, hud, other)
|
||||
|
@ -15,14 +15,14 @@ package de.bixilon.minosoft.data.entities
|
||||
import glm_.func.cos
|
||||
import glm_.func.rad
|
||||
import glm_.func.sin
|
||||
import glm_.vec3.Vec3d
|
||||
import glm_.vec3.Vec3
|
||||
|
||||
data class EntityRotation(
|
||||
val yaw: Double,
|
||||
val pitch: Double,
|
||||
) {
|
||||
val front: Vec3d
|
||||
get() = Vec3d(
|
||||
val front: Vec3
|
||||
get() = Vec3(
|
||||
(yaw + 90).rad.cos * (-pitch).rad.cos,
|
||||
(-pitch).rad.sin,
|
||||
(yaw + 90).rad.sin * (-pitch).rad.cos
|
||||
|
@ -49,7 +49,7 @@ 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.gui.rendering.util.VecUtil.toVec3d
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
@ -128,10 +128,10 @@ abstract class Entity(
|
||||
}
|
||||
open val positionInfo = EntityPositionInfo(connection, this)
|
||||
|
||||
val eyePosition: Vec3d
|
||||
val eyePosition: Vec3
|
||||
get() = cameraPosition + Vec3(0.0f, eyeHeight, 0.0f)
|
||||
|
||||
var cameraPosition: Vec3d = position.toVec3d
|
||||
var cameraPosition: Vec3 = position.toVec3
|
||||
private set
|
||||
|
||||
open val spawnSprintingParticles: Boolean
|
||||
@ -362,7 +362,7 @@ abstract class Entity(
|
||||
postTick()
|
||||
lastTickTime = currentTime
|
||||
}
|
||||
cameraPosition = VecUtil.lerp((currentTime - lastTickTime) / ProtocolDefinition.TICK_TIMEd, previousPosition, position)
|
||||
cameraPosition = VecUtil.lerp((currentTime - lastTickTime) / ProtocolDefinition.TICK_TIMEf, Vec3(previousPosition), Vec3(position))
|
||||
}
|
||||
|
||||
open val pushableByFluids: Boolean = false
|
||||
|
@ -28,7 +28,7 @@ import de.bixilon.minosoft.data.registries.items.Item
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
||||
import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.gui.rendering.tint.TintProvider
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
@ -75,7 +75,7 @@ open class Block(
|
||||
return resourceLocation.full
|
||||
}
|
||||
|
||||
open fun getPlacementState(connection: PlayConnection, hit: BlockRaycastHit): BlockState? = defaultState
|
||||
open fun getPlacementState(connection: PlayConnection, target: BlockTarget): BlockState? = defaultState
|
||||
|
||||
open fun onBreak(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState, blockEntity: BlockEntity?) = Unit
|
||||
|
||||
@ -83,7 +83,7 @@ open class Block(
|
||||
|
||||
open fun canPlaceAt(connection: PlayConnection, blockPosition: Vec3i, blockState: BlockState): Boolean = true
|
||||
|
||||
open fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
open fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
if (blockEntityType == null) {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
|
||||
import de.bixilon.minosoft.data.registries.items.tools.ShovelItem
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.campfire.CampfireSmokeParticle
|
||||
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire.SmokeParticle
|
||||
@ -92,13 +92,13 @@ open class CampfireBlock(resourceLocation: ResourceLocation, registries: Registr
|
||||
}
|
||||
}
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
// ToDo: Ignite (flint and steel, etc)
|
||||
if (itemStack?.item !is ShovelItem || hit.blockState.properties[BlockProperties.LIT] != true) {
|
||||
return super.onUse(connection, hit, hand, itemStack)
|
||||
if (itemStack?.item !is ShovelItem || target.blockState.properties[BlockProperties.LIT] != true) {
|
||||
return super.onUse(connection, target, hand, itemStack)
|
||||
}
|
||||
connection.world.setBlockState(hit.blockPosition, hit.blockState.withProperties(BlockProperties.LIT to false))
|
||||
extinguish(connection, hit.blockState, hit.blockPosition)
|
||||
connection.world.setBlockState(target.blockPosition, target.blockState.withProperties(BlockProperties.LIT to false))
|
||||
extinguish(connection, target.blockState, target.blockPosition)
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
||||
|
@ -21,22 +21,22 @@ import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
|
||||
import de.bixilon.minosoft.data.registries.materials.DefaultMaterials
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
open class DoorBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : DoubleSizeBlock(resourceLocation, registries, data) {
|
||||
|
||||
override fun getPlacementState(connection: PlayConnection, hit: BlockRaycastHit): BlockState? {
|
||||
override fun getPlacementState(connection: PlayConnection, target: BlockTarget): BlockState? {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
if (hit.blockState.material.resourceLocation == DefaultMaterials.METAL) {
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
if (target.blockState.material.resourceLocation == DefaultMaterials.METAL) {
|
||||
return InteractionResults.CONSUME
|
||||
}
|
||||
|
||||
connection.world[hit.blockPosition] = hit.blockState.cycle(BlockProperties.DOOR_OPEN)
|
||||
connection.world[target.blockPosition] = target.blockState.cycle(BlockProperties.DOOR_OPEN)
|
||||
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ import de.bixilon.minosoft.data.player.Hands
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockFactory
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
open class NoteBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : Block(resourceLocation, registries, data) {
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
||||
|
@ -19,17 +19,17 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
abstract class AbstractButtonBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : Block(resourceLocation, registries, data) {
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
if (hit.blockState.properties[BlockProperties.POWERED] == true) {
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
if (target.blockState.properties[BlockProperties.POWERED] == true) {
|
||||
return InteractionResults.CONSUME
|
||||
}
|
||||
connection.world[hit.blockPosition] = hit.blockState.withProperties(BlockProperties.POWERED to true)
|
||||
connection.world[target.blockPosition] = target.blockState.withProperties(BlockProperties.POWERED to true)
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.MinecraftBlocks
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
@ -30,12 +30,12 @@ open class PlantBlock(resourceLocation: ResourceLocation, registries: Registries
|
||||
return blockState.block.resourceLocation == MinecraftBlocks.DIRT || blockState.block.resourceLocation == MinecraftBlocks.FARMLAND
|
||||
}
|
||||
|
||||
override fun getPlacementState(connection: PlayConnection, hit: BlockRaycastHit): BlockState? {
|
||||
val below = connection.world[hit.blockPosition + hit.hitDirection + Directions.DOWN] ?: return null
|
||||
override fun getPlacementState(connection: PlayConnection, target: BlockTarget): BlockState? {
|
||||
val below = connection.world[target.blockPosition + target.direction + Directions.DOWN] ?: return null
|
||||
if (!canPlaceOn(below)) {
|
||||
return null
|
||||
}
|
||||
return super.getPlacementState(connection, hit)
|
||||
return super.getPlacementState(connection, target)
|
||||
}
|
||||
|
||||
companion object : BlockFactory<PlantBlock> {
|
||||
|
@ -20,18 +20,18 @@ import de.bixilon.minosoft.data.registries.blocks.BlockFactory
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
open class ComparatorBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : RedstoneGateBlock(resourceLocation, registries, data) {
|
||||
|
||||
override fun getPlacementState(connection: PlayConnection, hit: BlockRaycastHit): BlockState? {
|
||||
override fun getPlacementState(connection: PlayConnection, target: BlockTarget): BlockState? {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
connection.world[hit.blockPosition] = hit.blockState.cycle(BlockProperties.STRUCTURE_BLOCK_MODE)
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
connection.world[target.blockPosition] = target.blockState.cycle(BlockProperties.STRUCTURE_BLOCK_MODE)
|
||||
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
@ -20,18 +20,18 @@ import de.bixilon.minosoft.data.registries.blocks.BlockFactory
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
open class RepeaterBlock(resourceLocation: ResourceLocation, registries: Registries, data: Map<String, Any>) : RedstoneGateBlock(resourceLocation, registries, data) {
|
||||
|
||||
override fun getPlacementState(connection: PlayConnection, hit: BlockRaycastHit): BlockState? {
|
||||
override fun getPlacementState(connection: PlayConnection, target: BlockTarget): BlockState? {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
connection.world[hit.blockPosition] = hit.blockState.cycle(BlockProperties.REPEATER_DELAY)
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
connection.world[target.blockPosition] = target.blockState.cycle(BlockProperties.REPEATER_DELAY)
|
||||
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
|
||||
import de.bixilon.minosoft.data.registries.particle.data.DustParticleData
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.data.text.Colors
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.dust.DustParticle
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY
|
||||
@ -55,14 +55,14 @@ open class LeverBlock(resourceLocation: ResourceLocation, registries: Registries
|
||||
}
|
||||
}
|
||||
|
||||
override fun getPlacementState(connection: PlayConnection, hit: BlockRaycastHit): BlockState? {
|
||||
override fun getPlacementState(connection: PlayConnection, target: BlockTarget): BlockState? {
|
||||
TODO()
|
||||
}
|
||||
|
||||
override fun onUse(connection: PlayConnection, hit: BlockRaycastHit, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
val nextState = hit.blockState.cycle(BlockProperties.POWERED)
|
||||
connection.world[hit.blockPosition] = nextState
|
||||
spawnParticles(connection, nextState, hit.blockPosition, 1.0f)
|
||||
override fun onUse(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack?): InteractionResults {
|
||||
val nextState = target.blockState.cycle(BlockProperties.POWERED)
|
||||
connection.world[target.blockPosition] = nextState
|
||||
spawnParticles(connection, nextState, target.blockPosition, 1.0f)
|
||||
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.data.registries.registries.registry.RegistryItem
|
||||
import de.bixilon.minosoft.data.registries.registries.registry.ResourceLocationDeserializer
|
||||
import de.bixilon.minosoft.data.registries.registries.registry.Translatable
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.EntityRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.EntityTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.util.KUtil.toBoolean
|
||||
@ -69,15 +69,15 @@ open class Item(
|
||||
return 1.0f
|
||||
}
|
||||
|
||||
open fun interactBlock(connection: PlayConnection, raycastHit: BlockRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
open fun interactBlock(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
open fun interactEntity(connection: PlayConnection, raycastHit: EntityRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
open fun interactEntity(connection: PlayConnection, target: EntityTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
open fun interactEntityAt(connection: PlayConnection, raycastHit: EntityRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
open fun interactEntityAt(connection: PlayConnection, target: EntityTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.items.Item
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plusAssign
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
@ -37,14 +37,14 @@ open class BlockItem(
|
||||
this::block.inject(data["block"])
|
||||
}
|
||||
|
||||
override fun interactBlock(connection: PlayConnection, raycastHit: BlockRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
override fun interactBlock(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
if (!connection.player.gamemode.canBuild) {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
val placePosition = raycastHit.blockPosition
|
||||
if (!raycastHit.blockState.material.replaceable) {
|
||||
placePosition += raycastHit.hitDirection
|
||||
val placePosition = target.blockPosition
|
||||
if (!target.blockState.material.replaceable) {
|
||||
placePosition += target.direction
|
||||
|
||||
if (connection.world[placePosition]?.material?.replaceable == false) {
|
||||
return InteractionResults.PASS
|
||||
@ -62,7 +62,7 @@ open class BlockItem(
|
||||
|
||||
var placeBlockState: BlockState = block!!.defaultState
|
||||
try {
|
||||
placeBlockState = block.getPlacementState(connection, raycastHit) ?: return InteractionResults.PASS
|
||||
placeBlockState = block.getPlacementState(connection, target) ?: return InteractionResults.PASS
|
||||
} catch (exception: Throwable) {
|
||||
exception.printStackTrace()
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ import de.bixilon.minosoft.data.player.Hands
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.util.KUtil.mapCast
|
||||
@ -39,12 +39,12 @@ open class AxeItem(
|
||||
entries.toMap()
|
||||
}
|
||||
|
||||
override fun interactBlock(connection: PlayConnection, raycastHit: BlockRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
override fun interactBlock(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
if (!connection.profiles.controls.interaction.stripping) {
|
||||
return InteractionResults.CONSUME
|
||||
}
|
||||
|
||||
return super.interactWithTool(connection, raycastHit.blockPosition, strippableBlocks?.get(raycastHit.blockState.block)?.withProperties(raycastHit.blockState.properties))
|
||||
return super.interactWithTool(connection, target.blockPosition, strippableBlocks?.get(target.blockState.block)?.withProperties(target.blockState.properties))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -20,7 +20,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
@ -42,16 +42,16 @@ open class HoeItem(
|
||||
entries.toMap()
|
||||
}
|
||||
|
||||
override fun interactBlock(connection: PlayConnection, raycastHit: BlockRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
override fun interactBlock(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
if (!connection.profiles.controls.interaction.tilling) {
|
||||
return InteractionResults.CONSUME
|
||||
}
|
||||
|
||||
if (connection.world[raycastHit.blockPosition + Directions.UP] != null) {
|
||||
if (connection.world[target.blockPosition + Directions.UP] != null) {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
return super.interactWithTool(connection, raycastHit.blockPosition, tillableBlockStates?.get(raycastHit.blockState.block))
|
||||
return super.interactWithTool(connection, target.blockPosition, tillableBlockStates?.get(target.blockState.block))
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -20,7 +20,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.registries.blocks.types.Block
|
||||
import de.bixilon.minosoft.data.registries.registries.Registries
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionResults
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
@ -43,16 +43,16 @@ open class ShovelItem(
|
||||
}
|
||||
|
||||
|
||||
override fun interactBlock(connection: PlayConnection, raycastHit: BlockRaycastHit, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
override fun interactBlock(connection: PlayConnection, target: BlockTarget, hand: Hands, itemStack: ItemStack): InteractionResults {
|
||||
if (!connection.profiles.controls.interaction.flattening) {
|
||||
return InteractionResults.CONSUME
|
||||
}
|
||||
|
||||
if (connection.world[raycastHit.blockPosition + Directions.UP] != null) {
|
||||
if (connection.world[target.blockPosition + Directions.UP] != null) {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
return super.interactWithTool(connection, raycastHit.blockPosition, flattenableBlockStates?.get(raycastHit.blockState.block))
|
||||
return super.interactWithTool(connection, target.blockPosition, flattenableBlockStates?.get(target.blockState.block))
|
||||
}
|
||||
|
||||
|
||||
|
@ -22,6 +22,6 @@ object RainGradientSetGameEventHandler : GameEventHandler {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:rain_gradient_set".toResourceLocation()
|
||||
|
||||
override fun handle(data: Float, connection: PlayConnection) {
|
||||
connection.world.rainGradient = data
|
||||
connection.world.weather.rainGradient = data
|
||||
}
|
||||
}
|
||||
|
@ -22,6 +22,6 @@ object ThunderGradientSetGameEventHandler : GameEventHandler {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:thunder_gradient_set".toResourceLocation()
|
||||
|
||||
override fun handle(data: Float, connection: PlayConnection) {
|
||||
connection.world.thunderGradient = data
|
||||
connection.world.weather.thunderGradient = data
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ object RainStartGameEventHandler : GameEventHandler {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:rain_start".toResourceLocation()
|
||||
|
||||
override fun handle(data: Float, connection: PlayConnection) {
|
||||
connection.world.raining = true
|
||||
connection.world.rainGradient = 1.0f
|
||||
connection.world.weather.raining = true
|
||||
connection.world.weather.rainGradient = 1.0f
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ object RainStopGameEventHandler : GameEventHandler {
|
||||
override val RESOURCE_LOCATION: ResourceLocation = "minecraft:rain_stop".toResourceLocation()
|
||||
|
||||
override fun handle(data: Float, connection: PlayConnection) {
|
||||
connection.world.raining = false
|
||||
connection.world.rainGradient = 0.0f
|
||||
connection.world.weather.raining = false
|
||||
connection.world.weather.rainGradient = 0.0f
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,9 @@ import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
|
||||
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
|
||||
import de.bixilon.minosoft.data.world.biome.accessor.BiomeAccessor
|
||||
import de.bixilon.minosoft.data.world.biome.accessor.NoiseBiomeAccessor
|
||||
import de.bixilon.minosoft.data.world.time.WorldTime
|
||||
import de.bixilon.minosoft.data.world.view.WorldView
|
||||
import de.bixilon.minosoft.data.world.weather.WorldWeather
|
||||
import de.bixilon.minosoft.gui.rendering.particle.ParticleRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.particle.types.Particle
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.blockPosition
|
||||
@ -35,10 +37,8 @@ import de.bixilon.minosoft.modding.event.events.BlockSetEvent
|
||||
import de.bixilon.minosoft.modding.event.events.ChunkDataChangeEvent
|
||||
import de.bixilon.minosoft.modding.event.events.ChunkUnloadEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.KUtil.lockMapOf
|
||||
import de.bixilon.minosoft.util.KUtil.toSynchronizedMap
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import de.bixilon.minosoft.util.ReadWriteLock
|
||||
import de.bixilon.minosoft.util.chunk.ChunkUtil.canBuildBiomeCache
|
||||
import de.bixilon.minosoft.util.chunk.ChunkUtil.getChunkNeighbourPositions
|
||||
@ -46,13 +46,9 @@ import de.bixilon.minosoft.util.chunk.ChunkUtil.isInViewDistance
|
||||
import de.bixilon.minosoft.util.chunk.ChunkUtil.received
|
||||
import de.bixilon.minosoft.util.collections.LockMap
|
||||
import de.bixilon.minosoft.util.delegate.DelegateManager.delegate
|
||||
import glm_.func.common.clamp
|
||||
import glm_.vec2.Vec2i
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3i
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
import kotlin.random.Random
|
||||
|
||||
/**
|
||||
@ -70,11 +66,8 @@ class World(
|
||||
var difficulty: Difficulties? = null
|
||||
var difficultyLocked = false
|
||||
var hashedSeed = 0L
|
||||
var time = 0L
|
||||
var age = 0L
|
||||
var raining = false
|
||||
var rainGradient = 0.0f
|
||||
var thunderGradient = 0.0f
|
||||
val time = WorldTime(this)
|
||||
val weather = WorldWeather()
|
||||
val view = WorldView(connection)
|
||||
private val random = Random
|
||||
|
||||
@ -234,25 +227,6 @@ class World(
|
||||
return get(blockPosition.chunkPosition)?.getLight(blockPosition.inChunkPosition) ?: 0x00
|
||||
}
|
||||
|
||||
val skyAngle: Double
|
||||
get() {
|
||||
val fractionalPath = MMath.fractionalPart(abs(time) / ProtocolDefinition.TICKS_PER_DAYf - 0.25)
|
||||
val angle = 0.5 - cos(fractionalPath * Math.PI) / 2.0
|
||||
return (fractionalPath * 2.0 + angle) / 3.0
|
||||
}
|
||||
|
||||
val lightBase: Double
|
||||
get() {
|
||||
var base = 1.0f - (cos(skyAngle * 2.0 * PI) * 2.0 + 0.2)
|
||||
base = base.clamp(0.0, 1.0)
|
||||
base = 1.0 - base
|
||||
|
||||
base *= 1.0 - ((rainGradient * 5.0) / 16.0)
|
||||
base *= 1.0 - (((thunderGradient * rainGradient) * 5.0) / 16.0)
|
||||
return base * 0.8 + 0.2
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return All 8 neighbour chunks
|
||||
*/
|
||||
|
@ -0,0 +1,37 @@
|
||||
package de.bixilon.minosoft.data.world.time
|
||||
|
||||
import de.bixilon.minosoft.data.world.World
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import glm_.func.common.clamp
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.abs
|
||||
import kotlin.math.cos
|
||||
|
||||
class WorldTime(
|
||||
private val world: World,
|
||||
) {
|
||||
var time = 0L
|
||||
var age = 0L
|
||||
|
||||
|
||||
val skyAngle: Float
|
||||
get() {
|
||||
val fractionalPath = MMath.fractionalPart(abs(time) / ProtocolDefinition.TICKS_PER_DAYf - 0.25)
|
||||
val angle = 0.5 - cos(fractionalPath * Math.PI) / 2.0
|
||||
return ((fractionalPath * 2.0 + angle) / 3.0).toFloat()
|
||||
}
|
||||
|
||||
|
||||
val lightBase: Double
|
||||
get() {
|
||||
var base = 1.0f - (cos(skyAngle * 2.0 * PI) * 2.0 + 0.2)
|
||||
base = base.clamp(0.0, 1.0)
|
||||
base = 1.0 - base
|
||||
|
||||
base *= 1.0 - ((world.weather.rainGradient * 5.0) / 16.0)
|
||||
base *= 1.0 - (((world.weather.thunderGradient * world.weather.rainGradient) * 5.0) / 16.0)
|
||||
return base * 0.8 + 0.2
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package de.bixilon.minosoft.data.world.weather
|
||||
|
||||
class WorldWeather {
|
||||
|
||||
var raining = false
|
||||
var rainGradient = 0.0f
|
||||
var thunderGradient = 0.0f
|
||||
}
|
@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.text.BaseComponent
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.gui.rendering.camera.Camera
|
||||
import de.bixilon.minosoft.gui.rendering.entity.EntityHitboxRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.font.Font
|
||||
import de.bixilon.minosoft.gui.rendering.font.FontLoader
|
||||
@ -76,6 +77,7 @@ class RenderWindow(
|
||||
private val profile = connection.profiles.rendering
|
||||
val window: BaseWindow = GLFWWindow(this, connection)
|
||||
val renderSystem: RenderSystem = OpenGLRenderSystem(this)
|
||||
val camera = Camera(this)
|
||||
var initialized = false
|
||||
private set
|
||||
private lateinit var renderThread: Thread
|
||||
@ -163,7 +165,7 @@ class RenderWindow(
|
||||
window.init(connection.profiles.rendering)
|
||||
window.setDefaultIcon(connection.assetsManager)
|
||||
|
||||
inputHandler.camera.init(this)
|
||||
camera.init()
|
||||
|
||||
tintManager.init(connection.assetsManager)
|
||||
|
||||
@ -360,6 +362,7 @@ class RenderWindow(
|
||||
window.pollEvents()
|
||||
|
||||
inputHandler.draw(deltaFrameTime)
|
||||
camera.draw()
|
||||
|
||||
// handle opengl context tasks, but limit it per frame
|
||||
queue.timeWork(RenderConstants.MAXIMUM_QUEUE_TIME_PER_FRAME)
|
||||
|
@ -0,0 +1,23 @@
|
||||
package de.bixilon.minosoft.gui.rendering.camera
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.TargetHandler
|
||||
|
||||
class Camera(
|
||||
renderWindow: RenderWindow,
|
||||
) {
|
||||
val matrixHandler = MatrixHandler(renderWindow)
|
||||
val targetHandler = TargetHandler(renderWindow, this)
|
||||
val fogManager = FogManager(renderWindow)
|
||||
|
||||
fun init() {
|
||||
matrixHandler.init()
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
matrixHandler.entity.tick()
|
||||
matrixHandler.draw()
|
||||
targetHandler.raycast()
|
||||
fogManager.draw()
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package de.bixilon.minosoft.gui.rendering.camera
|
||||
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer
|
||||
import de.bixilon.minosoft.util.delegate.watcher.SimpleDelegateWatcher.Companion.watchRendering
|
||||
|
||||
@Deprecated("Needs some refactoring and improvements")
|
||||
class FogManager(
|
||||
private val renderWindow: RenderWindow,
|
||||
) {
|
||||
private var upToDate = false
|
||||
|
||||
var fogColor: RGBColor = ChatColors.GREEN
|
||||
set(value) {
|
||||
field = value
|
||||
upToDate = false
|
||||
}
|
||||
private var fogStart = 0.0f
|
||||
private var fogEnd = 0.0f
|
||||
|
||||
fun init() {
|
||||
renderWindow.connection.world.view::viewDistance.watchRendering(this, true) { calculateFog() }
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
if (upToDate) {
|
||||
return
|
||||
}
|
||||
calculateFog()
|
||||
updateShaders()
|
||||
}
|
||||
|
||||
private fun calculateFog() {
|
||||
if (!renderWindow.connection.profiles.rendering.fog.enabled) {
|
||||
// ToDo: This is not improving performance
|
||||
fogStart = Float.MAX_VALUE
|
||||
fogEnd = Float.MAX_VALUE
|
||||
} else {
|
||||
fogStart = renderWindow.connection.world.view.viewDistance * 16.0f - 8.0f // ToDo
|
||||
fogEnd = fogStart + 10.0f
|
||||
}
|
||||
renderWindow[SkyRenderer]?.let { fogColor = it.baseColor }
|
||||
}
|
||||
|
||||
|
||||
private fun updateShaders() {
|
||||
for (shader in renderWindow.renderSystem.shaders) {
|
||||
if (!shader.uniforms.contains("uFogColor")) {
|
||||
continue
|
||||
}
|
||||
|
||||
shader.use()
|
||||
|
||||
shader.setFloat("uFogStart", fogStart)
|
||||
shader.setFloat("uFogEnd", fogEnd)
|
||||
shader["uFogColor"] = fogColor
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,147 @@
|
||||
package de.bixilon.minosoft.gui.rendering.camera
|
||||
|
||||
import de.bixilon.minosoft.data.entities.EntityRotation
|
||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.camera.frustum.Frustum
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.CameraMatrixChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.CameraPositionChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.FrustumChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
|
||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||
import glm_.func.rad
|
||||
import glm_.glm
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec3.Vec3
|
||||
|
||||
class MatrixHandler(
|
||||
private val renderWindow: RenderWindow,
|
||||
) {
|
||||
private val connection = renderWindow.connection
|
||||
private val profile = renderWindow.connection.profiles.rendering.camera
|
||||
val frustum = Frustum(this)
|
||||
var entity: Entity = renderWindow.connection.player
|
||||
set(value) {
|
||||
field = value
|
||||
upToDate = false
|
||||
}
|
||||
|
||||
|
||||
var eyePosition = Vec3.EMPTY
|
||||
private set
|
||||
var rotation = EntityRotation(0.0, 0.0)
|
||||
private set
|
||||
private var previousFOV = 0.0
|
||||
|
||||
var cameraFront = Vec3(0.0, 0.0, -1.0)
|
||||
private set
|
||||
var cameraRight = Vec3(0.0, 0.0, -1.0)
|
||||
private set
|
||||
var cameraUp = Vec3(0.0, 1.0, 0.0)
|
||||
private set
|
||||
|
||||
|
||||
var zoom = 0.0f
|
||||
set(value) {
|
||||
field = value
|
||||
upToDate = false
|
||||
}
|
||||
|
||||
private var upToDate = false
|
||||
|
||||
var viewMatrix = calculateViewMatrix()
|
||||
private set
|
||||
var projectionMatrix = calculateProjectionMatrix(renderWindow.window.sizef)
|
||||
private set
|
||||
var viewProjectionMatrix = projectionMatrix * viewMatrix
|
||||
private set
|
||||
|
||||
|
||||
private val fov: Double
|
||||
get() {
|
||||
val fov = profile.fov / (zoom + 1.0)
|
||||
|
||||
if (!profile.dynamicFOV) {
|
||||
return fov
|
||||
}
|
||||
return fov * connection.player.fovMultiplier.interpolate()
|
||||
}
|
||||
|
||||
|
||||
private fun calculateViewMatrix(eyePosition: Vec3 = entity.eyePosition): Mat4 {
|
||||
return glm.lookAt(eyePosition, eyePosition + cameraFront, CAMERA_UP_VEC3)
|
||||
}
|
||||
|
||||
private fun calculateProjectionMatrix(screenDimensions: Vec2): Mat4 {
|
||||
return glm.perspective(fov.rad.toFloat(), screenDimensions.x / screenDimensions.y, 0.01f, 10000.0f)
|
||||
}
|
||||
|
||||
fun init() {
|
||||
connection.registerEvent(CallbackEventInvoker.of<ResizeWindowEvent> {
|
||||
projectionMatrix = calculateProjectionMatrix(Vec2(it.size))
|
||||
upToDate = false
|
||||
})
|
||||
draw() // set initial values
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
val fov = fov
|
||||
val eyePosition = entity.eyePosition
|
||||
val rotation = entity.rotation
|
||||
if (upToDate && eyePosition == this.eyePosition && rotation == this.rotation && fov == previousFOV) {
|
||||
return
|
||||
}
|
||||
this.eyePosition = eyePosition
|
||||
this.rotation = rotation
|
||||
previousFOV = fov
|
||||
|
||||
updateRotation(rotation)
|
||||
updateViewMatrix(eyePosition)
|
||||
updateFrustum()
|
||||
|
||||
connection.fireEvent(CameraPositionChangeEvent(renderWindow, eyePosition))
|
||||
|
||||
connection.fireEvent(CameraMatrixChangeEvent(
|
||||
renderWindow = renderWindow,
|
||||
viewMatrix = viewMatrix,
|
||||
projectionMatrix = projectionMatrix,
|
||||
viewProjectionMatrix = viewProjectionMatrix,
|
||||
))
|
||||
|
||||
updateShaders()
|
||||
}
|
||||
|
||||
private fun updateViewMatrix(eyePosition: Vec3) {
|
||||
viewMatrix = calculateViewMatrix(eyePosition)
|
||||
viewProjectionMatrix = projectionMatrix * viewMatrix
|
||||
}
|
||||
|
||||
private fun updateFrustum() {
|
||||
frustum.recalculate()
|
||||
connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
|
||||
}
|
||||
|
||||
private fun updateRotation(rotation: EntityRotation = entity.rotation) {
|
||||
cameraFront = rotation.front
|
||||
|
||||
cameraRight = (cameraFront cross CAMERA_UP_VEC3).normalize()
|
||||
cameraUp = (cameraRight cross cameraFront).normalize()
|
||||
}
|
||||
|
||||
private fun updateShaders() {
|
||||
for (shader in renderWindow.renderSystem.shaders) {
|
||||
if (shader.uniforms.contains("uViewProjectionMatrix")) {
|
||||
shader.use().setMat4("uViewProjectionMatrix", viewProjectionMatrix)
|
||||
}
|
||||
if (shader.uniforms.contains("uCameraPosition")) {
|
||||
shader.use().setVec3("uCameraPosition", connection.player.cameraPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CAMERA_UP_VEC3 = Vec3(0.0, 1.0, 0.0)
|
||||
}
|
||||
}
|
@ -11,34 +11,31 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.input.camera.frustum
|
||||
package de.bixilon.minosoft.gui.rendering.camera.frustum
|
||||
|
||||
|
||||
import de.bixilon.minosoft.data.registries.AABB
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.Camera
|
||||
import de.bixilon.minosoft.gui.rendering.camera.MatrixHandler
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec4.Vec4Util.dot
|
||||
import de.bixilon.minosoft.util.KUtil
|
||||
import de.bixilon.minosoft.util.KUtil.get
|
||||
import de.bixilon.minosoft.util.enum.ValuesEnum
|
||||
import glm_.mat3x3.Mat3
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.vec2.Vec2i
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3i
|
||||
import glm_.vec4.Vec4
|
||||
|
||||
// Big thanks to: https://gist.github.com/podgorskiy/e698d18879588ada9014768e3e82a644
|
||||
class Frustum(private val camera: Camera) {
|
||||
class Frustum(
|
||||
private val matrixHandler: MatrixHandler,
|
||||
) {
|
||||
private lateinit var data: FrustumData
|
||||
|
||||
init {
|
||||
recalculate()
|
||||
}
|
||||
|
||||
fun recalculate() {
|
||||
val matrix = Mat4(camera.viewProjectionMatrix).transpose()
|
||||
val matrix = matrixHandler.viewProjectionMatrix.transpose()
|
||||
val planes = arrayOf(
|
||||
matrix[3] + matrix[0],
|
||||
matrix[3] - matrix[0],
|
@ -0,0 +1,138 @@
|
||||
package de.bixilon.minosoft.gui.rendering.camera.target
|
||||
|
||||
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.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.camera.Camera
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.EntityTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.FluidTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.GenericTarget
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.floor
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.getWorldOffset
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3d
|
||||
import de.bixilon.minosoft.util.KUtil.decide
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3d
|
||||
|
||||
class TargetHandler(
|
||||
private val renderWindow: RenderWindow,
|
||||
private var camera: Camera,
|
||||
) {
|
||||
private val connection = renderWindow.connection
|
||||
|
||||
/**
|
||||
* Can ba a BlockTarget or an EntityTarget. Not a FluidTarget
|
||||
*/
|
||||
var target: GenericTarget? = null
|
||||
private set
|
||||
var fluidTarget: FluidTarget? = null
|
||||
private set
|
||||
|
||||
|
||||
fun raycast() {
|
||||
val eyePosition = camera.matrixHandler.eyePosition.toVec3d
|
||||
val cameraFront = camera.matrixHandler.cameraFront.toVec3d
|
||||
|
||||
target = raycast(eyePosition, cameraFront, blocks = true, fluids = false, entities = true)
|
||||
fluidTarget = raycast(eyePosition, cameraFront, blocks = false, fluids = true, entities = false) as FluidTarget?
|
||||
}
|
||||
|
||||
|
||||
private fun raycastEntity(origin: Vec3d, direction: Vec3d): EntityTarget? {
|
||||
var currentHit: EntityTarget? = null
|
||||
|
||||
val originF = Vec3(origin)
|
||||
for (entity in connection.world.entities) {
|
||||
if (entity is LocalPlayerEntity) {
|
||||
continue
|
||||
}
|
||||
if ((entity.cameraPosition - originF).length2() > MAX_ENTITY_DISTANCE) {
|
||||
continue
|
||||
}
|
||||
val target = VoxelShape(entity.cameraAABB).raycast(origin, direction)
|
||||
if (!target.hit) {
|
||||
continue
|
||||
}
|
||||
if ((currentHit?.distance ?: Double.MAX_VALUE) < target.distance) {
|
||||
continue
|
||||
}
|
||||
currentHit = EntityTarget(origin + direction * target.distance, target.distance, target.direction, entity)
|
||||
|
||||
}
|
||||
return currentHit
|
||||
}
|
||||
|
||||
private fun raycast(origin: Vec3d, direction: Vec3d, blocks: Boolean, fluids: Boolean, entities: Boolean): GenericTarget? {
|
||||
if (!blocks && !fluids && entities) {
|
||||
// only raycast entities
|
||||
return raycastEntity(origin, direction)
|
||||
}
|
||||
val currentPosition = Vec3d(origin)
|
||||
|
||||
fun getTotalDistance(): Double {
|
||||
return (origin - currentPosition).length()
|
||||
}
|
||||
|
||||
var target: GenericTarget? = null
|
||||
for (i in 0..RAYCAST_MAX_STEPS) {
|
||||
val blockPosition = currentPosition.floor
|
||||
val blockState = connection.world[blockPosition]
|
||||
|
||||
if (blockState == null) {
|
||||
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
|
||||
continue
|
||||
}
|
||||
val voxelShapeRaycastResult = (blockState.block.getOutlineShape(connection, blockState, blockPosition) + blockPosition + blockPosition.getWorldOffset(blockState.block)).raycast(currentPosition, direction)
|
||||
if (voxelShapeRaycastResult.hit) {
|
||||
val distance = getTotalDistance()
|
||||
currentPosition += direction * voxelShapeRaycastResult.distance
|
||||
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
|
||||
|
||||
if (blockState.block is FluidBlock) {
|
||||
if (!fluids) {
|
||||
continue
|
||||
}
|
||||
target = FluidTarget(
|
||||
currentPosition,
|
||||
distance,
|
||||
voxelShapeRaycastResult.direction,
|
||||
blockState,
|
||||
blockPosition,
|
||||
blockState.block.fluid,
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
if (!blocks) {
|
||||
continue
|
||||
}
|
||||
target = BlockTarget(
|
||||
currentPosition,
|
||||
distance,
|
||||
voxelShapeRaycastResult.direction,
|
||||
blockState,
|
||||
blockPosition,
|
||||
)
|
||||
break
|
||||
} else {
|
||||
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
|
||||
}
|
||||
}
|
||||
|
||||
if (entities) {
|
||||
val entityRaycastHit = raycastEntity(origin, direction) ?: return target
|
||||
target ?: return null
|
||||
return (entityRaycastHit.distance < target.distance).decide(entityRaycastHit, target)
|
||||
}
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val RAYCAST_MAX_STEPS = 100
|
||||
private const val MAX_ENTITY_DISTANCE = 20.0f * 20.0f // length2 does not get the square root
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.input.camera.hit
|
||||
package de.bixilon.minosoft.gui.rendering.camera.target.targets
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
@ -21,13 +21,13 @@ import de.bixilon.minosoft.data.text.TextFormattable
|
||||
import glm_.vec3.Vec3d
|
||||
import glm_.vec3.Vec3i
|
||||
|
||||
open class BlockRaycastHit(
|
||||
open class BlockTarget(
|
||||
position: Vec3d,
|
||||
distance: Double,
|
||||
hitDirection: Directions,
|
||||
direction: Directions,
|
||||
val blockState: BlockState,
|
||||
val blockPosition: Vec3i,
|
||||
) : RaycastHit(position, distance, hitDirection), TextFormattable {
|
||||
) : GenericTarget(position, distance, direction), TextFormattable {
|
||||
val hitPosition = position - blockPosition
|
||||
|
||||
override fun toString(): String {
|
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.input.camera.hit
|
||||
package de.bixilon.minosoft.gui.rendering.camera.target.targets
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
@ -20,12 +20,12 @@ import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.data.text.TextFormattable
|
||||
import glm_.vec3.Vec3d
|
||||
|
||||
class EntityRaycastHit(
|
||||
class EntityTarget(
|
||||
position: Vec3d,
|
||||
distance: Double,
|
||||
hitDirection: Directions,
|
||||
direction: Directions,
|
||||
val entity: Entity,
|
||||
) : RaycastHit(position, distance, hitDirection), TextFormattable {
|
||||
) : GenericTarget(position, distance, direction), TextFormattable {
|
||||
|
||||
override fun toString(): String {
|
||||
return toText().legacyText
|
@ -11,7 +11,7 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.input.camera.hit
|
||||
package de.bixilon.minosoft.gui.rendering.camera.target.targets
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
@ -22,14 +22,14 @@ import de.bixilon.minosoft.data.text.TextFormattable
|
||||
import glm_.vec3.Vec3d
|
||||
import glm_.vec3.Vec3i
|
||||
|
||||
class FluidRaycastHit(
|
||||
class FluidTarget(
|
||||
position: Vec3d,
|
||||
distance: Double,
|
||||
hitDirection: Directions,
|
||||
direction: Directions,
|
||||
val blockState: BlockState,
|
||||
val blockPosition: Vec3i,
|
||||
val fluid: Fluid,
|
||||
) : RaycastHit(position, distance, hitDirection), TextFormattable {
|
||||
) : GenericTarget(position, distance, direction), TextFormattable {
|
||||
|
||||
override fun toString(): String {
|
||||
return toText().legacyText
|
@ -11,13 +11,13 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.input.camera.hit
|
||||
package de.bixilon.minosoft.gui.rendering.camera.target.targets
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import glm_.vec3.Vec3d
|
||||
|
||||
abstract class RaycastHit(
|
||||
abstract class GenericTarget(
|
||||
val position: Vec3d,
|
||||
val distance: Double,
|
||||
val hitDirection: Directions,
|
||||
val direction: Directions,
|
||||
)
|
@ -18,7 +18,7 @@ import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
import de.bixilon.minosoft.data.registries.AABB
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.frustum.Frustum
|
||||
import de.bixilon.minosoft.gui.rendering.camera.frustum.Frustum
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
|
@ -45,7 +45,7 @@ class EntityHitboxRenderer(
|
||||
) : Renderer, OpaqueDrawable, SkipAll {
|
||||
override val renderSystem: RenderSystem = renderWindow.renderSystem
|
||||
val profile = connection.profiles.entity.hitbox
|
||||
private val frustum = renderWindow.inputHandler.camera.frustum
|
||||
private val frustum = renderWindow.camera.matrixHandler.frustum
|
||||
private val meshes: LockMap<Entity, EntityHitbox> = lockMapOf()
|
||||
private val toUnload: MutableSet<EntityHitbox> = synchronizedSetOf()
|
||||
|
||||
|
@ -16,13 +16,13 @@ package de.bixilon.minosoft.gui.rendering.gui.hud.elements.other
|
||||
import de.bixilon.minosoft.config.profile.delegate.watcher.SimpleProfileDelegateWatcher.Companion.profileWatch
|
||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.EntityTarget
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.HUDRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.atlas.HUDAtlasElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.CustomHUDElement
|
||||
import de.bixilon.minosoft.gui.rendering.gui.hud.elements.HUDBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIMesh
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.EntityRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import de.bixilon.minosoft.util.collections.floats.DirectArrayFloatList
|
||||
@ -69,8 +69,8 @@ class CrosshairHUDElement(hudRenderer: HUDRenderer) : CustomHUDElement(hudRender
|
||||
|
||||
// Custom draw to make the crosshair inverted
|
||||
if (renderWindow.connection.player.gamemode == Gamemodes.SPECTATOR) {
|
||||
val hitResult = renderWindow.inputHandler.camera.target ?: return
|
||||
if (hitResult !is EntityRaycastHit && (hitResult !is BlockRaycastHit || renderWindow.connection.world.getBlockEntity(hitResult.blockPosition) == null)) {
|
||||
val hitResult = renderWindow.camera.targetHandler.target ?: return
|
||||
if (hitResult !is EntityTarget && (hitResult !is BlockTarget || renderWindow.connection.world.getBlockEntity(hitResult.blockPosition) == null)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -128,7 +128,7 @@ class DebugHUDElement(hudRenderer: HUDRenderer) : LayoutedHUDElement<GridLayout>
|
||||
layout += AutoTextElement(hudRenderer, 1) {
|
||||
val text = BaseComponent("Facing ")
|
||||
|
||||
Directions.byDirection(hudRenderer.renderWindow.inputHandler.camera.cameraFront).apply {
|
||||
Directions.byDirection(hudRenderer.renderWindow.camera.matrixHandler.cameraFront).apply {
|
||||
text += this
|
||||
text += " "
|
||||
text += vector
|
||||
@ -227,7 +227,7 @@ class DebugHUDElement(hudRenderer: HUDRenderer) : LayoutedHUDElement<GridLayout>
|
||||
|
||||
layout += LineSpacerElement(hudRenderer)
|
||||
|
||||
renderWindow.inputHandler.camera.apply {
|
||||
renderWindow.camera.targetHandler.apply {
|
||||
layout += AutoTextElement(hudRenderer, 1, HorizontalAlignments.RIGHT) {
|
||||
// ToDo: Tags
|
||||
target ?: "No target"
|
||||
|
@ -0,0 +1,148 @@
|
||||
package de.bixilon.minosoft.gui.rendering.input
|
||||
|
||||
import de.bixilon.minosoft.config.key.KeyAction
|
||||
import de.bixilon.minosoft.config.key.KeyBinding
|
||||
import de.bixilon.minosoft.config.key.KeyCodes
|
||||
import de.bixilon.minosoft.data.entities.EntityRotation
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.camera.MatrixHandler
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.MovementInput
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import glm_.glm
|
||||
import glm_.vec2.Vec2d
|
||||
|
||||
class CameraInput(
|
||||
private val renderWindow: RenderWindow,
|
||||
val matrixHandler: MatrixHandler,
|
||||
) {
|
||||
private val connection = renderWindow.connection
|
||||
private val player = connection.player
|
||||
private val controlsProfile = connection.profiles.controls
|
||||
|
||||
private val ignoreInput: Boolean
|
||||
get() {
|
||||
val entity = matrixHandler.entity
|
||||
if (entity != player) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun registerKeyBindings() {
|
||||
renderWindow.inputHandler.registerCheckCallback(
|
||||
MOVE_SPRINT_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_LEFT_CONTROL),
|
||||
),
|
||||
),
|
||||
MOVE_FORWARDS_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_W),
|
||||
),
|
||||
),
|
||||
MOVE_BACKWARDS_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_S),
|
||||
),
|
||||
),
|
||||
MOVE_LEFT_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_A),
|
||||
),
|
||||
),
|
||||
MOVE_RIGHT_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_D),
|
||||
),
|
||||
),
|
||||
FLY_UP_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_SPACE),
|
||||
),
|
||||
),
|
||||
FLY_DOWN_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_LEFT_SHIFT),
|
||||
),
|
||||
),
|
||||
JUMP_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_SPACE),
|
||||
),
|
||||
),
|
||||
SNEAK_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_LEFT_SHIFT),
|
||||
),
|
||||
),
|
||||
TOGGLE_FLY_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.DOUBLE_PRESS to setOf(KeyCodes.KEY_SPACE),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
renderWindow.inputHandler.registerKeyCallback(ZOOM_KEYBINDING, KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_C),
|
||||
),
|
||||
)) { matrixHandler.zoom = if (it) 2.0f else 0.0f }
|
||||
}
|
||||
|
||||
fun init() {
|
||||
registerKeyBindings()
|
||||
}
|
||||
|
||||
fun update() {
|
||||
val input = if (ignoreInput) {
|
||||
MovementInput()
|
||||
} else {
|
||||
MovementInput(
|
||||
pressingForward = renderWindow.inputHandler.isKeyBindingDown(MOVE_FORWARDS_KEYBINDING),
|
||||
pressingBack = renderWindow.inputHandler.isKeyBindingDown(MOVE_BACKWARDS_KEYBINDING),
|
||||
pressingLeft = renderWindow.inputHandler.isKeyBindingDown(MOVE_LEFT_KEYBINDING),
|
||||
pressingRight = renderWindow.inputHandler.isKeyBindingDown(MOVE_RIGHT_KEYBINDING),
|
||||
jumping = renderWindow.inputHandler.isKeyBindingDown(JUMP_KEYBINDING),
|
||||
sneaking = renderWindow.inputHandler.isKeyBindingDown(SNEAK_KEYBINDING),
|
||||
sprinting = renderWindow.inputHandler.isKeyBindingDown(MOVE_SPRINT_KEYBINDING),
|
||||
flyDown = renderWindow.inputHandler.isKeyBindingDown(FLY_DOWN_KEYBINDING),
|
||||
flyUp = renderWindow.inputHandler.isKeyBindingDown(FLY_UP_KEYBINDING),
|
||||
toggleFlyDown = renderWindow.inputHandler.isKeyBindingDown(TOGGLE_FLY_KEYBINDING),
|
||||
)
|
||||
}
|
||||
connection.player.input = input
|
||||
}
|
||||
|
||||
fun mouseCallback(delta: Vec2d) {
|
||||
delta *= 0.1f * controlsProfile.mouse.sensitivity
|
||||
var yaw = delta.x + player.rotation.yaw
|
||||
if (yaw > 180) {
|
||||
yaw -= 360
|
||||
} else if (yaw < -180) {
|
||||
yaw += 360
|
||||
}
|
||||
yaw %= 180
|
||||
val pitch = glm.clamp(delta.y + player.rotation.pitch, -89.9, 89.9)
|
||||
val rotation = EntityRotation(yaw, pitch)
|
||||
player.rotation = rotation
|
||||
}
|
||||
|
||||
private companion object {
|
||||
private val MOVE_SPRINT_KEYBINDING = "minosoft:move_sprint".toResourceLocation()
|
||||
private val MOVE_FORWARDS_KEYBINDING = "minosoft:move_forward".toResourceLocation()
|
||||
private val MOVE_BACKWARDS_KEYBINDING = "minosoft:move_backwards".toResourceLocation()
|
||||
private val MOVE_LEFT_KEYBINDING = "minosoft:move_left".toResourceLocation()
|
||||
private val MOVE_RIGHT_KEYBINDING = "minosoft:move_right".toResourceLocation()
|
||||
|
||||
private val SNEAK_KEYBINDING = "minosoft:move_sneak".toResourceLocation()
|
||||
private val JUMP_KEYBINDING = "minosoft:move_jump".toResourceLocation()
|
||||
|
||||
private val TOGGLE_FLY_KEYBINDING = "minosoft:move_toggle_fly".toResourceLocation()
|
||||
private val FLY_UP_KEYBINDING = "minosoft:move_fly_up".toResourceLocation()
|
||||
private val FLY_DOWN_KEYBINDING = "minosoft:move_fly_down".toResourceLocation()
|
||||
|
||||
private val ZOOM_KEYBINDING = "minosoft:zoom".toResourceLocation()
|
||||
}
|
||||
}
|
@ -1,477 +0,0 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 Moritz Zwerger, Lukas Eisenhauer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.input.camera
|
||||
|
||||
import de.bixilon.minosoft.config.key.KeyAction
|
||||
import de.bixilon.minosoft.config.key.KeyBinding
|
||||
import de.bixilon.minosoft.config.key.KeyCodes
|
||||
import de.bixilon.minosoft.data.entities.EntityRotation
|
||||
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.fluid.DefaultFluids
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.world.view.ViewDistanceChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.frustum.Frustum
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.EntityRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.FluidRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.RaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.CameraMatrixChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.CameraPositionChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.FrustumChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.ResizeWindowEvent
|
||||
import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.floor
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.getWorldOffset
|
||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.PlayerActionC2SP
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.KUtil
|
||||
import de.bixilon.minosoft.util.KUtil.decide
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
import de.bixilon.minosoft.util.Previous
|
||||
import glm_.func.rad
|
||||
import glm_.glm
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.mat4x4.Mat4d
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec2.Vec2d
|
||||
import glm_.vec3.Vec3d
|
||||
|
||||
class Camera(
|
||||
val connection: PlayConnection,
|
||||
val renderWindow: RenderWindow,
|
||||
) {
|
||||
private val profile = connection.profiles.rendering.camera
|
||||
private val controlsProfile = connection.profiles.controls
|
||||
var fogColor = Previous(ChatColors.GREEN)
|
||||
var fogStart = connection.world.view.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() // ToDo
|
||||
|
||||
private var zoom = 0.0f
|
||||
|
||||
var cameraFront = Vec3d(0.0, 0.0, -1.0)
|
||||
var cameraRight = Vec3d(0.0, 0.0, -1.0)
|
||||
private var cameraUp = Vec3d(0.0, 1.0, 0.0)
|
||||
|
||||
// ToDo: They should also be available in headless mode
|
||||
var nonFluidTarget: RaycastHit? = null
|
||||
private set
|
||||
var target: RaycastHit? = null
|
||||
private set
|
||||
var blockTarget: BlockRaycastHit? = null // Block target or if blocked by entity null
|
||||
private set
|
||||
var fluidTarget: FluidRaycastHit? = null
|
||||
private set
|
||||
var entityTarget: EntityRaycastHit? = null
|
||||
private set
|
||||
|
||||
private val fov: Double
|
||||
get() {
|
||||
val fov = profile.fov / (zoom + 1.0)
|
||||
|
||||
if (!profile.dynamicFOV) {
|
||||
return fov
|
||||
}
|
||||
return fov * connection.player.fovMultiplier.interpolate()
|
||||
}
|
||||
|
||||
|
||||
var viewMatrix = calculateViewMatrix()
|
||||
private set
|
||||
var projectionMatrix = calculateProjectionMatrix(renderWindow.window.sizef)
|
||||
private set
|
||||
var viewProjectionMatrix = projectionMatrix * viewMatrix
|
||||
private set
|
||||
|
||||
|
||||
var previousEyePosition = Vec3d(connection.player.position)
|
||||
var previousRotation = connection.player.rotation.copy()
|
||||
var previousZoom = zoom
|
||||
|
||||
private var lastDropPacketSent = -1L
|
||||
|
||||
val frustum: Frustum = Frustum(this)
|
||||
|
||||
|
||||
fun mouseCallback(delta: Vec2d) {
|
||||
delta *= 0.1f * controlsProfile.mouse.sensitivity
|
||||
var yaw = delta.x + connection.player.rotation.yaw
|
||||
if (yaw > 180) {
|
||||
yaw -= 360
|
||||
} else if (yaw < -180) {
|
||||
yaw += 360
|
||||
}
|
||||
yaw %= 180
|
||||
val pitch = glm.clamp(delta.y + connection.player.rotation.pitch, -89.9, 89.9)
|
||||
val rotation = EntityRotation(yaw, pitch)
|
||||
connection.player.rotation = rotation
|
||||
setRotation(rotation)
|
||||
}
|
||||
|
||||
private fun calculateFogDistance() {
|
||||
if (!connection.profiles.rendering.fog.enabled) {
|
||||
fogStart = Float.MAX_VALUE
|
||||
return
|
||||
}
|
||||
|
||||
fogStart = if (connection.player.submergedFluid?.resourceLocation == DefaultFluids.WATER) {
|
||||
10.0f
|
||||
} else {
|
||||
connection.world.view.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() // ToDo
|
||||
}
|
||||
}
|
||||
|
||||
private fun applyFog() {
|
||||
for (shader in renderWindow.renderSystem.shaders) {
|
||||
if (!shader.uniforms.contains("uFogColor")) {
|
||||
continue
|
||||
|
||||
}
|
||||
shader.use()
|
||||
|
||||
shader.setFloat("uFogStart", fogStart)
|
||||
shader.setFloat("uFogEnd", fogStart + 10.0f)
|
||||
shader["uFogColor"] = fogColor
|
||||
}
|
||||
fogColor.assign()
|
||||
}
|
||||
|
||||
fun init(renderWindow: RenderWindow) {
|
||||
renderWindow.inputHandler.registerCheckCallback(
|
||||
MOVE_SPRINT_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_LEFT_CONTROL),
|
||||
),
|
||||
),
|
||||
MOVE_FORWARDS_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_W),
|
||||
),
|
||||
),
|
||||
MOVE_BACKWARDS_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_S),
|
||||
),
|
||||
),
|
||||
MOVE_LEFT_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_A),
|
||||
),
|
||||
),
|
||||
MOVE_RIGHT_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_D),
|
||||
),
|
||||
),
|
||||
FLY_UP_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_SPACE),
|
||||
),
|
||||
),
|
||||
FLY_DOWN_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_LEFT_SHIFT),
|
||||
),
|
||||
),
|
||||
ZOOM_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_C),
|
||||
),
|
||||
),
|
||||
JUMP_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_SPACE),
|
||||
),
|
||||
),
|
||||
SNEAK_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.CHANGE to setOf(KeyCodes.KEY_LEFT_SHIFT),
|
||||
),
|
||||
),
|
||||
TOGGLE_FLY_KEYBINDING to KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.DOUBLE_PRESS to setOf(KeyCodes.KEY_SPACE),
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
connection.registerEvent(CallbackEventInvoker.of<ResizeWindowEvent> { recalculateViewProjectionMatrix() })
|
||||
|
||||
connection.registerEvent(CallbackEventInvoker.of<ViewDistanceChangeEvent> { it.viewDistance * ProtocolDefinition.SECTION_WIDTH_X.toFloat() }) // ToDo
|
||||
|
||||
fun dropItem(stack: Boolean) {
|
||||
val time = KUtil.time
|
||||
if (time - lastDropPacketSent < ProtocolDefinition.TICK_TIME) {
|
||||
return
|
||||
}
|
||||
val type = if (stack) {
|
||||
connection.player.inventory.getHotbarSlot()?.count = 0
|
||||
PlayerActionC2SP.Actions.DROP_ITEM_STACK
|
||||
} else {
|
||||
connection.player.inventory.getHotbarSlot()?.let {
|
||||
it.count--
|
||||
}
|
||||
PlayerActionC2SP.Actions.DROP_ITEM
|
||||
}
|
||||
connection.sendPacket(PlayerActionC2SP(type))
|
||||
lastDropPacketSent = time
|
||||
}
|
||||
|
||||
// ToDo: This has nothing todo with the camera, should be in the interaction manager
|
||||
renderWindow.inputHandler.registerKeyCallback(DROP_ITEM_STACK_KEYBINDING, KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.PRESS to setOf(KeyCodes.KEY_Q),
|
||||
KeyAction.MODIFIER to setOf(KeyCodes.KEY_LEFT_CONTROL)
|
||||
),
|
||||
)) { dropItem(true) }
|
||||
renderWindow.inputHandler.registerKeyCallback(DROP_ITEM_KEYBINDING, KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.PRESS to setOf(KeyCodes.KEY_Q),
|
||||
),
|
||||
)) { dropItem(false) }
|
||||
frustum.recalculate()
|
||||
connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
|
||||
}
|
||||
|
||||
private fun recalculateViewProjectionMatrix() {
|
||||
viewMatrix = calculateViewMatrix()
|
||||
projectionMatrix = calculateProjectionMatrix(renderWindow.window.sizef)
|
||||
viewProjectionMatrix = projectionMatrix * viewMatrix
|
||||
connection.fireEvent(CameraMatrixChangeEvent(
|
||||
renderWindow = renderWindow,
|
||||
viewMatrix = viewMatrix,
|
||||
projectionMatrix = projectionMatrix,
|
||||
viewProjectionMatrix = viewProjectionMatrix,
|
||||
))
|
||||
|
||||
for (shader in renderWindow.renderSystem.shaders) {
|
||||
shader.use()
|
||||
if (shader.uniforms.contains("uViewProjectionMatrix")) {
|
||||
shader.setMat4("uViewProjectionMatrix", Mat4(viewProjectionMatrix))
|
||||
}
|
||||
if (shader.uniforms.contains("uCameraPosition")) {
|
||||
shader.setVec3("uCameraPosition", connection.player.cameraPosition)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun onPositionChange() {
|
||||
setRotation(connection.player.rotation)
|
||||
recalculateViewProjectionMatrix()
|
||||
frustum.recalculate()
|
||||
connection.fireEvent(FrustumChangeEvent(renderWindow, frustum))
|
||||
connection.fireEvent(CameraPositionChangeEvent(renderWindow, connection.player.eyePosition))
|
||||
|
||||
previousEyePosition = Vec3d(connection.player.eyePosition)
|
||||
previousRotation = connection.player.rotation.copy()
|
||||
previousZoom = zoom
|
||||
|
||||
setSkyColor()
|
||||
}
|
||||
|
||||
private fun setSkyColor() {
|
||||
renderWindow[SkyRenderer]?.let { skyRenderer ->
|
||||
skyRenderer.baseColor = connection.world.getBiome(connection.player.positionInfo.blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR
|
||||
|
||||
|
||||
connection.world.dimension?.hasSkyLight?.let {
|
||||
if (it) {
|
||||
skyRenderer.baseColor = connection.player.positionInfo.biome?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR
|
||||
} else {
|
||||
skyRenderer.baseColor = RenderConstants.BLACK_COLOR
|
||||
}
|
||||
} ?: let { skyRenderer.baseColor = RenderConstants.DEFAULT_SKY_COLOR }
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateProjectionMatrix(screenDimensions: Vec2): Mat4d {
|
||||
return glm.perspective(fov.rad, screenDimensions.x.toDouble() / screenDimensions.y, 0.01, 10000.0)
|
||||
}
|
||||
|
||||
private fun calculateViewMatrix(): Mat4d {
|
||||
val eyePosition = connection.player.eyePosition
|
||||
return glm.lookAt(eyePosition, eyePosition + cameraFront, CAMERA_UP_VEC3)
|
||||
}
|
||||
|
||||
private fun setRotation(rotation: EntityRotation) {
|
||||
cameraFront = rotation.front
|
||||
|
||||
cameraRight = (cameraFront cross CAMERA_UP_VEC3).normalize()
|
||||
cameraUp = (cameraRight cross cameraFront).normalize()
|
||||
recalculateViewProjectionMatrix()
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
calculateFogDistance()
|
||||
if (!fogColor.equals()) {
|
||||
applyFog()
|
||||
}
|
||||
//val input = if (renderWindow.inputHandler.currentKeyConsumer == null) {
|
||||
val input = MovementInput(
|
||||
pressingForward = renderWindow.inputHandler.isKeyBindingDown(MOVE_FORWARDS_KEYBINDING),
|
||||
pressingBack = renderWindow.inputHandler.isKeyBindingDown(MOVE_BACKWARDS_KEYBINDING),
|
||||
pressingLeft = renderWindow.inputHandler.isKeyBindingDown(MOVE_LEFT_KEYBINDING),
|
||||
pressingRight = renderWindow.inputHandler.isKeyBindingDown(MOVE_RIGHT_KEYBINDING),
|
||||
jumping = renderWindow.inputHandler.isKeyBindingDown(JUMP_KEYBINDING),
|
||||
sneaking = renderWindow.inputHandler.isKeyBindingDown(SNEAK_KEYBINDING),
|
||||
sprinting = renderWindow.inputHandler.isKeyBindingDown(MOVE_SPRINT_KEYBINDING),
|
||||
flyDown = renderWindow.inputHandler.isKeyBindingDown(FLY_DOWN_KEYBINDING),
|
||||
flyUp = renderWindow.inputHandler.isKeyBindingDown(FLY_UP_KEYBINDING),
|
||||
toggleFlyDown = renderWindow.inputHandler.isKeyBindingDown(TOGGLE_FLY_KEYBINDING),
|
||||
)
|
||||
//} else {
|
||||
// MovementInput()
|
||||
// }
|
||||
connection.player.input = input
|
||||
connection.player.tick() // The thread pool might be busy, we force a tick here to avoid lagging
|
||||
|
||||
zoom = if (renderWindow.inputHandler.isKeyBindingDown(ZOOM_KEYBINDING)) {
|
||||
2f
|
||||
} else {
|
||||
0.0f
|
||||
}
|
||||
|
||||
val eyePosition = connection.player.eyePosition
|
||||
|
||||
if (previousEyePosition != eyePosition || previousRotation != connection.player.rotation || zoom != previousZoom) {
|
||||
onPositionChange()
|
||||
} else {
|
||||
setSkyColor()
|
||||
}
|
||||
|
||||
val cameraFront = cameraFront
|
||||
|
||||
target = raycast(eyePosition, cameraFront, blocks = true, fluids = true, entities = true)
|
||||
nonFluidTarget = raycast(eyePosition, cameraFront, blocks = true, fluids = false, entities = true)
|
||||
blockTarget = raycast(eyePosition, cameraFront, blocks = true, fluids = false, entities = false) as BlockRaycastHit?
|
||||
fluidTarget = raycast(eyePosition, cameraFront, blocks = false, fluids = true, entities = false) as FluidRaycastHit?
|
||||
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? {
|
||||
if (!blocks && !fluids && entities) {
|
||||
// only raycast entities
|
||||
return raycastEntity(origin, direction)
|
||||
}
|
||||
val currentPosition = Vec3d(origin)
|
||||
|
||||
fun getTotalDistance(): Double {
|
||||
return (origin - currentPosition).length()
|
||||
}
|
||||
|
||||
var hit: RaycastHit? = null
|
||||
for (i in 0..RAYCAST_MAX_STEPS) {
|
||||
val blockPosition = currentPosition.floor
|
||||
val blockState = connection.world[blockPosition]
|
||||
|
||||
if (blockState == null) {
|
||||
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
|
||||
continue
|
||||
}
|
||||
val voxelShapeRaycastResult = (blockState.block.getOutlineShape(connection, blockState, blockPosition) + blockPosition + blockPosition.getWorldOffset(blockState.block)).raycast(currentPosition, direction)
|
||||
if (voxelShapeRaycastResult.hit) {
|
||||
val distance = getTotalDistance()
|
||||
currentPosition += direction * voxelShapeRaycastResult.distance
|
||||
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
|
||||
|
||||
if (blockState.block is FluidBlock) {
|
||||
if (!fluids) {
|
||||
continue
|
||||
}
|
||||
hit = FluidRaycastHit(
|
||||
currentPosition,
|
||||
distance,
|
||||
voxelShapeRaycastResult.direction,
|
||||
blockState,
|
||||
blockPosition,
|
||||
blockState.block.fluid,
|
||||
)
|
||||
break
|
||||
}
|
||||
|
||||
if (!blocks) {
|
||||
continue
|
||||
}
|
||||
hit = BlockRaycastHit(
|
||||
currentPosition,
|
||||
distance,
|
||||
voxelShapeRaycastResult.direction,
|
||||
blockState,
|
||||
blockPosition,
|
||||
)
|
||||
break
|
||||
} else {
|
||||
currentPosition += direction * (VecUtil.getDistanceToNextIntegerAxisInDirection(currentPosition, direction) + 0.001)
|
||||
}
|
||||
}
|
||||
|
||||
if (entities) {
|
||||
val entityRaycastHit = raycastEntity(origin, direction) ?: return hit
|
||||
hit ?: return null
|
||||
return (entityRaycastHit.distance < hit.distance).decide(entityRaycastHit, hit)
|
||||
}
|
||||
|
||||
return hit
|
||||
}
|
||||
|
||||
companion object {
|
||||
val CAMERA_UP_VEC3 = Vec3d(0.0, 1.0, 0.0)
|
||||
|
||||
private const val RAYCAST_MAX_STEPS = 100
|
||||
|
||||
private val MOVE_SPRINT_KEYBINDING = "minosoft:move_sprint".toResourceLocation()
|
||||
private val MOVE_FORWARDS_KEYBINDING = "minosoft:move_forward".toResourceLocation()
|
||||
private val MOVE_BACKWARDS_KEYBINDING = "minosoft:move_backwards".toResourceLocation()
|
||||
private val MOVE_LEFT_KEYBINDING = "minosoft:move_left".toResourceLocation()
|
||||
private val MOVE_RIGHT_KEYBINDING = "minosoft:move_right".toResourceLocation()
|
||||
|
||||
private val SNEAK_KEYBINDING = "minosoft:move_sneak".toResourceLocation()
|
||||
private val JUMP_KEYBINDING = "minosoft:move_jump".toResourceLocation()
|
||||
|
||||
private val TOGGLE_FLY_KEYBINDING = "minosoft:move_toggle_fly".toResourceLocation()
|
||||
private val FLY_UP_KEYBINDING = "minosoft:move_fly_up".toResourceLocation()
|
||||
private val FLY_DOWN_KEYBINDING = "minosoft:move_fly_down".toResourceLocation()
|
||||
|
||||
private val ZOOM_KEYBINDING = "minosoft:zoom".toResourceLocation()
|
||||
|
||||
|
||||
private val DROP_ITEM_KEYBINDING = "minosoft:drop_item".toResourceLocation()
|
||||
private val DROP_ITEM_STACK_KEYBINDING = "minosoft:drop_item_stack".toResourceLocation()
|
||||
}
|
||||
}
|
@ -24,7 +24,7 @@ import de.bixilon.minosoft.data.registries.enchantment.DefaultEnchantments
|
||||
import de.bixilon.minosoft.data.registries.fluid.DefaultFluids
|
||||
import de.bixilon.minosoft.data.registries.items.tools.MiningToolItem
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.modding.event.events.BlockBreakAckEvent
|
||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.ArmSwingC2SP
|
||||
@ -98,9 +98,9 @@ class BreakInteractionHandler(
|
||||
cancelDigging()
|
||||
return false
|
||||
}
|
||||
val raycastHit = renderWindow.inputHandler.camera.nonFluidTarget
|
||||
val raycastHit = renderWindow.camera.targetHandler.target
|
||||
|
||||
if (raycastHit !is BlockRaycastHit) {
|
||||
if (raycastHit !is BlockTarget) {
|
||||
cancelDigging()
|
||||
return false
|
||||
}
|
||||
@ -120,7 +120,7 @@ class BreakInteractionHandler(
|
||||
if (breakPosition != null) {
|
||||
return
|
||||
}
|
||||
connection.sendPacket(PlayerActionC2SP(PlayerActionC2SP.Actions.START_DIGGING, raycastHit.blockPosition, raycastHit.hitDirection))
|
||||
connection.sendPacket(PlayerActionC2SP(PlayerActionC2SP.Actions.START_DIGGING, raycastHit.blockPosition, raycastHit.direction))
|
||||
|
||||
breakPosition = raycastHit.blockPosition
|
||||
breakBlockState = raycastHit.blockState
|
||||
@ -130,7 +130,7 @@ class BreakInteractionHandler(
|
||||
}
|
||||
|
||||
fun finishDigging() {
|
||||
connection.sendPacket(PlayerActionC2SP(PlayerActionC2SP.Actions.FINISHED_DIGGING, raycastHit.blockPosition, raycastHit.hitDirection))
|
||||
connection.sendPacket(PlayerActionC2SP(PlayerActionC2SP.Actions.FINISHED_DIGGING, raycastHit.blockPosition, raycastHit.direction))
|
||||
clearDigging()
|
||||
connection.world.setBlockState(raycastHit.blockPosition, null)
|
||||
|
||||
|
@ -0,0 +1,57 @@
|
||||
package de.bixilon.minosoft.gui.rendering.input.interaction
|
||||
|
||||
import de.bixilon.minosoft.config.key.KeyAction
|
||||
import de.bixilon.minosoft.config.key.KeyBinding
|
||||
import de.bixilon.minosoft.config.key.KeyCodes
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.protocol.RateLimiter
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.PlayerActionC2SP
|
||||
import de.bixilon.minosoft.util.KUtil
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
|
||||
class DropInteractionManager(
|
||||
private val renderWindow: RenderWindow,
|
||||
) {
|
||||
private val connection = renderWindow.connection
|
||||
private val rateLimiter = RateLimiter()
|
||||
|
||||
fun init() {
|
||||
// ToDo: This creates a weird condition, because we first drop the stack and then the single item
|
||||
// ToDo: Does this swing the arm?
|
||||
renderWindow.inputHandler.registerKeyCallback(DROP_ITEM_STACK_KEYBINDING, KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.PRESS to setOf(KeyCodes.KEY_Q),
|
||||
KeyAction.MODIFIER to setOf(KeyCodes.KEY_LEFT_CONTROL)
|
||||
),
|
||||
)) { dropItem(true) }
|
||||
renderWindow.inputHandler.registerKeyCallback(DROP_ITEM_KEYBINDING, KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.PRESS to setOf(KeyCodes.KEY_Q),
|
||||
),
|
||||
)) { dropItem(false) }
|
||||
}
|
||||
|
||||
|
||||
fun dropItem(stack: Boolean) {
|
||||
val time = KUtil.time
|
||||
val type = if (stack) {
|
||||
connection.player.inventory.getHotbarSlot()?.count = 0
|
||||
PlayerActionC2SP.Actions.DROP_ITEM_STACK
|
||||
} else {
|
||||
connection.player.inventory.getHotbarSlot()?.let {
|
||||
it.count--
|
||||
}
|
||||
PlayerActionC2SP.Actions.DROP_ITEM
|
||||
}
|
||||
rateLimiter += { connection.sendPacket(PlayerActionC2SP(type)) }
|
||||
}
|
||||
|
||||
fun draw(delta: Double) {
|
||||
rateLimiter.work()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val DROP_ITEM_KEYBINDING = "minosoft:drop_item".toResourceLocation()
|
||||
private val DROP_ITEM_STACK_KEYBINDING = "minosoft:drop_item_stack".toResourceLocation()
|
||||
}
|
||||
}
|
@ -21,8 +21,8 @@ import de.bixilon.minosoft.data.inventory.ItemStack
|
||||
import de.bixilon.minosoft.data.player.Hands
|
||||
import de.bixilon.minosoft.data.registries.items.UsableItem
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.EntityRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.EntityTarget
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.BlockInteractC2SP
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.ItemUseC2SP
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.PlayerActionC2SP
|
||||
@ -71,16 +71,16 @@ class InteractInteractionHandler(
|
||||
interactingTicksLeft = 0
|
||||
}
|
||||
|
||||
fun interactBlock(hit: BlockRaycastHit, item: ItemStack?, hand: Hands): InteractionResults {
|
||||
if (hit.distance >= connection.player.reachDistance) {
|
||||
fun interactBlock(target: BlockTarget, item: ItemStack?, hand: Hands): InteractionResults {
|
||||
if (target.distance >= connection.player.reachDistance) {
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
// if out of world (border): return CONSUME
|
||||
|
||||
connection.sendPacket(BlockInteractC2SP(
|
||||
position = hit.blockPosition,
|
||||
direction = hit.hitDirection,
|
||||
cursorPosition = Vec3(hit.hitPosition),
|
||||
position = target.blockPosition,
|
||||
direction = target.direction,
|
||||
cursorPosition = Vec3(target.hitPosition),
|
||||
item = item,
|
||||
hand = hand,
|
||||
insideBlock = false, // ToDo: insideBlock
|
||||
@ -90,7 +90,7 @@ class InteractInteractionHandler(
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
|
||||
val result = hit.blockState.block.onUse(connection, hit, hand, item)
|
||||
val result = target.blockState.block.onUse(connection, target, hand, item)
|
||||
if (result == InteractionResults.SUCCESS) {
|
||||
return InteractionResults.SUCCESS
|
||||
}
|
||||
@ -102,13 +102,13 @@ class InteractInteractionHandler(
|
||||
return InteractionResults.PASS // ToDo: Check
|
||||
}
|
||||
|
||||
return item.item.interactBlock(connection, hit, hand, item)
|
||||
return item.item.interactBlock(connection, target, hand, item)
|
||||
}
|
||||
|
||||
fun interactEntityAt(hit: EntityRaycastHit, hand: Hands): InteractionResults {
|
||||
fun interactEntityAt(target: EntityTarget, hand: Hands): InteractionResults {
|
||||
// used in armor stands
|
||||
val player = connection.player
|
||||
connection.sendPacket(EntityInteractAtC2SP(connection, hit.entity, Vec3(hit.position), hand, player.isSneaking))
|
||||
connection.sendPacket(EntityInteractAtC2SP(connection, target.entity, Vec3(target.position), hand, player.isSneaking))
|
||||
|
||||
if (player.gamemode == Gamemodes.SPECTATOR) {
|
||||
return InteractionResults.PASS
|
||||
@ -117,9 +117,9 @@ class InteractInteractionHandler(
|
||||
return InteractionResults.PASS
|
||||
}
|
||||
|
||||
fun interactEntity(hit: EntityRaycastHit, hand: Hands): InteractionResults {
|
||||
fun interactEntity(target: EntityTarget, hand: Hands): InteractionResults {
|
||||
val player = connection.player
|
||||
connection.sendPacket(EntityInteractC2SP(connection, hit.entity, hand, player.isSneaking))
|
||||
connection.sendPacket(EntityInteractC2SP(connection, target.entity, hand, player.isSneaking))
|
||||
|
||||
if (player.gamemode == Gamemodes.SPECTATOR) {
|
||||
return InteractionResults.PASS
|
||||
@ -155,12 +155,12 @@ class InteractInteractionHandler(
|
||||
// if riding: return
|
||||
|
||||
val selectedSlot = connection.player.selectedHotbarSlot
|
||||
val target = renderWindow.inputHandler.camera.nonFluidTarget
|
||||
val target = renderWindow.camera.targetHandler.target
|
||||
|
||||
for (hand in Hands.VALUES) {
|
||||
val item = connection.player.inventory[hand]
|
||||
when (target) {
|
||||
is EntityRaycastHit -> {
|
||||
is EntityTarget -> {
|
||||
var result = interactEntityAt(target, hand)
|
||||
|
||||
if (result == InteractionResults.PASS) {
|
||||
@ -175,7 +175,7 @@ class InteractInteractionHandler(
|
||||
return
|
||||
}
|
||||
}
|
||||
is BlockRaycastHit -> {
|
||||
is BlockTarget -> {
|
||||
val result = interactBlock(target, item, hand)
|
||||
if (result == InteractionResults.SUCCESS) {
|
||||
interactionManager.swingHand(hand)
|
||||
|
@ -28,6 +28,8 @@ class InteractionManager(
|
||||
val attack = AttackInteractionHandler(renderWindow)
|
||||
val `break` = BreakInteractionHandler(renderWindow)
|
||||
val use = InteractInteractionHandler(renderWindow, this)
|
||||
val drop = DropInteractionManager(renderWindow)
|
||||
val spectate = SpectateInteractionManager(renderWindow)
|
||||
|
||||
private val swingArmRateLimiter = RateLimiter()
|
||||
|
||||
@ -38,6 +40,8 @@ class InteractionManager(
|
||||
pick.init()
|
||||
`break`.init()
|
||||
use.init()
|
||||
drop.init()
|
||||
spectate.init()
|
||||
}
|
||||
|
||||
fun draw(delta: Double) {
|
||||
@ -46,6 +50,8 @@ class InteractionManager(
|
||||
// attack.draw(delta)
|
||||
`break`.draw(delta)
|
||||
use.draw(delta)
|
||||
drop.draw(delta)
|
||||
spectate.draw(delta)
|
||||
|
||||
swingArmRateLimiter.work()
|
||||
}
|
||||
|
@ -20,8 +20,8 @@ import de.bixilon.minosoft.data.inventory.InventorySlots
|
||||
import de.bixilon.minosoft.data.inventory.ItemStack
|
||||
import de.bixilon.minosoft.data.registries.other.containers.PlayerInventory
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.EntityRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.EntityTarget
|
||||
import de.bixilon.minosoft.protocol.RateLimiter
|
||||
import de.bixilon.minosoft.protocol.packets.c2s.play.ItemStackCreateC2SP
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
@ -48,25 +48,25 @@ class ItemPickInteractionHandler(
|
||||
if (!connection.player.baseAbilities.creative) {
|
||||
return
|
||||
}
|
||||
val raycast = renderWindow.inputHandler.camera.nonFluidTarget ?: return
|
||||
val target = renderWindow.camera.targetHandler.target ?: return
|
||||
|
||||
if (raycast.distance > connection.player.reachDistance) {
|
||||
if (target.distance > connection.player.reachDistance) {
|
||||
return
|
||||
}
|
||||
|
||||
val itemStack: ItemStack?
|
||||
|
||||
when (raycast) {
|
||||
is BlockRaycastHit -> {
|
||||
itemStack = ItemStack(raycast.blockState.block.item!!, connection, 1)
|
||||
when (target) {
|
||||
is BlockTarget -> {
|
||||
itemStack = ItemStack(target.blockState.block.item!!, connection, 1)
|
||||
|
||||
if (copyNBT) {
|
||||
val blockEntity = connection.world.getBlockEntity(raycast.blockPosition)
|
||||
val blockEntity = connection.world.getBlockEntity(target.blockPosition)
|
||||
blockEntity?.nbt?.let { itemStack.nbt.putAll(it) }
|
||||
}
|
||||
}
|
||||
is EntityRaycastHit -> {
|
||||
val entity = raycast.entity
|
||||
is EntityTarget -> {
|
||||
val entity = target.entity
|
||||
itemStack = entity.entityType.spawnEgg?.let { ItemStack(it, connection) } ?: let {
|
||||
entity.equipment[InventorySlots.EquipmentSlots.MAIN_HAND]?.copy()
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
package de.bixilon.minosoft.gui.rendering.input.interaction
|
||||
|
||||
import de.bixilon.minosoft.config.key.KeyAction
|
||||
import de.bixilon.minosoft.config.key.KeyBinding
|
||||
import de.bixilon.minosoft.config.key.KeyCodes
|
||||
import de.bixilon.minosoft.data.abilities.Gamemodes
|
||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
import de.bixilon.minosoft.data.registries.other.game.event.handlers.gamemode.GamemodeChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.modding.event.events.CameraSetEvent
|
||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||
import de.bixilon.minosoft.protocol.RateLimiter
|
||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||
|
||||
class SpectateInteractionManager(
|
||||
private val renderWindow: RenderWindow,
|
||||
) {
|
||||
private val connection = renderWindow.connection
|
||||
private val rateLimiter = RateLimiter()
|
||||
|
||||
fun init() {
|
||||
renderWindow.inputHandler.registerKeyCallback(STOP_SPECTATING, KeyBinding(
|
||||
mapOf(
|
||||
KeyAction.PRESS to setOf(KeyCodes.KEY_LEFT_SHIFT),
|
||||
),
|
||||
)) { spectate(null) }
|
||||
|
||||
renderWindow.connection.registerEvent(CallbackEventInvoker.of<GamemodeChangeEvent> { spectate(null) })
|
||||
renderWindow.connection.registerEvent(CallbackEventInvoker.of<CameraSetEvent> { spectate(it.entity) })
|
||||
}
|
||||
|
||||
|
||||
fun spectate(entity: Entity?) {
|
||||
var entity = entity ?: connection.player
|
||||
if (connection.player.gamemode != Gamemodes.SPECTATOR) {
|
||||
entity = connection.player
|
||||
}
|
||||
renderWindow.camera.matrixHandler.entity = entity
|
||||
}
|
||||
|
||||
fun draw(delta: Double) {
|
||||
rateLimiter.work()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private val STOP_SPECTATING = "minosoft:stop_spectating".toResourceLocation()
|
||||
}
|
||||
}
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.config.profile.delegate.watcher.entry.MapProfileDeleg
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.Camera
|
||||
import de.bixilon.minosoft.gui.rendering.input.CameraInput
|
||||
import de.bixilon.minosoft.gui.rendering.input.interaction.InteractionManager
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.input.MouseMoveEvent
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.input.RawCharInputEvent
|
||||
@ -38,7 +38,7 @@ class RenderWindowInputHandler(
|
||||
val renderWindow: RenderWindow,
|
||||
) {
|
||||
val connection: PlayConnection = renderWindow.connection
|
||||
val camera: Camera = Camera(connection, renderWindow)
|
||||
val cameraInput = CameraInput(renderWindow, renderWindow.camera.matrixHandler)
|
||||
private val profile = connection.profiles.controls
|
||||
|
||||
private val keyBindingCallbacks: MutableMap<ResourceLocation, KeyBindingCallbackPair> = mutableMapOf()
|
||||
@ -80,7 +80,8 @@ class RenderWindowInputHandler(
|
||||
//if (renderWindow.inputHandler.currentKeyConsumer != null) {
|
||||
// return
|
||||
//}
|
||||
camera.mouseCallback(it.delta)
|
||||
|
||||
cameraInput.mouseCallback(it.delta)
|
||||
})
|
||||
|
||||
profile::keyBindings.profileWatchMap(this, profile = profile) {
|
||||
@ -93,6 +94,7 @@ class RenderWindowInputHandler(
|
||||
keyBinding.keyBinding = it.valueAdded
|
||||
}
|
||||
}
|
||||
cameraInput.init()
|
||||
}
|
||||
|
||||
|
||||
@ -275,8 +277,7 @@ class RenderWindowInputHandler(
|
||||
}
|
||||
|
||||
fun draw(delta: Double) {
|
||||
camera.draw()
|
||||
|
||||
cameraInput.update()
|
||||
interactionManager.draw(delta)
|
||||
}
|
||||
}
|
||||
|
@ -15,20 +15,20 @@ package de.bixilon.minosoft.gui.rendering.modding.events
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.Rendering
|
||||
import glm_.mat4x4.Mat4d
|
||||
import glm_.mat4x4.Mat4
|
||||
|
||||
class CameraMatrixChangeEvent(
|
||||
renderWindow: RenderWindow = Rendering.currentContext!!,
|
||||
viewMatrix: Mat4d,
|
||||
projectionMatrix: Mat4d,
|
||||
viewProjectionMatrix: Mat4d,
|
||||
viewMatrix: Mat4,
|
||||
projectionMatrix: Mat4,
|
||||
viewProjectionMatrix: Mat4,
|
||||
) : RenderEvent(renderWindow) {
|
||||
val viewMatrix: Mat4d = viewMatrix
|
||||
get() = Mat4d(field)
|
||||
val viewMatrix: Mat4 = viewMatrix
|
||||
get() = Mat4(field)
|
||||
|
||||
val projectionMatrix: Mat4d = projectionMatrix
|
||||
get() = Mat4d(field)
|
||||
val projectionMatrix: Mat4 = projectionMatrix
|
||||
get() = Mat4(field)
|
||||
|
||||
val viewProjectionMatrix: Mat4d = viewProjectionMatrix
|
||||
get() = Mat4d(field)
|
||||
val viewProjectionMatrix: Mat4 = viewProjectionMatrix
|
||||
get() = Mat4(field)
|
||||
}
|
||||
|
@ -15,12 +15,12 @@ package de.bixilon.minosoft.gui.rendering.modding.events
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.Rendering
|
||||
import glm_.vec3.Vec3d
|
||||
import glm_.vec3.Vec3
|
||||
|
||||
class CameraPositionChangeEvent(
|
||||
renderWindow: RenderWindow = Rendering.currentContext!!,
|
||||
newPosition: Vec3d,
|
||||
newPosition: Vec3,
|
||||
) : RenderEvent(renderWindow) {
|
||||
val newPosition: Vec3d = newPosition
|
||||
get() = Vec3d(field)
|
||||
val newPosition: Vec3 = newPosition
|
||||
get() = Vec3(field)
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.modding.events
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.Rendering
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.frustum.Frustum
|
||||
import de.bixilon.minosoft.gui.rendering.camera.frustum.Frustum
|
||||
|
||||
class FrustumChangeEvent(
|
||||
renderWindow: RenderWindow = Rendering.currentContext!!,
|
||||
|
@ -14,7 +14,6 @@
|
||||
package de.bixilon.minosoft.gui.rendering.sky
|
||||
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.registries.fluid.DefaultFluids
|
||||
import de.bixilon.minosoft.data.text.ChatColors
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
@ -35,9 +34,7 @@ import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import glm_.func.rad
|
||||
import glm_.mat4x4.Mat4
|
||||
import glm_.mat4x4.Mat4d
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3d
|
||||
|
||||
class SkyRenderer(
|
||||
private val connection: PlayConnection,
|
||||
@ -49,7 +46,7 @@ class SkyRenderer(
|
||||
private val skyboxMesh = SkyboxMesh(renderWindow)
|
||||
private var skySunMesh = SimpleTextureMesh(renderWindow)
|
||||
private lateinit var sunTexture: AbstractTexture
|
||||
private var sunMatrixUpToDate: Boolean = true
|
||||
private var updateSun: Boolean = true
|
||||
var baseColor = RenderConstants.DEFAULT_SKY_COLOR
|
||||
|
||||
|
||||
@ -69,22 +66,21 @@ class SkyRenderer(
|
||||
}
|
||||
})
|
||||
connection.registerEvent(CallbackEventInvoker.of<TimeChangeEvent> {
|
||||
if (connection.world.time != it.time) {
|
||||
sunMatrixUpToDate = true
|
||||
if (connection.world.time.time != it.time) {
|
||||
updateSun = true
|
||||
}
|
||||
})
|
||||
sunTexture = renderWindow.textureManager.staticTextures.createTexture(SUN_TEXTURE_RESOURCE_LOCATION)
|
||||
}
|
||||
|
||||
private fun setSunMatrix(projectionViewMatrix: Mat4d) {
|
||||
val timeAngle = (connection.world.skyAngle * 360.0).rad
|
||||
val rotatedMatrix = if (timeAngle == 0.0) {
|
||||
private fun setSunMatrix(projectionViewMatrix: Mat4) {
|
||||
val timeAngle = (connection.world.time.skyAngle * 360.0f).rad
|
||||
val rotatedMatrix = if (timeAngle == 0.0f) {
|
||||
projectionViewMatrix
|
||||
} else {
|
||||
projectionViewMatrix.rotate(timeAngle, Vec3d(0.0f, 0.0f, 1.0f))
|
||||
projectionViewMatrix.rotate(timeAngle, Vec3(0.0f, 0.0f, 1.0f))
|
||||
}
|
||||
skySunShader.use().setMat4("uSkyViewProjectionMatrix", Mat4(rotatedMatrix))
|
||||
sunMatrixUpToDate = false
|
||||
skySunShader.use().setMat4("uSkyViewProjectionMatrix", rotatedMatrix)
|
||||
}
|
||||
|
||||
override fun postInit() {
|
||||
@ -92,8 +88,8 @@ class SkyRenderer(
|
||||
}
|
||||
|
||||
private fun drawSun() {
|
||||
if (sunMatrixUpToDate) {
|
||||
setSunMatrix(renderWindow.inputHandler.camera.projectionMatrix * renderWindow.inputHandler.camera.viewMatrix.toMat3().toMat4())
|
||||
if (updateSun) {
|
||||
setSunMatrix(renderWindow.camera.matrixHandler.projectionMatrix * renderWindow.camera.matrixHandler.viewMatrix.toMat3().toMat4())
|
||||
skySunMesh.unload()
|
||||
|
||||
skySunMesh = SimpleTextureMesh(renderWindow)
|
||||
@ -105,11 +101,12 @@ class SkyRenderer(
|
||||
position = position,
|
||||
texture = sunTexture,
|
||||
uv = uv,
|
||||
tintColor = ChatColors.WHITE.with(alpha = 1.0f - connection.world.rainGradient), // ToDo: Depends on time
|
||||
tintColor = ChatColors.WHITE.with(alpha = 1.0f - connection.world.weather.rainGradient), // ToDo: Depends on time
|
||||
)
|
||||
}
|
||||
)
|
||||
skySunMesh.load()
|
||||
updateSun = false
|
||||
|
||||
}
|
||||
renderSystem.enable(RenderingCapabilities.BLENDING)
|
||||
@ -123,18 +120,18 @@ class SkyRenderer(
|
||||
val brightness = 1.0f
|
||||
val skyColor = RGBColor((baseColor.red * brightness).toInt(), (baseColor.green * brightness).toInt(), (baseColor.blue * brightness).toInt())
|
||||
|
||||
renderWindow.inputHandler.camera.fogColor.value = if (connection.player.submergedFluid?.resourceLocation == DefaultFluids.WATER) {
|
||||
connection.player.positionInfo.biome?.waterFogColor ?: skyColor
|
||||
} else {
|
||||
skyColor
|
||||
}
|
||||
baseColor = connection.world.getBiome(connection.player.positionInfo.blockPosition)?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR
|
||||
|
||||
|
||||
for (shader in renderWindow.renderSystem.shaders) {
|
||||
if (shader.uniforms.contains("uSkyColor")) {
|
||||
shader.use().setRGBColor("uSkyColor", skyColor)
|
||||
connection.world.dimension?.hasSkyLight?.let {
|
||||
baseColor = if (it) {
|
||||
connection.player.positionInfo.biome?.skyColor ?: RenderConstants.DEFAULT_SKY_COLOR
|
||||
} else {
|
||||
RenderConstants.BLACK_COLOR
|
||||
}
|
||||
}
|
||||
} ?: let { baseColor = RenderConstants.DEFAULT_SKY_COLOR }
|
||||
|
||||
|
||||
skyboxShader.use().setRGBColor("uSkyColor", skyColor)
|
||||
}
|
||||
|
||||
private fun drawSkybox() {
|
||||
|
@ -17,7 +17,7 @@ import de.bixilon.minosoft.config.profile.delegate.watcher.SimpleProfileDelegate
|
||||
import de.bixilon.minosoft.data.registries.ResourceLocation
|
||||
import de.bixilon.minosoft.data.world.AbstractAudioPlayer
|
||||
import de.bixilon.minosoft.gui.rendering.Rendering
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.Camera
|
||||
import de.bixilon.minosoft.gui.rendering.camera.MatrixHandler
|
||||
import de.bixilon.minosoft.gui.rendering.modding.events.CameraPositionChangeEvent
|
||||
import de.bixilon.minosoft.gui.rendering.sound.sounds.Sound
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
|
||||
@ -96,7 +96,7 @@ class AudioPlayer(
|
||||
connection.registerEvent(CallbackEventInvoker.of<CameraPositionChangeEvent> {
|
||||
queue += {
|
||||
listener.position = Vec3(it.newPosition)
|
||||
listener.setOrientation(it.renderWindow.inputHandler.camera.cameraFront, Camera.CAMERA_UP_VEC3)
|
||||
listener.setOrientation(it.renderWindow.camera.matrixHandler.cameraFront, MatrixHandler.CAMERA_UP_VEC3)
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -14,9 +14,7 @@
|
||||
package de.bixilon.minosoft.gui.rendering.sound
|
||||
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3d
|
||||
import org.lwjgl.openal.AL10.*
|
||||
|
||||
class SoundListener(position: Vec3 = Vec3.EMPTY) {
|
||||
@ -36,13 +34,13 @@ class SoundListener(position: Vec3 = Vec3.EMPTY) {
|
||||
get() = alGetListenerf(AL_MAX_GAIN)
|
||||
set(value) = alListenerf(AL_MAX_GAIN, value)
|
||||
|
||||
fun setOrientation(look: Vec3d, up: Vec3d) {
|
||||
alListenerfv(AL_ORIENTATION, floatArrayOf(look.x.toFloat(), look.y.toFloat(), look.z.toFloat(), up.x.toFloat(), up.y.toFloat(), up.z.toFloat()))
|
||||
fun setOrientation(look: Vec3, up: Vec3) {
|
||||
alListenerfv(AL_ORIENTATION, floatArrayOf(look.x, look.y, look.z, up.x, up.y, up.z))
|
||||
}
|
||||
|
||||
init {
|
||||
this.position = position
|
||||
this.velocity = Vec3.EMPTY
|
||||
setOrientation(Vec3d.EMPTY, Vec3d(0.0, 1.0, 0.0))
|
||||
setOrientation(Vec3.EMPTY, Vec3(0.0, 1.0, 0.0))
|
||||
}
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.sin
|
||||
|
||||
|
||||
@Deprecated("Needs refactoring")
|
||||
class LightMap(private val connection: PlayConnection) {
|
||||
private val profile = connection.profiles.rendering.light
|
||||
private val nightVisionStatusEffect = connection.registries.statusEffectRegistry[DefaultStatusEffects.NIGHT_VISION]
|
||||
@ -50,7 +50,7 @@ class LightMap(private val connection: PlayConnection) {
|
||||
}
|
||||
|
||||
fun update() {
|
||||
val skyGradient = connection.world.lightBase.toFloat()
|
||||
val skyGradient = connection.world.time.lightBase.toFloat()
|
||||
|
||||
// ToDo: Lightning
|
||||
|
||||
|
@ -46,7 +46,6 @@ import de.bixilon.minosoft.gui.rendering.util.VecUtil.of
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil.sectionHeight
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.toVec3
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
|
||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3
|
||||
import de.bixilon.minosoft.gui.rendering.world.mesh.VisibleMeshes
|
||||
@ -87,7 +86,7 @@ class WorldRenderer(
|
||||
) : Renderer, OpaqueDrawable, TranslucentDrawable, TransparentDrawable {
|
||||
private val profile = connection.profiles.block
|
||||
override val renderSystem: RenderSystem = renderWindow.renderSystem
|
||||
private val frustum = renderWindow.inputHandler.camera.frustum
|
||||
private val frustum = renderWindow.camera.matrixHandler.frustum
|
||||
private val shader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
||||
private val transparentShader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
||||
private val world: World = connection.world
|
||||
@ -660,7 +659,7 @@ class WorldRenderer(
|
||||
|
||||
private fun onFrustumChange() {
|
||||
var sortQueue = false
|
||||
val cameraPosition = connection.player.cameraPosition.toVec3()
|
||||
val cameraPosition = connection.player.cameraPosition
|
||||
if (this.cameraPosition != cameraPosition) {
|
||||
this.cameraPosition = cameraPosition
|
||||
this.cameraChunkPosition = connection.player.positionInfo.chunkPosition
|
||||
|
@ -21,7 +21,7 @@ import de.bixilon.minosoft.gui.rendering.RenderConstants
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.Renderer
|
||||
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.input.camera.hit.BlockRaycastHit
|
||||
import de.bixilon.minosoft.gui.rendering.camera.target.targets.BlockTarget
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.DepthFunctions
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.phases.OtherDrawable
|
||||
@ -82,7 +82,7 @@ class BlockOutlineRenderer(
|
||||
}
|
||||
|
||||
override fun prepareDraw() {
|
||||
val raycastHit = renderWindow.inputHandler.camera.target.nullCast<BlockRaycastHit>()
|
||||
val raycastHit = renderWindow.camera.targetHandler.target.nullCast<BlockTarget>()
|
||||
|
||||
var currentMesh = currentMesh
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
package de.bixilon.minosoft.modding.event.events
|
||||
|
||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
|
||||
class CameraSetEvent(
|
||||
connection: PlayConnection,
|
||||
val entity: Entity,
|
||||
) : PlayConnectionEvent(connection)
|
@ -16,6 +16,7 @@ import de.bixilon.minosoft.modding.event.EventInitiators
|
||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.play.WorldTimeSetS2CP
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
|
||||
class TimeChangeEvent(
|
||||
connection: PlayConnection,
|
||||
@ -25,5 +26,5 @@ class TimeChangeEvent(
|
||||
) : PlayConnectionEvent(connection, initiator) {
|
||||
|
||||
|
||||
constructor(connection: PlayConnection, packet: WorldTimeSetS2CP) : this(connection, EventInitiators.SERVER, packet.age, packet.time)
|
||||
constructor(connection: PlayConnection, packet: WorldTimeSetS2CP) : this(connection, EventInitiators.SERVER, packet.age, packet.time % ProtocolDefinition.TICKS_PER_DAY)
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Teleports our self in spectator mode to an entity
|
||||
*/
|
||||
class EntitySpectateC2SP(
|
||||
val entityUUID: UUID,
|
||||
) : PlayC2SPacket {
|
||||
|
@ -12,6 +12,8 @@
|
||||
*/
|
||||
package de.bixilon.minosoft.protocol.packets.s2c.play
|
||||
|
||||
import de.bixilon.minosoft.modding.event.events.CameraSetEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
@ -21,6 +23,11 @@ import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
class CameraS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
val entityId: Int = buffer.readVarInt()
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
val entity = connection.world.entities[entityId] ?: return
|
||||
connection.fireEvent(CameraSetEvent(connection, entity))
|
||||
}
|
||||
|
||||
override fun log(reducedLog: Boolean) {
|
||||
Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Camera (entityId=$entityId)" }
|
||||
}
|
||||
|
@ -16,6 +16,7 @@ import de.bixilon.minosoft.modding.event.events.TimeChangeEvent
|
||||
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.packets.s2c.PlayS2CPacket
|
||||
import de.bixilon.minosoft.protocol.protocol.PlayInByteBuffer
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
@ -25,8 +26,8 @@ class WorldTimeSetS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() {
|
||||
val time = buffer.readLong()
|
||||
|
||||
override fun handle(connection: PlayConnection) {
|
||||
connection.world.age = age
|
||||
connection.world.time = time
|
||||
connection.world.time.age = age
|
||||
connection.world.time.time = time % ProtocolDefinition.TICKS_PER_DAY
|
||||
|
||||
connection.fireEvent(TimeChangeEvent(connection, this))
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.text.ChatComponent
|
||||
import de.bixilon.minosoft.protocol.network.connection.Connection
|
||||
import de.bixilon.minosoft.util.Util
|
||||
import de.bixilon.minosoft.util.nbt.tag.NBTTagTypes
|
||||
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.type
|
||||
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.nbtType
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3d
|
||||
import glm_.vec3.Vec3i
|
||||
@ -178,7 +178,7 @@ open class OutByteBuffer(open val connection: Connection? = null) {
|
||||
this.writeNBTTagType(type)
|
||||
}
|
||||
|
||||
val type = tag.type
|
||||
val type = tag.nbtType
|
||||
writeNBTTagType(type)
|
||||
if (type == NBTTagTypes.END) {
|
||||
return
|
||||
@ -206,7 +206,7 @@ open class OutByteBuffer(open val connection: Connection? = null) {
|
||||
this.writeNBTTagType(if (tag.isEmpty()) {
|
||||
NBTTagTypes.END
|
||||
} else {
|
||||
tag.iterator().next().type
|
||||
tag.iterator().next().nbtType
|
||||
})
|
||||
|
||||
writeInt(tag.size)
|
||||
@ -217,7 +217,7 @@ open class OutByteBuffer(open val connection: Connection? = null) {
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
for ((key, value) in tag) {
|
||||
val valueType = value.type
|
||||
val valueType = value.nbtType
|
||||
if (valueType == NBTTagTypes.END) {
|
||||
error("NBT does not support null as value in a compound tag!")
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ object NBTUtil {
|
||||
return null
|
||||
}
|
||||
|
||||
val Any?.type: NBTTagTypes
|
||||
val Any?.nbtType: NBTTagTypes
|
||||
get() {
|
||||
return when (this) {
|
||||
null -> NBTTagTypes.END
|
||||
@ -76,7 +76,7 @@ object NBTUtil {
|
||||
is Map<*, *> -> NBTTagTypes.COMPOUND
|
||||
is IntArray -> NBTTagTypes.INT_ARRAY
|
||||
is LongArray -> NBTTagTypes.LONG_ARRAY
|
||||
else -> throw IllegalArgumentException("NBT does not support ${type::class.java.name}")
|
||||
else -> throw IllegalArgumentException("NBT does not support ${this::class.java.name}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user