aboutsummaryrefslogtreecommitdiff
path: root/src/main/java
diff options
context:
space:
mode:
authorAaron <51387595+AzureAaron@users.noreply.github.com>2023-11-13 21:03:26 -0500
committerGitHub <noreply@github.com>2023-11-13 21:03:26 -0500
commit736db8f1b0076ebe639bf0c1590e86d05191f01f (patch)
tree490e07d455521daa0579ec6b5ae49649925caa07 /src/main/java
parent4828dd781882324bd455c199bbf6ad625886a96b (diff)
parentf4ff9aad7b97230fd70dd70f067c0aac4d1e2682 (diff)
downloadSkyblocker-736db8f1b0076ebe639bf0c1590e86d05191f01f.tar.gz
Skyblocker-736db8f1b0076ebe639bf0c1590e86d05191f01f.tar.bz2
Skyblocker-736db8f1b0076ebe639bf0c1590e86d05191f01f.zip
Merge branch 'master' into batched-rendering
Diffstat (limited to 'src/main/java')
-rw-r--r--src/main/java/de/hysky/skyblocker/SkyblockerMod.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java6
-rw-r--r--src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java3
-rw-r--r--src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java8
-rw-r--r--src/main/java/de/hysky/skyblocker/debug/Debug.java14
-rw-r--r--src/main/java/de/hysky/skyblocker/debug/DumpPlayersCommand.java31
-rw-r--r--src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java2
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/MobGlow.java66
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java4
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java99
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java13
-rw-r--r--src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java83
13 files changed, 221 insertions, 113 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
index 52c44082..ad3b6318 100644
--- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
+++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java
@@ -3,6 +3,7 @@ package de.hysky.skyblocker;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.debug.Debug;
import de.hysky.skyblocker.skyblock.*;
import de.hysky.skyblocker.skyblock.diana.MythologicalRitual;
import de.hysky.skyblocker.skyblock.dungeon.*;
@@ -114,6 +115,7 @@ public class SkyblockerMod implements ClientModInitializer {
MuseumItemCache.init();
SecretsTracker.init();
ApiUtils.init();
+ Debug.init();
RenderHelper.init();
containerSolverManager.init();
statusBarTracker.init();
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java
index b52d6ff5..218eb8d1 100644
--- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java
+++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockEmiRecipe.java
@@ -4,7 +4,6 @@ import de.hysky.skyblocker.skyblock.itemlist.SkyblockCraftingRecipe;
import de.hysky.skyblocker.utils.ItemUtils;
import dev.emi.emi.api.recipe.EmiCraftingRecipe;
import dev.emi.emi.api.recipe.EmiRecipeCategory;
-import dev.emi.emi.api.stack.Comparison;
import dev.emi.emi.api.stack.EmiIngredient;
import dev.emi.emi.api.stack.EmiStack;
import dev.emi.emi.api.widget.WidgetHolder;
@@ -16,7 +15,7 @@ public class SkyblockEmiRecipe extends EmiCraftingRecipe {
private final String craftText;
public SkyblockEmiRecipe(SkyblockCraftingRecipe recipe) {
- super(recipe.getGrid().stream().map(EmiStack::of).map(EmiIngredient.class::cast).toList(), EmiStack.of(recipe.getResult()).comparison(Comparison.compareNbt()), Identifier.of("skyblock", ItemUtils.getItemId(recipe.getResult()).toLowerCase().replace(';', '_') + "_" + recipe.getResult().getCount()));
+ super(recipe.getGrid().stream().map(EmiStack::of).map(EmiIngredient.class::cast).toList(), EmiStack.of(recipe.getResult()), Identifier.of("skyblock", ItemUtils.getItemId(recipe.getResult()).toLowerCase().replace(';', '_') + "_" + recipe.getResult().getCount()));
this.craftText = recipe.getCraftText();
}
diff --git a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java
index 6ed6a32a..8dfc5dc9 100644
--- a/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java
+++ b/src/main/java/de/hysky/skyblocker/compatibility/emi/SkyblockerEMIPlugin.java
@@ -7,6 +7,7 @@ import dev.emi.emi.api.EmiPlugin;
import dev.emi.emi.api.EmiRegistry;
import dev.emi.emi.api.recipe.EmiRecipeCategory;
import dev.emi.emi.api.render.EmiTexture;
+import dev.emi.emi.api.stack.Comparison;
import dev.emi.emi.api.stack.EmiStack;
import net.minecraft.item.Items;
import net.minecraft.util.Identifier;
@@ -21,7 +22,10 @@ public class SkyblockerEMIPlugin implements EmiPlugin {
@Override
public void register(EmiRegistry registry) {
- ItemRepository.getItemsStream().map(EmiStack::of).forEach(registry::addEmiStack);
+ ItemRepository.getItemsStream().map(EmiStack::of).forEach(emiStack -> {
+ registry.addEmiStack(emiStack);
+ registry.setDefaultComparison(emiStack, Comparison.compareNbt());
+ });
registry.addCategory(SKYBLOCK);
registry.addWorkstation(SKYBLOCK, EmiStack.of(Items.CRAFTING_TABLE));
ItemRepository.getRecipesStream().map(SkyblockEmiRecipe::new).forEach(registry::addRecipe);
diff --git a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
index 699f91ef..974c451d 100644
--- a/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
+++ b/src/main/java/de/hysky/skyblocker/config/SkyblockerConfig.java
@@ -760,6 +760,9 @@ public class SkyblockerConfig {
public boolean mirrorverseWaypoints = true;
@SerialEntry
+ public boolean blobbercystGlow = true;
+
+ @SerialEntry
public boolean enigmaSoulWaypoints = false;
@SerialEntry
diff --git a/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java b/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java
index 55629a66..0b388d16 100644
--- a/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java
+++ b/src/main/java/de/hysky/skyblocker/config/categories/LocationsCategory.java
@@ -47,6 +47,14 @@ public class LocationsCategory {
.controller(ConfigUtils::createBooleanController)
.build())
.option(Option.<Boolean>createBuilder()
+ .name(Text.translatable("text.autoconfig.skyblocker.option.locations.rift.blobbercystGlow"))
+ .description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.rift.blobbercystGlow.@Tooltip")))
+ .binding(defaults.locations.rift.blobbercystGlow,
+ () -> config.locations.rift.blobbercystGlow,
+ newValue -> config.locations.rift.blobbercystGlow = newValue)
+ .controller(ConfigUtils::createBooleanController)
+ .build())
+ .option(Option.<Boolean>createBuilder()
.name(Text.translatable("text.autoconfig.skyblocker.option.locations.rift.enigmaSoulWaypoints"))
.description(OptionDescription.of(Text.translatable("text.autoconfig.skyblocker.option.locations.rift.enigmaSoulWaypoints.@Tooltip")))
.binding(defaults.locations.rift.enigmaSoulWaypoints,
diff --git a/src/main/java/de/hysky/skyblocker/debug/Debug.java b/src/main/java/de/hysky/skyblocker/debug/Debug.java
new file mode 100644
index 00000000..1fc22d2a
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/debug/Debug.java
@@ -0,0 +1,14 @@
+package de.hysky.skyblocker.debug;
+
+import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
+import net.fabricmc.loader.api.FabricLoader;
+
+public class Debug {
+ private static final boolean DEBUG_ENABLED = Boolean.parseBoolean(System.getProperty("skyblocker.debug", "false"));
+
+ public static void init() {
+ if (DEBUG_ENABLED || FabricLoader.getInstance().isDevelopmentEnvironment()) {
+ ClientCommandRegistrationCallback.EVENT.register(DumpPlayersCommand::register);
+ }
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/debug/DumpPlayersCommand.java b/src/main/java/de/hysky/skyblocker/debug/DumpPlayersCommand.java
new file mode 100644
index 00000000..5f6e0362
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/debug/DumpPlayersCommand.java
@@ -0,0 +1,31 @@
+package de.hysky.skyblocker.debug;
+
+import com.mojang.brigadier.Command;
+import com.mojang.brigadier.CommandDispatcher;
+import de.hysky.skyblocker.SkyblockerMod;
+import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource;
+import net.minecraft.command.CommandRegistryAccess;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.text.Text;
+
+import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.literal;
+
+public class DumpPlayersCommand {
+
+ static void register(CommandDispatcher<FabricClientCommandSource> dispatcher, CommandRegistryAccess registryAccess) {
+ dispatcher.register(literal(SkyblockerMod.NAMESPACE)
+ .then(literal("debug")
+ .then(literal("dumpPlayers")
+ .executes(context -> {
+ FabricClientCommandSource source = context.getSource();
+
+ source.getWorld().getEntities().forEach(e -> {
+ if (e instanceof PlayerEntity player) {
+ source.sendFeedback(Text.of("'" + player.getName().getString() + "'"));
+ }
+ });
+
+ return Command.SINGLE_SUCCESS;
+ }))));
+ }
+}
diff --git a/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java b/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java
index 78c61416..42601546 100644
--- a/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java
+++ b/src/main/java/de/hysky/skyblocker/mixin/WorldRendererMixin.java
@@ -9,7 +9,7 @@ import com.llamalad7.mixinextras.sugar.Local;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalBooleanRef;
-import de.hysky.skyblocker.skyblock.dungeon.MobGlow;
+import de.hysky.skyblocker.skyblock.entity.MobGlow;
import net.minecraft.client.render.WorldRenderer;
import net.minecraft.entity.Entity;
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/MobGlow.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/MobGlow.java
deleted file mode 100644
index 523b7a98..00000000
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/MobGlow.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package de.hysky.skyblocker.skyblock.dungeon;
-
-import de.hysky.skyblocker.config.SkyblockerConfigManager;
-import de.hysky.skyblocker.utils.Utils;
-import de.hysky.skyblocker.utils.render.culling.OcclusionCulling;
-import net.minecraft.entity.Entity;
-import net.minecraft.entity.decoration.ArmorStandEntity;
-import net.minecraft.entity.passive.BatEntity;
-import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.predicate.entity.EntityPredicates;
-import net.minecraft.util.math.Box;
-import net.minecraft.world.World;
-
-import java.util.List;
-
-public class MobGlow {
- public static boolean shouldMobGlow(Entity entity) {
- Box box = entity.getBoundingBox();
-
- if (Utils.isInDungeons() && !entity.isInvisible() && OcclusionCulling.isVisible(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ)) {
- String name = entity.getName().getString();
-
- // Minibosses
- if (entity instanceof PlayerEntity) {
- switch (name) {
- case "Lost Adventurer", "Shadow Assassin", "Diamond Guy": return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow;
- case "Arcade Livid", "Crossed Livid", "Doctor Livid", "Frog Livid", "Hockey Livid",
- "Purple Livid", "Scream Livid", "Smile Livid", "Vendetta Livid": return LividColor.shouldGlow(name);
- }
- }
-
- // Regular Mobs
- if (!(entity instanceof ArmorStandEntity)) {
- List<ArmorStandEntity> armorStands = getArmorStands(entity.getWorld(), box);
-
- if (!armorStands.isEmpty() && armorStands.get(0).getName().getString().contains("✯")) return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow;
- }
-
- // Bats
- return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow && entity instanceof BatEntity;
- }
-
- return false;
- }
-
- private static List<ArmorStandEntity> getArmorStands(World world, Box box) {
- return world.getEntitiesByClass(ArmorStandEntity.class, box.expand(0, 2, 0), EntityPredicates.NOT_MOUNTED);
- }
-
- public static int getGlowColor(Entity entity) {
- String name = entity.getName().getString();
-
- if (entity instanceof PlayerEntity) {
- return switch (name) {
- case "Lost Adventurer" -> 0xfee15c;
- case "Shadow Assassin" -> 0x5b2cb2;
- case "Diamond Guy" -> 0x57c2f7;
- case "Arcade Livid", "Crossed Livid", "Doctor Livid", "Frog Livid", "Hockey Livid",
- "Purple Livid", "Scream Livid", "Smile Livid", "Vendetta Livid" -> LividColor.getGlowColor(name);
- default -> 0xf57738;
- };
- }
-
- return 0xf57738;
- }
-}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java
index eda08cf6..ee517eb8 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/DungeonSecrets.java
@@ -255,7 +255,7 @@ public class DungeonSecrets {
dungeonFutures.add(CompletableFuture.runAsync(() -> {
try (BufferedReader customWaypointsReader = Files.newBufferedReader(CUSTOM_WAYPOINTS_DIR)) {
SkyblockerMod.GSON.fromJson(customWaypointsReader, JsonObject.class).asMap().forEach((room, waypointsJson) ->
- addCustomWaypoints(room, SecretWaypoint.LIST_CODEC.parse(JsonOps.INSTANCE, waypointsJson).resultOrPartial(LOGGER::error).orElseThrow())
+ addCustomWaypoints(room, SecretWaypoint.LIST_CODEC.parse(JsonOps.INSTANCE, waypointsJson).resultOrPartial(LOGGER::error).orElseGet(ArrayList::new))
);
LOGGER.debug("[Skyblocker Dungeon Secrets] Loaded custom dungeon secret waypoints");
} catch (Exception e) {
@@ -273,7 +273,7 @@ public class DungeonSecrets {
try (BufferedWriter writer = Files.newBufferedWriter(CUSTOM_WAYPOINTS_DIR)) {
JsonObject customWaypointsJson = new JsonObject();
customWaypoints.rowMap().forEach((room, waypoints) ->
- customWaypointsJson.add(room, SecretWaypoint.LIST_CODEC.encodeStart(JsonOps.INSTANCE, new ArrayList<>(waypoints.values())).resultOrPartial(LOGGER::error).orElseThrow())
+ customWaypointsJson.add(room, SecretWaypoint.LIST_CODEC.encodeStart(JsonOps.INSTANCE, new ArrayList<>(waypoints.values())).resultOrPartial(LOGGER::error).orElseGet(JsonArray::new))
);
SkyblockerMod.GSON.toJson(customWaypointsJson, writer);
LOGGER.info("[Skyblocker Dungeon Secrets] Saved custom dungeon secret waypoints");
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java
index ecfcf496..9b95f146 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/Room.java
@@ -41,6 +41,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Room {
+ private static final Pattern SECRET_INDEX = Pattern.compile("^(\\d+)");
private static final Pattern SECRETS = Pattern.compile("§7(\\d{1,2})/(\\d{1,2}) Secrets");
@NotNull
private final Type type;
@@ -70,11 +71,12 @@ public class Room {
private int doubleCheckBlocks;
/**
* Represents the matching state of the room with the following possible values:
- * <li>{@link TriState#DEFAULT} means that the room has not been checked, is being processed, or does not {@link Type#needsScanning() need to be processed}.
- * <li>{@link TriState#FALSE} means that the room has been checked and there is no match.
- * <li>{@link TriState#TRUE} means that the room has been checked and there is a match.
+ * <li>{@link MatchState#MATCHING} means that the room has not been checked, is being processed, or does not {@link Type#needsScanning() need to be processed}.</li>
+ * <li>{@link MatchState#DOUBLE_CHECKING} means that the room has a unique match and is being double checked.</li>
+ * <li>{@link MatchState#MATCHED} means that the room has a unique match ans has been double checked.</li>
+ * <li>{@link MatchState#FAILED} means that the room has been checked and there is no match.</li>
*/
- private TriState matched = TriState.DEFAULT;
+ private MatchState matchState = MatchState.MATCHING;
private Table<Integer, BlockPos, SecretWaypoint> secretWaypoints;
private String name;
private Direction direction;
@@ -96,7 +98,7 @@ public class Room {
}
public boolean isMatched() {
- return matched == TriState.TRUE;
+ return matchState == MatchState.DOUBLE_CHECKING || matchState == MatchState.MATCHED;
}
/**
@@ -108,7 +110,7 @@ public class Room {
@Override
public String toString() {
- return "Room{type=" + type + ", shape=" + shape + ", matched=" + matched + ", segments=" + Arrays.toString(segments.toArray()) + "}";
+ return "Room{type=%s, segments=%s, shape=%s, matchState=%s, name=%s, direction=%s, physicalCornerPos=%s}".formatted(type, Arrays.toString(segments.toArray()), shape, matchState, name, direction, physicalCornerPos);
}
@NotNull
@@ -208,6 +210,7 @@ public class Room {
/**
* Removes a custom waypoint relative to this room from {@link DungeonSecrets#customWaypoints} and all existing instances of this room.
+ *
* @param pos the position of the secret waypoint relative to this room
* @return the removed secret waypoint or {@code null} if there was no secret waypoint at the given position
*/
@@ -223,6 +226,7 @@ public class Room {
/**
* Removes a custom waypoint relative to this room from this instance of the room.
+ *
* @param secretIndex the index of the secret waypoint
* @param relativePos the position of the secret waypoint relative to this room
*/
@@ -237,7 +241,7 @@ public class Room {
* This method returns immediately if any of the following conditions are met:
* <ul>
* <li> The room does not need to be scanned and matched. (When the room is not of type {@link Type.ROOM}, {@link Type.PUZZLE}, or {@link Type.TRAP}. See {@link Type#needsScanning()}) </li>
- * <li> The room has been matched or failed to match and is on cooldown. See {@link #matched}. </li>
+ * <li> The room has been matched or failed to match and is on cooldown. See {@link #matchState}. </li>
* <li> {@link #findRoom The previous update} has not completed. </li>
* </ul>
* Then this method tries to match this room through:
@@ -251,7 +255,7 @@ public class Room {
@SuppressWarnings("JavadocReference")
protected void update() {
// Logical AND has higher precedence than logical OR
- if (!type.needsScanning() || matched != TriState.DEFAULT || !DungeonSecrets.isRoomsLoaded() || findRoom != null && !findRoom.isDone()) {
+ if (!type.needsScanning() || matchState != MatchState.MATCHING && matchState != MatchState.DOUBLE_CHECKING || !DungeonSecrets.isRoomsLoaded() || findRoom != null && !findRoom.isDone()) {
return;
}
MinecraftClient client = MinecraftClient.getInstance();
@@ -266,6 +270,9 @@ public class Room {
break;
}
}
+ }).exceptionally(e -> {
+ DungeonSecrets.LOGGER.error("[Skyblocker Dungeon Secrets] Encountered an unknown exception while matching room {}", this, e);
+ return null;
});
}
@@ -297,16 +304,24 @@ public class Room {
* </ul>
* <li> If there are no matching rooms left: </li>
* <ul>
- * <li> Terminate matching by setting {@link #matched} to {@link TriState#FALSE}. </li>
+ * <li> Terminate matching by setting {@link #matchState} to {@link TriState#FALSE}. </li>
* <li> Schedule another matching attempt in 50 ticks (2.5 seconds). </li>
* <li> Reset {@link #possibleRooms} and {@link #checkedBlocks} with {@link #reset()}. </li>
* <li> Return {@code true} </li>
* </ul>
* <li> If there are exactly one room matching: </li>
* <ul>
- * <li> Call {@link #roomMatched()}. </li>
- * <li> Discard the no longer needed fields to save memory. </li>
- * <li> Return {@code true} </li>
+ * <li> If {@link #matchState} is {@link MatchState#MATCHING}: </li>
+ * <ul>
+ * <li> Call {@link #roomMatched()}. </li>
+ * <li> Return {@code false}. </li>
+ * </ul>
+ * <li> If {@link #matchState} is {@link MatchState#DOUBLE_CHECKING}: </li>
+ * <ul>
+ * <li> Set the match state to {@link MatchState#MATCHED}. </li>
+ * <li> Discard the no longer needed fields to save memory. </li>
+ * <li> Return {@code true}. </li>
+ * </ul>
* </ul>
* <li> Return {@code false} </li>
* </ul>
@@ -334,26 +349,29 @@ public class Room {
int matchingRoomsSize = possibleRooms.stream().map(Triple::getRight).mapToInt(Collection::size).sum();
if (matchingRoomsSize == 0) {
// If no rooms match, reset the fields and scan again after 50 ticks.
- matched = TriState.FALSE;
- DungeonSecrets.LOGGER.warn("[Skyblocker] No dungeon room matches after checking {} block(s)", checkedBlocks.size());
- Scheduler.INSTANCE.schedule(() -> matched = TriState.DEFAULT, 50);
+ DungeonSecrets.LOGGER.warn("[Skyblocker Dungeon Secrets] No dungeon room matched after checking {} block(s) including double checking {} block(s)", checkedBlocks.size(), doubleCheckBlocks);
+ Scheduler.INSTANCE.schedule(() -> matchState = MatchState.MATCHING, 50);
reset();
return true;
- } else if (matchingRoomsSize == 1 && ++doubleCheckBlocks >= 10) {
- // If one room matches, load the secrets for that room and discard the no longer needed fields.
- for (Triple<Direction, Vector2ic, List<String>> directionRooms : possibleRooms) {
- if (directionRooms.getRight().size() == 1) {
- name = directionRooms.getRight().get(0);
- direction = directionRooms.getLeft();
- physicalCornerPos = directionRooms.getMiddle();
- roomMatched();
- discard();
- return true;
- }
+ } else if (matchingRoomsSize == 1) {
+ if (matchState == MatchState.MATCHING) {
+ // If one room matches, load the secrets for that room and set state to double-checking.
+ Triple<Direction, Vector2ic, List<String>> directionRoom = possibleRooms.stream().filter(directionRooms -> directionRooms.getRight().size() == 1).findAny().orElseThrow();
+ name = directionRoom.getRight().get(0);
+ direction = directionRoom.getLeft();
+ physicalCornerPos = directionRoom.getMiddle();
+ DungeonSecrets.LOGGER.info("[Skyblocker Dungeon Secrets] Room {} matched after checking {} block(s), starting double checking", name, checkedBlocks.size());
+ roomMatched();
+ return false;
+ } else if (matchState == MatchState.DOUBLE_CHECKING && ++doubleCheckBlocks >= 10) {
+ // If double-checked, set state to matched and discard the no longer needed fields.
+ DungeonSecrets.LOGGER.info("[Skyblocker Dungeon Secrets] Room {} matched after checking {} block(s) including double checking {} block(s)", name, checkedBlocks.size(), doubleCheckBlocks);
+ discard();
+ return true;
}
- return false; // This should never happen, we just checked that there is one possible room, and the return true in the loop should activate
+ return false;
} else {
- DungeonSecrets.LOGGER.debug("[Skyblocker] {} room(s) remaining after checking {} block(s)", matchingRoomsSize, checkedBlocks.size());
+ DungeonSecrets.LOGGER.debug("[Skyblocker Dungeon Secrets] {} room(s) remaining after checking {} block(s)", matchingRoomsSize, checkedBlocks.size());
return false;
}
}
@@ -371,7 +389,7 @@ public class Room {
/**
* Loads the secret waypoints for the room from {@link DungeonSecrets#waypointsJson} once it has been matched
- * and sets {@link #matched} to {@link TriState#TRUE}.
+ * and sets {@link #matchState} to {@link MatchState#DOUBLE_CHECKING}.
*
* @param directionRooms the direction, position, and name of the room
*/
@@ -381,25 +399,29 @@ public class Room {
for (JsonElement waypointElement : DungeonSecrets.getRoomWaypoints(name)) {
JsonObject waypoint = waypointElement.getAsJsonObject();
String secretName = waypoint.get("secretName").getAsString();
- int secretIndex = Integer.parseInt(secretName.substring(0, Character.isDigit(secretName.charAt(1)) ? 2 : 1));
+ Matcher secretIndexMatcher = SECRET_INDEX.matcher(secretName);
+ int secretIndex = secretIndexMatcher.find() ? Integer.parseInt(secretIndexMatcher.group(1)) : 0;
BlockPos pos = DungeonMapUtils.relativeToActual(direction, physicalCornerPos, waypoint);
secretWaypoints.put(secretIndex, pos, new SecretWaypoint(secretIndex, waypoint, secretName, pos));
}
DungeonSecrets.getCustomWaypoints(name).values().forEach(this::addCustomWaypoint);
- matched = TriState.TRUE;
-
- DungeonSecrets.LOGGER.info("[Skyblocker] Room {} matched after checking {} block(s)", name, checkedBlocks.size());
+ matchState = MatchState.DOUBLE_CHECKING;
}
/**
* Resets fields for another round of matching after room matching fails.
*/
private void reset() {
+ matchState = MatchState.FAILED;
IntSortedSet segmentsX = IntSortedSets.unmodifiable(new IntRBTreeSet(segments.stream().mapToInt(Vector2ic::x).toArray()));
IntSortedSet segmentsY = IntSortedSets.unmodifiable(new IntRBTreeSet(segments.stream().mapToInt(Vector2ic::y).toArray()));
possibleRooms = getPossibleRooms(segmentsX, segmentsY);
checkedBlocks = new HashSet<>();
doubleCheckBlocks = 0;
+ secretWaypoints = null;
+ name = null;
+ direction = null;
+ physicalCornerPos = null;
}
/**
@@ -407,6 +429,7 @@ public class Room {
* These fields are no longer needed and are discarded to save memory.
*/
private void discard() {
+ matchState = MatchState.MATCHED;
roomsData = null;
possibleRooms = null;
checkedBlocks = null;
@@ -473,7 +496,7 @@ public class Room {
BlockState state = world.getBlockState(hitResult.getBlockPos());
if (state.isOf(Blocks.CHEST) || state.isOf(Blocks.PLAYER_HEAD) || state.isOf(Blocks.PLAYER_WALL_HEAD)) {
secretWaypoints.column(hitResult.getBlockPos()).values().stream().filter(SecretWaypoint::needsInteraction).findAny()
- .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker] Detected {} interaction, setting secret #{} as found", secretWaypoint.category, secretWaypoint.secretIndex));
+ .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} interaction, setting secret #{} as found", secretWaypoint.category, secretWaypoint.secretIndex));
} else if (state.isOf(Blocks.LEVER)) {
secretWaypoints.column(hitResult.getBlockPos()).values().stream().filter(SecretWaypoint::isLever).forEach(SecretWaypoint::setFound);
}
@@ -491,7 +514,7 @@ public class Room {
return;
}
secretWaypoints.values().stream().filter(SecretWaypoint::needsItemPickup).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(collector))).filter(SecretWaypoint.getRangePredicate(collector))
- .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker] Detected {} picked up a {} from a {} secret, setting secret #{} as found", collector.getName().getString(), itemEntity.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
+ .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} picked up a {} from a {} secret, setting secret #{} as found", collector.getName().getString(), itemEntity.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
}
/**
@@ -502,7 +525,7 @@ public class Room {
*/
protected void onBatRemoved(AmbientEntity bat) {
secretWaypoints.values().stream().filter(SecretWaypoint::isBat).min(Comparator.comparingDouble(SecretWaypoint.getSquaredDistanceToFunction(bat)))
- .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker] Detected {} killed for a {} secret, setting secret #{} as found", bat.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
+ .ifPresent(secretWaypoint -> onSecretFound(secretWaypoint, "[Skyblocker Dungeon Secrets] Detected {} killed for a {} secret, setting secret #{} as found", bat.getName().getString(), secretWaypoint.category, secretWaypoint.secretIndex));
}
/**
@@ -575,4 +598,8 @@ public class Room {
public enum Direction {
NW, NE, SW, SE
}
+
+ public enum MatchState {
+ MATCHING, DOUBLE_CHECKING, MATCHED, FAILED
+ }
}
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java
index 0c2d1b34..43f624f6 100644
--- a/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java
+++ b/src/main/java/de/hysky/skyblocker/skyblock/dungeon/secrets/SecretWaypoint.java
@@ -20,6 +20,8 @@ import net.minecraft.util.dynamic.Codecs;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import org.jetbrains.annotations.NotNull;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.util.List;
import java.util.function.Predicate;
@@ -27,6 +29,7 @@ import java.util.function.Supplier;
import java.util.function.ToDoubleFunction;
public class SecretWaypoint extends Waypoint {
+ protected static final Logger LOGGER = LoggerFactory.getLogger(SecretWaypoint.class);
public static final Codec<SecretWaypoint> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codec.INT.fieldOf("secretIndex").forGetter(secretWaypoint -> secretWaypoint.secretIndex),
Category.CODEC.fieldOf("category").forGetter(secretWaypoint -> secretWaypoint.category),
@@ -35,8 +38,8 @@ public class SecretWaypoint extends Waypoint {
).apply(instance, SecretWaypoint::new));
public static final Codec<List<SecretWaypoint>> LIST_CODEC = CODEC.listOf();
static final List<String> SECRET_ITEMS = List.of("Decoy", "Defuse Kit", "Dungeon Chest Key", "Healing VIII", "Inflatable Jerry", "Spirit Leap", "Training Weights", "Trap", "Treasure Talisman");
- private static final SkyblockerConfig.SecretWaypoints CONFIG = SkyblockerConfigManager.get().locations.dungeons.secretWaypoints;
- private static final Supplier<Type> TYPE_SUPPLIER = () -> CONFIG.waypointType;
+ private static final Supplier<SkyblockerConfig.SecretWaypoints> CONFIG = () -> SkyblockerConfigManager.get().locations.dungeons.secretWaypoints;
+ private static final Supplier<Type> TYPE_SUPPLIER = () -> CONFIG.get().waypointType;
final int secretIndex;
final Category category;
final Text name;
@@ -95,7 +98,7 @@ public class SecretWaypoint extends Waypoint {
//TODO In the future, shrink the box for wither essence and items so its more realistic
super.render(context);
- if (CONFIG.showSecretText) {
+ if (CONFIG.get().showSecretText) {
Vec3d posUp = centerPos.add(0, 1, 0);
RenderHelper.renderText(context, name, posUp, true);
double distance = context.camera().getPos().distanceTo(centerPos);
@@ -135,8 +138,8 @@ public class SecretWaypoint extends Waypoint {
}
}
- private static Category get(JsonObject waypointJson) {
- return CODEC.parse(JsonOps.INSTANCE, waypointJson.get("category")).resultOrPartial(DungeonSecrets.LOGGER::error).orElseThrow();
+ static Category get(JsonObject waypointJson) {
+ return CODEC.parse(JsonOps.INSTANCE, waypointJson.get("category")).resultOrPartial(LOGGER::error).orElse(Category.DEFAULT);
}
boolean needsInteraction() {
diff --git a/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
new file mode 100644
index 00000000..5e0995e6
--- /dev/null
+++ b/src/main/java/de/hysky/skyblocker/skyblock/entity/MobGlow.java
@@ -0,0 +1,83 @@
+package de.hysky.skyblocker.skyblock.entity;
+
+import java.util.List;
+
+import de.hysky.skyblocker.config.SkyblockerConfigManager;
+import de.hysky.skyblocker.skyblock.dungeon.LividColor;
+import de.hysky.skyblocker.utils.Utils;
+import de.hysky.skyblocker.utils.render.culling.OcclusionCulling;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.decoration.ArmorStandEntity;
+import net.minecraft.entity.passive.BatEntity;
+import net.minecraft.entity.player.PlayerEntity;
+import net.minecraft.predicate.entity.EntityPredicates;
+import net.minecraft.util.Formatting;
+import net.minecraft.util.math.Box;
+import net.minecraft.world.World;
+
+public class MobGlow {
+ public static boolean shouldMobGlow(Entity entity) {
+ Box box = entity.getBoundingBox();
+
+ if (!entity.isInvisible() && OcclusionCulling.isVisible(box.minX, box.minY, box.minZ, box.maxX, box.maxY, box.maxZ)) {
+ String name = entity.getName().getString();
+
+ // Dungeons
+ if (Utils.isInDungeons()) {
+
+ // Minibosses
+ if (entity instanceof PlayerEntity) {
+ switch (name) {
+ case "Lost Adventurer", "Shadow Assassin", "Diamond Guy": return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow;
+ case "Arcade Livid", "Crossed Livid", "Doctor Livid", "Frog Livid", "Hockey Livid",
+ "Purple Livid", "Scream Livid", "Smile Livid", "Vendetta Livid": return LividColor.shouldGlow(name);
+ }
+ }
+
+ // Regular Mobs
+ if (!(entity instanceof ArmorStandEntity)) {
+ List<ArmorStandEntity> armorStands = getArmorStands(entity.getWorld(), box);
+
+ if (!armorStands.isEmpty() && armorStands.get(0).getName().getString().contains("✯")) return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow;
+ }
+
+ // Bats
+ return SkyblockerConfigManager.get().locations.dungeons.starredMobGlow && entity instanceof BatEntity;
+ }
+
+ // Rift
+ if (Utils.isInTheRift()) {
+ if (entity instanceof PlayerEntity) {
+ switch (name) {
+ // They have a space in their name for some reason...
+ case "Blobbercyst ": return SkyblockerConfigManager.get().locations.rift.blobbercystGlow;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ private static List<ArmorStandEntity> getArmorStands(World world, Box box) {
+ return world.getEntitiesByClass(ArmorStandEntity.class, box.expand(0, 2, 0), EntityPredicates.NOT_MOUNTED);
+ }
+
+ public static int getGlowColor(Entity entity) {
+ String name = entity.getName().getString();
+
+ if (entity instanceof PlayerEntity) {
+ return switch (name) {
+ case "Lost Adventurer" -> 0xfee15c;
+ case "Shadow Assassin" -> 0x5b2cb2;
+ case "Diamond Guy" -> 0x57c2f7;
+ case "Arcade Livid", "Crossed Livid", "Doctor Livid", "Frog Livid", "Hockey Livid",
+ "Purple Livid", "Scream Livid", "Smile Livid", "Vendetta Livid" -> LividColor.getGlowColor(name);
+ case "Blobbercyst " -> Formatting.GREEN.getColorValue();
+ default -> 0xf57738;
+ };
+ }
+
+ return 0xf57738;
+ }
+}