diff options
author | syeyoung <cyoung06@naver.com> | 2023-01-22 16:31:36 +0900 |
---|---|---|
committer | syeyoung <cyoung06@naver.com> | 2023-01-22 16:42:56 +0900 |
commit | 4b6f8e059e8417c14fc5e93a6bda55526986f646 (patch) | |
tree | 41f68e37dc2d42ebfb2231913e745a9e539b4631 /mod | |
parent | 394c52045bcb53a93c08cfab6d60a42bfd777d59 (diff) | |
download | Skyblock-Dungeons-Guide-4b6f8e059e8417c14fc5e93a6bda55526986f646.tar.gz Skyblock-Dungeons-Guide-4b6f8e059e8417c14fc5e93a6bda55526986f646.tar.bz2 Skyblock-Dungeons-Guide-4b6f8e059e8417c14fc5e93a6bda55526986f646.zip |
- parallel universe (process stuff based on packets)
=> Now there wouldn't be mod conflicts on tablist, scoreboard, and teams
- Fixes Bettermap Incompatibility #79
Signed-off-by: syeyoung <cyoung06@naver.com>
Diffstat (limited to 'mod')
30 files changed, 1063 insertions, 357 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java index cc380f0a..9cd0af73 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/DungeonsGuide.java @@ -33,6 +33,7 @@ import kr.syeyoung.dungeonsguide.mod.discord.DiscordIntegrationManager; import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonFacade; import kr.syeyoung.dungeonsguide.mod.events.annotations.EventHandlerRegistry; import kr.syeyoung.dungeonsguide.mod.events.listener.DungeonListener; +import kr.syeyoung.dungeonsguide.mod.events.listener.PacketInjector; import kr.syeyoung.dungeonsguide.mod.events.listener.PacketListener; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.guiv2.elements.richtext.fonts.DefaultFontRenderer; @@ -156,7 +157,7 @@ public class DungeonsGuide implements DGInterface { } - private PacketListener packetListener; + private PacketInjector packetInjector; public void init(File f) { ProgressManager.ProgressBar progressbar = ProgressManager.push("DungeonsGuide", 4); @@ -220,8 +221,8 @@ public class DungeonsGuide implements DGInterface { registerEventsForge(commandReparty = new CommandReparty()); -// registerEventsForge(new FeatureListener()); - registerEventsForge(packetListener = new PacketListener()); + registerEventsForge(packetInjector = new PacketInjector()); + registerEventsForge(new PacketListener()); registerEventsForge(new Keybinds()); registerEventsForge(PartyManager.INSTANCE); @@ -317,7 +318,7 @@ public class DungeonsGuide implements DGInterface { commands.remove(registeredCommand); } - if (packetListener != null) packetListener.cleanup(); + if (packetInjector != null) packetInjector.cleanup(); try { EntityPlayerSP ep = (EntityPlayerSP) Minecraft.getMinecraft().getRenderManager().livingPlayer; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/SkyblockStatus.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/SkyblockStatus.java index 960c927a..dc48415f 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/SkyblockStatus.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/SkyblockStatus.java @@ -24,14 +24,13 @@ import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonLeftEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.HypixelJoinedEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.SkyblockJoinedEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.SkyblockLeftEvent; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Objective; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Score; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.ScoreboardManager; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import lombok.Getter; import lombok.Setter; import net.minecraft.client.Minecraft; -import net.minecraft.scoreboard.Score; -import net.minecraft.scoreboard.ScoreObjective; -import net.minecraft.scoreboard.ScorePlayerTeam; -import net.minecraft.scoreboard.Scoreboard; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.gameevent.TickEvent; @@ -111,11 +110,10 @@ public class SkyblockStatus { return; } - Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); - ScoreObjective scoreObjective = scoreboard.getObjectiveInDisplaySlot(1); - if (scoreObjective == null) return; + Objective objective = ScoreboardManager.INSTANCE.getSidebarObjective(); + if (objective == null) return; - String objectiveName = TextUtils.stripColor(scoreObjective.getDisplayName()); + String objectiveName = TextUtils.stripColor(objective.getDisplayName()); boolean skyblockFound = false; for (String skyblock : SKYBLOCK_IN_ALL_LANGUAGES) { if (objectiveName.startsWith(skyblock)) { @@ -131,20 +129,21 @@ public class SkyblockStatus { return; } - Collection<Score> scores = scoreboard.getSortedScores(scoreObjective); + Collection<Score> scores = objective.getScores(); boolean foundDungeon = false; for (Score sc : scores) { - ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); - String strippedLine = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()))).trim(); + String strippedLine = TextUtils.keepScoreboardCharacters( + TextUtils.stripColor(sc.getJustTeam())).trim(); if (strippedLine.contains("Cleared: ")) { foundDungeon = true; DungeonContext context = DungeonsGuide.getDungeonsGuide().getDungeonFacade().getContext(); if(context != null){ - context.setPercentage(Integer.parseInt(strippedLine.substring(9).split(" ")[0])); + context.setPercentage(Integer.parseInt( + strippedLine.substring(9).split(" ")[0])); } } - if (ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()).startsWith(" §7⏣")) { + if (sc.getJustTeam().startsWith(" §7⏣")) { DungeonContext.setDungeonName(strippedLine.trim()); } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java index 69518af8..7fefe9d7 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/chat/ChatTransmitter.java @@ -71,7 +71,7 @@ public class ChatTransmitter { public void onTick(TickEvent.ClientTickEvent clientTickEvent) { if(clientTickEvent.phase != TickEvent.Phase.START && Minecraft.getMinecraft().thePlayer == null) return; - if (!receiveQueue.isEmpty()) { + while (!receiveQueue.isEmpty() && Minecraft.getMinecraft().thePlayer != null) { ClientChatReceivedEvent event = new ClientChatReceivedEvent((byte) 1, receiveQueue.poll()); MinecraftForge.EVENT_BUS.post(event); if (!event.isCanceled()) { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java index 620f4e75..45eb7dd2 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/commands/CommandDgDebug.java @@ -40,23 +40,30 @@ import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightPr import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonLeftEvent; import kr.syeyoung.dungeonsguide.mod.features.AbstractFeature; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.features.impl.dungeon.FeatureDungeonMap; import kr.syeyoung.dungeonsguide.mod.guiv2.GuiScreenAdapter; import kr.syeyoung.dungeonsguide.mod.guiv2.view.TestView; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Score; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.ScoreboardManager; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.party.PartyContext; import kr.syeyoung.dungeonsguide.mod.party.PartyManager; import kr.syeyoung.dungeonsguide.mod.utils.AhUtils; import kr.syeyoung.dungeonsguide.mod.utils.MapUtils; -import kr.syeyoung.dungeonsguide.mod.utils.ScoreBoardUtils; import kr.syeyoung.dungeonsguide.mod.utils.ShortUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TabListUtil; import kr.syeyoung.dungeonsguide.mod.wsresource.StaticResourceCache; import net.minecraft.block.Block; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.command.CommandBase; import net.minecraft.command.CommandException; import net.minecraft.command.ICommandSender; import net.minecraft.nbt.CompressedStreamTools; import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.server.MinecraftServer; import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentText; @@ -96,13 +103,18 @@ public class CommandDgDebug extends CommandBase { if ("scoreboard".equals(arg)) { - ScoreBoardUtils.forEachLine(l -> { - ChatTransmitter.addToQueue("LINE: " + l, false); - }); + for (Score score : ScoreboardManager.INSTANCE.getSidebarObjective().getScores()) { + ChatTransmitter.addToQueue("LINE: " + score.getVisibleName()+": "+score.getScore()); + } } else if ("scoreboardclean".equals(arg)) { - ScoreBoardUtils.forEachLineClean(l -> { - ChatTransmitter.addToQueue("LINE: " + l, false); - }); + for (Score score : ScoreboardManager.INSTANCE.getSidebarObjective().getScores()) { + ChatTransmitter.addToQueue("LINE: " + score.getJustTeam()+": "+score.getScore()); + } + }else if ("tablist".equals(arg)) { + for (TabListEntry entry : TabList.INSTANCE.getTabListEntries()) { + ChatTransmitter.addToQueue(entry.getFormatted()+" "+entry.getEffectiveName()+"("+entry.getPing()+")" + entry.getGamemode()); + } + ChatTransmitter.addToQueue("VS"); } else if ("mockdungeonstart".equals(arg)) { if (!Minecraft.getMinecraft().isSingleplayer()) { ChatTransmitter.addToQueue("This only works in singlepauer", false); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/cosmetics/CustomPacketPlayerListItem.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/impl/PacketProcessedEvent.java index 7cf0b6cf..2178fc03 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/cosmetics/CustomPacketPlayerListItem.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/impl/PacketProcessedEvent.java @@ -1,6 +1,6 @@ /* * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 + * Copyright (C) 2023 cyoung06 (syeyoung) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -16,24 +16,24 @@ * along with this program. If not, see <https://www.gnu.org/licenses/>. */ -package kr.syeyoung.dungeonsguide.mod.cosmetics; +package kr.syeyoung.dungeonsguide.mod.events.impl; - -import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerListItemPacketEvent; +import lombok.AllArgsConstructor; +import net.minecraft.network.Packet; import net.minecraft.network.play.INetHandlerPlayClient; -import net.minecraft.network.play.server.S38PacketPlayerListItem; -import net.minecraftforge.common.MinecraftForge; - -public class CustomPacketPlayerListItem extends S38PacketPlayerListItem { - public CustomPacketPlayerListItem(S38PacketPlayerListItem packet) { - super(packet.getAction()); - getEntries().addAll(packet.getEntries()); - } - - @Override - public void processPacket(INetHandlerPlayClient handler) { - super.processPacket(handler); +import net.minecraftforge.fml.common.eventhandler.Event; - MinecraftForge.EVENT_BUS.post(new PlayerListItemPacketEvent(this)); - } +@AllArgsConstructor +public abstract class PacketProcessedEvent extends Event { + public Packet<INetHandlerPlayClient> packet; + public static class Pre extends PacketProcessedEvent { + public Pre(Packet<INetHandlerPlayClient> packet) { + super(packet); + } + }; + public static class Post extends PacketProcessedEvent { + public Post(Packet<INetHandlerPlayClient> packet) { + super(packet); + } + }; } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/impl/RawPacketReceivedEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/impl/RawPacketReceivedEvent.java new file mode 100644 index 00000000..efeb8eeb --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/impl/RawPacketReceivedEvent.java @@ -0,0 +1,29 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.events.impl; + +import lombok.AllArgsConstructor; +import net.minecraft.network.Packet; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraftforge.fml.common.eventhandler.Event; + +@AllArgsConstructor +public class RawPacketReceivedEvent extends Event { + public Packet<INetHandlerPlayClient> packet; +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/DungeonListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/DungeonListener.java index c36fac6d..d29f1084 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/DungeonListener.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/DungeonListener.java @@ -35,6 +35,9 @@ import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessor; import kr.syeyoung.dungeonsguide.mod.events.impl.*; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.ScoreboardManager; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.TeamManager; import kr.syeyoung.dungeonsguide.mod.utils.MapUtils; import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; import lombok.Getter; @@ -43,6 +46,7 @@ import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.passive.EntityBat; +import net.minecraft.scoreboard.Scoreboard; import net.minecraft.util.AxisAlignedBB; import net.minecraft.util.BlockPos; import net.minecraft.util.ChatComponentText; @@ -74,6 +78,9 @@ public class DungeonListener { @SubscribeEvent public void onWorldLoad(WorldEvent.Unload event) { + TabList.INSTANCE.clear(); + TeamManager.INSTANCE.clear(); + ScoreboardManager.INSTANCE.clear(); try { Config.saveConfig(); } catch (IOException e) { diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketInjector.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketInjector.java new file mode 100644 index 00000000..a18a3641 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketInjector.java @@ -0,0 +1,92 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2021 cyoung06 + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.events.listener; + +import io.netty.channel.*; +import kr.syeyoung.dungeonsguide.mod.events.impl.*; +import net.minecraft.client.Minecraft; +import net.minecraft.network.Packet; +import net.minecraft.network.play.client.C02PacketUseEntity; +import net.minecraft.network.play.server.*; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.network.FMLNetworkEvent; + +import java.util.HashSet; +import java.util.Set; + +@ChannelHandler.Sharable +public class PacketInjector extends ChannelDuplexHandler { + + private static Set<Class> targettedPackets = new HashSet<>(); + static { + targettedPackets.add(S04PacketEntityEquipment.class); + targettedPackets.add(S45PacketTitle.class); + targettedPackets.add(S38PacketPlayerListItem.class); + targettedPackets.add(S30PacketWindowItems.class); + targettedPackets.add(S2FPacketSetSlot.class); + targettedPackets.add(S23PacketBlockChange.class); + targettedPackets.add(S22PacketMultiBlockChange.class); + targettedPackets.add(S3BPacketScoreboardObjective.class); + targettedPackets.add(S3CPacketUpdateScore.class); + targettedPackets.add(S3DPacketDisplayScoreboard.class); + targettedPackets.add(S3EPacketTeams.class); + } + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + Packet packet = (Packet) msg; + if (targettedPackets.contains(msg.getClass())) { + RawPacketReceivedEvent receivedEvent = new RawPacketReceivedEvent(packet); + MinecraftForge.EVENT_BUS.post(receivedEvent); + packet = new WrappedPacket(receivedEvent.packet); + } + super.channelRead(ctx, packet); + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + Packet packet = (Packet) msg; + if (packet instanceof C02PacketUseEntity) { + C02PacketUseEntity packet2 = (C02PacketUseEntity) packet; + PlayerInteractEntityEvent piee; + if (packet2.getAction() == C02PacketUseEntity.Action.ATTACK) + piee = new PlayerInteractEntityEvent(true, packet2.getEntityFromWorld(Minecraft.getMinecraft().theWorld)); + else + piee = new PlayerInteractEntityEvent(false, ((C02PacketUseEntity) packet).getEntityFromWorld(Minecraft.getMinecraft().theWorld)); + + if (MinecraftForge.EVENT_BUS.post(piee)) return; + } + super.write(ctx, msg, promise); + } + + private ChannelPipeline thePipeline; + @SubscribeEvent + public void onServerConnect(FMLNetworkEvent.ClientConnectedToServerEvent event) { + (thePipeline =event.manager.channel().pipeline()).addBefore("packet_handler", "dg_packet_handler", this); + } + + public void cleanup() { + try { + if (thePipeline != null) + thePipeline.remove("dg_packet_handler"); + } catch (Exception e) { + + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java index dcdc2c53..2012f129 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/PacketListener.java @@ -1,6 +1,6 @@ /* * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 + * Copyright (C) 2023 cyoung06 (syeyoung) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published @@ -18,181 +18,193 @@ package kr.syeyoung.dungeonsguide.mod.events.listener; -import io.netty.channel.*; import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; import kr.syeyoung.dungeonsguide.mod.SkyblockStatus; -import kr.syeyoung.dungeonsguide.mod.cosmetics.CustomPacketPlayerListItem; -import kr.syeyoung.dungeonsguide.mod.events.impl.BlockUpdateEvent; -import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; -import kr.syeyoung.dungeonsguide.mod.events.impl.TitleEvent; -import kr.syeyoung.dungeonsguide.mod.events.impl.WindowUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.*; import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; -import net.minecraft.block.state.IBlockState; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Objective; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.ScoreboardManager; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.NameTagVisibility; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.Team; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.TeamManager; import net.minecraft.client.Minecraft; import net.minecraft.network.Packet; -import net.minecraft.network.play.INetHandlerPlayClient; -import net.minecraft.network.play.client.C02PacketUseEntity; import net.minecraft.network.play.server.*; -import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumChatFormatting; import net.minecraft.util.Tuple; import net.minecraftforge.common.MinecraftForge; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.network.FMLNetworkEvent; -import java.util.Arrays; - -@ChannelHandler.Sharable -public class PacketListener extends ChannelDuplexHandler { +public class PacketListener { private final SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { - Packet packet = (Packet) msg; + @SubscribeEvent + public void onPacketReceive(RawPacketReceivedEvent event) { + Packet packet = event.packet; if (skyblockStatus.isOnSkyblock() - && msg instanceof S04PacketEntityEquipment - && FeatureRegistry.FIX_SPIRIT_BOOTS.isEnabled()) { // Inventory packet name - S04PacketEntityEquipment packet2 = (S04PacketEntityEquipment) msg; + && packet instanceof S04PacketEntityEquipment + && FeatureRegistry.FIX_SPIRIT_BOOTS.isEnabled()) { // Inventory packet name + S04PacketEntityEquipment packet2 = (S04PacketEntityEquipment) packet; if (packet2.getEntityID() == Minecraft.getMinecraft().thePlayer.getEntityId()) { packet2 = new S04PacketEntityEquipment(packet2.getEntityID(), packet2.getEquipmentSlot() + 1, packet2.getItemStack()); packet = packet2; } } - if (packet instanceof S45PacketTitle) { - MinecraftForge.EVENT_BUS.post(new TitleEvent((S45PacketTitle) packet)); - } - if (packet instanceof S38PacketPlayerListItem) { - packet = new CustomPacketPlayerListItem((S38PacketPlayerListItem) packet); - } - if (packet instanceof S30PacketWindowItems) { - packet = new CustomWindowItems((S30PacketWindowItems) packet); - } - if (packet instanceof S2FPacketSetSlot) { - packet = new CustomSetSlot((S2FPacketSetSlot) packet); - } - if (packet instanceof S23PacketBlockChange) { - packet = new SingleBlockChange((S23PacketBlockChange) packet); - } else if (packet instanceof S22PacketMultiBlockChange) { - packet = new MultiBlockChange((S22PacketMultiBlockChange) packet); - } - super.channelRead(ctx, packet); + event.packet = packet; } - private static class CustomWindowItems extends S30PacketWindowItems { - public CustomWindowItems(S30PacketWindowItems parent) { - super(parent.func_148911_c(), Arrays.asList(parent.getItemStacks())); - } - - @Override - public void processPacket(INetHandlerPlayClient handler) { - super.processPacket(handler); - MinecraftForge.EVENT_BUS.post(new WindowUpdateEvent(this, null)); - } - } - private static class CustomSetSlot extends S2FPacketSetSlot { - public CustomSetSlot(S2FPacketSetSlot parent) { - super(parent.func_149175_c(), parent.func_149173_d(), parent.func_149174_e()); - } - @Override - public void processPacket(INetHandlerPlayClient handler) { - super.processPacket(handler); - MinecraftForge.EVENT_BUS.post(new WindowUpdateEvent(null, this)); + @SubscribeEvent + public void packetProcessPost(PacketProcessedEvent.Post post) { + Packet packet = post.packet; + if (packet instanceof S30PacketWindowItems) { + MinecraftForge.EVENT_BUS.post(new WindowUpdateEvent((S30PacketWindowItems) packet, null)); + } else if (packet instanceof S2FPacketSetSlot) { + MinecraftForge.EVENT_BUS.post(new WindowUpdateEvent( null, (S2FPacketSetSlot) packet)); + } else if (packet instanceof S23PacketBlockChange) { + BlockUpdateEvent blockUpdateEvent = new BlockUpdateEvent.Post(); + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>( + ((S23PacketBlockChange) packet).getBlockPosition(), ((S23PacketBlockChange) packet).getBlockState())); + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + } else if (packet instanceof S22PacketMultiBlockChange) { + BlockUpdateEvent blockUpdateEvent = new BlockUpdateEvent.Post(); + for (S22PacketMultiBlockChange.BlockUpdateData changedBlock : ((S22PacketMultiBlockChange) packet).getChangedBlocks()) { + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(changedBlock.getPos(), changedBlock.getBlockState())); + } + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + }else if (packet instanceof S45PacketTitle) { + MinecraftForge.EVENT_BUS.post(new TitleEvent((S45PacketTitle) packet)); + } else if (packet instanceof S38PacketPlayerListItem) { + MinecraftForge.EVENT_BUS.post(new PlayerListItemPacketEvent((S38PacketPlayerListItem) packet)); } } - private static class SingleBlockChange extends S23PacketBlockChange { - private S23PacketBlockChange old; - public SingleBlockChange(S23PacketBlockChange blockChange) { - this.old = blockChange; - } - - @Override - public void processPacket(INetHandlerPlayClient handler) { - + @SubscribeEvent + public void onPrePacketProcess(PacketProcessedEvent.Pre event) { + Packet packet =event.packet; + if (event.packet instanceof S23PacketBlockChange) { BlockUpdateEvent blockUpdateEvent = new BlockUpdateEvent.Pre(); - blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(getBlockPosition(),getBlockState())); - - - MinecraftForge.EVENT_BUS.post(blockUpdateEvent); - super.processPacket(handler); - blockUpdateEvent = new BlockUpdateEvent.Post(); - blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(getBlockPosition(), getBlockState())); - MinecraftForge.EVENT_BUS.post(blockUpdateEvent); - - - - - } - - @Override - public BlockPos getBlockPosition() { - return old.getBlockPosition(); - } - - @Override - public IBlockState getBlockState() { - return old.getBlockState(); - } - } - - - private static class MultiBlockChange extends S22PacketMultiBlockChange { - private S22PacketMultiBlockChange old; - public MultiBlockChange(S22PacketMultiBlockChange blockChange) { - this.old = blockChange; - } - @Override - public void processPacket(INetHandlerPlayClient handler) { - - + blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>( + ((S23PacketBlockChange) event.packet).getBlockPosition(), + ((S23PacketBlockChange) event.packet).getBlockState())); + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + } else if (event.packet instanceof S22PacketMultiBlockChange) { BlockUpdateEvent blockUpdateEvent = new BlockUpdateEvent.Pre(); - for (S22PacketMultiBlockChange.BlockUpdateData changedBlock : getChangedBlocks()) { + for (S22PacketMultiBlockChange.BlockUpdateData changedBlock : ((S22PacketMultiBlockChange) event.packet).getChangedBlocks()) { blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(changedBlock.getPos(), changedBlock.getBlockState())); } - MinecraftForge.EVENT_BUS.post(blockUpdateEvent); - super.processPacket(handler); - blockUpdateEvent = new BlockUpdateEvent.Post(); - for (S22PacketMultiBlockChange.BlockUpdateData changedBlock : getChangedBlocks()) { - blockUpdateEvent.getUpdatedBlocks().add(new Tuple<>(changedBlock.getPos(), changedBlock.getBlockState())); + MinecraftForge.EVENT_BUS.post(blockUpdateEvent); + } else if (packet instanceof S3BPacketScoreboardObjective) { + S3BPacketScoreboardObjective objectivePkt = (S3BPacketScoreboardObjective) packet; + if (objectivePkt.func_149338_e() == 2) { + Objective objective = ScoreboardManager.INSTANCE.getObjective(objectivePkt.func_149339_c()); + if (objective != null) { + objective.setDisplayName(objectivePkt.func_149337_d()); + objective.setDisplayType(objectivePkt.func_179817_d()); + } + } else if (objectivePkt.func_149338_e() == 1) { + ScoreboardManager.INSTANCE.removeObjective(objectivePkt.func_149339_c()); + } else if (objectivePkt.func_149338_e() == 0) { + Objective objective = new Objective(objectivePkt.func_149339_c()); + objective.setDisplayName(objectivePkt.func_149337_d()); + objective.setDisplayType(objectivePkt.func_179817_d()); + ScoreboardManager.INSTANCE.addObjective(objective); + } + } else if (packet instanceof S3CPacketUpdateScore) { + S3CPacketUpdateScore score = (S3CPacketUpdateScore) packet; + Objective objective = ScoreboardManager.INSTANCE.getObjective(score.getObjectiveName()); + if (objective != null) { + if (score.getScoreAction() == S3CPacketUpdateScore.Action.CHANGE) { + objective.updateScore(score.getPlayerName(), score.getScoreValue()); + } else if (score.getScoreAction() == S3CPacketUpdateScore.Action.REMOVE) { + objective.removeScore(score.getPlayerName()); + } + } + } else if (packet instanceof S3DPacketDisplayScoreboard) { + S3DPacketDisplayScoreboard board = (S3DPacketDisplayScoreboard) packet; + ScoreboardManager.INSTANCE.displayScoreboard(board.func_149371_c(), board.func_149370_d()); + } else if (packet instanceof S3EPacketTeams) { + S3EPacketTeams pkt = (S3EPacketTeams) packet; + if (pkt.getAction() == 0) { + // CREATE + Team team = new Team(pkt.getName()); + team.setDisplayName(pkt.getDisplayName()); + team.setPrefix(pkt.getPrefix()); + team.setSuffix(pkt.getSuffix()); + team.setNameTagVisibility(NameTagVisibility.of(pkt.getNameTagVisibility())); + team.setColor(EnumChatFormatting.func_175744_a(pkt.getColor())); + + for (String player : pkt.getPlayers()) { + team.addTeamMember(player); + } + + TeamManager.INSTANCE.createTeam(team); + } else if (pkt.getAction() == 1) { + // REMOVE + TeamManager.INSTANCE.removeTeam(pkt.getName()); + } else if (pkt.getAction() == 2) { + // UPDATE + Team team = TeamManager.INSTANCE.getTeamByName(pkt.getName()); + if (team != null) { + team.setDisplayName(pkt.getDisplayName()); + team.setPrefix(pkt.getPrefix()); + team.setSuffix(pkt.getSuffix()); + team.setNameTagVisibility(NameTagVisibility.of(pkt.getNameTagVisibility())); + team.setColor(EnumChatFormatting.func_175744_a(pkt.getColor())); + } + } else if (pkt.getAction() == 3) { + // PLAYER UPDATE + Team team = TeamManager.INSTANCE.getTeamByName(pkt.getName()); + if (team != null) { + for (String player : pkt.getPlayers()) { + team.addTeamMember(player); + } + } + } else if (pkt.getAction() == 4) { + // PLAYER REMOVE + Team team = TeamManager.INSTANCE.getTeamByName(pkt.getName()); + if (team != null) { + for (String player : pkt.getPlayers()) { + team.removeTeamMember(player); + } + } + } + } else if (packet instanceof S38PacketPlayerListItem) { + S38PacketPlayerListItem pkt = (S38PacketPlayerListItem) packet; + S38PacketPlayerListItem.Action action = pkt.getAction(); + if (action == S38PacketPlayerListItem.Action.ADD_PLAYER) { + for (S38PacketPlayerListItem.AddPlayerData entry : pkt.getEntries()) { + TabListEntry tabListEntry = new TabListEntry(entry.getProfile(), entry.getGameMode()); + tabListEntry.setPing(entry.getPing()); + tabListEntry.setDisplayName(entry.getDisplayName()); + TabList.INSTANCE.updateEntry(tabListEntry); + } + } else if (action == S38PacketPlayerListItem.Action.REMOVE_PLAYER) { + for (S38PacketPlayerListItem.AddPlayerData entry : pkt.getEntries()) { + TabList.INSTANCE.removeEntry(entry.getProfile().getId()); + } + } else if (action == S38PacketPlayerListItem.Action.UPDATE_LATENCY) { + for (S38PacketPlayerListItem.AddPlayerData entry : pkt.getEntries()) { + TabListEntry entry1 = TabList.INSTANCE.getEntry(entry.getProfile().getId()); + if (entry1 != null) entry1.setPing(entry.getPing()); + } + } else if (action == S38PacketPlayerListItem.Action.UPDATE_DISPLAY_NAME) { + for (S38PacketPlayerListItem.AddPlayerData entry : pkt.getEntries()) { + TabListEntry entry1 = TabList.INSTANCE.getEntry(entry.getProfile().getId()); + if (entry1 != null) entry1.setDisplayName(entry.getDisplayName()); + } + } else if (action == S38PacketPlayerListItem.Action.UPDATE_GAME_MODE) { + for (S38PacketPlayerListItem.AddPlayerData entry : pkt.getEntries()) { + TabListEntry entry1 = TabList.INSTANCE.getEntry(entry.getProfile().getId()); + TabListEntry neu = new TabListEntry(entry1.getGameProfile(), entry.getGameMode()); + neu.setPing(entry1.getPing()); + neu.setDisplayName(entry1.getDisplayName()); + + TabList.INSTANCE.updateEntry(neu); + } } - MinecraftForge.EVENT_BUS.post(blockUpdateEvent); - - - } - - @Override - public BlockUpdateData[] getChangedBlocks() { - return old.getChangedBlocks(); - } - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - Packet packet = (Packet) msg; - if (packet instanceof C02PacketUseEntity) { - C02PacketUseEntity packet2 = (C02PacketUseEntity) packet; - PlayerInteractEntityEvent piee; - if (packet2.getAction() == C02PacketUseEntity.Action.ATTACK) - piee = new PlayerInteractEntityEvent(true, packet2.getEntityFromWorld(Minecraft.getMinecraft().theWorld)); - else - piee = new PlayerInteractEntityEvent(false, ((C02PacketUseEntity) packet).getEntityFromWorld(Minecraft.getMinecraft().theWorld)); - - if (MinecraftForge.EVENT_BUS.post(piee)) return; } - super.write(ctx, msg, promise); - } - - private ChannelPipeline thePipeline; - @SubscribeEvent - public void onServerConnect(FMLNetworkEvent.ClientConnectedToServerEvent event) { - (thePipeline =event.manager.channel().pipeline()).addBefore("packet_handler", "dg_packet_handler", this); } - public void cleanup() { - try { - if (thePipeline != null) - thePipeline.remove("dg_packet_handler"); - } catch (Exception e) { - - } - } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/WrappedPacket.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/WrappedPacket.java new file mode 100644 index 00000000..5b2548b8 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/events/listener/WrappedPacket.java @@ -0,0 +1,63 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.events.listener; + +import kr.syeyoung.dungeonsguide.mod.events.impl.PacketProcessedEvent; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import net.minecraft.client.Minecraft; +import net.minecraft.network.Packet; +import net.minecraft.network.PacketBuffer; +import net.minecraft.network.play.INetHandlerPlayClient; +import net.minecraftforge.common.MinecraftForge; + +import java.io.IOException; + +@RequiredArgsConstructor +public class WrappedPacket implements Packet<INetHandlerPlayClient> { + private final Packet<INetHandlerPlayClient> delegate; + @Override + public void readPacketData(PacketBuffer buf) throws IOException { + delegate.readPacketData(buf); + } + + @Override + public void writePacketData(PacketBuffer buf) throws IOException { + delegate.writePacketData(buf); + } + + private INetHandlerPlayClient iNetHandlerPlayClient; + private boolean processed = false; + @Override + public void processPacket(INetHandlerPlayClient handler) { + if (processed) { + delegate.processPacket(handler); + } + this.iNetHandlerPlayClient = handler; + processed =true; + // lmao + Minecraft.getMinecraft().addScheduledTask(this::legitProcessPacket); + } + + private void legitProcessPacket() { + MinecraftForge.EVENT_BUS.post(new PacketProcessedEvent.Pre(delegate)); + delegate.processPacket(iNetHandlerPlayClient); + MinecraftForge.EVENT_BUS.post(new PacketProcessedEvent.Post(delegate)); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java index 235093de..ab939091 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/advanced/FeatureTestPepole.java @@ -25,6 +25,8 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler; import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonStartedEvent; import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter; import kr.syeyoung.dungeonsguide.mod.features.RawRenderingGuiFeature; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.party.PartyManager; import kr.syeyoung.dungeonsguide.mod.stomp.StompManager; import kr.syeyoung.dungeonsguide.mod.stomp.StompPayload; @@ -283,16 +285,8 @@ public class FeatureTestPepole extends RawRenderingGuiFeature { * @param networkPlayerInfo the network player info of player * @return the username of player */ - private String getPlayerNameWithChecks(NetworkPlayerInfo networkPlayerInfo) { - String name; - if (networkPlayerInfo.getDisplayName() != null) { - name = networkPlayerInfo.getDisplayName().getFormattedText(); - } else { - name = ScorePlayerTeam.formatPlayerName( - networkPlayerInfo.getPlayerTeam(), - networkPlayerInfo.getGameProfile().getName() - ); - } + private String getPlayerNameWithChecks(TabListEntry networkPlayerInfo) { + String name = networkPlayerInfo.getEffectiveName(); if (name.trim().equals("§r") || name.startsWith("§r ")) return null; @@ -303,14 +297,11 @@ public class FeatureTestPepole extends RawRenderingGuiFeature { boolean isPlayerInDungeon(String username) { - List<NetworkPlayerInfo> list = new ArrayList<>(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); - // 19 iterations bc we only want to scan the player part of tab list - for (int i = 1; i < 20; i++) { - if(list.size() < i) break; - NetworkPlayerInfo networkPlayerInfo = list.get(i); - - String name = getPlayerNameWithChecks(networkPlayerInfo); + int i = 0; + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + if (++i >= 20) break; + String name = getPlayerNameWithChecks(tabListEntry); if (name == null) continue; EntityPlayer entityplayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(name); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonDeaths.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonDeaths.java index 21e44ed3..5534fffb 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonDeaths.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonDeaths.java @@ -29,6 +29,8 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler; import kr.syeyoung.dungeonsguide.mod.features.text.StyledText; import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetworkPlayerInfo; @@ -123,8 +125,8 @@ public class FeatureDungeonDeaths extends TextHUDFeature { public int getTotalDeaths() { if (!skyblockStatus.isOnDungeon()) return 0; - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveName(); if (name.contains("Deaths")) { String whatever = TextUtils.keepIntegerCharactersOnly(TextUtils.keepScoreboardCharacters(TextUtils.stripColor(name))); if (whatever.isEmpty()) break; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java index afffbcb8..36e0afaf 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMap.java @@ -32,6 +32,8 @@ import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonEndedEvent; import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonStartedEvent; import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter; import kr.syeyoung.dungeonsguide.mod.features.RawRenderingGuiFeature; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; import kr.syeyoung.dungeonsguide.mod.utils.TabListUtil; import net.minecraft.block.material.MapColor; @@ -61,6 +63,7 @@ import org.lwjgl.opengl.GL14; import javax.vecmath.Vector2d; import java.awt.*; import java.util.List; +import java.util.Set; //TODO: reduce gl drawcalls somehow @@ -336,28 +339,15 @@ public class FeatureDungeonMap extends RawRenderingGuiFeature { return false; } - @Nullable - public Tuple<String[], List<NetworkPlayerInfo>> loadPlayerList() { - String[] names = new String[21]; - - List<NetworkPlayerInfo> networkList = sorter.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); - if (networkList.size() < 40) return null; - - for (int i = 0; i < 20; i++) { - names[i] = TabListUtil.getPlayerNameWithChecks(networkList.get(i)); - } - - return new Tuple<>(names, networkList); - } long nextRefresh; - Tuple<String[], List<NetworkPlayerInfo>> playerListCached; + Set<TabListEntry> playerListCached; - public Tuple<String[], List<NetworkPlayerInfo>> getPlayerListCached(){ + public Set<TabListEntry> getPlayerListCached(){ if(playerListCached == null || nextRefresh <= System.currentTimeMillis()){ ChatTransmitter.sendDebugChat("Refreshing players on map"); - playerListCached = loadPlayerList(); + playerListCached = TabList.INSTANCE.getTabListEntries(); nextRefresh = System.currentTimeMillis() + 10000; } return playerListCached; @@ -367,18 +357,15 @@ public class FeatureDungeonMap extends RawRenderingGuiFeature { private void renderHeads(MapProcessor mapProcessor, MapData mapData, float scale, float postScale, float partialTicks) { EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer; - Tuple<String[], List<NetworkPlayerInfo>> playerList = getPlayerListCached(); - - List<NetworkPlayerInfo> networkList = playerList.getSecond(); - String[] names = playerList.getFirst(); - + Set<TabListEntry> playerList = getPlayerListCached(); // 21 iterations bc we only want to scan the player part of tab list - for (int i = 1; i < 20; i++) { - NetworkPlayerInfo networkPlayerInfo = networkList.get(i); + int i = 0; + for (TabListEntry playerInfo : playerList) { + if (++i >= 20) break; - String name = names[i]; + String name = TabListUtil.getPlayerNameWithChecks(playerInfo); if (name == null) continue; @@ -413,7 +400,7 @@ public class FeatureDungeonMap extends RawRenderingGuiFeature { if(pt2 == null) return; if (entityplayer == thePlayer || shouldShowOtherPlayers) { - drawHead(scale, postScale, networkPlayerInfo, entityplayer, pt2, (float) yaw2); + drawHead(scale, postScale, playerInfo, entityplayer, pt2, (float) yaw2); } } @@ -427,11 +414,13 @@ public class FeatureDungeonMap extends RawRenderingGuiFeature { * @param pt2 * @param yaw2 */ - private void drawHead(float scale, float postScale, NetworkPlayerInfo networkPlayerInfo, EntityPlayer entityplayer, Vector2d pt2, float yaw2) { + private void drawHead(float scale, float postScale, TabListEntry networkPlayerInfo, EntityPlayer entityplayer, Vector2d pt2, float yaw2) { GlStateManager.pushMatrix(); boolean flag1 = entityplayer != null && entityplayer.isWearing(EnumPlayerModelParts.CAPE); GlStateManager.enableTexture2D(); - Minecraft.getMinecraft().getTextureManager().bindTexture(networkPlayerInfo.getLocationSkin()); + Minecraft.getMinecraft().getTextureManager().bindTexture( + networkPlayerInfo.getLocationSkin() + ); int l2 = 8 + (flag1 ? 8 : 0); int i3 = 8 * (flag1 ? -1 : 1); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMilestone.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMilestone.java index aa9689d1..7331b34c 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMilestone.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonMilestone.java @@ -29,6 +29,8 @@ import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.features.text.StyledText; import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetworkPlayerInfo; @@ -79,8 +81,8 @@ public class FeatureDungeonMilestone extends TextHUDFeature { List<StyledText> actualBit = new ArrayList<StyledText>(); actualBit.add(new StyledText("Milestone","title")); actualBit.add(new StyledText(": ","separator")); - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveName(); if (name.startsWith("§r Milestone: §r")) { String milestone = TextUtils.stripColor(name).substring(13); actualBit.add(new StyledText(milestone+"","number")); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java index 1e3b7f1a..e06d4c3c 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonScore.java @@ -29,6 +29,8 @@ import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; import kr.syeyoung.dungeonsguide.mod.features.text.StyledText; import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import kr.syeyoung.dungeonsguide.mod.utils.TimeScoreUtil; import kr.syeyoung.dungeonsguide.mod.wsresource.StaticResource; @@ -177,8 +179,8 @@ public class FeatureDungeonScore extends TextHUDFeature { } public int getCompleteRooms() { - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveName(); if (name.startsWith("§r Completed Rooms: §r")) { String milestone = TextUtils.stripColor(name).substring(18); return Integer.parseInt(milestone); @@ -193,8 +195,8 @@ public class FeatureDungeonScore extends TextHUDFeature { } public int getUndiscoveredPuzzles() { int cnt = 0; - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveName(); if (name.startsWith("§r ???: ")) { cnt ++; } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonSecrets.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonSecrets.java index 1483f7e9..bcc5d168 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonSecrets.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonSecrets.java @@ -27,6 +27,8 @@ import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; import kr.syeyoung.dungeonsguide.mod.features.text.StyledText; import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetworkPlayerInfo; @@ -50,8 +52,8 @@ public class FeatureDungeonSecrets extends TextHUDFeature { SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); public int getSecretsFound() { - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveName(); if (name.startsWith("§r Secrets Found: §r§b") && !name.contains("%")) { String noColor = TextUtils.stripColor(name); return Integer.parseInt(noColor.substring(16)); @@ -60,8 +62,8 @@ public class FeatureDungeonSecrets extends TextHUDFeature { return 0; } public double getSecretPercentage() { - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveName(); if (name.startsWith("§r Secrets Found: §r") && name.contains("%")) { String noColor = TextUtils.stripColor(name); return Double.parseDouble(noColor.substring(16).replace("%", "")); diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonTombs.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonTombs.java index e0de09db..72a09dd7 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonTombs.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureDungeonTombs.java @@ -25,6 +25,8 @@ import kr.syeyoung.dungeonsguide.mod.config.types.AColor; import kr.syeyoung.dungeonsguide.mod.features.text.StyledText; import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetworkPlayerInfo; @@ -46,8 +48,8 @@ public class FeatureDungeonTombs extends TextHUDFeature { SkyblockStatus skyblockStatus = DungeonsGuide.getDungeonsGuide().getSkyblockStatus(); public int getTombsFound() { - for (NetworkPlayerInfo networkPlayerInfoIn : Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()) { - String name = networkPlayerInfoIn.getDisplayName() != null ? networkPlayerInfoIn.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfoIn.getPlayerTeam(), networkPlayerInfoIn.getGameProfile().getName()); + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + String name = tabListEntry.getEffectiveWithoutName(); if (name.startsWith("§r Crypts: §r§6")) { return Integer.parseInt(TextUtils.stripColor(name).substring(9)); } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java index 24bc2df6..bfbab9f3 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/dungeon/FeatureWarnLowHealth.java @@ -26,9 +26,11 @@ import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter; import kr.syeyoung.dungeonsguide.mod.features.text.StyledText; import kr.syeyoung.dungeonsguide.mod.features.text.TextHUDFeature; import kr.syeyoung.dungeonsguide.mod.features.text.TextStyle; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Objective; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Score; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.ScoreboardManager; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; -import net.minecraft.scoreboard.Score; import net.minecraft.scoreboard.ScoreObjective; import net.minecraft.scoreboard.ScorePlayerTeam; import net.minecraft.scoreboard.Scoreboard; @@ -80,11 +82,10 @@ public class FeatureWarnLowHealth extends TextHUDFeature { public List<StyledText> getText() { String lowestHealthName = ""; int lowestHealth = 999999999; - Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); - ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); - for (Score sc : scoreboard.getSortedScores(objective)) { - ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); - String line = ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()).trim(); + Objective objective = ScoreboardManager.INSTANCE.getSidebarObjective(); + + for (Score sc : objective.getScores()) { + String line = sc.getVisibleName(); String stripped = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(line)); if (line.contains("[") && line.endsWith("❤")) { String name = stripped.split(" ")[stripped.split(" ").length - 2]; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java index 246845fa..77a38dd6 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/features/impl/etc/FeatureEpicCountdown.java @@ -23,7 +23,9 @@ import kr.syeyoung.dungeonsguide.mod.events.annotations.DGEventHandler; import kr.syeyoung.dungeonsguide.mod.events.impl.DGTickEvent; import kr.syeyoung.dungeonsguide.mod.features.FeatureParameter; import kr.syeyoung.dungeonsguide.mod.features.SimpleFeature; -import kr.syeyoung.dungeonsguide.mod.utils.ScoreBoardUtils; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Objective; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Score; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.ScoreboardManager; import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; import net.minecraft.client.Minecraft; import net.minecraftforge.client.event.ClientChatReceivedEvent; @@ -99,15 +101,19 @@ public class FeatureEpicCountdown extends SimpleFeature { if(!isEnabled() || !DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return; - ScoreBoardUtils.forEachLineClean(line -> { - if(line.contains("Starting in:")){ - String time = line.replace("Starting in: ", "").replace("§r", "").replace("0:", ""); - if(!time.isEmpty()){ - secondsLeft = Integer.parseInt(time); - updatedAt = System.currentTimeMillis(); + Objective objective = ScoreboardManager.INSTANCE.getSidebarObjective(); + if (objective != null) { + for (Score score : objective.getScores()) { + String line = TextUtils.stripColor(score.getJustTeam()); + if(line.contains("Starting in:")){ + String time = line.replace("Starting in: ", "").replace("§r", "").replace("0:", ""); + if(!time.isEmpty()){ + secondsLeft = Integer.parseInt(time); + updatedAt = System.currentTimeMillis(); + } } } - }); + } long timepassed = System.currentTimeMillis() - updatedAt; long secs = timepassed / 1000; diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/README.md b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/README.md new file mode 100644 index 00000000..8997e573 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/README.md @@ -0,0 +1 @@ +this package exists to prevent incompatibilities with other mods due to them modifying various visible parts of the game.
\ No newline at end of file diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/Objective.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/Objective.java new file mode 100644 index 00000000..0b921092 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/Objective.java @@ -0,0 +1,62 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import net.minecraft.scoreboard.IScoreObjectiveCriteria; + +import java.util.*; + +@RequiredArgsConstructor +public class Objective { + @Getter + private final String objectiveName; + @Getter @Setter + private String displayName; + @Getter @Setter + private IScoreObjectiveCriteria.EnumRenderType displayType; + private SortedSet<Score> scores = new TreeSet<>(Comparator.comparingInt(Score::getScore).reversed()); + private Map<String, Score> currentObjects = new HashMap<>(); + + public SortedSet<Score> getScores() { + return Collections.unmodifiableSortedSet(scores); + } + + public void updateScore(String playerName, int score) { + removeScore(playerName); + addScore(playerName, score); + } + + public void removeScore(String playerName) { + if (currentObjects.containsKey(playerName)) { + Score scoreObj = currentObjects.remove(playerName); + scores.remove(scoreObj); + } + } + public void addScore(String playerName, int score) { + if (!currentObjects.containsKey(playerName)) { + Score scoreObj = new Score(playerName, score); + currentObjects.put(playerName, scoreObj); + scores.add(scoreObj); + } + } + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/Score.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/Score.java new file mode 100644 index 00000000..5d0d3706 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/Score.java @@ -0,0 +1,44 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard; + +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.Team; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.TeamManager; +import lombok.Data; + +@Data +public class Score { + private final String playerName; + private final int score; + + public String getVisibleName() { + Team team = TeamManager.INSTANCE.getPlayerTeam(playerName); + if (team != null) { + return team.getPrefix() + playerName + team.getSuffix(); + } + return playerName; + } + public String getJustTeam() { + Team team = TeamManager.INSTANCE.getPlayerTeam(playerName); + if (team != null) { + return team.getPrefix()+ team.getSuffix(); + } + return playerName; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/ScoreboardManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/ScoreboardManager.java new file mode 100644 index 00000000..1cdfcd4b --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/scoreboard/ScoreboardManager.java @@ -0,0 +1,71 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard; + +import java.util.HashMap; +import java.util.Map; + +public class ScoreboardManager { + + public static final ScoreboardManager INSTANCE = new ScoreboardManager(); + private ScoreboardManager() {} + + private Map<String, Objective> objectiveMap = new HashMap<>(); + private String sidebarObjective; + private String tablistObjective; + private String belowNameObjective; + + public void displayScoreboard(int slot, String objectiveName) { + if (slot == 0) tablistObjective = objectiveName; + else if (slot == 1) sidebarObjective = objectiveName; + else if (slot == 2) belowNameObjective = objectiveName; + } + + public Objective getSidebarObjective() { + return objectiveMap.get(sidebarObjective); + } + public Objective getTablistObjective() { + return objectiveMap.get(tablistObjective); + } + public Objective getBelownameObjective() { + return objectiveMap.get(belowNameObjective); + } + + public Objective getObjective(String name) { + return objectiveMap.get(name); + } + + public void addObjective(Objective objective) { + objectiveMap.put(objective.getObjectiveName(), objective); + } + + public void removeObjective(String name){ + objectiveMap.remove(name); + + if (name.equals(sidebarObjective)) sidebarObjective = null; + if (name.equals(tablistObjective)) tablistObjective = null; + if (name.equals(belowNameObjective)) belowNameObjective = null; + } + + + public void clear() { + objectiveMap.clear(); + belowNameObjective = null; tablistObjective = null; sidebarObjective = null; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/tab/TabList.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/tab/TabList.java new file mode 100644 index 00000000..bcda9c6c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/tab/TabList.java @@ -0,0 +1,86 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab; + +import com.google.common.collect.BiMap; +import com.google.common.collect.ComparisonChain; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Ordering; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.scoreboard.Score; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.Team; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.TeamManager; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.world.WorldSettings; + +import java.util.*; + +public class TabList { + public static final TabList INSTANCE = new TabList(); + + private final SortedSet<TabListEntry> tabListEntries = new TreeSet<>(Ordering.from((compare1, compare2) -> { + Team scoreplayerteam = TeamManager.INSTANCE.getPlayerTeam(compare1.getGameProfile().getName()); + Team scoreplayerteam1 = TeamManager.INSTANCE.getPlayerTeam(compare2.getGameProfile().getName()); + return ComparisonChain.start() + .compareTrueFirst(compare1.getGamemode() != WorldSettings.GameType.SPECTATOR, + compare2.getGamemode() != WorldSettings.GameType.SPECTATOR) + .compare(scoreplayerteam != null ? scoreplayerteam.getTeamName() : "", + scoreplayerteam1 != null ? scoreplayerteam1.getTeamName() : "") + .compare(compare1.getGameProfile().getName(), compare2.getGameProfile().getName()).result(); + })); + private final Map<UUID, TabListEntry> registered = new HashMap<>(); + private final BiMap<String, UUID> playerMap = HashBiMap.create(); + + public void clear() { + registered.clear(); + playerMap.clear(); + tabListEntries.clear(); + } + + public UUID getPlayer(String name) { + return playerMap.get(name); + } + + public SortedSet<TabListEntry> getTabListEntries() { + return Collections.unmodifiableSortedSet(tabListEntries); + } + + public void updateEntry(TabListEntry tabListEntry) { + removeEntry(tabListEntry.getGameProfile().getId()); + addEntry(tabListEntry); + } + + public TabListEntry getEntry(UUID uuid) { + return registered.get(uuid); + } + + public void removeEntry(UUID uuid) { + if (registered.containsKey(uuid)) { + TabListEntry scoreObj = registered.remove(uuid); + playerMap.inverse().remove(uuid); + tabListEntries.remove(scoreObj); + } + } + public void addEntry(TabListEntry tabListEntry) { + if (!registered.containsKey(tabListEntry.getGameProfile().getId())) { + registered.put(tabListEntry.getGameProfile().getId(), tabListEntry); + playerMap.put(tabListEntry.getGameProfile().getName(), tabListEntry.getGameProfile().getId()); + tabListEntries.add(tabListEntry); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/tab/TabListEntry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/tab/TabListEntry.java new file mode 100644 index 00000000..adea8511 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/tab/TabListEntry.java @@ -0,0 +1,135 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab; + +import com.google.common.base.Objects; +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.minecraft.MinecraftProfileTexture; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.Team; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams.TeamManager; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.network.NetworkPlayerInfo; +import net.minecraft.client.resources.DefaultPlayerSkin; +import net.minecraft.client.resources.SkinManager; +import net.minecraft.scoreboard.ScorePlayerTeam; +import net.minecraft.util.IChatComponent; +import net.minecraft.util.ResourceLocation; +import net.minecraft.world.WorldSettings.GameType; + +import java.util.UUID; + +@RequiredArgsConstructor +public class TabListEntry { + @Getter + private final GameProfile gameProfile; + // properties? + @Getter @Setter + private final GameType gamemode; + @Getter @Setter + private int ping; + @Getter + private IChatComponent displayName; + + @Getter + private String formatted; + + public void setDisplayName(IChatComponent displayName) { + this.displayName = displayName; + formatted = displayName == null ? null : displayName.getFormattedText(); + } + + public String getEffectiveName() { + if (formatted != null) return formatted; + + Team team = TeamManager.INSTANCE.getPlayerTeam(gameProfile.getName()); + if (team != null) { + return team.getPrefix() + gameProfile.getName() + team.getSuffix(); + } + return gameProfile.getName(); + } + public String getEffectiveWithoutName() { + if (formatted != null) return formatted; + + Team team = TeamManager.INSTANCE.getPlayerTeam(gameProfile.getName()); + if (team != null) { + return team.getPrefix() + team.getSuffix(); + } + return gameProfile.getName(); + } + + + private boolean playerTexturesLoaded = false; + private ResourceLocation locationSkin; + private ResourceLocation locationCape; + private String skinType; + + + public boolean hasLocationSkin() { + return this.locationSkin != null; + } + + public String getSkinType() { + return this.skinType == null ? DefaultPlayerSkin.getSkinType(this.gameProfile.getId()) : this.skinType; + } + + public ResourceLocation getLocationSkin() { + if (this.locationSkin == null) { + this.loadPlayerTextures(); + } + + return (ResourceLocation) Objects.firstNonNull(this.locationSkin, DefaultPlayerSkin.getDefaultSkin(this.gameProfile.getId())); + } + + public ResourceLocation getLocationCape() { + if (this.locationCape == null) { + this.loadPlayerTextures(); + } + + return this.locationCape; + } + protected void loadPlayerTextures() { + synchronized(this) { + if (!this.playerTexturesLoaded) { + this.playerTexturesLoaded = true; + Minecraft.getMinecraft().getSkinManager().loadProfileTextures(this.gameProfile, new SkinManager.SkinAvailableCallback() { + public void skinAvailable(MinecraftProfileTexture.Type type, ResourceLocation location, MinecraftProfileTexture profileTexture) { + switch (type) { + case SKIN: + TabListEntry.this.locationSkin = location; + TabListEntry.this.skinType = profileTexture.getMetadata("model"); + if (TabListEntry.this.skinType == null) { + TabListEntry.this.skinType = "default"; + } + break; + case CAPE: + TabListEntry.this.locationCape = location; + } + + } + }, true); + } + + } + } + + +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/NameTagVisibility.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/NameTagVisibility.java new file mode 100644 index 00000000..b384db56 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/NameTagVisibility.java @@ -0,0 +1,33 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams; + +public enum NameTagVisibility { + HIDE_FOR_OTHER_TEAMS, + HIDE_FOR_OWN_TEAM, + NEVER, + UNKNOWN; + + public static NameTagVisibility of(String val) { + if (val.equals("hideForOtherTeams")) return NameTagVisibility.HIDE_FOR_OTHER_TEAMS; + if (val.equals("hideForOwnTeam")) return NameTagVisibility.HIDE_FOR_OWN_TEAM; + if (val.equals("never")) return NameTagVisibility.NEVER; + return NameTagVisibility.UNKNOWN; + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/Team.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/Team.java new file mode 100644 index 00000000..304407a7 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/Team.java @@ -0,0 +1,56 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams; + +import lombok.*; +import net.minecraft.util.EnumChatFormatting; + +import java.util.*; + +@RequiredArgsConstructor +public class Team { + @Getter + private final String teamName; + @Getter @Setter + private String prefix; + @Getter @Setter + private String suffix; + @Getter @Setter + private String displayName; + + @Getter @Setter + private EnumChatFormatting color; + @Getter @Setter + private NameTagVisibility nameTagVisibility; + + private Set<String> players = new HashSet<>(); + + public Set<String> getPlayers() { + return Collections.unmodifiableSet(players); + } + + public void addTeamMember(String player) { + players.add(player); + TeamManager.INSTANCE.registerTeamMember(this, player); + } + public void removeTeamMember(String player) { + players.remove(player); + TeamManager.INSTANCE.unregisterTeamMember( player); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/TeamManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/TeamManager.java new file mode 100644 index 00000000..eaa079b6 --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/parallelUniverse/teams/TeamManager.java @@ -0,0 +1,89 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero 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 Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +package kr.syeyoung.dungeonsguide.mod.parallelUniverse.teams; + +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class TeamManager { + public static final TeamManager INSTANCE = new TeamManager(); + + private Map<String, Team> registeredTeams = new HashMap<>(); + + private Map<String, Team> player2team = new HashMap<>(); + + public void createTeam(Team team) { + registeredTeams.put(team.getTeamName(), team); + for (String player : team.getPlayers()) { + player2team.put(player, team); + } + } + + public void removeTeam(String teamName) { + Team team = registeredTeams.remove(teamName); + if (team != null) { + for (String player : team.getPlayers()) { + player2team.remove(player); + } + } + } + + public Team getTeamByName(String teamName) { + return registeredTeams.get(teamName); + } + + public Team getPlayerTeam(String playerName){ + return player2team.get(playerName); + } + + public void registerTeamMember(Team team, String player) { + if (!registeredTeams.containsKey(team.getTeamName())) return; + UUID uuid = TabList.INSTANCE.getPlayer(player); + TabListEntry tabListEntry = TabList.INSTANCE.getEntry(uuid); + if (tabListEntry != null) { + TabList.INSTANCE.removeEntry(uuid); + } + player2team.put(player, team); + if (tabListEntry != null) { + TabList.INSTANCE.updateEntry(tabListEntry); + } + } + public void unregisterTeamMember(String player) { + if (!player2team.containsKey(player)) return; + UUID uuid = TabList.INSTANCE.getPlayer(player); + TabListEntry tabListEntry = TabList.INSTANCE.getEntry(uuid); + if (tabListEntry != null) { + TabList.INSTANCE.removeEntry(uuid); + } + player2team.remove(player); + if (tabListEntry != null) { + TabList.INSTANCE.updateEntry(tabListEntry); + } + } + + + public void clear() { + registeredTeams.clear(); + player2team.clear(); + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/ScoreBoardUtils.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/ScoreBoardUtils.java deleted file mode 100644 index 5536e08f..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/ScoreBoardUtils.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2022 cyoung06 (syeyoung) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero 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 Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see <https://www.gnu.org/licenses/>. - */ - -package kr.syeyoung.dungeonsguide.mod.utils; - -import net.minecraft.client.Minecraft; -import net.minecraft.scoreboard.Score; -import net.minecraft.scoreboard.ScoreObjective; -import net.minecraft.scoreboard.ScorePlayerTeam; -import net.minecraft.scoreboard.Scoreboard; - -import java.util.function.Consumer; - -public class ScoreBoardUtils { - - public static void forEachLine(Consumer<String> lineConsumer){ - Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); - ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); - for (Score sc : scoreboard.getSortedScores(objective)) { - ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); - String line = ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()).trim(); - String stripped = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(line)); -// if (line.contains("[") && line.endsWith("❤")) { -// String name = stripped.split(" ")[stripped.split(" ").length - 2]; -// int health = Integer.parseInt(stripped.split(" ")[stripped.split(" ").length - 1]); -// if (health < lowestHealth) { -// lowestHealth = health; -// lowestHealthName = name; -// } -// } - - lineConsumer.accept(line); - - } - } - - public static void forEachLineClean(Consumer<String> lineConsumer){ - Scoreboard scoreboard = Minecraft.getMinecraft().thePlayer.getWorldScoreboard(); - ScoreObjective objective = scoreboard.getObjectiveInDisplaySlot(1); - for (Score sc : scoreboard.getSortedScores(objective)) { - ScorePlayerTeam scorePlayerTeam = scoreboard.getPlayersTeam(sc.getPlayerName()); - String line = ScorePlayerTeam.formatPlayerName(scorePlayerTeam, sc.getPlayerName()).trim(); - String stripped = TextUtils.keepScoreboardCharacters(TextUtils.stripColor(line)); -// if (line.contains("[") && line.endsWith("❤")) { -// String name = stripped.split(" ")[stripped.split(" ").length - 2]; -// int health = Integer.parseInt(stripped.split(" ")[stripped.split(" ").length - 1]); -// if (health < lowestHealth) { -// lowestHealth = health; -// lowestHealthName = name; -// } -// } - - lineConsumer.accept(stripped); - - } - } - - - - -} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TabListUtil.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TabListUtil.java index 98140fbc..8785f641 100644 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TabListUtil.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/utils/TabListUtil.java @@ -19,6 +19,8 @@ package kr.syeyoung.dungeonsguide.mod.utils; import kr.syeyoung.dungeonsguide.mod.features.impl.dungeon.FeatureDungeonMap; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabList; +import kr.syeyoung.dungeonsguide.mod.parallelUniverse.tab.TabListEntry; import net.minecraft.client.Minecraft; import net.minecraft.client.network.NetworkPlayerInfo; import net.minecraft.scoreboard.ScorePlayerTeam; @@ -34,17 +36,16 @@ public class TabListUtil { public static List<String> getPlayersInDungeon(){ List<String> players = new ArrayList<>(); - List<NetworkPlayerInfo> list = FeatureDungeonMap.sorter.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap()); - if(list.size() >= 20){ - for (int i = 1; i < 20; i++) { + int i = 1; + for (TabListEntry tabListEntry : TabList.INSTANCE.getTabListEntries()) { + if (i >= 20) break; + String na = getPlayerNameWithChecks(tabListEntry); - String na = getPlayerNameWithChecks(list.get(i)); - - if(na != null){ - players.add(na); - } + if(na != null){ + players.add(na); } + i++; } return players; @@ -52,20 +53,12 @@ public class TabListUtil { /** * We make sure that the player is alive and regex their name out - * @param networkPlayerInfo the network player info of player + * @param tabListEntry the network player info of player * @return the username of player */ @Nullable - public static String getPlayerNameWithChecks(NetworkPlayerInfo networkPlayerInfo) { - String name; - if (networkPlayerInfo.getDisplayName() != null) { - name = networkPlayerInfo.getDisplayName().getFormattedText(); - } else { - name = ScorePlayerTeam.formatPlayerName( - networkPlayerInfo.getPlayerTeam(), - networkPlayerInfo.getGameProfile().getName() - ); - } + public static String getPlayerNameWithChecks(TabListEntry tabListEntry) { + String name = tabListEntry.getEffectiveName(); if (name.trim().equals("§r") || name.startsWith("§r ")) return null; |