Skip to content

Commit

Permalink
Bug Fixes
Browse files Browse the repository at this point in the history
- Fix close window packet not being sent when the fancy warp menu is closed in certain situations
- Convert SkyBlockJoinListener to chat-based detection for slight performance improvement
- Settings and regular warp menu button logic fixes
  • Loading branch information
ILikePlayingGames committed Dec 25, 2023
1 parent 7416510 commit 0476361
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 147 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -140,10 +140,6 @@ public WarpMenuListener getWarpMenuListener() {
return warpMenuListener;
}

public boolean isPlayerOnSkyBlock() {
return skyblockJoinListener.isOnSkyBlock();
}

public void reloadResources() {
Minecraft.getMinecraft().refreshResources();
reloadSkyBlockConstants();
Expand Down
23 changes: 21 additions & 2 deletions src/main/java/ca/tirelesstraveler/fancywarpmenu/GameState.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,29 @@

package ca.tirelesstraveler.fancywarpmenu;

import ca.tirelesstraveler.fancywarpmenu.data.Settings;
import ca.tirelesstraveler.fancywarpmenu.data.skyblockconstants.Menu;

/**
* This class stores the state of the SkyBlock server the player is on. This information is used for the conditional hiding of warps.
* This class stores information about the state of the SkyBlock game the player is currently in.
*/
public class GameState {
/**
* Whether the player is currently on SkyBlock
*/
private static boolean onSkyBlock;
/**
* Whether the current SkyBlock season is Late Winter
*/
private static boolean lateWinter;

/**
* Current in-game menu the player has open
*/
private static Menu currentMenu;

public static boolean isOnSkyBlock() {
return onSkyBlock;
return onSkyBlock || Settings.shouldSkipSkyBlockCheck();
}

public static void setOnSkyBlock(boolean onSkyBlock) {
Expand All @@ -47,4 +58,12 @@ public static boolean isLateWinter() {
public static void setLateWinter(boolean lateWinter) {
GameState.lateWinter = lateWinter;
}

public static Menu getCurrentMenu() {
return currentMenu;
}

public static void setCurrentMenu(Menu currentMenu) {
GameState.currentMenu = currentMenu;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (c) 2023. TirelessTraveler
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
* OR OTHER DEALINGS IN THE SOFTWARE.
*/

package ca.tirelesstraveler.fancywarpmenu.data.skyblockconstants;

/**
* In-game menus, not serialized
*/
public enum Menu {
/** Value used when player is not in a menu or in an unknown or irrelevant menu */
NONE("None"),
SKYBLOCK_MENU("SkyBlock Menu"),
FAST_TRAVEL("Fast Travel"),
PORHTAL("Porhtal");

/** Title of menu as it appears on the top of the {@code GuiChest}*/
private final String MENU_TITLE;
Menu(String menuTitle) {
MENU_TITLE = menuTitle;
}

public String getMenuTitle() {
return MENU_TITLE;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@

package ca.tirelesstraveler.fancywarpmenu.data.skyblockconstants;

import org.apache.commons.lang3.StringUtils;

import java.util.List;

import static ca.tirelesstraveler.fancywarpmenu.data.DataCommon.gson;
Expand All @@ -31,8 +33,12 @@ public class SkyBlockConstants {
private SkyBlockConstants() {
}

/** Chat messages sent by the server when a warp attempt succeeds or fails */
private WarpMessages warpMessages;
/** Names of the warp command and its aliases */
private List<WarpCommandVariant> warpCommandVariants;
/** Chat messages are checked to see if they start with this string in order to see if the player joined SkyBlock */
private String skyBlockJoinMessage;

public WarpMessages getWarpMessages() {
return warpMessages;
Expand All @@ -42,6 +48,10 @@ public List<WarpCommandVariant> getWarpCommandVariants() {
return warpCommandVariants;
}

public String getSkyBlockJoinMessage() {
return skyBlockJoinMessage;
}

@Override
public String toString() {
return gson.toJson(this);
Expand All @@ -61,5 +71,9 @@ public static void validateSkyBlockConstants(SkyBlockConstants skyBlockConstants
for (WarpCommandVariant warpCommandVariant : skyBlockConstants.warpCommandVariants) {
WarpCommandVariant.validateWarpCommandVariant(warpCommandVariant);
}

if (StringUtils.isEmpty(skyBlockConstants.skyBlockJoinMessage)) {
throw new IllegalArgumentException("SkyBlock join message cannot be null or empty.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ protected void actionPerformed(GuiButton button) {
} else if (button instanceof GuiButtonConfig) {
mc.displayGuiScreen(new FancyWarpMenuConfigScreen(this));
} else if (button instanceof GuiButtonRegularWarpMenu) {
Settings.setWarpMenuEnabled(false);
sendCommand("/warp");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@
package ca.tirelesstraveler.fancywarpmenu.gui.buttons;

import ca.tirelesstraveler.fancywarpmenu.FancyWarpMenu;
import ca.tirelesstraveler.fancywarpmenu.data.Settings;
import ca.tirelesstraveler.fancywarpmenu.data.layout.ConfigButton;
import ca.tirelesstraveler.fancywarpmenu.data.layout.Island;
import ca.tirelesstraveler.fancywarpmenu.data.Settings;
import ca.tirelesstraveler.fancywarpmenu.gui.GuiFancyWarp;
import ca.tirelesstraveler.fancywarpmenu.data.skyblockconstants.Menu;
import ca.tirelesstraveler.fancywarpmenu.gui.grid.GridRectangle;
import ca.tirelesstraveler.fancywarpmenu.gui.grid.ScaledGrid;
import ca.tirelesstraveler.fancywarpmenu.gui.transitions.ScaleTransition;
import ca.tirelesstraveler.fancywarpmenu.listeners.WarpMenuListener;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.client.resources.I18n;
Expand Down Expand Up @@ -83,15 +84,13 @@ public void drawButton(Minecraft mc, int mouseX, int mouseY) {

@Override
public boolean mousePressed(Minecraft mc, int mouseX, int mouseY) {
WarpMenuListener warpMenuListener = FancyWarpMenu.getInstance().getWarpMenuListener();
boolean clicked = super.mousePressed(mc, mouseX, mouseY);

if (clicked && !(mc.currentScreen instanceof GuiFancyWarp)) {
if (!Settings.isWarpMenuEnabled()) {
Settings.setWarpMenuEnabled(true);
mc.thePlayer.addChatMessage(new ChatComponentTranslation("fancywarpmenu.messages.fancyWarpMenuEnabled").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GREEN)));
}

FancyWarpMenu.getInstance().getWarpMenuListener().createFastTravelMenu(true);
if (clicked && !Settings.isWarpMenuEnabled()) {
Settings.setWarpMenuEnabled(true);
mc.thePlayer.addChatMessage(new ChatComponentTranslation("fancywarpmenu.messages.fancyWarpMenuEnabled").setChatStyle(new ChatStyle().setColor(EnumChatFormatting.GREEN)));
warpMenuListener.createFastTravelMenu(Menu.FAST_TRAVEL, false);
}

return clicked;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package ca.tirelesstraveler.fancywarpmenu.hooks;

import ca.tirelesstraveler.fancywarpmenu.FancyWarpMenu;
import ca.tirelesstraveler.fancywarpmenu.GameState;
import ca.tirelesstraveler.fancywarpmenu.LogHelper;
import ca.tirelesstraveler.fancywarpmenu.data.Settings;
import ca.tirelesstraveler.fancywarpmenu.data.skyblockconstants.WarpCommandVariant;
Expand All @@ -11,7 +12,7 @@

public class EntityPlayerSPHook {
public static void onSendChatMessage(String message, CallbackInfo ci) {
if (Settings.isWarpMenuEnabled() && FancyWarpMenu.getInstance().isPlayerOnSkyBlock() && message.startsWith("/")) {
if (Settings.isWarpMenuEnabled() && GameState.isOnSkyBlock() && message.startsWith("/")) {
WarpCommandVariant warpCommandVariant = WarpMenuListener.getWarpCommandVariant(message);

LogHelper.logDebug("Caught sent command: {}", message);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@

import ca.tirelesstraveler.fancywarpmenu.FancyWarpMenu;
import ca.tirelesstraveler.fancywarpmenu.GameState;
import ca.tirelesstraveler.fancywarpmenu.data.Settings;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.network.play.server.S3DPacketDisplayScoreboard;
import net.minecraft.client.gui.GuiDownloadTerrain;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraftforge.client.event.ClientChatReceivedEvent;
import net.minecraftforge.client.event.GuiOpenEvent;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.network.FMLNetworkEvent;
import org.apache.logging.log4j.LogManager;
Expand All @@ -40,86 +40,61 @@
* Forge event and packet listener that detects when the player joins/leaves SkyBlock
*/
@ChannelHandler.Sharable
public class SkyBlockJoinListener extends SimpleChannelInboundHandler<S3DPacketDisplayScoreboard> {
public class SkyBlockJoinListener {
private static final String SERVER_BRAND_START = "Hypixel BungeeCord";
private static final String PACKET_LISTENER_NAME = String.format("%s:skyblock_join_listener",
FancyWarpMenu.getInstance().getModId());

private static final Logger logger = LogManager.getLogger();
private boolean serverBrandChecked;
private boolean onHypixel;

public SkyBlockJoinListener() {
super(false);
}

@SubscribeEvent
public void onClientConnectedToServer(FMLNetworkEvent.ClientConnectedToServerEvent e) {
if (e.manager.channel().pipeline().get(PACKET_LISTENER_NAME) == null) {
e.manager.channel().pipeline().addBefore("packet_handler", PACKET_LISTENER_NAME, this);
}
}

@SubscribeEvent
public void onClientDisconnect(FMLNetworkEvent.ClientDisconnectionFromServerEvent e) {
if (onHypixel) {
serverBrandChecked = false;
onHypixel = false;
GameState.setOnSkyBlock(false);
logger.info("Disconnected from Hypixel.");
logger.debug("Disconnected from Hypixel.");
}
}

/**
* This method listens for {@link S3DPacketDisplayScoreboard} packets. These are sent once per world join/switch
* and contain the name of the game mode, thus making them excellent for checking whether the player is on SkyBlock.
*/
@Override
protected void channelRead0(ChannelHandlerContext channelHandlerContext, S3DPacketDisplayScoreboard packet) {
if (channelHandlerContext.channel().isOpen()) {
EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer;

try {
logger.debug("Received S3DPacketDisplayScoreboard packet with title \"{}\"", packet.func_149370_d());

// Player hasn't been spawned yet, skip this packet.
if (thePlayer != null && thePlayer.getClientBrand() != null) {
if (!serverBrandChecked) {
onHypixel = thePlayer.getClientBrand().startsWith(SERVER_BRAND_START);
serverBrandChecked = true;
@SubscribeEvent
public void onGuiOpen(GuiOpenEvent event) {
// Reset on world switch
if (event.gui instanceof GuiDownloadTerrain) {
GameState.setOnSkyBlock(false);
}
}

if (onHypixel) {
logger.info("Player joined Hypixel.");
}
@SubscribeEvent
public void onChatMessageReceived(ClientChatReceivedEvent event) {
if (!serverBrandChecked || onHypixel) {
// type 0 is a standard chat message
if (event.type == 0 && event.message.getUnformattedText().startsWith(
FancyWarpMenu.getSkyBlockConstants().getSkyBlockJoinMessage())) {
EntityPlayerSP thePlayer = Minecraft.getMinecraft().thePlayer;

if (!serverBrandChecked) {
onHypixel = thePlayer.getClientBrand().startsWith(SERVER_BRAND_START);
serverBrandChecked = true;

if (onHypixel) {
logger.debug("Player joined Hypixel.");
}
}

// 1 is the sidebar objective slot.
if (onHypixel && packet.func_149371_c() == 1) {
String objectiveName = packet.func_149370_d();
boolean newSkyBlockState = objectiveName.equals("SBScoreboard");

if (newSkyBlockState && !GameState.isOnSkyBlock()) {
logger.info("Player joined SkyBlock.");
} else if (!newSkyBlockState && GameState.isOnSkyBlock()) {
logger.info("Player left SkyBlock.");
}
if (onHypixel) {
Scoreboard scoreboard = thePlayer.getWorldScoreboard();
boolean newSkyBlockState = scoreboard != null && scoreboard.getObjective("SBScoreboard") != null;

GameState.setOnSkyBlock(newSkyBlockState);
if (newSkyBlockState && !GameState.isOnSkyBlock()) {
logger.debug("Player joined SkyBlock.");
} else if (!newSkyBlockState && GameState.isOnSkyBlock()) {
logger.debug("Player left SkyBlock.");
}

GameState.setOnSkyBlock(newSkyBlockState);
}
} catch (RuntimeException e) {
logger.error(String.format("SkyBlock Join Check Failed: %s" +
"\nBrand: %s" +
"\nPacket contents:" +
"\n Position: %s" +
"\n Score Name: %s", e.getMessage(), thePlayer.getClientBrand(), packet.func_149371_c(), packet.func_149370_d()), e);
}
}

channelHandlerContext.fireChannelRead(packet);
}

public boolean isOnSkyBlock() {
return (Settings.isDebugModeEnabled() && Settings.shouldSkipSkyBlockCheck()) || GameState.isOnSkyBlock();
}
}
Loading

0 comments on commit 0476361

Please sign in to comment.