diff --git a/src/main/java/de/bixilon/minosoft/data/DefaultEntityFactories.kt b/src/main/java/de/bixilon/minosoft/data/DefaultEntityFactories.kt index 5316afbec..e77a0df52 100644 --- a/src/main/java/de/bixilon/minosoft/data/DefaultEntityFactories.kt +++ b/src/main/java/de/bixilon/minosoft/data/DefaultEntityFactories.kt @@ -33,7 +33,7 @@ import de.bixilon.minosoft.data.entities.entities.monster.piglin.PiglinBrute import de.bixilon.minosoft.data.entities.entities.monster.raid.* import de.bixilon.minosoft.data.entities.entities.npc.villager.Villager import de.bixilon.minosoft.data.entities.entities.npc.villager.WanderingTrader -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.projectile.* import de.bixilon.minosoft.data.entities.entities.vehicle.* import de.bixilon.minosoft.data.entities.meta.EntityMetaData @@ -156,7 +156,7 @@ object DefaultEntityFactories : DefaultFactory>( ZombieVillager, ZombiePigman, ZombifiedPiglin, - PlayerEntity, + RemotePlayerEntity, FishingHook, GlowSquid, EvokerFangs, diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt index 268664ffc..26f8e4227 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/Entity.kt @@ -21,7 +21,7 @@ import de.bixilon.minosoft.data.inventory.InventorySlots.EquipmentSlots import de.bixilon.minosoft.data.inventory.ItemStack import de.bixilon.minosoft.data.mappings.effects.StatusEffect import de.bixilon.minosoft.data.mappings.entities.EntityType -import de.bixilon.minosoft.data.physics.Speedable +import de.bixilon.minosoft.data.physics.PhysicsEntity import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.gui.rendering.chunk.models.AABB import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY @@ -34,13 +34,15 @@ import glm_.vec3.Vec3 import java.lang.reflect.InvocationTargetException import java.util.* import kotlin.math.pow +import kotlin.random.Random abstract class Entity( protected val connection: PlayConnection, val entityType: EntityType, override var position: Vec3, var rotation: EntityRotation, -) : Speedable { +) : PhysicsEntity { + protected val random = Random val equipment: MutableMap = mutableMapOf() val activeStatusEffects: MutableMap = synchronizedMapOf() @@ -62,6 +64,8 @@ abstract class Entity( Vec3(+(entityType.width / 2 + HITBOX_MARGIN), entityType.height, +(entityType.width / 2 + HITBOX_MARGIN)) ) + private var lastTickTime = -1L + fun forceMove(deltaPosition: Vec3) { position = position + deltaPosition } @@ -232,8 +236,16 @@ abstract class Entity( check(deltaMillis > 0L) { "Delta tick time is <= 0: $deltaMillis" } tickMovement(deltaMillis) + + val currentTime = System.currentTimeMillis() + if (currentTime - lastTickTime >= ProtocolDefinition.TICK_TIME) { + realTick() + lastTickTime = currentTime + } } + open fun realTick() {} + private val aabb: AABB get() = defaultAABB + position diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt index 3711d5914..5f59dc47c 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt @@ -17,17 +17,25 @@ import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.entities.attributes.DefaultEntityAttributes import de.bixilon.minosoft.data.mappings.entities.EntityType import de.bixilon.minosoft.data.player.Hands +import de.bixilon.minosoft.data.text.ChatColors +import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.data.text.RGBColor.Companion.asRGBColor +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell.AmbientEntityEffectParticle +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell.EntityEffectParticle +import de.bixilon.minosoft.gui.rendering.util.VecUtil.vertical import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.util.KUtil.chance import glm_.vec3.Vec3 import glm_.vec3.Vec3i abstract class LivingEntity(connection: PlayConnection, entityType: EntityType, position: Vec3, rotation: EntityRotation) : Entity(connection, entityType, position, rotation) { + private val entityEffectParticle = connection.registries.particleTypeRegistry[EntityEffectParticle] + private val ambientEntityEffectParticle = connection.registries.particleTypeRegistry[AmbientEntityEffectParticle] private fun getLivingEntityFlag(bitMask: Int): Boolean { return entityMetaData.sets.getBitMask(EntityMetaDataFields.LIVING_ENTITY_FLAGS, bitMask) } - // = isUsingItem @get:EntityMetaDataFunction(name = "Is hand active") val isHandActive: Boolean get() = getLivingEntityFlag(0x01) @@ -52,8 +60,8 @@ abstract class LivingEntity(connection: PlayConnection, entityType: EntityType, } @get:EntityMetaDataFunction(name = "Effect color") - val effectColor: Int - get() = entityMetaData.sets.getInt(EntityMetaDataFields.LIVING_ENTITY_EFFECT_COLOR) + val effectColor: RGBColor + get() = entityMetaData.sets.getInt(EntityMetaDataFields.LIVING_ENTITY_EFFECT_COLOR).asRGBColor() @get:EntityMetaDataFunction(name = "Is effect ambient") val effectAmbient: Boolean @@ -70,4 +78,46 @@ abstract class LivingEntity(connection: PlayConnection, entityType: EntityType, @get:EntityMetaDataFunction(name = "Bed location") val bedPosition: Vec3i? get() = entityMetaData.sets.getBlockPosition(EntityMetaDataFields.LIVING_ENTITY_BED_POSITION) + + + private fun tickStatusEffects() { + if (entityEffectParticle == null && ambientEntityEffectParticle == null) { + return + } + if (effectColor == ChatColors.BLACK) { + return + } + var spawnParticles = if (isInvisible) { + random.nextInt(15) == 0 + } else { + random.nextBoolean() + } + + if (effectAmbient) { + spawnParticles = spawnParticles && random.chance(20) + } + + if (!spawnParticles) { + return + } + + val particlePosition = position + Vec3.vertical( + { entityType.width * ((2.0f * random.nextFloat() - 1.0f) * 0.5f) }, + entityType.height * random.nextFloat() + ) + if (effectAmbient) { + ambientEntityEffectParticle ?: return + connection.world += AmbientEntityEffectParticle(connection, particlePosition, effectColor, ambientEntityEffectParticle.default()) + } else { + entityEffectParticle ?: return + connection.world += EntityEffectParticle(connection, particlePosition, effectColor, entityEffectParticle.default()) + } + } + + override fun realTick() { + super.realTick() + tickStatusEffects() + } + + } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt index 7e7b312f4..c6efe3f1a 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt @@ -17,8 +17,6 @@ import de.bixilon.minosoft.data.entities.EntityMetaDataFields import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.entities.entities.EntityMetaDataFunction import de.bixilon.minosoft.data.entities.entities.LivingEntity -import de.bixilon.minosoft.data.mappings.ResourceLocation -import de.bixilon.minosoft.data.mappings.entities.EntityFactory import de.bixilon.minosoft.data.mappings.entities.EntityType import de.bixilon.minosoft.data.player.Hands import de.bixilon.minosoft.data.player.PlayerProperties @@ -27,7 +25,7 @@ import de.bixilon.minosoft.data.player.tab.TabListItem import de.bixilon.minosoft.protocol.network.connection.PlayConnection import glm_.vec3.Vec3 -class PlayerEntity( +abstract class PlayerEntity( connection: PlayConnection, entityType: EntityType, position: Vec3 = Vec3(0, 0, 0), @@ -82,8 +80,4 @@ class PlayerEntity( @get:EntityMetaDataFunction(name = "Right shoulder entity data") val rightShoulderData: Map? get() = entityMetaData.sets.getNBT(EntityMetaDataFields.PLAYER_RIGHT_SHOULDER_DATA) - - companion object : EntityFactory { - override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("player") - } } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/RemotePlayerEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/RemotePlayerEntity.kt new file mode 100644 index 000000000..a822d6155 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/RemotePlayerEntity.kt @@ -0,0 +1,40 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.data.entities.entities.player + +import de.bixilon.minosoft.data.abilities.Gamemodes +import de.bixilon.minosoft.data.entities.EntityRotation +import de.bixilon.minosoft.data.mappings.ResourceLocation +import de.bixilon.minosoft.data.mappings.entities.EntityFactory +import de.bixilon.minosoft.data.mappings.entities.EntityType +import de.bixilon.minosoft.data.player.PlayerProperties +import de.bixilon.minosoft.data.player.PlayerProperty +import de.bixilon.minosoft.data.player.tab.TabListItem +import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import glm_.vec3.Vec3 + +class RemotePlayerEntity( + connection: PlayConnection, + entityType: EntityType, + position: Vec3 = Vec3(0, 0, 0), + rotation: EntityRotation = EntityRotation(0.0, 0.0), + name: String = "TBA", + properties: Map = mapOf(), + tabListItem: TabListItem = TabListItem(name = name, gamemode = Gamemodes.SURVIVAL, properties = properties), +) : PlayerEntity(connection, entityType, position, rotation, name, properties, tabListItem) { + + companion object : EntityFactory { + override val RESOURCE_LOCATION: ResourceLocation = ResourceLocation("minecraft:player") + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/items/BlockItem.kt b/src/main/java/de/bixilon/minosoft/data/mappings/items/BlockItem.kt index a6e7e6394..658ecd93c 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/items/BlockItem.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/items/BlockItem.kt @@ -36,7 +36,7 @@ open class BlockItem( val block: Block = registries.blockRegistry[data["block"].asInt] override fun use(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, raycastHit: RaycastHit, hands: Hands, itemStack: ItemStack): BlockUsages { - if (!connection.player.entity.gamemode.canBuild) { + if (!connection.player.gamemode.canBuild) { return BlockUsages.PASS } @@ -57,7 +57,7 @@ open class BlockItem( connection.world[placePosition] = placeBlockState - if (connection.player.entity.gamemode != Gamemodes.CREATIVE) { + if (connection.player.gamemode != Gamemodes.CREATIVE) { itemStack.count-- connection.player.inventory.validate() } diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/items/tools/MiningToolItem.kt b/src/main/java/de/bixilon/minosoft/data/mappings/items/tools/MiningToolItem.kt index edc2c9183..7ed8a8c64 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/items/tools/MiningToolItem.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/items/tools/MiningToolItem.kt @@ -53,7 +53,7 @@ abstract class MiningToolItem( } protected fun interactWithTool(connection: PlayConnection, blockPosition: Vec3i, replace: BlockState?): BlockUsages { - if (!connection.player.entity.gamemode.useTools) { + if (!connection.player.gamemode.useTools) { return BlockUsages.PASS } diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/other/game/event/handlers/GameMoveChangeGameEventHandler.kt b/src/main/java/de/bixilon/minosoft/data/mappings/other/game/event/handlers/GameMoveChangeGameEventHandler.kt index 386943b81..e83c81971 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/other/game/event/handlers/GameMoveChangeGameEventHandler.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/other/game/event/handlers/GameMoveChangeGameEventHandler.kt @@ -22,6 +22,6 @@ object GameMoveChangeGameEventHandler : GameEventHandler { override val RESOURCE_LOCATION: ResourceLocation = "minecraft:gamemode_change".asResourceLocation() override fun handle(data: Float, connection: PlayConnection) { - connection.player.entity.tabListItem.gamemode = Gamemodes[data.toInt()] + connection.player.tabListItem.gamemode = Gamemodes[data.toInt()] } } diff --git a/src/main/java/de/bixilon/minosoft/data/physics/CollisionDetector.kt b/src/main/java/de/bixilon/minosoft/data/physics/CollisionDetector.kt index 1cde5c11b..16949d423 100644 --- a/src/main/java/de/bixilon/minosoft/data/physics/CollisionDetector.kt +++ b/src/main/java/de/bixilon/minosoft/data/physics/CollisionDetector.kt @@ -42,19 +42,19 @@ class CollisionDetector(val connection: PlayConnection) { return result } - fun collide(speedable: Speedable, deltaPosition: Vec3, collisionsToCheck: VoxelShape, aabb: AABB): Vec3 { + fun collide(physicsEntity: PhysicsEntity, deltaPosition: Vec3, collisionsToCheck: VoxelShape, aabb: AABB): Vec3 { val delta = Vec3(deltaPosition) if (delta.y != 0.0f) { delta.y = collisionsToCheck.computeOffset(aabb, deltaPosition.y, Axes.Y) if (delta.y != deltaPosition.y) { - speedable.onGround = false - speedable.velocity.y = 0.0f + physicsEntity.onGround = false + physicsEntity.velocity.y = 0.0f if (deltaPosition.y < 0) { - speedable.onGround = true + physicsEntity.onGround = true } aabb += Vec3(0f, delta.y, 0f) } else if (delta.y < 0) { - speedable.onGround = false + physicsEntity.onGround = false } } if ((deltaPosition.x != 0f || deltaPosition.z != 0f)) { @@ -72,21 +72,21 @@ class CollisionDetector(val connection: PlayConnection) { delta.x = collisionsToCheck.computeOffset(aabb, deltaPosition.x, Axes.X) aabb += Vec3(delta.x, 0f, 0f) if (delta.x != deltaPosition.x) { - speedable.velocity.x = 0.0f + physicsEntity.velocity.x = 0.0f } } if (delta.z != 0.0f) { delta.z = collisionsToCheck.computeOffset(aabb, deltaPosition.z, Axes.Z) aabb += Vec3(0f, 0f, delta.z) if (delta.z != deltaPosition.z) { - speedable.velocity.z = 0.0f + physicsEntity.velocity.z = 0.0f } } if (delta.x != 0.0f && !xPriority) { delta.x = collisionsToCheck.computeOffset(aabb, deltaPosition.x, Axes.X) // no need to offset the aabb any more, as it won't be used any more if (delta.x != deltaPosition.x) { - speedable.velocity.x = 0.0f + physicsEntity.velocity.x = 0.0f } } if (delta.length() > deltaPosition.length() + Entity.STEP_HEIGHT) { diff --git a/src/main/java/de/bixilon/minosoft/data/physics/Speedable.kt b/src/main/java/de/bixilon/minosoft/data/physics/PhysicsEntity.kt similarity index 97% rename from src/main/java/de/bixilon/minosoft/data/physics/Speedable.kt rename to src/main/java/de/bixilon/minosoft/data/physics/PhysicsEntity.kt index 3fca7612a..c9b9cd9a9 100644 --- a/src/main/java/de/bixilon/minosoft/data/physics/Speedable.kt +++ b/src/main/java/de/bixilon/minosoft/data/physics/PhysicsEntity.kt @@ -15,7 +15,7 @@ package de.bixilon.minosoft.data.physics import glm_.vec3.Vec3 -interface Speedable { +interface PhysicsEntity { val position: Vec3 val velocity: Vec3 var onGround: Boolean diff --git a/src/main/java/de/bixilon/minosoft/data/player/Player.kt b/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt similarity index 89% rename from src/main/java/de/bixilon/minosoft/data/player/Player.kt rename to src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt index 6e66437ac..443e7086a 100644 --- a/src/main/java/de/bixilon/minosoft/data/player/Player.kt +++ b/src/main/java/de/bixilon/minosoft/data/player/LocalPlayerEntity.kt @@ -16,6 +16,7 @@ import de.bixilon.minosoft.data.abilities.ItemCooldown 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.mappings.items.Item import de.bixilon.minosoft.data.mappings.other.containers.Container import de.bixilon.minosoft.data.mappings.other.containers.PlayerInventory @@ -26,14 +27,13 @@ import de.bixilon.minosoft.util.KUtil.synchronizedMapOf import glm_.vec3.Vec3 import glm_.vec3.Vec3i -class Player( +class LocalPlayerEntity( account: Account, connection: PlayConnection, -) { +) : PlayerEntity(connection, connection.registries.entityTypeRegistry[RemotePlayerEntity.RESOURCE_LOCATION]!!, Vec3.EMPTY, EntityRotation(0.0, 0.0), account.username) { val healthCondition = PlayerHealthCondition() val experienceCondition = PlayerExperienceCondition() var spawnPosition: Vec3i = Vec3i.EMPTY - val entity: PlayerEntity = PlayerEntity(connection, connection.registries.entityTypeRegistry[PlayerEntity.RESOURCE_LOCATION]!!, Vec3.EMPTY, EntityRotation(0.0, 0.0), account.username) @Deprecated(message = "Will be replaced with some kind of teleport manager, ...") var isSpawnConfirmed = false diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.kt b/src/main/java/de/bixilon/minosoft/data/world/World.kt index f4d9df488..9d6f30d08 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -184,7 +184,7 @@ class World( } private fun randomTick(radius: Int) { - val blockPosition = connection.player.entity.position.blockPosition + { random.nextInt(radius) } - { random.nextInt(radius) } + val blockPosition = connection.player.position.blockPosition + { random.nextInt(radius) } - { random.nextInt(radius) } val blockState = this[blockPosition] ?: return diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt index 866206d03..befc88390 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/block/outline/BlockOutlineRenderer.kt @@ -150,7 +150,7 @@ class BlockOutlineRenderer( return } - if (connection.player.entity.gamemode == Gamemodes.ADVENTURE || connection.player.entity.gamemode == Gamemodes.SPECTATOR) { + if (connection.player.gamemode == Gamemodes.ADVENTURE || connection.player.gamemode == Gamemodes.SPECTATOR) { if (raycastHit.blockState.block.blockEntityType == null) { unload() return diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/debug/HUDWorldDebugNode.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/debug/HUDWorldDebugNode.kt index fcfbcb589..cdbb1450d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/debug/HUDWorldDebugNode.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/nodes/debug/HUDWorldDebugNode.kt @@ -76,7 +76,7 @@ class HUDWorldDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer) // ToDo: Prepare on change - gamemodeText.sText = "Gamemode: ${hudRenderer.connection.player.entity.gamemode.name.lowercase(Locale.getDefault())}" + gamemodeText.sText = "Gamemode: ${hudRenderer.connection.player.gamemode.name.lowercase(Locale.getDefault())}" positionText.sText = "XYZ ${getPosition()}" blockPositionText.sText = "Block ${getBlockPosition()}" chunkPositionText.sText = "Chunk ${getChunkLocation()}" diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/input/LeftClickHandler.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/input/LeftClickHandler.kt index 897348333..290dd2ddc 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/input/LeftClickHandler.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/input/LeftClickHandler.kt @@ -91,7 +91,7 @@ class LeftClickHandler( return false } - if (!connection.player.entity.gamemode.canBreak) { + if (!connection.player.gamemode.canBreak) { cancelDigging() return false } @@ -140,7 +140,7 @@ class LeftClickHandler( val canStartBreaking = currentTime - breakSent >= ProtocolDefinition.TICK_TIME - val canInstantBreak = connection.player.baseAbilities.canInstantBreak || connection.player.entity.gamemode == Gamemodes.CREATIVE + val canInstantBreak = connection.player.baseAbilities.canInstantBreak || connection.player.gamemode == Gamemodes.CREATIVE if (canInstantBreak) { if (!canStartBreaking) { @@ -189,17 +189,17 @@ class LeftClickHandler( } } - connection.player.entity.activeStatusEffects[hasteStatusEffect]?.let { + connection.player.activeStatusEffects[hasteStatusEffect]?.let { speedMultiplier *= (0.2f * it.amplifier) + 1.0f } - connection.player.entity.activeStatusEffects[miningFatigueStatusEffect]?.let { + connection.player.activeStatusEffects[miningFatigueStatusEffect]?.let { speedMultiplier *= 0.3f.pow(it.amplifier + 1) } // ToDo: Check if is in water - if (!connection.player.entity.onGround) { + if (!connection.player.onGround) { speedMultiplier /= 5.0f } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt index f1a007b54..5b164f62a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/input/camera/Camera.kt @@ -61,7 +61,7 @@ class Camera( private var lastMouseX = 0.0 private var lastMouseY = 0.0 val playerEntity: PlayerEntity - get() = connection.player.entity + get() = connection.player var yaw = 0.0 var pitch = 0.0 private var zoom = 0.0f @@ -222,7 +222,7 @@ class Camera( if (renderWindow.inputHandler.currentKeyConsumer != null) { // ToDo return } - var cameraSpeed = if (connection.player.entity.isFlying) { + var cameraSpeed = if (connection.player.isFlying) { flyingSpeed } else { walkingSpeed diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/DefaultParticleFactory.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/DefaultParticleFactory.kt index a6cb1f9ac..9283432de 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/DefaultParticleFactory.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/DefaultParticleFactory.kt @@ -21,6 +21,8 @@ import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.Ex import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.dust.DustParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.fire.SmokeParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.lava.LavaParticle +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell.AmbientEntityEffectParticle +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell.EntityEffectParticle import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.suspend.DolphinParticle object DefaultParticleFactory : DefaultFactory>( @@ -32,4 +34,6 @@ object DefaultParticleFactory : DefaultFactory>( SmokeParticle, DolphinParticle, DustParticle, + EntityEffectParticle, + AmbientEntityEffectParticle, ) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/Particle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/Particle.kt index 9ca6e75b0..88a916c90 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/Particle.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/Particle.kt @@ -14,7 +14,7 @@ package de.bixilon.minosoft.gui.rendering.particle.types import de.bixilon.minosoft.data.mappings.particle.data.ParticleData -import de.bixilon.minosoft.data.physics.Speedable +import de.bixilon.minosoft.data.physics.PhysicsEntity import de.bixilon.minosoft.gui.rendering.chunk.models.AABB import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory import de.bixilon.minosoft.gui.rendering.particle.ParticleMesh @@ -36,7 +36,7 @@ abstract class Particle( final override val position: Vec3, final override val velocity: Vec3 = Vec3.EMPTY, data: ParticleData? = null, -) : Speedable { +) : PhysicsEntity { protected val data: ParticleData = data ?: let { val resourceLocation = this::class.companionObjectInstance as ParticleFactory<*> connection.registries.particleTypeRegistry[resourceLocation]!!.default() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/AmbientEntityEffectParticle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/AmbientEntityEffectParticle.kt new file mode 100644 index 000000000..40cc1a641 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/AmbientEntityEffectParticle.kt @@ -0,0 +1,37 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell + +import de.bixilon.minosoft.data.mappings.ResourceLocation +import de.bixilon.minosoft.data.mappings.particle.data.ParticleData +import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory +import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.util.KUtil.asResourceLocation +import glm_.vec3.Vec3 + +class AmbientEntityEffectParticle(connection: PlayConnection, position: Vec3, color: RGBColor, data: ParticleData? = null) : SpellParticle(connection, position, Vec3(color.red, color.green, color.blue), data) { + + init { + this.color = color.with(alpha = 0.15f) + } + + companion object : ParticleFactory { + override val RESOURCE_LOCATION: ResourceLocation = "minecraft:ambient_entity_effect".asResourceLocation() + + override fun build(connection: PlayConnection, position: Vec3, velocity: Vec3, data: ParticleData): AmbientEntityEffectParticle { + return AmbientEntityEffectParticle(connection, position, color = RGBColor(velocity.x, velocity.y, velocity.z), data) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/EntityEffectParticle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/EntityEffectParticle.kt new file mode 100644 index 000000000..ece218537 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/EntityEffectParticle.kt @@ -0,0 +1,37 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell + +import de.bixilon.minosoft.data.mappings.ResourceLocation +import de.bixilon.minosoft.data.mappings.particle.data.ParticleData +import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.gui.rendering.particle.ParticleFactory +import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.util.KUtil.asResourceLocation +import glm_.vec3.Vec3 + +class EntityEffectParticle(connection: PlayConnection, position: Vec3, color: RGBColor, data: ParticleData? = null) : SpellParticle(connection, position, Vec3(color.red, color.green, color.blue), data) { + + init { + this.color = color + } + + companion object : ParticleFactory { + override val RESOURCE_LOCATION: ResourceLocation = "minecraft:entity_effect".asResourceLocation() + + override fun build(connection: PlayConnection, position: Vec3, velocity: Vec3, data: ParticleData): EntityEffectParticle { + return EntityEffectParticle(connection, position, color = RGBColor(velocity.x, velocity.y, velocity.z), data) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/SpellParticle.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/SpellParticle.kt new file mode 100644 index 000000000..eb84e39ab --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/types/render/texture/simple/spell/SpellParticle.kt @@ -0,0 +1,46 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.spell + +import de.bixilon.minosoft.data.mappings.particle.data.ParticleData +import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.SimpleTextureParticle +import de.bixilon.minosoft.protocol.network.connection.PlayConnection +import de.bixilon.minosoft.util.MMath +import glm_.vec3.Vec3 +import kotlin.random.Random + +abstract class SpellParticle(connection: PlayConnection, position: Vec3, velocity: Vec3, data: ParticleData? = null) : SimpleTextureParticle(connection, position, Vec3(0.5f - Random.nextFloat(), velocity.y, 0.5 - Random.nextFloat()), data) { + + init { + friction = 0.96f + gravityStrength = -0.1f + accelerateIfYBlocked = true + this.velocity.y *= 0.20000000298023224f + if (velocity.x == 0.0f && velocity.z == 0.0f) { + this.velocity.x *= 0.10000000149011612f + this.velocity.z *= 0.10000000149011612f + } + super.scale *= 0.75f + maxAge = (8.0f / (random.nextFloat() * 0.8f + 0.2f)).toInt() + this.physics = false + + // ToDo: Toggle if using spyglass + } + + override fun realTick() { + super.realTick() + + color = color.with(alpha = MMath.lerp(0.05f, color.floatAlpha, 1.0f)) + } +} diff --git a/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt b/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt index dce724454..b2c220c25 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/network/connection/PlayConnection.kt @@ -25,7 +25,7 @@ import de.bixilon.minosoft.data.mappings.recipes.Recipes import de.bixilon.minosoft.data.mappings.versions.Registries import de.bixilon.minosoft.data.mappings.versions.Version import de.bixilon.minosoft.data.physics.CollisionDetector -import de.bixilon.minosoft.data.player.Player +import de.bixilon.minosoft.data.player.LocalPlayerEntity import de.bixilon.minosoft.data.player.tab.TabList import de.bixilon.minosoft.data.scoreboard.ScoreboardManager import de.bixilon.minosoft.data.tags.Tag @@ -75,7 +75,7 @@ class PlayConnection( var rendering: Rendering? = null private set - lateinit var player: Player + lateinit var player: LocalPlayerEntity private set private lateinit var entityTickTask: TimeWorkerTask @@ -186,7 +186,7 @@ class PlayConnection( version.load(latch) // ToDo: show gui loader assetsManager = MultiAssetsManager(version.assetsManager, Minosoft.MINOSOFT_ASSETS_MANAGER, Minosoft.MINECRAFT_FALLBACK_ASSETS_MANAGER) registries.parentRegistries = version.registries - player = Player(account, this) + player = LocalPlayerEntity(account, this) if (!RenderConstants.DISABLE_RENDERING && !StaticConfiguration.HEADLESS_MODE) { val renderer = Rendering(this) diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/c2s/login/LoginStartC2SP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/c2s/login/LoginStartC2SP.kt index 54c1064e6..3126340df 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/c2s/login/LoginStartC2SP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/c2s/login/LoginStartC2SP.kt @@ -12,7 +12,7 @@ */ package de.bixilon.minosoft.protocol.packets.c2s.login -import de.bixilon.minosoft.data.player.Player +import de.bixilon.minosoft.data.player.LocalPlayerEntity import de.bixilon.minosoft.protocol.packets.c2s.PlayC2SPacket import de.bixilon.minosoft.protocol.protocol.PlayOutByteBuffer import de.bixilon.minosoft.util.logging.Log @@ -23,7 +23,7 @@ class LoginStartC2SP( val username: String, ) : PlayC2SPacket { - constructor(player: Player) : this(player.entity.name) + constructor(player: LocalPlayerEntity) : this(player.name) override fun write(buffer: PlayOutByteBuffer) { buffer.writeString(username) diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/login/LoginSuccessS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/login/LoginSuccessS2CP.kt index 76e893567..6032626a3 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/login/LoginSuccessS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/login/LoginSuccessS2CP.kt @@ -35,7 +35,7 @@ class LoginSuccessS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { override fun handle(connection: PlayConnection) { connection.connectionState = ConnectionStates.PLAY - val playerEntity = connection.player.entity + val playerEntity = connection.player playerEntity.tabListItem.name = name playerEntity.tabListItem.displayName = ChatComponent.of(name) diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/ExplosionS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/ExplosionS2CP.kt index a7f3fceb8..ac38a8a05 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/ExplosionS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/ExplosionS2CP.kt @@ -41,7 +41,7 @@ class ExplosionS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { val blockPosition = Vec3i(position + record) connection.world.setBlockState(blockPosition, null) } - connection.player.entity.velocity = connection.player.entity.velocity + velocity + connection.player.velocity = connection.player.velocity + velocity connection.fireEvent(ExplosionEvent(connection, this)) } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/JoinGameS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/JoinGameS2CP.kt index a64c244cb..1cbe9a777 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/JoinGameS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/JoinGameS2CP.kt @@ -136,7 +136,7 @@ class JoinGameS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { if (connection.fireEvent(JoinGameEvent(connection, this))) { return } - val playerEntity = connection.player.entity + val playerEntity = connection.player playerEntity.tabListItem.gamemode = gamemode connection.world.hardcore = isHardcore diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerAbilitiesS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerAbilitiesS2CP.kt index 101ed3b9c..625a5f930 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerAbilitiesS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerAbilitiesS2CP.kt @@ -46,7 +46,7 @@ class PlayerAbilitiesS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { } override fun log() { - Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Player abilities: (isInvulnerable=$isInvulnerable, isFlying=$isFlying, canFly=$canFly, canInstantBuild=$canInstantBuild, flyingSpeed=$flyingSpeed, walkingSpeed=$walkingSpeed)" } + Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "LocalPlayerEntity abilities: (isInvulnerable=$isInvulnerable, isFlying=$isFlying, canFly=$canFly, canInstantBuild=$canInstantBuild, flyingSpeed=$flyingSpeed, walkingSpeed=$walkingSpeed)" } } override fun handle(connection: PlayConnection) { diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerEntitySpawnS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerEntitySpawnS2CP.kt index 2e10d2283..fee8358f4 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerEntitySpawnS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PlayerEntitySpawnS2CP.kt @@ -16,6 +16,7 @@ import de.bixilon.minosoft.config.StaticConfiguration import de.bixilon.minosoft.data.PlayerPropertyData 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.meta.EntityMetaData import de.bixilon.minosoft.modding.event.events.EntitySpawnEvent import de.bixilon.minosoft.protocol.network.connection.PlayConnection @@ -66,9 +67,9 @@ class PlayerEntitySpawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { if (buffer.versionId < ProtocolVersions.V_19W34A) { metaData = buffer.readMetaData() } - entity = PlayerEntity( + entity = RemotePlayerEntity( connection = buffer.connection, - entityType = buffer.connection.registries.entityTypeRegistry[PlayerEntity.RESOURCE_LOCATION]!!, + entityType = buffer.connection.registries.entityTypeRegistry[RemotePlayerEntity.RESOURCE_LOCATION]!!, position = position, rotation = EntityRotation(yaw.toFloat(), pitch.toFloat(), 0.0f), name = name, @@ -91,6 +92,6 @@ class PlayerEntitySpawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { } override fun log() { - Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Player entity spawn (position=${entity.position}, entityId=$entityId, name=${entity.name}, uuid=$entityUUID)" } + Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "LocalPlayerEntity entity spawn (position=${entity.position}, entityId=$entityId, name=${entity.name}, uuid=$entityUUID)" } } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PositionAndRotationS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PositionAndRotationS2CP.kt index 1da71e919..29ed23e52 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PositionAndRotationS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/PositionAndRotationS2CP.kt @@ -51,7 +51,7 @@ class PositionAndRotationS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { } override fun handle(connection: PlayConnection) { - val entity = connection.player.entity + val entity = connection.player // correct position with flags (relative position possible) if (BitByte.isBitMask(flags, 0x01)) { position.x += entity.position.x @@ -82,6 +82,6 @@ class PositionAndRotationS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { } override fun log() { - Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Player position (position=$position, rotation=$rotation, onGround=$isOnGround)" } + Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "LocalPlayerEntity position (position=$position, rotation=$rotation, onGround=$isOnGround)" } } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/RespawnS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/RespawnS2CP.kt index c83d8eb31..d0ea1b56b 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/RespawnS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/RespawnS2CP.kt @@ -89,8 +89,8 @@ class RespawnS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { connection.world.chunks.clear() connection.world.dimension = dimension connection.player.isSpawnConfirmed = false - connection.player.entity.tabListItem.gamemode = gamemode - connection.player.entity.velocity = Vec3() + connection.player.tabListItem.gamemode = gamemode + connection.player.velocity = Vec3() connection.fireEvent(RespawnEvent(connection, this)) } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/TabListDataS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/TabListDataS2CP.kt index 389d85734..2ccb9a651 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/TabListDataS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/TabListDataS2CP.kt @@ -158,7 +158,7 @@ class TabListDataS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket() { } ?: continue - if (entity === connection.player.entity) { + if (entity === connection.player) { entity.tabListItem.specialMerge(data) continue } diff --git a/src/main/java/de/bixilon/minosoft/util/MMath.kt b/src/main/java/de/bixilon/minosoft/util/MMath.kt index 4a5ba0c66..46ed13581 100644 --- a/src/main/java/de/bixilon/minosoft/util/MMath.kt +++ b/src/main/java/de/bixilon/minosoft/util/MMath.kt @@ -97,10 +97,15 @@ object MMath { val Float.ceilInt: Int get() = glm.ceil(this).toInt() - val Boolean.positiveNegative: Int get() = - if (this) { - 1 - } else { - -1 - } + val Boolean.positiveNegative: Int + get() = + if (this) { + 1 + } else { + -1 + } + + fun lerp(delta: Float, start: Float, end: Float): Float { + return start + delta * (end - start) + } }