diff options
Diffstat (limited to 'src/main/java/cc/polyfrost/oneconfig/utils')
9 files changed, 528 insertions, 24 deletions
diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/IOUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/IOUtils.java index 64cabfd..efb0c16 100644 --- a/src/main/java/cc/polyfrost/oneconfig/utils/IOUtils.java +++ b/src/main/java/cc/polyfrost/oneconfig/utils/IOUtils.java @@ -10,6 +10,9 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.file.Files; +/** + * Utility class for I/O operations. + */ public final class IOUtils { /** diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/InputUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/InputUtils.java index 86e6c86..0ba4c00 100644 --- a/src/main/java/cc/polyfrost/oneconfig/utils/InputUtils.java +++ b/src/main/java/cc/polyfrost/oneconfig/utils/InputUtils.java @@ -25,27 +25,78 @@ public final class InputUtils { return mouseX > x && mouseY > y && mouseX < x + width && mouseY < y + height; } + /** + * Checks whether the mouse is currently over a specific region and clicked. + * + * @param x the x position of the region + * @param y the y position of the region + * @param width the width of the region + * @param height the height of the region + * @param ignoreBlock if true, will ignore {@link InputUtils#blockClicks(boolean)} + * @return true if the mouse is clicked and is over the region, false if not + * @see InputUtils#isAreaHovered(int, int, int, int) + */ public static boolean isAreaClicked(int x, int y, int width, int height, boolean ignoreBlock) { return isAreaHovered(x, y, width, height) && isClicked(ignoreBlock); } + /** + * Checks whether the mouse is currently over a specific region and clicked. + * + * @param x the x position of the region + * @param y the y position of the region + * @param width the width of the region + * @param height the height of the region + * @return true if the mouse is clicked and is over the region, false if not + * @see InputUtils#isAreaClicked(int, int, int, int, boolean) + */ public static boolean isAreaClicked(int x, int y, int width, int height) { return isAreaClicked(x, y, width, height, false); } + /** + * Checks whether the mouse is clicked or not. + * + * @param ignoreBlock if true, will ignore {@link InputUtils#blockClicks(boolean)} + * @return true if the mouse is clicked, false if not + */ public static boolean isClicked(boolean ignoreBlock) { return OneConfigGui.INSTANCE != null && OneConfigGui.INSTANCE.mouseDown && !Mouse.isButtonDown(0) && (!blockClicks || ignoreBlock); } + /** + * Checks whether the mouse is clicked or not. + * + * @return true if the mouse is clicked, false if not + * @see InputUtils#isClicked(boolean) + */ public static boolean isClicked() { return isClicked(false); } + /** + * Gets the current mouse X position. + * <p> + * All values returned from this class are not scaled to Minecraft's GUI scale. + * For scaled values, see {@link cc.polyfrost.oneconfig.libs.universal.UMouse}. + * </p> + * + * @return the current mouse X position + */ public static int mouseX() { if (OneConfigGui.INSTANCE == null) return Mouse.getX(); return (int) (Mouse.getX() / OneConfigGui.INSTANCE.getScaleFactor()); } + /** + * Gets the current mouse Y position. + * <p> + * All values returned from this class are not scaled to Minecraft's GUI scale. + * For scaled values, see {@link cc.polyfrost.oneconfig.libs.universal.UMouse}. + * </p> + * + * @return the current mouse Y position + */ public static int mouseY() { if (OneConfigGui.INSTANCE == null) return UResolution.getWindowHeight() - Math.abs(Mouse.getY()); return (int) ((UResolution.getWindowHeight() - Math.abs(Mouse.getY())) / OneConfigGui.INSTANCE.getScaleFactor()); @@ -58,6 +109,10 @@ public final class InputUtils { blockClicks = value; } + /** + * Whether clicks are blocked + * @return true if clicks are blocked, false if not + */ public static boolean isBlockingClicks() { return blockClicks; } diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/JsonUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/JsonUtils.java index 4ea9ce2..67881e9 100644 --- a/src/main/java/cc/polyfrost/oneconfig/utils/JsonUtils.java +++ b/src/main/java/cc/polyfrost/oneconfig/utils/JsonUtils.java @@ -3,9 +3,24 @@ package cc.polyfrost.oneconfig.utils; import com.google.gson.JsonElement; import com.google.gson.JsonParser; +/** + * Various utility methods for working with JSON. + */ public final class JsonUtils { + + /** + * The instance of the parser. + */ public static final JsonParser PARSER = new JsonParser(); + /** + * Parses a string into a {@link JsonElement}. + * + * @param string The string to parse. + * @param catchExceptions Whether to catch exceptions. + * @return The {@link JsonElement}. + * @see JsonParser#parse(String) + */ public static JsonElement parseString(String string, boolean catchExceptions) { try { return PARSER.parse(string); @@ -18,6 +33,13 @@ public final class JsonUtils { } } + /** + * Parses a string into a {@link JsonElement}. + * + * @param string The string to parse. + * @return The {@link JsonElement}. + * @see JsonUtils#parseString(String, boolean) + */ public static JsonElement parseString(String string) { return parseString(string, true); } diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/Multithreading.java b/src/main/java/cc/polyfrost/oneconfig/utils/Multithreading.java new file mode 100644 index 0000000..518d699 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/utils/Multithreading.java @@ -0,0 +1,75 @@ +package cc.polyfrost.oneconfig.utils; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; + +import java.util.concurrent.*; + +/** + * Allows for easy multithreading. + * <p> + * Taken from Seraph by Scherso under LGPL-2.1 + * <a href="https://github.com/Scherso/Seraph/blob/master/LICENSE">https://github.com/Scherso/Seraph/blob/master/LICENSE</a> + * </p> + */ +public class Multithreading { + private static final ExecutorService executorService = Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat("OneConfig-%d").build()); + private static final ScheduledExecutorService runnableExecutor = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors() + 1); + + /** + * Runs the runnable asynchronously. + * + * @param runnable The runnable to run. + * @see Multithreading#submit(Runnable) + */ + public static void runAsync(Runnable runnable) { + submit(runnable); + } + + /** + * Runs the provided runnables asynchronously. + * + * @param runnables The runnables to run. + * @see Multithreading#runAsync(Runnable) + */ + public static void runAsync(Runnable... runnables) { + for (Runnable runnable : runnables) { + runAsync(runnable); + } + } + + /** + * Submits the Runnable to the executor, making it run asynchronously. + * + * @param runnable The runnable to run. + * @return The future representing the submitted runnable. + * @see ExecutorService#submit(Runnable) + */ + public static Future<?> submit(Runnable runnable) { + return executorService.submit(runnable); + } + + /** + * Schedules the runnable to run asynchronously after the specified delay. + * + * @param runnable The runnable to run. + * @param delay The delay before the runnable is run. + * @param timeUnit The {@link TimeUnit} of the delay. + * @see Multithreading#submitScheduled(Runnable, long, TimeUnit) + */ + public static void schedule(Runnable runnable, long delay, TimeUnit timeUnit) { + submitScheduled(runnable, delay, timeUnit); + } + + /** + * Submits the Runnable to the executor after a delay, making it run asynchronously. + * + * @param runnable The runnable to run. + * @param delay The delay before the runnable is run. + * @param timeUnit The {@link TimeUnit} of the delay. + * @return The future representing the submitted runnable. + * @see ScheduledExecutorService#schedule(Runnable, long, TimeUnit) + */ + public static ScheduledFuture<?> submitScheduled(Runnable runnable, long delay, TimeUnit timeUnit) { + return runnableExecutor.schedule(runnable, delay, timeUnit); + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/NetworkUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/NetworkUtils.java index 34d4382..767f36f 100644 --- a/src/main/java/cc/polyfrost/oneconfig/utils/NetworkUtils.java +++ b/src/main/java/cc/polyfrost/oneconfig/utils/NetworkUtils.java @@ -11,18 +11,19 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; +/** + * Utility class for accessing the internet. + */ public final class NetworkUtils { - private static InputStream setupConnection(String url, String userAgent, int timeout, boolean useCaches) throws IOException { - HttpURLConnection connection = ((HttpURLConnection) new URL(url).openConnection()); - connection.setRequestMethod("GET"); - connection.setUseCaches(useCaches); - connection.addRequestProperty("User-Agent", userAgent); - connection.setReadTimeout(timeout); - connection.setConnectTimeout(timeout); - connection.setDoOutput(true); - return connection.getInputStream(); - } + /** + * Gets the contents of a URL as a String. + * @param url The URL to read. + * @param userAgent The user agent to use. + * @param timeout The timeout in milliseconds. + * @param useCaches Whether to use caches. + * @return The contents of the URL. + */ public static String getString(String url, String userAgent, int timeout, boolean useCaches) { try (InputStreamReader input = new InputStreamReader(setupConnection(url, userAgent, timeout, useCaches), StandardCharsets.UTF_8)) { return IOUtils.toString(input); @@ -32,23 +33,52 @@ public final class NetworkUtils { } } + /** + * Gets the contents of a URL as a String. + * + * @param url The URL to read. + * @return The contents of the URL. + * @see NetworkUtils#getString(String, String, int, boolean) + */ public static String getString(String url) { return getString(url, "OneConfig/1.0.0", 5000, false); } + /** + * Gets the contents of a URL as a JsonElement. + * + * @param url The URL to read. + * @param userAgent The user agent to use. + * @param timeout The timeout in milliseconds. + * @param useCaches Whether to use caches. + * @return The contents of the URL. + * @see NetworkUtils#getString(String, String, int, boolean) + * @see JsonUtils#parseString(String) + */ public static JsonElement getJsonElement(String url, String userAgent, int timeout, boolean useCaches) { return JsonUtils.parseString(getString(url, userAgent, timeout, useCaches)); } + /** + * Gets the contents of a URL as a JsonElement. + * + * @param url The URL to read. + * @return The contents of the URL. + * @see NetworkUtils#getJsonElement(String, String, int, boolean) + */ public static JsonElement getJsonElement(String url) { return getJsonElement(url, "OneConfig/1.0.0", 5000, false); } - - public static boolean downloadFile(String url, File file) { - return downloadFile(url, file, "OneConfig/1.0.0", 5000, false); - } - + /** + * Downloads a file from a URL. + * @param url The URL to download from. + * @param file The file to download to. + * @param userAgent The user agent to use. + * @param timeout The timeout in milliseconds. + * @param useCaches Whether to use caches. + * @return Whether the download was successful. + */ public static boolean downloadFile(String url, File file, String userAgent, int timeout, boolean useCaches) { url = url.replace(" ", "%20"); try (FileOutputStream fileOut = new FileOutputStream(file); BufferedInputStream in = new BufferedInputStream(setupConnection(url, userAgent, timeout, useCaches))) { @@ -60,8 +90,24 @@ public final class NetworkUtils { return true; } - public static String getFileChecksum(String filename) { - try (FileInputStream inputStream = new FileInputStream(filename)) { + /** + * Downloads a file from a URL. + * @param url The URL to download from. + * @param file The file to download to. + * @return Whether the download was successful. + * @see NetworkUtils#downloadFile(String, File, String, int, boolean) + */ + public static boolean downloadFile(String url, File file) { + return downloadFile(url, file, "OneConfig/1.0.0", 5000, false); + } + + /** + * Gets the SHA-256 hash of a file. + * @param file The file to hash. + * @return The SHA-256 hash of the file. + */ + public static String getFileChecksum(File file) { + try (FileInputStream inputStream = new FileInputStream(file)) { MessageDigest digest = MessageDigest.getInstance("SHA-256"); byte[] bytesBuffer = new byte[1024]; int bytesRead; @@ -77,6 +123,28 @@ public final class NetworkUtils { return ""; } + /** + * Launches a URL in the default browser. + * + * @param uri The URI to launch. + * @see UDesktop#browse(URI) + * @see java.awt.Desktop#browse(URI) + */ + public static void browseLink(String uri) { + UDesktop.browse(URI.create(uri)); + } + + private static InputStream setupConnection(String url, String userAgent, int timeout, boolean useCaches) throws IOException { + HttpURLConnection connection = ((HttpURLConnection) new URL(url).openConnection()); + connection.setRequestMethod("GET"); + connection.setUseCaches(useCaches); + connection.addRequestProperty("User-Agent", userAgent); + connection.setReadTimeout(timeout); + connection.setConnectTimeout(timeout); + connection.setDoOutput(true); + return connection.getInputStream(); + } + private static String convertByteArrayToHexString(byte[] arrayBytes) { StringBuilder stringBuffer = new StringBuilder(); for (byte arrayByte : arrayBytes) { @@ -85,8 +153,4 @@ public final class NetworkUtils { } return stringBuffer.toString(); } - - public static void browseLink(String uri) { - UDesktop.browse(URI.create(uri)); - } } diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java index 252a588..f9f0fbd 100644 --- a/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java +++ b/src/main/java/cc/polyfrost/oneconfig/utils/TextUtils.java @@ -5,7 +5,20 @@ import cc.polyfrost.oneconfig.lwjgl.font.Fonts; import java.util.ArrayList; +/** + * Simple text utility class for NanoVG text rendering. + */ public final class TextUtils { + + /** + * Wraps a string into an array of lines. + * @param vg The NanoVG context. + * @param text The text to wrap. + * @param maxWidth The maximum width of each line. + * @param fontSize The font size. + * @param font The font to use. + * @return The array of lines. + */ public static ArrayList<String> wrapText(long vg, String text, float maxWidth, float fontSize, Fonts font) { ArrayList<String> wrappedText = new ArrayList<>(); text += " "; diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/TickDelay.java b/src/main/java/cc/polyfrost/oneconfig/utils/TickDelay.java index 2fa2017..35b7b8b 100644 --- a/src/main/java/cc/polyfrost/oneconfig/utils/TickDelay.java +++ b/src/main/java/cc/polyfrost/oneconfig/utils/TickDelay.java @@ -5,23 +5,26 @@ import cc.polyfrost.oneconfig.events.event.Stage; import cc.polyfrost.oneconfig.events.event.TickEvent; import cc.polyfrost.oneconfig.libs.eventbus.Subscribe; +/** + * Schedules a Runnable to be called after a certain amount of ticks. + */ public class TickDelay { private int delay; private final Runnable function; public TickDelay(Runnable functionName, int ticks) { - EventManager.INSTANCE.getEventBus().register(this); + EventManager.INSTANCE.register(this); delay = ticks; function = functionName; } @Subscribe - public void onTick(TickEvent event) { + protected void onTick(TickEvent event) { if (event.stage == Stage.START) { // Delay expired if (delay < 1) { function.run(); - EventManager.INSTANCE.getEventBus().unregister(this); + EventManager.INSTANCE.unregister(this); } delay--; } diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/hypixel/HypixelUtils.java b/src/main/java/cc/polyfrost/oneconfig/utils/hypixel/HypixelUtils.java new file mode 100644 index 0000000..d7a9b0d --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/utils/hypixel/HypixelUtils.java @@ -0,0 +1,159 @@ +package cc.polyfrost.oneconfig.utils.hypixel; + +import cc.polyfrost.oneconfig.events.EventManager; +import cc.polyfrost.oneconfig.events.event.*; +import cc.polyfrost.oneconfig.libs.eventbus.Subscribe; +import cc.polyfrost.oneconfig.libs.universal.UChat; +import cc.polyfrost.oneconfig.libs.universal.UMinecraft; +import cc.polyfrost.oneconfig.libs.universal.wrappers.UPlayer; +import cc.polyfrost.oneconfig.libs.universal.wrappers.message.UTextComponent; +import cc.polyfrost.oneconfig.utils.JsonUtils; +import cc.polyfrost.oneconfig.utils.Multithreading; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; + +import java.util.Locale; +import java.util.concurrent.TimeUnit; + +/** + * Various utilities for Hypixel. + * <p> + * Locraw utilities taken from Seraph by Scherso under LGPL-2.1 + * <a href="https://github.com/Scherso/Seraph/blob/master/LICENSE">https://github.com/Scherso/Seraph/blob/master/LICENSE</a> + * </p> + */ +public class HypixelUtils { + public static final HypixelUtils INSTANCE = new HypixelUtils(); + private final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); + private int tick = 0; + private int limboLoop = 0; + + private boolean sentCommand = false; + private boolean sendPermitted = false; + private boolean inGame; + + private LocrawInfo locraw; + private LocrawInfo previousLocraw; + + /** + * Checks whether the player is on Hypixel. + * + * @return Whether the player is on Hypixel. + * @see <a href="https://canary.discord.com/channels/864592657572560958/945075920664928276/978649312013725747">this discord link from jade / asbyth</a> + */ + public boolean isHypixel() { + if (UMinecraft.getWorld() == null || UMinecraft.getMinecraft().isIntegratedServerRunning()) return false; + + net.minecraft.client.entity.EntityPlayerSP player = UPlayer.getPlayer(); + if (player == null) return false; + String serverBrand = player.getClientBrand(); + + if (serverBrand == null) return false; + + return serverBrand.toLowerCase(Locale.ENGLISH).contains("hypixel"); + } + + /** + * Queues a locraw update after the specified interval. + * + * @param interval The interval in milliseconds. + */ + public void queueUpdate(long interval) { + sendPermitted = true; + Multithreading.schedule(() -> { + if (sendPermitted) { + UChat.say("/locraw"); + } + }, interval, TimeUnit.MILLISECONDS); + } + + @Subscribe + private void onTick(TickEvent event) { + if (event.stage == Stage.START) { + tick++; + + if (tick % 20 == 0) { + tick = 0; + if (isHypixel() && !sentCommand) { + queueUpdate(500); + sentCommand = true; + } + } + } + } + + @Subscribe + private void onWorldLoad(WorldLoadEvent event) { + locraw = null; + sendPermitted = false; + sentCommand = false; + limboLoop = 0; + } + + @Subscribe + private void onMessageReceived(ChatReceiveEvent event) { + if (!sentCommand) return; + try { + final String msg = UTextComponent.Companion.stripFormatting(event.message.getUnformattedText()); + // Checking for rate limitation. + if (!(msg.startsWith("{") && msg.endsWith("}"))) { + if (msg.contains("You are sending too many commands! Please try again in a few seconds.")) // if you're being rate limited, the /locraw command will be resent in 5 seconds. + queueUpdate(5000); + return; + } + + JsonElement raw = JsonUtils.parseString(msg); + if (!raw.isJsonObject()) return; + JsonObject json = raw.getAsJsonObject(); + LocrawInfo parsed = GSON.fromJson(json, LocrawInfo.class); + + if (5 > limboLoop && parsed.getGameType() == LocrawInfo.GameType.LIMBO) { + sentCommand = false; + limboLoop++; + queueUpdate(1000); + } else locraw = parsed; // if the player isn't in limbo, the parsed info is used. + + if (locraw != null) { + locraw.setGameType(LocrawInfo.GameType.getFromLocraw(this.locraw.getRawGameType())); + if (parsed.getGameMode().equals("lobby")) { + inGame = false; // If your gamemode returns "lobby", boolean inGame is false. + } else { + previousLocraw = parsed; + inGame = true; // If your gamemode does not return "lobby", boolean inGame is true. + } + EventManager.INSTANCE.post(new LocrawEvent(locraw)); + event.isCancelled = true; + } + } catch (Exception ex) { + ex.printStackTrace(); + } + } + + /** + * Returns whether the player is in game. + * @return Whether the player is in game. + */ + public boolean isInGame() { + return this.inGame; + } + + /** + * Returns the current {@link LocrawInfo}. + * @return The current {@link LocrawInfo}. + * @see LocrawInfo + */ + public LocrawInfo getLocrawInfo() { + return this.locraw; + } + + /** + * Returns the previous {@link LocrawInfo}. + * @return The previous {@link LocrawInfo}. + * @see LocrawInfo + */ + public LocrawInfo getPreviousLocraw() { + return this.previousLocraw; + } +} diff --git a/src/main/java/cc/polyfrost/oneconfig/utils/hypixel/LocrawInfo.java b/src/main/java/cc/polyfrost/oneconfig/utils/hypixel/LocrawInfo.java new file mode 100644 index 0000000..4a946f0 --- /dev/null +++ b/src/main/java/cc/polyfrost/oneconfig/utils/hypixel/LocrawInfo.java @@ -0,0 +1,110 @@ +package cc.polyfrost.oneconfig.utils.hypixel; + +import com.google.gson.annotations.SerializedName; + +import java.util.Objects; + +/** + * Represents the location of the player in Hypixel. + * <p> + * Locraw utilities taken from Seraph by Scherso under LGPL-2.1 + * <a href="https://github.com/Scherso/Seraph/blob/master/LICENSE">https://github.com/Scherso/Seraph/blob/master/LICENSE</a> + * </p> + * + * @see HypixelUtils + */ +public class LocrawInfo { + @SerializedName("server") + private String serverId; + @SerializedName("mode") + private String gameMode = "lobby"; + @SerializedName("map") + private String mapName; + @SerializedName("gametype") + private String rawGameType; + private GameType gameType; + + /** + * @return The serverID of the server you are currently on, ex: mini121 + */ + public String getServerId() { + return serverId; + } + + /** + * @return The GameType of the server as a String. + */ + public String getRawGameType() { + return rawGameType; + } + + /** + * @return The GameMode of the server, ex: solo_insane + */ + public String getGameMode() { + return gameMode; + } + + /** + * @return The GameType of the server as an Enum. + */ + public GameType getGameType() { + return gameType; + } + + /** + * @param gameType The GameType to set it to. + */ + public void setGameType(GameType gameType) { + this.gameType = gameType; + } + + /** + * @return The map of the server, ex: Shire. + */ + public String getMapName() { + return mapName; + } + + @Override + public String toString() { + return "LocrawInfo{" + "serverId='" + serverId + '\'' + ", gameMode='" + gameMode + '\'' + ", mapName='" + mapName + '\'' + ", rawGameType='" + rawGameType + '\'' + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + LocrawInfo that = (LocrawInfo) o; + return Objects.equals(serverId, that.serverId) && Objects.equals(gameMode, that.gameMode) && Objects.equals(mapName, that.mapName) && Objects.equals(rawGameType, that.rawGameType); + } + + @Override + public int hashCode() { + return Objects.hash(serverId, gameMode, mapName, rawGameType); + } + + public enum GameType { + UNKNOWN(""), LIMBO("LIMBO"), BEDWARS("BEDWARS"), SKYWARS("SKYWARS"), PROTOTYPE("PROTOTYPE"), SKYBLOCK("SKYBLOCK"), MAIN("MAIN"), MURDER_MYSTERY("MURDER_MYSTERY"), HOUSING("HOUSING"), ARCADE_GAMES("ARCADE"), BUILD_BATTLE("BUILD_BATTLE"), DUELS("DUELS"), PIT("PIT"), UHC_CHAMPIONS("UHC"), SPEED_UHC("SPEED_UHC"), TNT_GAMES("TNTGAMES"), CLASSIC_GAMES("LEGACY"), COPS_AND_CRIMS("MCGO"), BLITZ_SG("SURVIVAL_GAMES"), MEGA_WALLS("WALLS3"), SMASH_HEROES("SUPER_SMASH"), WARLORDS("BATTLEGROUND"); + + private final String serverName; + + GameType(String serverName) { + this.serverName = serverName; + } + + public static GameType getFromLocraw(String gameType) { + for (GameType value : values()) { + if (value.serverName.equals(gameType)) { + return value; + } + } + + return UNKNOWN; + } + + public String getServerName() { + return serverName; + } + } +} |