fluid tags, check if entity is in water

This commit is contained in:
Bixilon 2021-06-17 20:55:32 +02:00
parent 3c8a8dd630
commit e538871e1b
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 246 additions and 6 deletions

View File

@ -21,25 +21,31 @@ import de.bixilon.minosoft.data.accounts.Account
import de.bixilon.minosoft.data.entities.EntityRotation
import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity
import de.bixilon.minosoft.data.entities.entities.player.RemotePlayerEntity
import de.bixilon.minosoft.data.entities.entities.vehicle.Boat
import de.bixilon.minosoft.data.inventory.InventorySlots
import de.bixilon.minosoft.data.physics.PhysicsConstants
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.blocks.DefaultBlocks
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
import de.bixilon.minosoft.data.registries.effects.DefaultStatusEffects
import de.bixilon.minosoft.data.registries.effects.attributes.DefaultStatusEffectAttributeNames
import de.bixilon.minosoft.data.registries.effects.attributes.DefaultStatusEffectAttributes
import de.bixilon.minosoft.data.registries.effects.attributes.StatusEffectAttributeInstance
import de.bixilon.minosoft.data.registries.enchantment.DefaultEnchantments
import de.bixilon.minosoft.data.registries.fluid.FlowableFluid
import de.bixilon.minosoft.data.registries.items.DefaultItems
import de.bixilon.minosoft.data.registries.items.Item
import de.bixilon.minosoft.data.registries.other.containers.Container
import de.bixilon.minosoft.data.registries.other.containers.PlayerInventory
import de.bixilon.minosoft.data.tags.DefaultBlockTags
import de.bixilon.minosoft.data.tags.DefaultFluidTags
import de.bixilon.minosoft.data.tags.Tag
import de.bixilon.minosoft.gui.rendering.chunk.models.AABB
import de.bixilon.minosoft.gui.rendering.input.camera.MovementInput
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.VecUtil.assign
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.clearZero
import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty
@ -62,6 +68,7 @@ import glm_.vec2.Vec2
import glm_.vec3.Vec3
import glm_.vec3.Vec3d
import glm_.vec3.Vec3i
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.pow
@ -87,6 +94,9 @@ class LocalPlayerEntity(
val itemCooldown: MutableMap<Item, ItemCooldown> = synchronizedMapOf()
// fluids stuff
private val fluidHeights: MutableMap<ResourceLocation, Float> = synchronizedMapOf()
var input = MovementInput()
// last state (for updating movement on server)
@ -604,6 +614,86 @@ class LocalPlayerEntity(
val canSneak: Boolean
get() = (onGround && fallDistance < PhysicsConstants.STEP_HEIGHT) && !connection.world.isSpaceEmpty(aabb + Vec3(0.0f, fallDistance - PhysicsConstants.STEP_HEIGHT, 0.0f))
private fun updateFluidState(fluidType: ResourceLocation, velocityMultiplier: Float): Boolean {
val aabb = aabb.shrink()
var height = 0.0f
var inFluid = false
val pushable = !baseAbilities.isFlying
val velocity = Vec3d.EMPTY
var checks = 0
for ((blockPosition, blockState) in connection.world[aabb]) {
if (blockState.block !is FluidBlock) {
continue
}
if (!connection.inTag(blockState.block.stillFluid, TagsS2CP.FLUID_TAG_RESOURCE_LOCATION, DefaultFluidTags.WATER_TAG)) { // ToDo: stillFluid
continue
}
val fluidHeight = blockPosition.y + blockState.block.getFluidHeight(blockState)
if (fluidHeight < aabb.min.y) {
continue
}
inFluid = true
height = max(fluidHeight - aabb.min.y.toFloat(), height)
if (!pushable) {
continue
}
val fluid = blockState.block.stillFluid
if (fluid !is FlowableFluid) {
continue
}
val fluidVelocity = fluid.getVelocity(connection, blockState, blockPosition)
if (height < 0.4) {
fluidVelocity *= height
}
velocity += fluidVelocity
checks++
}
if (velocity.length() > 0.0) {
if (checks > 0) {
velocity *= 1.0 / checks
}
velocity *= velocityMultiplier
if (abs(velocity.x) < 0.004 && abs(velocity.z) < 0.003 && velocity.length() < 0.0045000000000000005) {
velocity assign velocity.normalize() * 0.0045000000000000005
}
this.velocity assign (this.velocity + velocity)
}
fluidHeights[fluidType] = height
return inFluid
}
private fun updateWaterState() {
fluidHeights.clear()
if (vehicle is Boat) {
return // ToDo
}
if (updateFluidState(DefaultFluidTags.WATER_TAG, 0.014f)) {
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE){"In Water: Yes"}
return
// ToDo
}
// Log.log(LogMessageType.OTHER, LogLevels.VERBOSE){"In Water: No"}
}
override fun realTick() {
if (connection.world[positionInfo.blockPosition.chunkPosition] == null) {
// chunk not loaded, so we don't tick?
@ -611,6 +701,7 @@ class LocalPlayerEntity(
}
super.realTick()
tickMovement()
updateWaterState()
sendMovementPackets()

View File

@ -15,10 +15,13 @@ package de.bixilon.minosoft.data.registries.blocks.types
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.registries.fluid.Fluid
import de.bixilon.minosoft.data.registries.versions.Registries
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.BlockLikeRenderer
import de.bixilon.minosoft.gui.rendering.chunk.models.renderable.FluidRenderer
import de.bixilon.minosoft.util.KUtil.nullCast
open class FluidBlock(resourceLocation: ResourceLocation, registries: Registries, data: JsonObject) : Block(resourceLocation, registries, data) {
open val stillFluid: Fluid = registries.fluidRegistry[data["still_fluid"].asInt]
@ -29,10 +32,17 @@ open class FluidBlock(resourceLocation: ResourceLocation, registries: Registries
override val renderOverride: List<BlockLikeRenderer>
init {
also {
let {
fluidRenderer = FluidRenderer(it, stillFluid, flowingFluid)
renderOverride = listOf(fluidRenderer)
}
}
fun getFluidHeight(blockState: BlockState): Float {
return (blockState.properties[BlockProperties.FLUID_LEVEL]?.nullCast() ?: 0) * FLUID_HEIGHT_CALCULATOR
}
companion object {
private const val FLUID_HEIGHT_CALCULATOR = 1.0f / 16.0f
}
}

View File

@ -0,0 +1,24 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* 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.data.registries.fluid
import de.bixilon.minosoft.util.KUtil.asResourceLocation
object DefaultFluids {
val EMPTY = "minecraft:empty".asResourceLocation()
val FLOWING_WATER = "minecraft:flowing_water".asResourceLocation()
val WATER = "minecraft:water".asResourceLocation()
val FLOWING_LAVA = "minecraft:flowing_lava".asResourceLocation()
val LAVA = "minecraft:lava".asResourceLocation()
}

View File

@ -0,0 +1,35 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* 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.data.registries.fluid
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.registries.versions.Registries
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import glm_.vec3.Vec3d
import glm_.vec3.Vec3i
open class FlowableFluid(
override val resourceLocation: ResourceLocation,
registries: Registries,
data: JsonObject,
) : Fluid(resourceLocation, registries, data) {
fun getVelocity(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i): Vec3d {
// ToDo
return Vec3d.EMPTY
}
}

View File

@ -15,11 +15,11 @@ package de.bixilon.minosoft.data.registries.fluid.lava
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.fluid.Fluid
import de.bixilon.minosoft.data.registries.fluid.FlowableFluid
import de.bixilon.minosoft.data.registries.versions.Registries
abstract class LavaFluid(
resourceLocation: ResourceLocation,
registries: Registries,
data: JsonObject,
) : Fluid(resourceLocation, registries, data)
) : FlowableFluid(resourceLocation, registries, data)

View File

@ -15,11 +15,11 @@ package de.bixilon.minosoft.data.registries.fluid.water
import com.google.gson.JsonObject
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.fluid.Fluid
import de.bixilon.minosoft.data.registries.fluid.FlowableFluid
import de.bixilon.minosoft.data.registries.versions.Registries
abstract class WaterFluid(
resourceLocation: ResourceLocation,
registries: Registries,
data: JsonObject,
) : Fluid(resourceLocation, registries, data)
) : FlowableFluid(resourceLocation, registries, data)

View File

@ -0,0 +1,32 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* 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.data.tags
import de.bixilon.minosoft.data.registries.fluid.DefaultFluids
import de.bixilon.minosoft.util.KUtil.asResourceLocation
object DefaultFluidTags {
// ToDo: Improve this
val WATER_TAG = "minecraft:water".asResourceLocation()
val WATER = setOf(DefaultFluids.WATER, DefaultFluids.FLOWING_WATER)
val LAVA_TAG = "minecraft:lava".asResourceLocation()
val LAVA = setOf(DefaultFluids.LAVA, DefaultFluids.FLOWING_LAVA)
val FLUID_TAGS = mapOf(
WATER_TAG to WATER,
LAVA_TAG to LAVA,
)
}

View File

@ -0,0 +1,22 @@
/*
* Minosoft
* Copyright (C) 2021 Moritz Zwerger
*
* 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.data.tags
import de.bixilon.minosoft.protocol.packets.s2c.play.TagsS2CP
object DefaultTags {
val TAGS = mapOf(
TagsS2CP.FLUID_TAG_RESOURCE_LOCATION to DefaultFluidTags.FLUID_TAGS,
)
}

View File

@ -184,6 +184,14 @@ class World(
blockState.block.randomTick(connection, blockState, blockPosition, random)
}
operator fun get(aabb: AABB): Map<Vec3i, BlockState> {
var ret: MutableMap<Vec3i, BlockState> = mutableMapOf()
for (position in aabb.blockPositions) {
this[position]?.let { ret[position] = it }
}
return ret.toMap()
}
fun getBlocks(start: Vec3i, end: Vec3i): Map<Vec3i, BlockState> {
val blocks: MutableMap<Vec3i, BlockState> = mutableMapOf()

View File

@ -188,7 +188,7 @@ class AABB(
return AABB(min + vec, max - vec)
}
fun shrink(size: Double): AABB {
fun shrink(size: Double = 1.0E-7): AABB {
return AABB(min + size, max - size)
}

View File

@ -24,10 +24,12 @@ import de.bixilon.minosoft.data.player.LocalPlayerEntity
import de.bixilon.minosoft.data.player.tab.TabList
import de.bixilon.minosoft.data.registries.RegistriesLoadingException
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.registries.ResourceLocationAble
import de.bixilon.minosoft.data.registries.recipes.Recipes
import de.bixilon.minosoft.data.registries.versions.Registries
import de.bixilon.minosoft.data.registries.versions.Version
import de.bixilon.minosoft.data.scoreboard.ScoreboardManager
import de.bixilon.minosoft.data.tags.DefaultTags
import de.bixilon.minosoft.data.tags.Tag
import de.bixilon.minosoft.data.text.ChatComponent
import de.bixilon.minosoft.data.world.World
@ -236,6 +238,22 @@ class PlayConnection(
}
}
fun inTag(`object`: Any?, tagType: ResourceLocation, tag: ResourceLocation): Boolean {
fun fallback(): Boolean {
if (`object` !is ResourceLocationAble) {
return false
}
return DefaultTags.TAGS[tagType]?.get(tag)?.contains(`object`.resourceLocation) == true
}
(tags[tagType] ?: return fallback()).let { map ->
(map[tag] ?: return fallback()).let {
return it.entries.contains(`object`)
}
}
}
val eventListenerSize: Int
get() = eventListeners.size
}