aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/me/xmrvizzy/skyblocker/utils
diff options
context:
space:
mode:
authorKevin <92656833+kevinthegreat1@users.noreply.github.com>2023-06-24 12:47:20 +0800
committerGitHub <noreply@github.com>2023-06-24 12:47:20 +0800
commit579feae3e4a2231bf7e6f98977762bf38b762f3b (patch)
tree6a68eb47de855a3bcee42569f79cbca2f36d4d28 /src/main/java/me/xmrvizzy/skyblocker/utils
parent4c987071fbc4dc2898afaa0f45f4887808a56de3 (diff)
parent272131e0c082493e0df12b510012460f07a88694 (diff)
downloadSkyblocker-579feae3e4a2231bf7e6f98977762bf38b762f3b.tar.gz
Skyblocker-579feae3e4a2231bf7e6f98977762bf38b762f3b.tar.bz2
Skyblocker-579feae3e4a2231bf7e6f98977762bf38b762f3b.zip
Merge pull request #167 from kevinthegreat1/fairy-souls
Fairy Souls Helper
Diffstat (limited to 'src/main/java/me/xmrvizzy/skyblocker/utils')
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/NEURepo.java101
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java30
-rw-r--r--src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java149
3 files changed, 278 insertions, 2 deletions
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/NEURepo.java b/src/main/java/me/xmrvizzy/skyblocker/utils/NEURepo.java
new file mode 100644
index 00000000..29b39aa3
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/NEURepo.java
@@ -0,0 +1,101 @@
+package me.xmrvizzy.skyblocker.utils;
+
+import me.xmrvizzy.skyblocker.SkyblockerMod;
+import me.xmrvizzy.skyblocker.skyblock.itemlist.ItemRegistry;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.text.Text;
+import org.eclipse.jgit.api.Git;
+import org.eclipse.jgit.api.errors.TransportException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * Initializes the NEU repo, which contains item metadata and fairy souls location data. Clones the repo if it does not exist and checks for updates. Use {@link #runAsyncAfterLoad(Runnable)} to run code after the repo is initialized.
+ */
+public class NEURepo {
+ private static final Logger LOGGER = LoggerFactory.getLogger(NEURepo.class);
+ public static final String REMOTE_REPO_URL = "https://github.com/NotEnoughUpdates/NotEnoughUpdates-REPO.git";
+ public static final Path LOCAL_REPO_DIR = SkyblockerMod.CONFIG_DIR.resolve("item-repo");
+ private static final CompletableFuture<Void> REPO_INITIALIZED = initRepository();
+
+ /**
+ * Adds command to update repository manually from ingame.
+ * <p></p>
+ * TODO A button could be added to the settings menu that will trigger this command.
+ */
+ public static void init() {
+ ClientCommandRegistrationCallback.EVENT.register((dispatcher, registryAccess) ->
+ dispatcher.register(ClientCommandManager.literal(SkyblockerMod.NAMESPACE)
+ .then(ClientCommandManager.literal("updaterepository").executes(context -> {
+ deleteAndDownloadRepository();
+ return 1;
+ }))));
+ }
+
+ private static CompletableFuture<Void> initRepository() {
+ return CompletableFuture.runAsync(() -> {
+ try {
+ if (Files.isDirectory(NEURepo.LOCAL_REPO_DIR)) {
+ try (Git localRepo = Git.open(NEURepo.LOCAL_REPO_DIR.toFile())) {
+ localRepo.pull().setRebase(true).call();
+ LOGGER.info("[Skyblocker] NEU Repository Updated");
+ }
+ } else {
+ Git.cloneRepository().setURI(REMOTE_REPO_URL).setDirectory(NEURepo.LOCAL_REPO_DIR.toFile()).setBranchesToClone(List.of("refs/heads/master")).setBranch("refs/heads/master").call().close();
+ LOGGER.info("[Skyblocker] NEU Repository Downloaded");
+ }
+ } catch (TransportException e){
+ LOGGER.error("[Skyblocker] Transport operation failed. Most likely unable to connect to the remote NEU repo on github", e);
+ } catch (RepositoryNotFoundException e) {
+ LOGGER.warn("[Skyblocker] Local NEU Repository not found or corrupted, downloading new one", e);
+ deleteAndDownloadRepository();
+ } catch (Exception e) {
+ LOGGER.error("[Skyblocker] Encountered unknown exception while initializing NEU Repository", e);
+ }
+ });
+ }
+
+ private static void deleteAndDownloadRepository() {
+ CompletableFuture.runAsync(() -> {
+ try {
+ ItemRegistry.filesImported = false;
+ File dir = NEURepo.LOCAL_REPO_DIR.toFile();
+ recursiveDelete(dir);
+ } catch (Exception ex) {
+ if (MinecraftClient.getInstance().player != null)
+ MinecraftClient.getInstance().player.sendMessage(Text.translatable("skyblocker.updaterepository.failed"), false);
+ return;
+ }
+ initRepository();
+ });
+ }
+
+ @SuppressWarnings("ResultOfMethodCallIgnored")
+ private static void recursiveDelete(File dir) {
+ File[] children;
+ if (dir.isDirectory() && !Files.isSymbolicLink(dir.toPath()) && (children = dir.listFiles()) != null) {
+ for (File child : children) {
+ recursiveDelete(child);
+ }
+ }
+ dir.delete();
+ }
+
+ /**
+ * Runs the given runnable after the NEU repo is initialized.
+ * @param runnable the runnable to run
+ * @return a completable future of the given runnable
+ */
+ public static CompletableFuture<Void> runAsyncAfterLoad(Runnable runnable) {
+ return REPO_INITIALIZED.thenRunAsync(runnable);
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java
new file mode 100644
index 00000000..79308dc3
--- /dev/null
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java
@@ -0,0 +1,30 @@
+package me.xmrvizzy.skyblocker.utils;
+
+import me.x150.renderer.render.Renderer3d;
+import me.xmrvizzy.skyblocker.mixin.accessor.BeaconBlockEntityRendererInvoker;
+import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext;
+import net.minecraft.client.render.block.entity.BeaconBlockEntityRenderer;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
+
+import java.awt.*;
+
+public class RenderHelper {
+ public static void renderFilledThroughWallsWithBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) {
+ renderFilledThroughWalls(context, pos, colorComponents, alpha);
+ renderBeaconBeam(context, pos, colorComponents);
+ }
+
+ public static void renderFilledThroughWalls(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) {
+ Renderer3d.renderThroughWalls();
+ Renderer3d.renderFilled(context.matrixStack(), new Color(colorComponents[0], colorComponents[1], colorComponents[2], alpha), Vec3d.of(pos), new Vec3d(1, 1, 1));
+ Renderer3d.stopRenderThroughWalls();
+ }
+
+ public static void renderBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents) {
+ context.matrixStack().push();
+ context.matrixStack().translate(pos.getX() - context.camera().getPos().x, pos.getY() - context.camera().getPos().y, pos.getZ() - context.camera().getPos().z);
+ BeaconBlockEntityRendererInvoker.renderBeam(context.matrixStack(), context.consumers(), context.tickDelta(), context.world().getTime(), 0, BeaconBlockEntityRenderer.MAX_BEAM_HEIGHT, colorComponents);
+ context.matrixStack().pop();
+ }
+}
diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
index a4e403fc..90939fe8 100644
--- a/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
+++ b/src/main/java/me/xmrvizzy/skyblocker/utils/Utils.java
@@ -1,13 +1,22 @@
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 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.minecraft.client.MinecraftClient;
+import net.minecraft.client.network.ClientPlayNetworkHandler;
import net.minecraft.client.network.ClientPlayerEntity;
+import net.minecraft.client.network.PlayerListEntry;
import net.minecraft.scoreboard.Scoreboard;
import net.minecraft.scoreboard.ScoreboardObjective;
import net.minecraft.scoreboard.ScoreboardPlayerScore;
import net.minecraft.scoreboard.Team;
+import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import java.util.ArrayList;
@@ -18,9 +27,22 @@ import java.util.List;
* Utility variables and methods for retrieving Skyblock related information.
*/
public class Utils {
+ private static final String PROFILE_PREFIX = "Profile: ";
private static boolean isOnSkyblock = false;
private static boolean isInDungeons = false;
private static boolean isInjected = false;
+ /**
+ * The following fields store data returned from /locraw: {@link #profile}, {@link #server}, {@link #gameType}, {@link #locationRaw}, and {@link #map}.
+ */
+ @SuppressWarnings("JavadocDeclaration")
+ private static String profile = "";
+ private static String server = "";
+ private static String gameType = "";
+ private static String locationRaw = "";
+ private static String map = "";
+ private static long clientWorldJoinTime = 0;
+ private static boolean sentLocRaw = false;
+ private static long lastLocRaw = 0;
public static boolean isOnSkyblock() {
return isOnSkyblock;
@@ -34,8 +56,61 @@ public class Utils {
return isInjected;
}
- public static void sbChecker() {
+ /**
+ * @return the profile parsed from the player list.
+ */
+ public static String getProfile() {
+ return profile;
+ }
+
+ /**
+ * @return the server parsed from /locraw.
+ */
+ public static String getServer() {
+ return server;
+ }
+
+ /**
+ * @return the game type parsed from /locraw.
+ */
+ public static String getGameType() {
+ return gameType;
+ }
+
+ /**
+ * @return the location raw parsed from /locraw.
+ */
+ public static String getLocationRaw() {
+ return locationRaw;
+ }
+
+ /**
+ * @return the map parsed from /locraw.
+ */
+ public static String getMap() {
+ return map;
+ }
+
+ public static void init() {
+ ClientPlayConnectionEvents.JOIN.register(Utils::onClientWorldJoin);
+ ClientReceiveMessageEvents.ALLOW_GAME.register(Utils::onChatMessage);
+ ClientReceiveMessageEvents.GAME_CANCELED.register(Utils::onChatMessage); // Somehow this works even though onChatMessage returns a boolean
+ }
+
+ /**
+ * Updates all the fields stored in this class from the sidebar, player list, and /locraw.
+ */
+ public static void update() {
MinecraftClient client = MinecraftClient.getInstance();
+ updateFromScoreboard(client);
+ updateFromPlayerList(client);
+ updateLocRaw();
+ }
+
+ /**
+ * Updates {@link #isOnSkyblock}, {@link #isInDungeons}, and {@link #isInjected} from the scoreboard.
+ */
+ public static void updateFromScoreboard(MinecraftClient client) {
List<String> sidebar;
if (client.world == null || client.isInSingleplayer() || (sidebar = getSidebar()) == null) {
@@ -67,7 +142,7 @@ public class Utils {
String location = null;
List<String> sidebarLines = getSidebar();
try {
- if( sidebarLines != null) {
+ if (sidebarLines != null) {
for (String sidebarLine : sidebarLines) {
if (sidebarLine.contains("⏣")) location = sidebarLine;
}
@@ -149,4 +224,74 @@ public class Utils {
return null;
}
}
+
+ private static void updateFromPlayerList(MinecraftClient client) {
+ if (client.getNetworkHandler() == null) {
+ return;
+ }
+ for (PlayerListEntry playerListEntry : client.getNetworkHandler().getPlayerList()) {
+ if (playerListEntry.getDisplayName() == null) {
+ continue;
+ }
+ String name = playerListEntry.getDisplayName().getString();
+ if (name.startsWith(PROFILE_PREFIX)) {
+ profile = name.substring(PROFILE_PREFIX.length());
+ }
+ }
+ }
+
+ public static void onClientWorldJoin(ClientPlayNetworkHandler handler, PacketSender sender, MinecraftClient client) {
+ clientWorldJoinTime = System.currentTimeMillis();
+ resetLocRawInfo();
+ }
+
+ /**
+ * Sends /locraw to the server if the player is on skyblock and on a new island.
+ */
+ private static void updateLocRaw() {
+ if (isOnSkyblock) {
+ long currentTime = System.currentTimeMillis();
+ if (!sentLocRaw && currentTime > clientWorldJoinTime + 1000 && currentTime > lastLocRaw + 15000) {
+ SkyblockerMod.getInstance().messageScheduler.sendMessageAfterCooldown("/locraw");
+ sentLocRaw = true;
+ lastLocRaw = currentTime;
+ }
+ } else {
+ resetLocRawInfo();
+ }
+ }
+
+ /**
+ * Parses the /locraw reply from the server
+ *
+ * @return not display the message in chat is the command is sent by the mod
+ */
+ public static boolean onChatMessage(Text text, boolean overlay) {
+ String message = text.getString();
+ if (message.startsWith("{\"server\":") && message.endsWith("}")) {
+ JsonObject locRaw = JsonParser.parseString(message).getAsJsonObject();
+ if (locRaw.has("server")) {
+ server = locRaw.get("server").getAsString();
+ if (locRaw.has("gameType")) {
+ gameType = locRaw.get("gameType").getAsString();
+ }
+ if (locRaw.has("mode")) {
+ locationRaw = locRaw.get("mode").getAsString();
+ }
+ if (locRaw.has("map")) {
+ map = locRaw.get("map").getAsString();
+ }
+ return !sentLocRaw;
+ }
+ }
+ return true;
+ }
+
+ private static void resetLocRawInfo() {
+ sentLocRaw = false;
+ server = "";
+ gameType = "";
+ locationRaw = "";
+ map = "";
+ }
} \ No newline at end of file