Skip to content
This repository was archived by the owner on Nov 28, 2025. It is now read-only.

Commit db0c9f3

Browse files
authored
Merge pull request #115 from DockyardMC/feature/metadata-fixes
Feature/metadata fixes
2 parents a048b19 + 1b99e05 commit db0c9f3

File tree

11 files changed

+117
-32
lines changed

11 files changed

+117
-32
lines changed

src/main/kotlin/io/github/dockyardmc/entity/Entity.kt

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import cz.lukynka.bindables.BindableList
55
import cz.lukynka.bindables.BindableMap
66
import cz.lukynka.bindables.BindablePool
77
import io.github.dockyardmc.config.ConfigManager
8+
import io.github.dockyardmc.entity.EntityManager.despawnEntity
89
import io.github.dockyardmc.entity.handlers.*
910
import io.github.dockyardmc.events.*
1011
import io.github.dockyardmc.extentions.sendPacket
@@ -19,9 +20,11 @@ import io.github.dockyardmc.protocol.packets.ClientboundPacket
1920
import io.github.dockyardmc.protocol.packets.play.clientbound.*
2021
import io.github.dockyardmc.registry.AppliedPotionEffect
2122
import io.github.dockyardmc.registry.AppliedPotionEffectSettings
23+
import io.github.dockyardmc.registry.DamageTypes
2224
import io.github.dockyardmc.registry.registries.DamageType
2325
import io.github.dockyardmc.registry.registries.EntityType
2426
import io.github.dockyardmc.registry.registries.PotionEffect
27+
import io.github.dockyardmc.runnables.ticks
2528
import io.github.dockyardmc.sounds.Sound
2629
import io.github.dockyardmc.sounds.playSound
2730
import io.github.dockyardmc.team.Team
@@ -53,14 +56,17 @@ abstract class Entity(open var location: Location, open var world: World) : Disp
5356
open var isOnGround: Boolean = true
5457
open var tickable: Boolean = true
5558

56-
val displayName: Bindable<String?> = bindablePool.provideBindable(null)
59+
val customName: Bindable<String?> = bindablePool.provideBindable(null)
60+
val customNameVisible: Bindable<Boolean> = bindablePool.provideBindable(false)
5761
val metadata: BindableMap<EntityMetadataType, EntityMetadata> = bindablePool.provideBindableMap()
5862
val pose: Bindable<EntityPose> = bindablePool.provideBindable(EntityPose.STANDING)
59-
val walkSpeed: Bindable<Float> = Bindable(0.15f)
63+
val walkSpeed: Bindable<Float> = bindablePool.provideBindable(0.15f)
6064
val metadataLayers: BindableMap<PersistentPlayer, MutableMap<EntityMetadataType, EntityMetadata>> = bindablePool.provideBindableMap()
6165
val isOnFire: Bindable<Boolean> = bindablePool.provideBindable(false)
6266
val freezeTicks: Bindable<Int> = bindablePool.provideBindable(0)
63-
var hasNoGravity: Bindable<Boolean> = Bindable(true)
67+
var hasNoGravity: Bindable<Boolean> = bindablePool.provideBindable(true)
68+
val isSilent: Bindable<Boolean> = bindablePool.provideBindable(false)
69+
val stuckArrows: Bindable<Int> = bindablePool.provideBindable(0)
6470

6571
val potionEffects: BindableMap<PotionEffect, AppliedPotionEffect> = bindablePool.provideBindableMap()
6672
val isInvisible: Bindable<Boolean> = bindablePool.provideBindable(false)
@@ -82,12 +88,13 @@ abstract class Entity(open var location: Location, open var world: World) : Disp
8288
val potionEffectsHandler = EntityPotionEffectsHandler(this)
8389
val itemPickupHandler = EntityItemPickupHandler(this)
8490

91+
var isDead: Boolean = false
92+
8593
override var autoViewable: Boolean = true
8694

8795
constructor(location: Location) : this(location, location.world)
8896

8997
init {
90-
9198
equipmentHandler.handle(equipment, equipmentLayers)
9299
vehicleHandler.handle(passengers)
93100
potionEffectsHandler.handle(potionEffects)
@@ -99,7 +106,11 @@ abstract class Entity(open var location: Location, open var world: World) : Disp
99106
metadataLayers = metadataLayers,
100107
isGlowing = isGlowing,
101108
isInvisible = isInvisible,
102-
pose = pose
109+
pose = pose,
110+
isSilent = isSilent,
111+
customName = customName,
112+
customNameVisible = customNameVisible,
113+
stuckArrows = stuckArrows,
103114
)
104115

