Skip to content

Commit 3d4aa5f

Browse files
committed
feat: introduce glowing support for blocks and refactor glowing API
- Added block-specific glowing functionality in `SurfGlowingApi` with `makeGlowing` and `removeGlowing` for both blocks and locations. - Implemented `BlockGlowingData` and `BlockPlayerData` for managing block-specific glowing states. - Enhanced packet handling with `GlowingPacketListener` for better bundle packet support and glowing flag updates. - Introduced `GlowingBlockTest` command to test block-related glowing features. - Refactored entity-related glowing classes (`GlowingData` to `EntityGlowingData`, `PlayerData` to `EntityPlayerData`) for consistency. - Updated `GlowingListener` to handle chunk load events for block glowing states. - Improved internal APIs and tests to align with the new glowing features.
1 parent 2d908c4 commit 3d4aa5f

File tree

14 files changed

+334
-41
lines changed

14 files changed

+334
-41
lines changed

surf-api-bukkit/surf-api-bukkit-api/api/surf-api-bukkit-api.api

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1384,6 +1384,33 @@ public final class dev/slne/surf/surfapi/bukkit/api/extensions/Org_bukkit_plugin
13841384
public static final fun getPluginManager ()Lorg/bukkit/plugin/PluginManager;
13851385
}
13861386

1387+
public abstract interface class dev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi {
1388+
public static final field Companion Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi$Companion;
1389+
public abstract fun makeGlowing (ILjava/lang/String;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;B)V
1390+
public abstract fun makeGlowing (Lorg/bukkit/Location;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;)V
1391+
public abstract fun makeGlowing (Lorg/bukkit/block/Block;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;)V
1392+
public abstract fun makeGlowing (Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;)V
1393+
public static synthetic fun makeGlowing$default (Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi;ILjava/lang/String;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;BILjava/lang/Object;)V
1394+
public static synthetic fun makeGlowing$default (Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi;Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;ILjava/lang/Object;)V
1395+
public abstract fun removeGlowing (ILorg/bukkit/entity/Player;)V
1396+
public abstract fun removeGlowing (Lorg/bukkit/Location;Lorg/bukkit/entity/Player;)V
1397+
public abstract fun removeGlowing (Lorg/bukkit/block/Block;Lorg/bukkit/entity/Player;)V
1398+
public abstract fun removeGlowing (Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Player;)V
1399+
}
1400+
1401+
public final class dev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi$Companion {
1402+
public final fun getInstance ()Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi;
1403+
}
1404+
1405+
public final class dev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi$DefaultImpls {
1406+
public static synthetic fun makeGlowing$default (Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi;ILjava/lang/String;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;BILjava/lang/Object;)V
1407+
public static synthetic fun makeGlowing$default (Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi;Lorg/bukkit/entity/Entity;Lorg/bukkit/entity/Player;Lnet/kyori/adventure/text/format/NamedTextColor;ILjava/lang/Object;)V
1408+
}
1409+
1410+
public final class dev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApiKt {
1411+
public static final fun getGlowingApi ()Ldev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi;
1412+
}
1413+
13871414
public abstract interface class dev/slne/surf/surfapi/bukkit/api/hook/papi/SurfBukkitPAPIHook {
13881415
public static final field Companion Ldev/slne/surf/surfapi/bukkit/api/hook/papi/SurfBukkitPAPIHook$Companion;
13891416
public static fun getInstance ()Ldev/slne/surf/surfapi/bukkit/api/hook/papi/SurfBukkitPAPIHook;
@@ -1590,6 +1617,19 @@ public final class dev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsCom
15901617
public static final fun getNmsCommonBridge ()Ldev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsCommonBridge;
15911618
}
15921619

