Skip to content

Commit

Permalink
feat: implement bonfire-addon model system
Browse files Browse the repository at this point in the history
  • Loading branch information
Boy0000 committed Oct 14, 2024
1 parent 8157ec3 commit 9e4419a
Show file tree
Hide file tree
Showing 7 changed files with 105 additions and 7 deletions.
2 changes: 2 additions & 0 deletions src/main/kotlin/com/mineinabyss/bonfire/BonfireCommands.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.mineinabyss.blocky.helpers.GenericHelpers.toBlockCenterLocation
import com.mineinabyss.bonfire.components.Bonfire
import com.mineinabyss.bonfire.components.BonfireDebug
import com.mineinabyss.bonfire.components.BonfireRespawn
import com.mineinabyss.bonfire.extensions.BonfirePacketHelpers
import com.mineinabyss.bonfire.extensions.updateBonfireState
import com.mineinabyss.geary.papermc.datastore.decode
import com.mineinabyss.geary.papermc.datastore.encode
Expand Down Expand Up @@ -127,6 +128,7 @@ object BonfireCommands {
}
bonfire.bonfirePlayers += offlinePlayer.uniqueId
bonfireEntity.updateBonfireState()
BonfirePacketHelpers.sendAddonPacket(bonfireEntity)
sender.success("Set respawn point for ${offlinePlayer.name} to $x $y $z in ${world.name}")
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/com/mineinabyss/bonfire/components/Bonfire.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.mineinabyss.bonfire.components

