11package org.polyfrost.polyplus.client.cosmetics
22
3- import dev.deftu.omnicore.api.client.player
43import net.minecraft.network.play.server.S38PacketPlayerListItem
5- import net.minecraftforge.event.world.WorldEvent
64import org.apache.logging.log4j.LogManager
5+ import org.polyfrost.oneconfig.api.event.v1.eventHandler
76import org.polyfrost.oneconfig.api.event.v1.events.PacketEvent
8- import org.polyfrost.oneconfig.api.event.v1.invoke.impl.Subscribe
7+ import org.polyfrost.oneconfig.api.event.v1.events.WorldEvent
98import org.polyfrost.polyplus.client.network.http.PolyCosmetics
109import org.polyfrost.polyplus.client.network.websocket.ClientboundPacket
1110import org.polyfrost.polyplus.client.network.websocket.PolyConnection
1211import org.polyfrost.polyplus.client.network.websocket.ServerboundPacket
1312import org.polyfrost.polyplus.events.WebSocketMessage
1413import org.polyfrost.polyplus.utils.Batcher
14+ import org.polyfrost.polyplus.utils.EarlyInitializable
1515import java.time.Duration
1616import java.util.UUID
1717import kotlin.collections.component1
1818import kotlin.collections.component2
1919import kotlin.collections.iterator
2020
21- object ApplyCosmetics {
21+ // #if MC >= 1.20.1
22+ // $$ import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket
23+ // #endif
24+
25+ object ApplyCosmetics : EarlyInitializable {
2226 private val LOGGER = LogManager .getLogger()
2327 private val BATCHER = Batcher (Duration .ofMillis(200 ), HashSet <String >()) { players ->
2428 PolyConnection .sendPacket(ServerboundPacket .GetActiveCosmetics (players.toList()))
2529 }
2630
27- @Subscribe
28- fun onWorldLoad (event : WorldEvent .Load ) {
29- PolyCosmetics .reset()
31+ override fun earlyInitialize () {
32+ eventHandler<WorldEvent .Load > {
33+ PolyCosmetics .reset()
34+ }.register()
35+
36+ eventHandler<WebSocketMessage > { event ->
37+ val cosmeticInfo = event.packet as ? ClientboundPacket .CosmeticsInfo ? : return @eventHandler
38+
39+ // todo: have a map of type to valid ids? or ask ty to include type in the returned info. for now theyre all capes.
40+ for ((uuid, active) in cosmeticInfo.all) {
41+ active.forEach {
42+ PolyCosmetics .cacheActive(UUID .fromString(uuid), " cape" , it)
43+ LOGGER .info(" Cached cosmetic for player $uuid : cape -> $it " )
44+ }
45+ }
46+ }.register()
47+
48+ eventHandler<PacketEvent .Receive > { event ->
49+ val packet = event.getPacket<Any >() as ? S38PacketPlayerListItem ? : return @eventHandler
50+
51+ // #if MC >= 1.20.1
52+ // $$ for (action in packet.actions()) {
53+ // $$ processPlayerInfoAction(action, packet.entries())
54+ // $$ }
55+ // #else
56+ processPlayerInfoAction(packet.action, packet.entries)
57+ // #endif
58+ }
59+
60+ // #if MC >= 1.20.1
61+ // $$ eventHandler<PacketEvent.Receive> { event ->
62+ // $$ val packet = event.getPacket<Any>() as? ClientboundPlayerInfoRemovePacket ?: return@eventHandler
63+ // $$ for (uuid in packet.profileIds) {
64+ // $$ PolyCosmetics.removeFromCache(uuid)
65+ // $$ }
66+ // $$ }
67+ // #endif
3068 }
3169
32- @Subscribe
33- fun onPlayerList (event : PacketEvent .Receive ) {
34- // Not sure how to cleanly make this version agnostic atm.
35- val packet = try { event.getPacket<S38PacketPlayerListItem >() ? : return } catch (e: Exception ) { return }
36- when (packet.action) {
70+ private fun processPlayerInfoAction (action : S38PacketPlayerListItem .Action , entries : List <S38PacketPlayerListItem .AddPlayerData >) {
71+ when (action) {
3772 S38PacketPlayerListItem .Action .ADD_PLAYER -> {
38- packet.entries.forEach {
39- // mojang doesnt use uuidv2 so if it is, its a bot and wont have a cape.
40- if (it.profile.id.version() != 2 ) BATCHER .add(it.profile.id.toString())
73+ entries.forEach { playerData ->
74+ val uuid = playerData.profile?.id ? : return @forEach
75+ if (uuid.isRealPlayer()) {
76+ BATCHER .add(uuid.toString())
77+ }
4178 }
4279 }
4380
81+ // #if MC < 1.20.1
4482 S38PacketPlayerListItem .Action .REMOVE_PLAYER -> {
45- for (entry in packet. entries) {
83+ for (entry in entries) {
4684 PolyCosmetics .removeFromCache(entry.profile.id)
4785 }
4886 }
87+ // #endif
4988
5089 else -> return
5190 }
5291 }
5392
54- @Subscribe
55- fun onRecieveCosmetics (event : WebSocketMessage ) {
56- val cosmeticInfo = event.packet as ? ClientboundPacket .CosmeticsInfo ? : return
57- // todo: have a map of type to valid ids? or ask ty to include type in the returned info. for now theyre all capes.
58- for ((uuid, active) in cosmeticInfo.all) {
59- active.forEach {
60- PolyCosmetics .cacheActive(UUID .fromString(uuid), " cape" , it)
61- LOGGER .info(" Cached cosmetic for player $uuid : cape -> $it " )
62- }
63- }
93+ /* *
94+ * Mojang doesn't use UUID v2 so, if it is, it's a bot and won't have cosmetics
95+ */
96+ private fun UUID.isRealPlayer (): Boolean {
97+ return this .version() != 2
6498 }
6599}
0 commit comments