105116
//TODO add attribute modifiers
@@ -253,18 +264,29 @@ abstract class Entity(open var location: Location, open var world: World) : Disp
253264
val event = EntityDamageEvent(this, damage, damageType, attacker, projectile)
254265
Events.dispatch(event)
255266
if (event.cancelled) return
267+
if(isDead) return
256268

257269
var location: Location? = null
258270
if (attacker != null) location = attacker.location
259271
if (projectile != null) location = projectile.location
260272

261273
if (event.damage > 0) {
274+
playDamageAnimation(damageType)
262275
if (!isInvulnerable) {
263276
if (health.value - event.damage <= 0) kill() else health.value -= event.damage
264277
}
265278
}
279+
}
266280

267-
val packet = ClientboundDamageEventPacket(this, event.damageType, event.attacker, event.projectile, location)
281+
fun playDeathAnimation() {
282+
val packet = ClientboundEntityEventPacket(this, EntityEvent.ENTITY_DIE)
283+
pose.value = EntityPose.DYING
284+
viewers.sendPacket(packet)
285+
passengers.clear(false)
286+
}
287+
288+
fun playDamageAnimation(damageType: DamageType = DamageTypes.GENERIC) {
289+
val packet = ClientboundDamageEventPacket(this, damageType, null, null, null)
268290
viewers.sendPacket(packet)
269291
}
270292

@@ -273,13 +295,19 @@ abstract class Entity(open var location: Location, open var world: World) : Disp
273295
}
274296

275297
open fun kill() {
298+
if(isDead) return
276299
val event = EntityDeathEvent(this)
277300
Events.dispatch(event)
278301
if (event.cancelled) {
279302
health.value = 0.1f
280303
return
281304
}
305+
isDead = true
282306
health.value = 0f;
307+
playDeathAnimation()
308+
world.scheduler.runLater(20.ticks) {
309+
world.despawnEntity(this)
310+
}
283311
}
284312