import com.charleskorn.kaml.YamlComment
import com.mineinabyss.bonfire.bonfire
import com.mineinabyss.geary.prefabs.PrefabKey
import com.mineinabyss.geary.prefabs.serializers.PrefabKeySerializer
Expand All @@ -18,6 +19,8 @@ data class Bonfire(
val maxPlayerCount: Int = bonfire.config.maxPlayerCount,
val bonfireExpirationTime: @Serializable(with = DurationSerializer::class) Duration = bonfire.config.bonfireExpirationTime,
val states: BonfireStates,
@YamlComment("Item to spawn in addition to bonfire, mainly for visually representing player-count")
val addons: List<@Serializable(PrefabKeySerializer::class) PrefabKey> = emptyList()
) {
@Serializable
data class BonfireStates(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ fun Player.removeOldBonfire() {
}
}



/**
* Updates the bonfire state for all players.
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package com.mineinabyss.bonfire.extensions

import com.github.shynixn.mccoroutine.bukkit.launch
import com.mineinabyss.blocky.api.BlockyFurnitures.isBlockyFurniture
import com.mineinabyss.blocky.helpers.FurnitureUUID
import com.mineinabyss.bonfire.bonfire
import com.mineinabyss.bonfire.components.Bonfire
import com.mineinabyss.geary.papermc.tracking.entities.toGearyOrNull
import com.mineinabyss.geary.papermc.tracking.items.gearyItems
import com.mineinabyss.idofront.nms.aliases.toNMS
import com.mineinabyss.idofront.time.ticks
import it.unimi.dsi.fastutil.ints.IntList
import kotlinx.coroutines.delay
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket
import net.minecraft.network.protocol.game.ClientboundBundlePacket
import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket
import net.minecraft.network.syncher.EntityDataSerializers
import net.minecraft.network.syncher.SynchedEntityData
import net.minecraft.world.entity.Display
import net.minecraft.world.entity.EntityType
import org.bukkit.craftbukkit.entity.CraftPlayer
import org.bukkit.craftbukkit.inventory.CraftItemStack
import org.bukkit.entity.ItemDisplay
import org.bukkit.entity.Player

object BonfirePacketHelpers {

data class BonfireAddonEntity(val furnitureUUID: FurnitureUUID, val addonEntity: Display.ItemDisplay)
data class BonfireAddonPacket(val addonEntity: Display.ItemDisplay, val addEntity: ClientboundAddEntityPacket, val addons: List<ClientboundSetEntityDataPacket>) {
fun bundlePacket(bonfireSize: Int) : ClientboundBundlePacket {
return ClientboundBundlePacket(listOf(addEntity, addons.elementAtOrNull(bonfireSize)))
}
}

private val bonfireAddons = mutableSetOf<BonfireAddonEntity>()
private val bonfireAddonPackets = mutableMapOf<FurnitureUUID, BonfireAddonPacket>()

fun sendAddonPacket(furniture: ItemDisplay) {
furniture.world.players.filter { it.canSee(furniture) }.forEach { sendAddonPacket(furniture, it) }
}

fun sendAddonPacket(furniture: ItemDisplay, player: Player) {
if (!furniture.isBlockyFurniture) return

val plugin = bonfire.plugin
val bonfire = furniture.toGearyOrNull()?.get<Bonfire>() ?: return
val nmsFurniture = furniture.toNMS()
val nmsWorld = nmsFurniture.level()
bonfireAddonPackets.computeIfAbsent(furniture.uniqueId) {
val addonEntity = bonfireAddons.firstOrNull { it.furnitureUUID == furniture.uniqueId }?.addonEntity
?: BonfireAddonEntity(furniture.uniqueId, Display.ItemDisplay(EntityType.ITEM_DISPLAY, nmsWorld))
.apply(bonfireAddons::add).addonEntity.apply { teleportTo(furniture.x, furniture.y, furniture.z) }

val entityPacket = ClientboundAddEntityPacket(addonEntity, nmsFurniture.`moonrise$getTrackedEntity`().serverEntity)
val metadataPackets = bonfire.addons.mapNotNull { addon ->
val item = gearyItems.createItem(addon) ?: return@mapNotNull null
ClientboundSetEntityDataPacket(addonEntity.id,
listOf(SynchedEntityData.DataValue(23, EntityDataSerializers.ITEM_STACK, CraftItemStack.asNMSCopy(item)))
)
}
BonfireAddonPacket(addonEntity, entityPacket, metadataPackets)
}.bundlePacket(bonfire.bonfirePlayers.size).let {
plugin.launch {
delay(2.ticks)
(player as CraftPlayer).handle.connection.send(it)
}
}
}

fun removeAddonPacket(furniture: ItemDisplay) {
furniture.world.players.filter { it.canSee(furniture) }.forEach {
removeAddonPacket(furniture, it)
}
bonfireAddons.removeIf { it.furnitureUUID == furniture.uniqueId }
bonfireAddonPackets.remove(furniture.uniqueId)
}

fun removeAddonPacket(furniture: ItemDisplay, player: Player) {
val addonEntity = bonfireAddons.firstOrNull { it.furnitureUUID == furniture.uniqueId }?.addonEntity ?: return
(player as CraftPlayer).handle.connection.send(ClientboundRemoveEntitiesPacket(IntList.of(addonEntity.id)))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import com.mineinabyss.blocky.api.events.furniture.BlockyFurnitureInteractEvent
import com.mineinabyss.blocky.api.events.furniture.BlockyFurniturePlaceEvent
import com.mineinabyss.bonfire.bonfire
import com.mineinabyss.bonfire.components.*
import com.mineinabyss.bonfire.extensions.canBreakBonfire
import com.mineinabyss.bonfire.extensions.isBonfire
import com.mineinabyss.bonfire.extensions.removeOldBonfire
import com.mineinabyss.bonfire.extensions.updateBonfireState
import com.mineinabyss.bonfire.extensions.*
import com.mineinabyss.geary.actions.ActionGroupContext
import com.mineinabyss.geary.actions.execute
import com.mineinabyss.geary.helpers.with
Expand Down Expand Up @@ -142,9 +139,10 @@ class BonfireListener : Listener {
}
}

baseEntity.updateBonfireState()
gearyBonfire.encodeComponentsTo(baseEntity) // Ensure data is saved to PDC
gearyPlayer.encodeComponentsTo(player)
baseEntity.updateBonfireState()
BonfirePacketHelpers.sendAddonPacket(baseEntity)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class DebugListener : Listener {
}

private fun createDebugText(bonfire: Bonfire) = """
<yellow>Bonfire-size <gold>"${bonfire.bonfirePlayers.size}/${bonfire.maxPlayerCount}"
<yellow>Bonfire-size <gold>${bonfire.bonfirePlayers.size}/${bonfire.maxPlayerCount}
<gray>Players: ${bonfire.bonfirePlayers.joinToString { it.toOfflinePlayer().name.toString() }}
""".trimIndent()
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import com.mineinabyss.bonfire.bonfire
import com.mineinabyss.bonfire.components.Bonfire
import com.mineinabyss.bonfire.components.BonfireRemoved
import com.mineinabyss.bonfire.components.BonfireRespawn
import com.mineinabyss.bonfire.extensions.BonfirePacketHelpers
import com.mineinabyss.bonfire.extensions.filterIsBonfire
import com.mineinabyss.bonfire.extensions.isBonfire
import com.mineinabyss.bonfire.extensions.updateBonfireState
Expand All @@ -15,6 +16,7 @@ import com.mineinabyss.idofront.entities.rightClicked
import com.mineinabyss.idofront.messaging.error
import com.mineinabyss.idofront.messaging.info
import io.papermc.paper.event.player.PlayerTrackEntityEvent
import io.papermc.paper.event.player.PlayerUntrackEntityEvent
import kotlinx.coroutines.delay
import org.bukkit.block.Block
import org.bukkit.block.BlockFace
Expand Down Expand Up @@ -74,7 +76,15 @@ class PlayerListener : Listener {

@EventHandler
fun PlayerTrackEntityEvent.onTrackBonfire() {
(entity as? ItemDisplay)?.updateBonfireState()
val furniture = entity as? ItemDisplay ?: return
furniture.updateBonfireState()
BonfirePacketHelpers.sendAddonPacket(furniture, player)
}

@EventHandler
fun PlayerUntrackEntityEvent.onUntrackBonfire() {
val furniture = entity as? ItemDisplay ?: return
BonfirePacketHelpers.removeAddonPacket(furniture, player)
}

@EventHandler(priority = EventPriority.HIGHEST)
Expand Down

0 comments on commit 9e4419a

Please sign in to comment.