1620+
public abstract interface class dev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsGlowingBridge {
1621+
public static final field Companion Ldev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsGlowingBridge$Companion;
1622+
public abstract fun getCurrentFlags (Lorg/bukkit/entity/Entity;)B
1623+
}
1624+
1625+
public final class dev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsGlowingBridge$Companion {
1626+
public final fun getInstance ()Ldev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsGlowingBridge;
1627+
}
1628+
1629+
public final class dev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsGlowingBridgeKt {
1630+
public static final fun getGlowingBridge ()Ldev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsGlowingBridge;
1631+
}
1632+
15931633
public abstract interface class dev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsItemBridge {
15941634
public static final field Companion Ldev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsItemBridge$Companion;
15951635
public static fun getInstance ()Ldev/slne/surf/surfapi/bukkit/api/nms/bridges/SurfBukkitNmsItemBridge;

surf-api-bukkit/surf-api-bukkit-api/src/main/kotlin/dev/slne/surf/surfapi/bukkit/api/glow/SurfGlowingApi.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package dev.slne.surf.surfapi.bukkit.api.glow
22

33
import dev.slne.surf.surfapi.core.api.util.requiredService
44
import net.kyori.adventure.text.format.NamedTextColor
5+
import org.bukkit.Location
6+
import org.bukkit.block.Block
57
import org.bukkit.entity.Entity
68
import org.bukkit.entity.Player
79

@@ -17,9 +19,15 @@ interface SurfGlowingApi {
1719
otherFlags: Byte = 0,
1820
)
1921

22+
fun makeGlowing(block: Block, viewer: Player, color: NamedTextColor)
23+
fun makeGlowing(location: Location, viewer: Player, color: NamedTextColor)
24+
2025
fun removeGlowing(target: Entity, viewer: Player)
2126
fun removeGlowing(targetId: Int, viewer: Player)
2227

28+
fun removeGlowing(block: Block, viewer: Player)
29+
fun removeGlowing(location: Location, viewer: Player)
30+
2331
companion object {
2432
val instance = requiredService<SurfGlowingApi>()
2533
}
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package dev.slne.surf.surfapi.bukkit.test.command.subcommands
22

33
import dev.jorel.commandapi.CommandAPICommand
4+
import dev.slne.surf.surfapi.bukkit.test.command.subcommands.glowing.GlowingBlockTest
45
import dev.slne.surf.surfapi.bukkit.test.command.subcommands.glowing.GlowingEntityTest
56

6-
class GlowingTest(name: String): CommandAPICommand(name) {
7+
class GlowingTest(name: String) : CommandAPICommand(name) {
78
init {
8-
withSubcommands(GlowingEntityTest("entity"))
9+
withSubcommands(GlowingEntityTest("entity"), GlowingBlockTest("block"))
910
}
1011
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package dev.slne.surf.surfapi.bukkit.test.command.subcommands.glowing
2+
3+
import dev.jorel.commandapi.CommandAPICommand
4+
import dev.jorel.commandapi.arguments.LocationType
5+
import dev.jorel.commandapi.kotlindsl.*
6+
import dev.slne.surf.surfapi.bukkit.api.glow.glowingApi
7+
import net.kyori.adventure.text.format.NamedTextColor
8+
import org.bukkit.Location
9+
10+
class GlowingBlockTest(name: String) : CommandAPICommand(name) {
11+
init {
12+
booleanArgument("glow")
13+
locationArgument("location", LocationType.BLOCK_POSITION)
14+
adventureChatColorArgument("color")
15+
16+
playerExecutor { sender, args ->
17+
val glow: Boolean by args
18+
val location: Location by args
19+
val color: NamedTextColor by args
20+
21+
if (glow) {
22+
glowingApi.makeGlowing(location, sender, color)
23+
} else {
24+
glowingApi.removeGlowing(location, sender)
25+
}
26+
27+
sender.sendMessage("Block at ${location.blockX}, ${location.blockY}, ${location.blockZ} is now ${if (glow) "glowing" else "not glowing"} with color $color.")
28+
}
29+
30+
}
31+
}

surf-api-bukkit/surf-api-bukkit-server/src/main/kotlin/dev/slne/surf/surfapi/bukkit/server/impl/glow/GlowingListener.kt

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package dev.slne.surf.surfapi.bukkit.server.impl.glow
22

3+
import dev.slne.surf.surfapi.bukkit.api.nms.bridges.packets.PacketOperation
4+
import dev.slne.surf.surfapi.bukkit.api.util.chunkX
5+
import dev.slne.surf.surfapi.bukkit.api.util.chunkZ
6+
import io.papermc.paper.event.packet.PlayerChunkLoadEvent
37
import org.bukkit.event.EventHandler
48
import org.bukkit.event.Listener
59
import org.bukkit.event.player.PlayerQuitEvent
@@ -10,4 +14,19 @@ object GlowingListener : Listener {
1014
SurfGlowingApiImpl.removeAllGlowingOnQuit(event.player)
1115
}
1216

17+
@EventHandler
18+
fun onPlayerChunkLoad(event: PlayerChunkLoadEvent) {
19+
val playerData = SurfGlowingApiImpl.getBlockPlayerData(event.player) ?: return
20+
val blockDataList = playerData.blocks
21+
if (blockDataList.isEmpty()) return
22+
23+
val spawnOperation = PacketOperation.start()
24+
for ((loc, block) in blockDataList) {
25+
val chunk = event.chunk
26+
if (loc.chunkX != chunk.x || loc.chunkZ != chunk.z || loc.world != chunk.world) continue
27+
spawnOperation.add(block.spawn())
28+
}
29+
30+
spawnOperation.execute(event.player)
31+
}
1332
}

surf-api-bukkit/surf-api-bukkit-server/src/main/kotlin/dev/slne/surf/surfapi/bukkit/server/impl/glow/GlowingPacketListener.kt

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,17 @@ import dev.slne.surf.surfapi.bukkit.api.packet.listener.listener.PacketListener
77
import dev.slne.surf.surfapi.bukkit.api.packet.listener.listener.annotation.ClientboundListener
88
import dev.slne.surf.surfapi.bukkit.server.reflection.Reflection
99
import dev.slne.surf.surfapi.core.api.util.mutableObjectListOf
10+
import dev.slne.surf.surfapi.core.api.util.toMutableObjectList
1011
import glm_.or
1112
import net.minecraft.network.protocol.Packet
13+
import net.minecraft.network.protocol.game.ClientboundBundlePacket
1214
import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket
13-
import net.minecraft.network.syncher.SynchedEntityData
15+
import net.minecraft.network.syncher.SynchedEntityData.DataValue
1416
import org.bukkit.entity.Player
1517
import kotlin.time.Duration.Companion.seconds
1618

1719
@OptIn(NmsUseWithCaution::class)
18-
object GlowingPacketListener: PacketListener {
20+
object GlowingPacketListener : PacketListener {
1921

2022
val ignoreCache = Caffeine.newBuilder()
2123
.weakKeys()
@@ -26,21 +28,40 @@ object GlowingPacketListener: PacketListener {
2628
ignoreCache.put(packet, Unit)
2729
}
2830

31+
@ClientboundListener
32+
fun onBundlePacket(packet: ClientboundBundlePacket, player: Player): ClientboundBundlePacket {
33+
val bundles = packet.subPackets().toMutableObjectList()
34+
bundles.replaceAll { subPacket ->
35+
if (subPacket is ClientboundSetEntityDataPacket) {
36+
updatePacketIfNeeded(subPacket, player)
37+
} else {
38+
subPacket
39+
}
40+
}
41+
42+
return ClientboundBundlePacket(bundles)
43+
}
44+
2945
@ClientboundListener
3046
fun onSetEntityDataPacket(
3147
packet: ClientboundSetEntityDataPacket,
3248
player: Player,
3349
): ClientboundSetEntityDataPacket {
50+
return updatePacketIfNeeded(packet, player)
51+
}
52+
53+
private fun updatePacketIfNeeded(packet: ClientboundSetEntityDataPacket, player: Player): ClientboundSetEntityDataPacket {
3454
// Ignore packets that we don't care about
3555
if (ignoreCache.asMap().remove(packet) != null) {
3656
return packet
3757
}
3858

39-
val playerData = SurfGlowingApiImpl.getPlayerData(player) ?: return packet
59+
val playerData = SurfGlowingApiImpl.getEntityPlayerData(player) ?: return packet
4060
val glowingData = playerData.entities.get(packet.id) ?: return packet
4161
val incoming = packet.packedItems
4262
var flagsFound = false
43-
val newItems = mutableObjectListOf<SynchedEntityData.DataValue<*>>(incoming.size + 1)
63+
var edited = false
64+
val newItems = mutableObjectListOf<DataValue<*>>(incoming.size + 1)
4465
val dataFlagsShared = Reflection.ENTITY_PROXY.getDataFlagsSharedId()
4566
val dataFlagsSharedId = dataFlagsShared.id
4667

@@ -50,24 +71,26 @@ object GlowingPacketListener: PacketListener {
5071
val current = dataValue.value as Byte
5172
glowingData.otherFlags = current
5273
val withGlow: Byte = current or SurfGlowingApiImpl.glowingFlag
53-
newItems.add(
54-
SynchedEntityData.DataValue(
55-
dataFlagsSharedId,
56-
dataFlagsShared.serializer,
57-
withGlow
58-
)
59-
)
74+
75+
if (withGlow != current) {
76+
edited = true
77+
newItems.add(DataValue(dataFlagsSharedId, dataFlagsShared.serializer, withGlow))
78+
} else {
79+
newItems.add(dataValue)
80+
}
6081
} else {
6182
newItems.add(dataValue)
6283
}
6384
}
6485

65-
if (!flagsFound) {
66-
// Add our own flags value (assume not glowing yet)
67-
val newVal = glowingData.otherFlags or SurfGlowingApiImpl.glowingFlag
68-
newItems.add(SynchedEntityData.DataValue(dataFlagsSharedId, dataFlagsShared.serializer, newVal))
86+
if (!edited && !flagsFound) {
87+
val withGlow = glowingData.otherFlags or SurfGlowingApiImpl.glowingFlag
88+
if (withGlow != 0.toByte()) {
89+
edited = true
90+
newItems.add(DataValue(dataFlagsSharedId, dataFlagsShared.serializer, withGlow))
91+
}
6992
}
7093

71-
return ClientboundSetEntityDataPacket(packet.id, newItems)
94+
return if (edited) ClientboundSetEntityDataPacket(packet.id, newItems) else packet
7295
}
7396
}

surf-api-bukkit/surf-api-bukkit-server/src/main/kotlin/dev/slne/surf/surfapi/bukkit/server/impl/glow/PlayerData.kt

Lines changed: 0 additions & 8 deletions
This file was deleted.

0 commit comments

Comments
 (0)