aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/xmrvizzy/skyblocker/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker/utils')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Constants.java8
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Http.java89
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/PosUtils.java14
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java63
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java2
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/render/title/TitleContainer.java3
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/MessageScheduler.java7
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/Scheduler.java85
8 files changed, 207 insertions, 64 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Constants.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Constants.java
new file mode 100644
index 00000000..aef55687
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Constants.java
@@ -0,0 +1,8 @@
+package me.xmrvizzy.skyblocker.utils;
+
+/**
+ * Holds generic static constants
+ */
+public interface Constants {
+ String LEVEL_EMBLEMS = "\u2E15\u273F\u2741\u2E19\u03B1\u270E\u2615\u2616\u2663\u213B\u2694\u27B6\u26A1\u2604\u269A\u2693\u2620\u269B\u2666\u2660\u2764\u2727\u238A\u1360\u262C\u269D\u29C9\uA214\u32D6\u2E0E\u26A0\uA541\u3020\u30C4\u2948\u2622\u2623\u273E\u269C\u0BD0\u0A6D\u2742\u16C3\u3023\u10F6\u0444\u266A\u266B\u04C3\u26C1\u26C3\u16DD\uA03E\u1C6A\u03A3\u09EB\u2603\u2654\u26C2\u12DE";
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Http.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Http.java
new file mode 100644
index 00000000..3461189c
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Http.java
@@ -0,0 +1,89 @@
+package me.xmrvizzy.skyblocker.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UncheckedIOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpClient.Version;
+import java.net.http.HttpHeaders;
+import java.net.http.HttpRequest;
+import java.net.http.HttpRequest.BodyPublishers;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+import java.time.Duration;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.InflaterInputStream;
+
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import net.minecraft.SharedConstants;
+
+/**
+ * @implNote All http requests are sent using HTTP 2
+ */
+public class Http {
+ private static final String USER_AGENT = "Skyblocker/" + SkyblockerMod.VERSION + " (" + SharedConstants.getGameVersion().getName() + ")";
+ private static final HttpClient HTTP_CLIENT = HttpClient.newBuilder()
+ .connectTimeout(Duration.ofSeconds(10))
+ .build();
+
+ public static String sendGetRequest(String url) throws IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .GET()
+ .header("Accept", "application/json")
+ .header("Accept-Encoding", "gzip, deflate")
+ .header("User-Agent", USER_AGENT)
+ .version(Version.HTTP_2)
+ .uri(URI.create(url))
+ .build();
+
+ HttpResponse<InputStream> response = HTTP_CLIENT.send(request, BodyHandlers.ofInputStream());
+ InputStream decodedInputStream = getDecodedInputStream(response);
+ String body = new String(decodedInputStream.readAllBytes());
+
+ return body;
+ }
+
+ public static HttpHeaders sendHeadRequest(String url) throws IOException, InterruptedException {
+ HttpRequest request = HttpRequest.newBuilder()
+ .method("HEAD", BodyPublishers.noBody())
+ .header("User-Agent", USER_AGENT)
+ .version(Version.HTTP_2)
+ .uri(URI.create(url))
+ .build();
+
+ HttpResponse<Void> response = HTTP_CLIENT.send(request, BodyHandlers.discarding());
+ return response.headers();
+ }
+
+ private static InputStream getDecodedInputStream(HttpResponse<InputStream> response) {
+ String encoding = getContentEncoding(response);
+
+ try {
+ switch (encoding) {
+ case "":
+ return response.body();
+ case "gzip":
+ return new GZIPInputStream(response.body());
+ case "deflate":
+ return new InflaterInputStream(response.body());
+ default:
+ throw new UnsupportedOperationException("The server sent content in an unexpected encoding: " + encoding);
+ }
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+ }
+
+ private static String getContentEncoding(HttpResponse<InputStream> response) {
+ return response.headers().firstValue("Content-Encoding").orElse("");
+ }
+
+ public static String getEtag(HttpHeaders headers) {
+ return headers.firstValue("Etag").orElse("");
+ }
+
+ public static String getLastModified(HttpHeaders headers) {
+ return headers.firstValue("Last-Modified").orElse("");
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/PosUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/PosUtils.java
new file mode 100644
index 00000000..4f32292c
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/PosUtils.java
@@ -0,0 +1,14 @@
+package me.xmrvizzy.skyblocker.utils;
+
+import net.minecraft.util.math.BlockPos;
+
+public final class PosUtils {
+ public static BlockPos parsePosString(String posData) {
+ String[] posArray = posData.split(",");
+ return new BlockPos(Integer.parseInt(posArray[0]), Integer.parseInt(posArray[1]), Integer.parseInt(posArray[2]));
+ }
+
+ public static String getPosString(BlockPos blockPos) {
+ return blockPos.getX() + "," + blockPos.getY() + "," + blockPos.getZ();
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
index 839e0dae..755e191d 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
@@ -2,13 +2,14 @@ package me.xmrvizzy.skyblocker.utils;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
-import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.skyblock.item.PriceInfoTooltip;
import me.xmrvizzy.skyblocker.skyblock.rift.TheRift;
+import me.xmrvizzy.skyblocker.utils.scheduler.MessageScheduler;
import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback;
import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayConnectionEvents;
import net.fabricmc.fabric.api.networking.v1.PacketSender;
+import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
@@ -19,6 +20,8 @@ import net.minecraft.scoreboard.ScoreboardPlayerScore;
import net.minecraft.scoreboard.Team;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
@@ -28,6 +31,7 @@ import java.util.List;
* Utility variables and methods for retrieving Skyblock related information.
*/
public class Utils {
+ private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class);
private static final String ALTERNATE_HYPIXEL_ADDRESS = System.getProperty("skyblocker.alternateHypixelAddress", "");
private static final String PROFILE_PREFIX = "Profile: ";
private static boolean isOnHypixel = false;
@@ -45,7 +49,7 @@ public class Utils {
private static String map = "";
private static long clientWorldJoinTime = 0;
private static boolean sentLocRaw = false;
- private static long lastLocRaw = 0;
+ private static boolean canSendLocRaw = false;
public static boolean isOnHypixel() {
return isOnHypixel;
@@ -124,19 +128,25 @@ public class Utils {
public static void updateFromScoreboard(MinecraftClient client) {
List<String> sidebar;
- if (client.world == null || client.isInSingleplayer() || (sidebar = getSidebar()) == null) {
- isOnSkyblock = false;
- isInDungeons = false;
- return;
+ FabricLoader fabricLoader = FabricLoader.getInstance();
+ if ((client.world == null || client.isInSingleplayer() || (sidebar = getSidebar()) == null)) {
+ if (fabricLoader.isDevelopmentEnvironment()) {
+ sidebar = Collections.emptyList();
+ } else {
+ isOnSkyblock = false;
+ isInDungeons = false;
+ return;
+ }
}
+
+ if (sidebar.isEmpty() && !fabricLoader.isDevelopmentEnvironment()) return;
String string = sidebar.toString();
- if (sidebar.isEmpty()) return;
- if (isConnectedToHypixel(client)) {
+ if (fabricLoader.isDevelopmentEnvironment() || isConnectedToHypixel(client)) {
if (!isOnHypixel) {
isOnHypixel = true;
}
- if (sidebar.get(0).contains("SKYBLOCK") || sidebar.get(0).contains("SKIBLOCK")) {
+ if (fabricLoader.isDevelopmentEnvironment() || sidebar.get(0).contains("SKYBLOCK") || sidebar.get(0).contains("SKIBLOCK")) {
if (!isOnSkyblock) {
if (!isInjected) {
isInjected = true;
@@ -148,19 +158,18 @@ public class Utils {
} else {
leaveSkyblock();
}
- isInDungeons = isOnSkyblock && string.contains("The Catacombs");
+ isInDungeons = fabricLoader.isDevelopmentEnvironment() || isOnSkyblock && string.contains("The Catacombs");
} else if (isOnHypixel) {
isOnHypixel = false;
leaveSkyblock();
}
}
-
+
private static boolean isConnectedToHypixel(MinecraftClient client) {
- String serverAddress = (client.getCurrentServerEntry() != null) ? client.getCurrentServerEntry().address.toLowerCase() : "";
- String serverBrand = (client.player != null && client.player.getServerBrand() != null) ? client.player.getServerBrand() : "";
- boolean isOnHypixel = (serverAddress.equalsIgnoreCase(ALTERNATE_HYPIXEL_ADDRESS) || serverAddress.contains("hypixel.net") || serverAddress.contains("hypixel.io") || serverBrand.contains("Hypixel BungeeCord"));
-
- return isOnHypixel;
+ String serverAddress = (client.getCurrentServerEntry() != null) ? client.getCurrentServerEntry().address.toLowerCase() : "";
+ String serverBrand = (client.player != null && client.player.getServerBrand() != null) ? client.player.getServerBrand() : "";
+
+ return serverAddress.equalsIgnoreCase(ALTERNATE_HYPIXEL_ADDRESS) || serverAddress.contains("hypixel.net") || serverAddress.contains("hypixel.io") || serverBrand.contains("Hypixel BungeeCord");
}
private static void leaveSkyblock() {
@@ -184,7 +193,7 @@ public class Utils {
location = location.strip();
}
} catch (IndexOutOfBoundsException e) {
- e.printStackTrace();
+ LOGGER.error("[Skyblocker] Failed to get location from sidebar", e);
}
return location;
}
@@ -206,7 +215,7 @@ public class Utils {
else purse = 0;
} catch (IndexOutOfBoundsException e) {
- e.printStackTrace();
+ LOGGER.error("[Skyblocker] Failed to get purse from sidebar", e);
}
return purse;
}
@@ -225,12 +234,11 @@ public class Utils {
bits = Integer.parseInt(bitsString.replaceAll("[^0-9.]", "").strip());
}
} catch (IndexOutOfBoundsException e) {
- e.printStackTrace();
+ LOGGER.error("[Skyblocker] Failed to get bits from sidebar", e);
}
return bits;
}
-
public static List<String> getSidebar() {
try {
ClientPlayerEntity client = MinecraftClient.getInstance().player;
@@ -242,7 +250,7 @@ public class Utils {
Team team = scoreboard.getPlayerTeam(score.getPlayerName());
if (team != null) {
String line = team.getPrefix().getString() + team.getSuffix().getString();
- if (line.trim().length() > 0) {
+ if (!line.trim().isEmpty()) {
String formatted = Formatting.strip(line);
lines.add(formatted);
}
@@ -285,10 +293,10 @@ public class Utils {
private static void updateLocRaw() {
if (isOnSkyblock) {
long currentTime = System.currentTimeMillis();
- if (!sentLocRaw && currentTime > clientWorldJoinTime + 1000 && currentTime > lastLocRaw + 15000) {
- SkyblockerMod.getInstance().messageScheduler.sendMessageAfterCooldown("/locraw");
+ if (!sentLocRaw && canSendLocRaw && currentTime > clientWorldJoinTime + 1000) {
+ MessageScheduler.INSTANCE.sendMessageAfterCooldown("/locraw");
sentLocRaw = true;
- lastLocRaw = currentTime;
+ canSendLocRaw = false;
}
} else {
resetLocRawInfo();
@@ -315,7 +323,11 @@ public class Utils {
if (locRaw.has("map")) {
map = locRaw.get("map").getAsString();
}
- return !sentLocRaw;
+
+ boolean shouldFilter = !sentLocRaw;
+ sentLocRaw = false;
+
+ return shouldFilter;
}
}
return true;
@@ -323,6 +335,7 @@ public class Utils {
private static void resetLocRawInfo() {
sentLocRaw = false;
+ canSendLocRaw = true;
server = "";
gameType = "";
locationRaw = "";
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java b/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java
index aaf92d68..907896e2 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/render/RenderHelper.java
@@ -95,7 +95,7 @@ public class RenderHelper {
matrices.translate(-camera.getX(), -camera.getY(), -camera.getZ());
buffer.begin(DrawMode.LINES, VertexFormats.LINES);
- WorldRenderer.drawBox(matrices, buffer, box, colorComponents[0] * 255f, colorComponents[1] * 255f, colorComponents[2] * 255f, 1f);
+ WorldRenderer.drawBox(matrices, buffer, box, colorComponents[0], colorComponents[1], colorComponents[2], 1f);
tessellator.draw();
matrices.pop();
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/render/title/TitleContainer.java b/src/main/java/me/xmrvizzy/skyblocker/utils/render/title/TitleContainer.java
index 6e15c871..2555572c 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/render/title/TitleContainer.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/render/title/TitleContainer.java
@@ -1,6 +1,5 @@
package me.xmrvizzy.skyblocker.utils.render.title;
-import me.xmrvizzy.skyblocker.SkyblockerMod;
import me.xmrvizzy.skyblocker.config.SkyblockerConfig;
import me.xmrvizzy.skyblocker.utils.scheduler.Scheduler;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
@@ -66,7 +65,7 @@ public class TitleContainer {
*/
public static boolean addTitle(Title title, int ticks) {
if (addTitle(title)) {
- SkyblockerMod.getInstance().scheduler.schedule(() -> TitleContainer.removeTitle(title), ticks);
+ Scheduler.INSTANCE.schedule(() -> TitleContainer.removeTitle(title), ticks);
return true;
}
return false;
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/MessageScheduler.java b/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/MessageScheduler.java
index bde29c13..b8ffa548 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/MessageScheduler.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/MessageScheduler.java
@@ -3,19 +3,22 @@ package me.xmrvizzy.skyblocker.utils.scheduler;
import net.minecraft.client.MinecraftClient;
/**
- * A scheduler for sending chat messages or commands. Use the instance in {@link me.xmrvizzy.skyblocker.SkyblockerMod#messageScheduler SkyblockerMod.messageScheduler}. Do not instantiate this class.
+ * A scheduler for sending chat messages or commands. Use the instance in {@link #INSTANCE}. Do not instantiate this class.
*/
-@SuppressWarnings("deprecation")
public class MessageScheduler extends Scheduler {
/**
* The minimum delay that the server will accept between chat messages.
*/
private static final int MIN_DELAY = 200;
+ public static final MessageScheduler INSTANCE = new MessageScheduler();
/**
* The timestamp of the last message send,
*/
private long lastMessage = 0;
+ protected MessageScheduler() {
+ }
+
/**
* Sends a chat message or command after the minimum cooldown. Prefer this method to send messages or commands to the server.
*
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/Scheduler.java b/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/Scheduler.java
index 76112e0d..700bdce3 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/Scheduler.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/scheduler/Scheduler.java
@@ -1,30 +1,28 @@
package me.xmrvizzy.skyblocker.utils.scheduler;
import com.mojang.brigadier.Command;
-import me.xmrvizzy.skyblocker.SkyblockerMod;
+import it.unimi.dsi.fastutil.ints.AbstractInt2ObjectMap;
+import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.screen.Screen;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.PriorityQueue;
+import java.util.ArrayList;
+import java.util.List;
import java.util.function.Supplier;
/**
- * A scheduler for running tasks at a later time. Tasks will be run synchronously on the main client thread. Use the instance stored in {@link SkyblockerMod#scheduler}. Do not instantiate this class.
+ * A scheduler for running tasks at a later time. Tasks will be run synchronously on the main client thread. Use the instance stored in {@link #INSTANCE}. Do not instantiate this class.
*/
public class Scheduler {
private static final Logger LOGGER = LoggerFactory.getLogger(Scheduler.class);
+ public static final Scheduler INSTANCE = new Scheduler();
private int currentTick = 0;
- private final PriorityQueue<ScheduledTask> tasks = new PriorityQueue<>();
+ private final AbstractInt2ObjectMap<List<ScheduledTask>> tasks = new Int2ObjectOpenHashMap<>();
- /**
- * Do not instantiate this class. Use {@link SkyblockerMod#scheduler} instead.
- */
- @SuppressWarnings("DeprecatedIsStillUsed")
- @Deprecated
- public Scheduler() {
+ protected Scheduler() {
}
/**
@@ -34,11 +32,11 @@ public class Scheduler {
* @param delay the delay in ticks
*/
public void schedule(Runnable task, int delay) {
- if (delay < 0) {
+ if (delay >= 0) {
+ addTask(new ScheduledTask(task), currentTick + delay);
+ } else {
LOGGER.warn("Scheduled a task with negative delay");
}
- ScheduledTask tmp = new ScheduledTask(task, currentTick + delay);
- tasks.add(tmp);
}
/**
@@ -48,15 +46,15 @@ public class Scheduler {
* @param period the period in ticks
*/
public void scheduleCyclic(Runnable task, int period) {
- if (period <= 0) {
- LOGGER.error("Attempted to schedule a cyclic task with period lower than 1");
+ if (period > 0) {
+ addTask(new CyclicTask(task, period), currentTick);
} else {
- new CyclicTask(task, period).run();
+ LOGGER.error("Attempted to schedule a cyclic task with period lower than 1");
}
}
public static Command<FabricClientCommandSource> queueOpenScreenCommand(Supplier<Screen> screenSupplier) {
- return context -> SkyblockerMod.getInstance().scheduler.queueOpenScreen(screenSupplier);
+ return context -> INSTANCE.queueOpenScreen(screenSupplier);
}
/**
@@ -71,11 +69,18 @@ public class Scheduler {
}
public void tick() {
- currentTick += 1;
- ScheduledTask task;
- while ((task = tasks.peek()) != null && task.schedule <= currentTick && runTask(task)) {
- tasks.poll();
+ if (tasks.containsKey(currentTick)) {
+ List<ScheduledTask> currentTickTasks = tasks.get(currentTick);
+ //noinspection ForLoopReplaceableByForEach (or else we get a ConcurrentModificationException)
+ for (int i = 0; i < currentTickTasks.size(); i++) {
+ ScheduledTask task = currentTickTasks.get(i);
+ if (!runTask(task)) {
+ tasks.computeIfAbsent(currentTick + 1, key -> new ArrayList<>()).add(task);
+ }
+ }
+ tasks.remove(currentTick);
}
+ currentTick += 1;
}
/**
@@ -89,30 +94,42 @@ public class Scheduler {
return true;
}
+ private void addTask(ScheduledTask scheduledTask, int schedule) {
+ if (tasks.containsKey(schedule)) {
+ tasks.get(schedule).add(scheduledTask);
+ } else {
+ List<ScheduledTask> list = new ArrayList<>();
+ list.add(scheduledTask);
+ tasks.put(schedule, list);
+ }
+ }
+
/**
* A task that runs every period ticks. More specifically, this task reschedules itself to run again after period ticks every time it runs.
- *
- * @param inner the task to run
- * @param period the period in ticks
*/
- protected record CyclicTask(Runnable inner, int period) implements Runnable {
+ protected class CyclicTask extends ScheduledTask {
+ private final int period;
+
+ CyclicTask(Runnable inner, int period) {
+ super(inner);
+ this.period = period;
+ }
+
@Override
public void run() {
- SkyblockerMod.getInstance().scheduler.schedule(this, period);
- inner.run();
+ super.run();
+ addTask(this, currentTick + period);
}
}
/**
* A task that runs at a specific tick, relative to {@link #currentTick}.
- *
- * @param inner the task to run
- * @param schedule the tick to run at
*/
- protected record ScheduledTask(Runnable inner, int schedule) implements Comparable<ScheduledTask>, Runnable {
- @Override
- public int compareTo(ScheduledTask o) {
- return schedule - o.schedule;
+ protected static class ScheduledTask implements Runnable {
+ private final Runnable inner;
+
+ public ScheduledTask(Runnable inner) {
+ this.inner = inner;
}
@Override