285313
data class BoundingBox(

src/main/kotlin/io/github/dockyardmc/entity/TestZombie.kt

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,13 @@ import io.github.dockyardmc.location.Location
1313
import io.github.dockyardmc.pathfinding.Navigator
1414
import io.github.dockyardmc.pathfinding.Pathfinder
1515
import io.github.dockyardmc.pathfinding.RequiredHeightPathfindingFilter
16+
import io.github.dockyardmc.registry.DamageTypes
1617
import io.github.dockyardmc.registry.EntityTypes
18+
import io.github.dockyardmc.registry.Sounds
19+
import io.github.dockyardmc.registry.registries.DamageType
1720
import io.github.dockyardmc.registry.registries.EntityType
1821
import io.github.dockyardmc.sounds.Sound
22+
import io.github.dockyardmc.sounds.playSound
1923
import io.github.dockyardmc.utils.randomFloat
2024
import io.github.dockyardmc.utils.randomInt
2125

@@ -38,22 +42,16 @@ class TestZombie(location: Location) : Entity(location) {
3842
init {
3943

4044
brain.addGoal(ZombieLookAroundAIGoal(this, 1))
41-
brain.addGoal(ZombieGroanAiGoal(this, 1))
42-
brain.addGoal(RandomWalkAroundGoal(this, 1, navigator))
45+
// brain.addGoal(ZombieGroanAiGoal(this, 1))
46+
// brain.addGoal(RandomWalkAroundGoal(this, 1, navigator))
4347

44-
eventPool.on<PlayerDamageEntityEvent> {
45-
val entity = it.entity
48+
eventPool.on<PlayerDamageEntityEvent> { event ->
49+
val entity = event.entity
4650
if (entity != this) return@on
4751

48-
entity.playSoundToViewers(Sound("minecraft:entity.zombie.damage", pitch = randomFloat(0.7f, 1.2f)))
49-
}
50-
51-
eventPool.on<PlayerMoveEvent> {
52-
val dist = it.player.location.distance(this.location)
53-
if(it.player.isFlying.value) return@on
54-
if (dist > 7) return@on
55-
56-
navigator.updatePathfindingPath(it.player.location.subtract(0, 1, 0))
52+
entity.world.playSound(Sounds.ENTITY_ZOMBIE_HURT, pitch = randomFloat(0.7f, 1.2f))
53+
entity.damage(1f, DamageTypes.GENERIC, event.player, event.entity)
54+
event.player.sendMessage("<red>${health.value}")
5755
}
5856

5957
// eventPool.on<PlayerInteractWithEntityEvent> {

src/main/kotlin/io/github/dockyardmc/entity/handlers/EntityMetadataHandler.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import cz.lukynka.bindables.BindableMap
55
import io.github.dockyardmc.entity.*
66
import io.github.dockyardmc.player.EntityPose
77
import io.github.dockyardmc.player.PersistentPlayer
8+
import io.github.dockyardmc.scroll.extensions.toComponent
89

910
class EntityMetadataHandler(override val entity: Entity) : EntityHandler {
1011

@@ -17,6 +18,10 @@ class EntityMetadataHandler(override val entity: Entity) : EntityHandler {
1718
isGlowing: Bindable<Boolean>,
1819
isInvisible: Bindable<Boolean>,
1920
pose: Bindable<EntityPose>,
21+
isSilent: Bindable<Boolean>,
22+
customName: Bindable<String?>,
23+
customNameVisible: Bindable<Boolean>,
24+
stuckArrows: Bindable<Int>,
2025
) {
2126
hasNoGravity.valueChanged {
2227
val noGravityType = EntityMetadataType.HAS_NO_GRAVITY
@@ -35,6 +40,22 @@ class EntityMetadataHandler(override val entity: Entity) : EntityHandler {
3540
entity.metadata[EntityMetadataType.FROZEN_TICKS] = meta
3641
}
3742

43+
isSilent.valueChanged {
44+
val meta = EntityMetadata(EntityMetadataType.SILENT, EntityMetaValue.BOOLEAN, it.newValue)
45+
entity.metadata[EntityMetadataType.SILENT] = meta
46+
}
47+
48+
customName.valueChanged {
49+
val textComponent = if(it.newValue != null) it.newValue!!.toComponent() else null
50+
val meta = EntityMetadata(EntityMetadataType.CUSTOM_NAME, EntityMetaValue.OPTIONAL_TEXT_COMPONENT, textComponent)
51+
entity.metadata[EntityMetadataType.CUSTOM_NAME] = meta
52+
}
53+
54+
customNameVisible.valueChanged {
55+
val meta = EntityMetadata(EntityMetadataType.IS_CUSTOM_NAME_VISIBLE, EntityMetaValue.BOOLEAN, it.newValue)
56+
entity.metadata[EntityMetadataType.IS_CUSTOM_NAME_VISIBLE] = meta
57+
}
58+
3859
metadata.mapUpdated {
3960
entity.sendMetadataPacketToViewers()
4061
entity.sendSelfMetadataIfPlayer()

src/main/kotlin/io/github/dockyardmc/events/CancellableEvent.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,8 @@ package io.github.dockyardmc.events
22

33
abstract class CancellableEvent: Event {
44
open var cancelled: Boolean = false
5+
6+
fun cancel() {
7+
cancelled = true
8+
}
59
}

src/main/kotlin/io/github/dockyardmc/extentions/ExtendedByteBuf.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,11 +269,12 @@ fun ByteBuf.readUtfAndLength(i: Int): Pair<String, Int> {
269269
return string to size
270270
}
271271

272-
fun ByteBuf.writeString(text: String) {
272+
fun ByteBuf.writeString(text: String): ByteBuf {
273273
val utf8Bytes = text.toByteArray(StandardCharsets.UTF_8)
274274
val length = utf8Bytes.size
275275
this.writeVarInt(length)
276276
this.writeBytes(utf8Bytes)
277+
return this
277278
}
278279

279280
fun ByteBuf.toByteArraySafe(): ByteArray {

src/main/kotlin/io/github/dockyardmc/extentions/ExtendedMutableList.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import io.github.dockyardmc.player.setSkin
1212
import io.github.dockyardmc.player.systems.GameMode
1313
import io.github.dockyardmc.protocol.packets.ClientboundPacket
1414
import io.github.dockyardmc.registry.registries.Item
15+
import io.github.dockyardmc.protocol.packets.play.clientbound.SoundCategory
1516
import io.github.dockyardmc.scroll.Component
1617
import io.github.dockyardmc.scroll.extensions.toComponent
1718
import java.util.UUID
@@ -52,6 +53,14 @@ fun Collection<Player>.playChestAnimation(chestLocation: Location, animation: Ch
5253
this.forEach { player -> player.playChestAnimation(chestLocation, animation) }
5354
}
5455

56+
fun Collection<Player>.stopSound(sound: String? = null, category: SoundCategory? = null) {
57+
this.forEach { player -> player.stopSound(sound, category) }
58+
}
59+
60+
fun Collection<Player>.stopSound(category: SoundCategory = SoundCategory.MASTER) {
61+
this.forEach { player -> player.stopSound(null, category) }
62+
}
63+
5564
fun Collection<Player>.sendMessage(message: String) {
5665
this.forEach { it.sendMessage(message) }
5766
}

src/main/kotlin/io/github/dockyardmc/inventory/PlayerInventory.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ class PlayerInventory(var player: Player) : EntityInventory(player, INVENTORY_SI
7171
val mainHandItem = player.mainHandItem
7272

7373
val event = PlayerSwapOffhandEvent(player, mainHandItem, offhandItem, getPlayerEventContext(player))
74+
Events.dispatch(event)
7475
if(event.cancelled) return
7576

7677
player.mainHandItem = event.offHandItem

src/main/kotlin/io/github/dockyardmc/player/Player.kt

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ class Player(
139139
init {
140140

141141
gameModeSystem.handle(gameMode)
142-
playerInfoSystem.handle(displayName, isListed)
142+
playerInfoSystem.handle(customName, isListed)
143143

144144
heldSlotIndex.valueChanged {
145145
this.sendPacket(ClientboundSetHeldItemPacket(it.newValue))
@@ -246,7 +246,7 @@ class Player(
246246
if (player == this) return
247247
val infoUpdatePacket = PlayerInfoUpdate(uuid, AddPlayerInfoUpdateAction(ProfilePropertyMap(username, mutableListOf(profile!!.properties[0]))))
248248
player.sendPacket(ClientboundPlayerInfoUpdatePacket(infoUpdatePacket))
249-
val namePacket = ClientboundPlayerInfoUpdatePacket(PlayerInfoUpdate(uuid, SetDisplayNameInfoUpdateAction(displayName.value)))
249+
val namePacket = ClientboundPlayerInfoUpdatePacket(PlayerInfoUpdate(uuid, SetDisplayNameInfoUpdateAction(customName.value)))
250250
player.sendPacket(namePacket)
251251

252252
super.addViewer(player)
@@ -531,6 +531,18 @@ class Player(
531531
sendPacket(ClientboundBlockActionPacket(chestLocation, 1, animation.ordinal.toByte(), Blocks.CHEST))
532532
}
533533

534+
fun stopSound(sound: String? = null, category: SoundCategory? = null) {
535+
var flags = 0x0
536+
if(category != null) flags = flags or 0x1
537+
if(sound != null) flags = flags or 0x2
538+
539+
sendPacket(ClientboundStopSoundPacket(flags.toByte(), category, sound))
540+
}
541+
542+
fun stopSound(category: SoundCategory = SoundCategory.MASTER) {
543+
stopSound(null, category)
544+
}
545+
534546
enum class ChestAnimation {
535547
CLOSE,
536548
OPEN
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package io.github.dockyardmc.protocol.packets.play.clientbound
2+
3+
import io.github.dockyardmc.extentions.writeByte
4+
import io.github.dockyardmc.extentions.writeString
5+
import io.github.dockyardmc.extentions.writeVarInt
6+
import io.github.dockyardmc.protocol.packets.ClientboundPacket
7+
8+
class ClientboundStopSoundPacket(flags: Byte, category: SoundCategory?, sound: String?): ClientboundPacket() {
9+
10+
init {
11+
buffer.writeByte(flags)
12+
if((flags == 3.toByte() || flags == 1.toByte()) && category != null) {
13+
buffer.writeVarInt(category.ordinal)
14+
}
15+
if((flags == 2.toByte() || flags == 3.toByte()) && sound != null) {
16+
buffer.writeString(sound)
17+
}
18+
}
19+
20+
}

src/main/kotlin/io/github/dockyardmc/protocol/packets/play/serverbound/ServerboundEntityInteractPacket.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,6 @@ class ServerboundEntityInteractPacket(
3232
if (interactionType == EntityInteractionType.ATTACK) {
3333
val event = PlayerDamageEntityEvent(player, entity)
3434
Events.dispatch(event)
35-
if (event.cancelled) return
36-
37-
//TODO handle damagé stuff
3835
}
3936

4037
if (interactionType == EntityInteractionType.INTERACT) {
@@ -43,18 +40,12 @@ class ServerboundEntityInteractPacket(
4340

4441
val event = PlayerInteractWithEntityEvent(player, entity, hand!!)
4542
Events.dispatch(event)
46-
if (event.cancelled) return
47-
48-
//TODO handle stuff I guess
4943
}
5044

5145
if (interactionType == EntityInteractionType.INTERACT_AT) {
5246

5347
val event = PlayerInteractAtEntityEvent(player, entity, Vector3f(targetX!!, targetY!!, targetZ!!), hand!!)
5448
Events.dispatch(event)
55-
if (event.cancelled) return
56-
57-
//TODO what does this even do in vanilla actually
5849
}
5950
}
6051

0 commit comments

Comments
 (0)