aboutsummaryrefslogtreecommitdiff
path: root/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon
diff options
context:
space:
mode:
authorsyeyoung <cyoung06@naver.com>2022-05-21 21:18:14 +0900
committersyeyoung <cyoung06@naver.com>2022-05-21 21:28:52 +0900
commit20dd3f99a7b139b5848128246c622fd9cfefa478 (patch)
tree78e5f84ad22fd53876d488f6b58c3528aebe6501 /mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon
parent50de034c046c4ddea033b73793c8825ecb5bb86f (diff)
downloadSkyblock-Dungeons-Guide-20dd3f99a7b139b5848128246c622fd9cfefa478.tar.gz
Skyblock-Dungeons-Guide-20dd3f99a7b139b5848128246c622fd9cfefa478.tar.bz2
Skyblock-Dungeons-Guide-20dd3f99a7b139b5848128246c622fd9cfefa478.zip
- Project separation
Diffstat (limited to 'mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon')
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java35
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java207
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java495
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java57
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java40
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java101
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java71
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java78
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java91
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java41
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java71
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java81
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java89
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java112
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java112
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java48
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java124
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java83
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java83
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java60
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java110
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java39
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java172
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java127
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java81
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java38
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java39
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java33
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java34
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java35
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java41
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java25
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java32
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java33
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java28
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java33
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java44
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java36
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java39
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java36
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java157
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java129
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java108
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java105
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java98
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java130
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java40
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java107
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java134
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java129
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java132
-rw-r--r--mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java98
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java239
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java137
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java25
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java44
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java44
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java43
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java380
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java142
-rwxr-xr-xmod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java154
61 files changed, 5709 insertions, 0 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java
new file mode 100644
index 00000000..17aa0bbf
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonActionManager.java
@@ -0,0 +1,35 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon;
+
+import lombok.Getter;
+import net.minecraft.util.Vec3;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class DungeonActionManager {
+ @Getter
+ private static final Map<Integer , Vec3> spawnLocation = new HashMap<Integer, Vec3>();
+
+ @Getter
+ private static final List<Integer> killeds = new ArrayList<Integer>();
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java
new file mode 100755
index 00000000..fd2b8770
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/DungeonContext.java
@@ -0,0 +1,207 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon;
+
+import kr.syeyoung.dungeonsguide.dungeon.events.*;
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProvider;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProviderRegistry;
+import kr.syeyoung.dungeonsguide.dungeon.events.*;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.events.BossroomEnterEvent;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.features.impl.dungeon.FeatureDungeonMap;
+import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor;
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor;
+import kr.syeyoung.dungeonsguide.utils.TextUtils;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.network.NetworkPlayerInfo;
+import net.minecraft.scoreboard.ScorePlayerTeam;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.IChatComponent;
+import net.minecraft.world.World;
+import net.minecraftforge.client.event.ClientChatReceivedEvent;
+import net.minecraftforge.common.MinecraftForge;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class DungeonContext {
+ @Getter
+ private final World world;
+ @Getter
+ private final MapProcessor mapProcessor;
+
+ @Getter
+ @Setter
+ private BlockPos dungeonMin;
+
+ @Getter
+ private final Map<Point, DungeonRoom> roomMapper = new HashMap<Point, DungeonRoom>();
+ @Getter
+ private final List<DungeonRoom> dungeonRoomList = new ArrayList<DungeonRoom>();
+
+ @Getter
+ private final List<RoomProcessor> globalRoomProcessors = new ArrayList<RoomProcessor>();
+
+ @Getter
+ private final Map<String, Integer> deaths = new HashMap<String, Integer>();
+ @Getter
+ private final List<String[]> milestoneReached = new ArrayList<String[]>();
+ @Getter
+ @Setter
+ private long BossRoomEnterSeconds = -1;
+ @Getter
+ @Setter
+ private long init = -1;
+ @Getter
+ @Setter
+ private BlockPos bossroomSpawnPos = null;
+
+ @Getter
+ @Setter
+ private boolean trapRoomGen = false;
+
+ @Getter
+ private boolean gotMimic = false;
+
+ private int latestSecretCnt = 0;
+ private int latestTotalSecret = 0;
+ private int latestCrypts = 0;
+
+ @Getter
+ private int maxSpeed = 600;
+ @Getter
+ private double secretPercentage = 1.0;
+
+ public void setGotMimic(boolean gotMimic) {
+ this.gotMimic = gotMimic;
+ createEvent(new DungeonNodataEvent("MIMIC_KILLED"));
+ }
+
+ @Getter
+ @Setter
+ private BossfightProcessor bossfightProcessor;
+
+ @Getter
+ private final Set<String> players = new HashSet<String>();
+
+ @Getter
+ private final List<DungeonEvent> events = new ArrayList<DungeonEvent>();
+
+ public DungeonContext(World world) {
+ this.world = world;
+ createEvent(new DungeonNodataEvent("DUNGEON_CONTEXT_CREATION"));
+ mapProcessor = new MapProcessor(this);
+ DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ if (doorFinder != null) {
+ trapRoomGen = doorFinder.isTrapSpawn(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+
+ secretPercentage = doorFinder.secretPercentage(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ maxSpeed = doorFinder.speedSecond(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ } else mapProcessor.setBugged(true);
+ init = System.currentTimeMillis();
+ }
+
+ public void createEvent(DungeonEventData eventData) {
+ events.add(new DungeonEvent(eventData));
+ }
+
+
+ private final Rectangle roomBoundary = new Rectangle(-10,-10,138,138);
+
+ public void tick() {
+ mapProcessor.tick();
+
+ if (mapProcessor.isInitialized() && BossRoomEnterSeconds == -1 && !roomBoundary.contains(mapProcessor.worldPointToMapPoint(Minecraft.getMinecraft().thePlayer.getPositionVector()))) {
+ BossRoomEnterSeconds = FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed() / 1000;
+ bossroomSpawnPos = Minecraft.getMinecraft().thePlayer.getPosition();
+ MinecraftForge.EVENT_BUS.post(new BossroomEnterEvent());
+ createEvent(new DungeonNodataEvent("BOSSROOM_ENTER"));
+ DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ if (doorFinder != null) {
+ bossfightProcessor = doorFinder.createBossfightProcessor(world, DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ } else {
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Error:: Null Data Providier"));
+ }
+ }
+ List<NetworkPlayerInfo> list = FeatureDungeonMap.field_175252_a.sortedCopy(Minecraft.getMinecraft().thePlayer.sendQueue.getPlayerInfoMap());
+ try {
+ for (int i = 1; i < 20; i++) {
+ NetworkPlayerInfo networkPlayerInfo = list.get(i);
+ String name = networkPlayerInfo.getDisplayName() != null ? networkPlayerInfo.getDisplayName().getFormattedText() : ScorePlayerTeam.formatPlayerName(networkPlayerInfo.getPlayerTeam(), networkPlayerInfo.getGameProfile().getName());
+ if (name.trim().equals("§r") || name.startsWith("§r ")) continue;
+ players.add(TextUtils.stripColor(name).trim().split(" ")[0]);
+ }
+ } catch (Exception e) {}
+
+ if (latestSecretCnt != FeatureRegistry.DUNGEON_SECRETS.getSecretsFound()) {
+ int newSecretCnt = FeatureRegistry.DUNGEON_SECRETS.getSecretsFound();
+ createEvent(new DungeonSecretCountChangeEvent(latestSecretCnt, newSecretCnt, latestTotalSecret, FeatureRegistry.DUNGEON_SECRETS.sureOfTotalSecrets()));
+ latestSecretCnt = newSecretCnt;
+ }
+ if (latestTotalSecret != FeatureRegistry.DUNGEON_SECRETS.getTotalSecretsInt()) {
+ latestTotalSecret = FeatureRegistry.DUNGEON_SECRETS.getTotalSecretsInt();
+ createEvent(new DungeonSecretCountChangeEvent(latestSecretCnt, latestSecretCnt, latestTotalSecret, FeatureRegistry.DUNGEON_SECRETS.sureOfTotalSecrets()));
+ }
+ if (latestCrypts != FeatureRegistry.DUNGEON_TOMBS.getTombsFound()) {
+ int newlatestCrypts = FeatureRegistry.DUNGEON_TOMBS.getTombsFound();
+ createEvent(new DungeonCryptBrokenEvent(latestCrypts, newlatestCrypts));
+ this.latestCrypts = newlatestCrypts;
+ }
+ }
+
+ @Getter
+ private boolean ended = false;
+ @Getter
+ private boolean defeated = false;
+ public void onChat(ClientChatReceivedEvent event) {
+ IChatComponent component = event.message;
+ String formatted = component.getFormattedText();
+ if (formatted.contains("$DG-Comm")) {
+ event.setCanceled(true);
+ String data = component.getFormattedText().substring(component.getFormattedText().indexOf("$DG-Comm"));
+ String actual = TextUtils.stripColor(data);
+ String coords = actual.split(" ")[1];
+ String secrets = actual.split(" ")[2];
+ int x = Integer.parseInt(coords.split("/")[0]);
+ int z = Integer.parseInt(coords.split("/")[1]);
+ int secrets2 = Integer.parseInt(secrets);
+ Point roomPt = mapProcessor.worldPointToRoomPoint(new BlockPos(x,70,z));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Message from Other dungeons guide :: "+roomPt.x+" / " + roomPt.y + " total secrets "+secrets2));
+ DungeonRoom dr = roomMapper.get(roomPt);
+ if (dr != null) {
+ dr.setTotalSecrets(secrets2);
+ }
+ } else if (formatted.contains("$DG-Mimic")) {
+ setGotMimic(true);
+ } else if (formatted.startsWith("§r§c§lPUZZLE FAIL! ") && formatted.endsWith(" §r§4Y§r§ci§r§6k§r§ee§r§as§r§2!§r")) {
+ createEvent(new DungeonPuzzleFailureEvent(TextUtils.stripColor(formatted.split(" ")[2]), formatted));
+ } else if (formatted.contains("§6> §e§lEXTRA STATS §6<")) {
+ createEvent(new DungeonNodataEvent("DUNGEON_END"));
+ ended = true;
+ } else if (formatted.contains("§r§c☠ §r§eDefeated ")) {
+ defeated = true;
+ }
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java
new file mode 100755
index 00000000..da914ff3
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java
@@ -0,0 +1,495 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon;
+
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.events.DungeonMapUpdateEvent;
+import kr.syeyoung.dungeonsguide.dungeon.events.DungeonNodataEvent;
+import kr.syeyoung.dungeonsguide.dungeon.events.DungeonRoomDiscoverEvent;
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.EDungeonDoorType;
+import kr.syeyoung.dungeonsguide.dungeon.events.SerializableBlockPos;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProviderRegistry;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonSpecificDataProvider;
+import kr.syeyoung.dungeonsguide.events.DungeonContextInitializationEvent;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.stomp.StompPayload;
+import kr.syeyoung.dungeonsguide.utils.MapUtils;
+import kr.syeyoung.dungeonsguide.wsresource.StaticResourceCache;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.client.Minecraft;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.item.ItemMap;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.*;
+import net.minecraft.world.storage.MapData;
+import net.minecraftforge.common.MinecraftForge;
+import org.json.JSONObject;
+
+import javax.vecmath.Vector2d;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class MapProcessor {
+
+ private final DungeonContext context;
+
+ private byte[] lastMapData;
+
+ @Getter
+ private MapData lastMapData2;
+
+ @Getter
+ private final BiMap<String, String> mapIconToPlayerMap = HashBiMap.create();
+
+ @Getter @Setter
+ private Dimension unitRoomDimension;
+ @Getter @Setter
+ private Dimension doorDimension; // width: width of door, height: gap between rooms
+ @Getter @Setter
+ private Point topLeftMapPoint;
+
+ @Setter
+ private boolean bugged = false;
+
+ private final List<Point> roomsFound = new ArrayList<Point>();
+
+ private boolean axisMatch = false;
+
+ @Getter
+ private boolean initialized = false;
+
+ @Getter
+ private int undiscoveredRoom = 0;
+
+ public MapProcessor(DungeonContext context) {
+ this.context = context;
+ }
+
+ private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,1), new Vector2d(0, -1), new Vector2d(1, 0), new Vector2d(-1 , 0));
+
+ private int waitCnt = 0;
+ private void buildMap(final byte[] mapData) {
+ final Point startroom = MapUtils.findFirstColorWithIn(mapData, (byte) 30, new Rectangle(0,0,128,128));
+ if (startroom == null){
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't retrieve map data, disabling mod for this dungeon run"));
+ bugged = true;
+ return;
+ }
+ // Determine room dimension
+ {
+ int width = MapUtils.getWidthOfColorAt(mapData, (byte) 30, startroom);
+ int height = MapUtils.getHeightOfColorAt(mapData, (byte) 30, startroom);
+ unitRoomDimension = new Dimension(width, height);
+ }
+ Vector2d doorDir = null;
+ // determine the gap
+ {
+ Point midStartRoom = new Point(startroom.x + unitRoomDimension.width / 2, startroom.y +unitRoomDimension.height / 2);
+ final int halfWidth = unitRoomDimension.width / 2 + 2;
+ for (Vector2d v:directions) {
+ byte color = MapUtils.getMapColorAt(mapData, (int)(v.x * halfWidth +midStartRoom.x), (int)(v.y *halfWidth +midStartRoom.y));
+ if (color != 0) {
+ doorDir = v;
+ break;
+ }
+ }
+
+ if (doorDir == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't determine door of the room, disabling mod for this dungeon run"));
+ bugged = true;
+ return;
+ }
+ Point basePoint = new Point(startroom.x, startroom.y);
+ if (doorDir.x > 0) basePoint.x += unitRoomDimension.width;
+ if (doorDir.x < 0) basePoint.x += -1;
+ if (doorDir.y > 0) basePoint.y += unitRoomDimension.height;
+ if (doorDir.y < 0) basePoint.y += -1;
+ int gap = MapUtils.getLengthOfColorExtending(mapData, (byte) 0, basePoint, doorDir);
+ Point pt = MapUtils.findFirstColorWithInNegate(mapData, (byte)0, new Rectangle(basePoint.x, basePoint.y, (int)Math.abs(doorDir.y) * unitRoomDimension.width + 1, (int)Math.abs(doorDir.x) * unitRoomDimension.height + 1));
+ if (pt == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't determine door of the room, disabling mod for this dungeon run"));
+ bugged = true;
+ return;
+ }
+ int doorWidth = MapUtils.getLengthOfColorExtending(mapData, MapUtils.getMapColorAt(mapData, pt.x, pt.y), pt, new Vector2d((int)Math.abs(doorDir.y), (int)Math.abs(doorDir.x)));
+ doorDimension = new Dimension(doorWidth, gap);
+ }
+ // Determine Top Left
+ {
+ int x = startroom.x;
+ int y = startroom.y;
+ while (x >= unitRoomDimension.width + doorDimension.height) x -= unitRoomDimension.width + doorDimension.height;
+ while (y >= unitRoomDimension.height + doorDimension.height) y -= unitRoomDimension.height + doorDimension.height;
+ topLeftMapPoint = new Point(x, y);
+ }
+ // determine door location based on npc, and determine map min from there
+ {
+ DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ if (doorFinder == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't find door processor for "+ DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName()));
+ bugged = true;
+ return;
+ }
+ BlockPos door = doorFinder.findDoor(context.getWorld(), DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ if (door == null) {
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText("§eDungeons Guide §7:: §cCouldn't determine door of the room, disabling mod for this dungeon run"));
+ bugged = true;
+ return;
+ }
+
+ DungeonsGuide.sendDebugChat(new ChatComponentText("door Pos:"+door));
+
+ Point unitPoint = mapPointToRoomPoint(startroom);
+ unitPoint.translate(unitPoint.x + 1, unitPoint.y + 1);
+ unitPoint.translate((int)doorDir.x, (int)doorDir.y);
+
+ Vector2d offset = doorFinder.findDoorOffset(context.getWorld(), DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ axisMatch = doorDir.equals(offset);
+
+ int worldX = unitPoint.x * 16;
+ int worldY = unitPoint.y * 16;
+ BlockPos worldMin = door.add(-worldX, 0, -worldY);
+ context.setDungeonMin(worldMin);
+
+ }
+
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Found Green room:"+startroom));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Axis match:"+axisMatch));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("World Min:"+context.getDungeonMin()));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Dimension:"+unitRoomDimension));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("top Left:"+topLeftMapPoint));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("door dimension:"+doorDimension));
+ context.createEvent(new DungeonNodataEvent("MAP_PROCESSOR_INIT"));
+ initialized = true;
+ MinecraftForge.EVENT_BUS.post(new DungeonContextInitializationEvent());
+ }
+
+ public Point mapPointToRoomPoint(Point mapPoint) {
+ int x = (int)((mapPoint.x - topLeftMapPoint.x) / ((double)unitRoomDimension.width + doorDimension.height));
+ int y = (int)((mapPoint.y - topLeftMapPoint.y) / ((double)unitRoomDimension.height + doorDimension.height));
+ return new Point(x,y);
+ }
+ public BlockPos mapPointToWorldPoint(Point mapPoint) {
+ int x = (int)((mapPoint.x - topLeftMapPoint.x) / ((double)unitRoomDimension.width + doorDimension.height) * 32 + context.getDungeonMin().getX());
+ int y = (int)((mapPoint.y - topLeftMapPoint.y) / ((double)unitRoomDimension.height + doorDimension.height) * 32 + context.getDungeonMin().getZ());
+ return new BlockPos(x,70,y);
+ }
+ public Point roomPointToMapPoint(Point roomPoint) {
+ return new Point(roomPoint.x * (unitRoomDimension.width +doorDimension.height) + topLeftMapPoint.x,
+ roomPoint.y *(unitRoomDimension.height + doorDimension.height) + topLeftMapPoint.y);
+ }
+ public BlockPos roomPointToWorldPoint(Point roomPoint) {
+ return new BlockPos(context.getDungeonMin().getX() +(roomPoint.x * 32), context.getDungeonMin().getY(), context.getDungeonMin().getZ() +(roomPoint.y *32));
+ }
+ public Point worldPointToRoomPoint(BlockPos worldPoint) {
+ if (context.getDungeonMin() == null) return null;
+ return new Point((worldPoint.getX() - context.getDungeonMin().getX()) / 32, (worldPoint.getZ() - context.getDungeonMin().getZ()) / 32);
+ }
+ public Point worldPointToMapPoint(Vec3 worldPoint) {
+ if (context.getDungeonMin() == null) return null;
+ return new Point(topLeftMapPoint.x + (int)((worldPoint.xCoord - context.getDungeonMin().getX()) / 32.0f * (unitRoomDimension.width + doorDimension.height)), topLeftMapPoint.y + (int)((worldPoint.zCoord - context.getDungeonMin().getZ()) / 32.0f * (unitRoomDimension.height + doorDimension.height)));
+ }
+
+ private void processMap(byte[] mapData) {
+ int height = (int)((128.0 - topLeftMapPoint.y) / (unitRoomDimension.height + doorDimension.height));
+ int width = (int) ((128.0 - topLeftMapPoint.x) / (unitRoomDimension.width + doorDimension.height));
+ if (MapUtils.getMapColorAt(mapData,0,0) != 0) return;
+ undiscoveredRoom = 0;
+ for (int y = 0; y <= height; y++){
+ for (int x = 0; x <= width; x++) {
+ Point mapPoint = roomPointToMapPoint(new Point(x,y));
+ byte color = MapUtils.getMapColorAt(mapData, mapPoint.x, mapPoint.y);
+ MapUtils.record(mapData, mapPoint.x, mapPoint.y, new Color(255,255,0,80));
+ if (roomsFound.contains(new Point(x,y))) {
+ DungeonRoom dungeonRoom = context.getRoomMapper().get(new Point(x,y));
+ if (color == 18 && dungeonRoom.getCurrentState() != DungeonRoom.RoomState.FINISHED) {
+ dungeonRoom.setCurrentState(DungeonRoom.RoomState.COMPLETE_WITHOUT_SECRETS);
+ dungeonRoom.setTotalSecrets(0);
+ } else if (color == 30) {
+ dungeonRoom.setCurrentState(DungeonRoom.RoomState.FINISHED);
+ dungeonRoom.setTotalSecrets(0);
+ } else if (dungeonRoom.getCurrentState() != DungeonRoom.RoomState.FINISHED){
+ byte centerColor = MapUtils.getMapColorAt(mapData, mapPoint.x + unitRoomDimension.width / 2, mapPoint.y + unitRoomDimension.height / 2);
+ MapUtils.record(mapData, mapPoint.x + unitRoomDimension.width / 2, mapPoint.y + unitRoomDimension.height / 2, new Color(0,255,0,80));
+ if (centerColor == 34) {
+ dungeonRoom.setCurrentState(DungeonRoom.RoomState.COMPLETE_WITHOUT_SECRETS);
+ } else if (centerColor == 30) {
+ dungeonRoom.setCurrentState(DungeonRoom.RoomState.FINISHED);
+ } else if (centerColor == 18) { // red
+ dungeonRoom.setCurrentState(DungeonRoom.RoomState.FAILED);
+ }
+ }
+ if (dungeonRoom.getTotalSecrets() == -1) {
+ if (dungeonRoom.getColor() == 82) dungeonRoom.setTotalSecrets(0);
+ else if (dungeonRoom.getColor() == 74) dungeonRoom.setTotalSecrets(0);
+ MapUtils.record(mapData, mapPoint.x, mapPoint.y +1, new Color(0,255,0,80));
+ }
+ continue;
+ }
+
+ if (color != 0 && color != 85) {
+ MapUtils.record(mapData, mapPoint.x, mapPoint.y, new Color(0,255,255,80));
+ DungeonRoom rooms = buildRoom(mapData, new Point(x,y));
+ if (rooms == null) continue;
+ context.createEvent(new DungeonRoomDiscoverEvent(rooms.getUnitPoints().get(0), rooms.getRoomMatcher().getRotation(), new SerializableBlockPos(rooms.getMin()), new SerializableBlockPos(rooms.getMax()), rooms.getShape(),rooms.getColor(), rooms.getDungeonRoomInfo().getUuid(), rooms.getDungeonRoomInfo().getName(), rooms.getDungeonRoomInfo().getProcessorId()));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("New Map discovered! shape: "+rooms.getShape()+ " color: "+rooms.getColor()+" unitPos: "+x+","+y));
+ DungeonsGuide.sendDebugChat(new ChatComponentText("New Map discovered! mapMin: "+rooms.getMin() + " mapMx: "+rooms.getMax()));
+ StringBuilder builder = new StringBuilder();
+ for (int dy =0;dy<4;dy++) {
+ builder.append("\n");
+ for (int dx = 0; dx < 4; dx ++) {
+ boolean isSet = ((rooms.getShape() >> (dy * 4 + dx)) & 0x1) != 0;
+ builder.append(isSet ? "O" : "X");
+ }
+ }
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Shape visual: "+ builder));
+
+ context.getDungeonRoomList().add(rooms);
+ for (Point p:rooms.getUnitPoints()) {
+ roomsFound.add(p);
+ context.getRoomMapper().put(p, rooms);
+ }
+ if (rooms.getRoomProcessor() != null && rooms.getRoomProcessor().readGlobalChat())
+ context.getGlobalRoomProcessors().add(rooms.getRoomProcessor());
+ } else if (color == 85){
+ undiscoveredRoom++;
+ }
+
+ }
+ }
+ }
+
+ private static final Set<Vector2d> door_dirs = Sets.newHashSet(new Vector2d(0,0.5), new Vector2d(0, -0.5), new Vector2d(0.5, 0), new Vector2d(-0.5 , 0));
+ private DungeonRoom buildRoom(byte[] mapData, Point unitPoint) {
+ Queue<Point[]> toCheck = new LinkedList<Point[]>();
+ toCheck.add(new Point[] {unitPoint, unitPoint}); // requestor, target
+ Set<Point> checked = new HashSet<Point>();
+ List<Point> ayConnected = new ArrayList<Point>();
+
+ int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE;
+ int maxX = 0, maxY = 0;
+ while(toCheck.peek() != null) {
+ Point[] check = toCheck.poll();
+ if (checked.contains(check[1])) continue;
+ checked.add(check[1]);
+
+ if (checkIfConnected(mapData, check[0], check[1])) {
+ ayConnected.add(check[1]);
+ if (check[1].x < minX) minX = check[1].x;
+ if (check[1].y < minY) minY = check[1].y;
+ if (check[1].x > maxX) maxX = check[1].x;
+ if (check[1].y > maxY) maxY = check[1].y;
+ for (Vector2d dir: directions) {
+ Point newPt = new Point(check[1].x + (int)dir.x, check[1].y +(int)dir.y);
+ toCheck.add(new Point[]{check[1], newPt});
+ }
+ }
+ }
+
+ short shape = 0;
+ for (Point p:ayConnected) {
+ int localX = p.x - minX, localY = p.y - minY;
+ shape |= 1 <<(localY *4 + localX);
+ }
+ Set<Vector2d> doors = new HashSet<>();
+ for (Point p: ayConnected) {
+ for (Vector2d v: door_dirs) {
+ Vector2d v2 = new Vector2d(p.x + v.x , p.y + v.y );
+ if (doors.contains(v2)) doors.remove(v2);
+ else doors.add(v2);
+ }
+ }
+ Point pt2 = roomPointToMapPoint(ayConnected.get(0));
+ byte unit1 = MapUtils.getMapColorAt(mapData, pt2.x, pt2.y);
+
+ // 0: none 1: open door door 2. unopen door 3: wither door 4. red door
+ Set<Tuple<Vector2d, EDungeonDoorType>> doorsAndStates = new HashSet<>();
+ final int halfWidth = unitRoomDimension.width + 4;
+ for (Vector2d door : doors) {
+ int floorX = (int)Math.floor(door.x), floorY = (int)Math.floor(door.y);
+ Point mapPt = roomPointToMapPoint(new Point(floorX, floorY));
+ Point target = new Point(mapPt.x+ unitRoomDimension.width/2 + (int)(halfWidth*(door.x - floorX)), mapPt.y + unitRoomDimension.height/2 + (int)(halfWidth*(door.y - floorY)) );
+ MapUtils.record(mapData, target.x, target.y, Color.green);
+ byte color = MapUtils.getMapColorAt(mapData, target.x, target.y);
+
+ Vector2d vector2d = new Vector2d(door.x - minX, door.y - minY);
+ if (color == 0) {
+ doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.NONE));
+ } else if (color == 85) {
+ doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.UNOPEN));
+ } else if (color == 119) {
+ doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.WITHER));
+ } else if (color == 18 && unit1 != 18) {
+ doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.BLOOD));
+ } else {
+ doorsAndStates.add(new Tuple<>(vector2d, EDungeonDoorType.ENTRANCE));
+ }
+ }
+
+
+ try{
+ return new DungeonRoom(ayConnected, shape, unit1, roomPointToWorldPoint(new Point(minX, minY)), roomPointToWorldPoint(new Point(maxX+1, maxY+1)).add(-1, 0, -1), context, doorsAndStates);
+ } catch (IllegalStateException ex) {
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Failed to load room, retrying later :: "+ex.getLocalizedMessage()));
+ return null;
+ }
+ }
+
+ private boolean checkIfConnected(byte[] mapData, Point unitPoint1, Point unitPoint2) {
+ if (unitPoint1 == unitPoint2) return true;
+ if (unitPoint1.equals(unitPoint2)) return true;
+
+
+ Point high = (unitPoint2.y > unitPoint1.y) ? unitPoint2 :(unitPoint2.x > unitPoint1.x) ? unitPoint2 : unitPoint1;
+ Point low = high == unitPoint2 ? unitPoint1 : unitPoint2;
+
+ int xOff = low.x - high.x;
+ int yOff = low.y - high.y;
+ Point pt = roomPointToMapPoint(high);
+ Point pt2 = roomPointToMapPoint(low);
+ byte unit1 = MapUtils.getMapColorAt(mapData, pt.x, pt.y);
+ byte unit2 = MapUtils.getMapColorAt(mapData, pt2.x, pt2.y);
+ pt.translate(xOff, yOff);
+ byte unit3 = MapUtils.getMapColorAt(mapData, pt.x, pt.y);
+
+ return unit1 == unit2 && unit2 == unit3 && unit1 != 0;
+ }
+
+ public boolean isThereDifference(byte[] colors1, byte[] colors) {
+ if (colors1 == null || colors == null) return true;
+ for (int i =0; i < colors.length; i++)
+ if (colors[i] != colors1[i]) return true;
+ return false;
+ }
+ private int stabilizationTick = 0;
+
+ private boolean processed = false;
+ private void processFinishedMap(byte[] mapData) {
+ if (MapUtils.getMapColorAt(mapData, 0, 0) == 0) return;
+ if (processed) return;
+ processed = true;
+ MapUtils.clearMap();
+ MapUtils.record(mapData, 0, 0, Color.GREEN);
+
+ int skill = MapUtils.readNumber(mapData, 51, 35, 9);
+ int exp = MapUtils.readNumber(mapData, 51, 54, 9);
+ int time = MapUtils.readNumber(mapData, 51, 73, 9);
+ int bonus = MapUtils.readNumber(mapData, 51, 92, 9);
+ DungeonsGuide.sendDebugChat(new ChatComponentText(("skill: " + skill + " / exp: " + exp + " / time: " + time + " / bonus : " + bonus)));
+ JSONObject payload = new JSONObject().put("timeSB", FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed())
+ .put("timeR", FeatureRegistry.DUNGEON_REALTIME.getTimeElapsed())
+ .put("timeScore", time)
+ .put("completionStage", context.getBossRoomEnterSeconds() == -1 ? 0 :
+ context.isDefeated() ? 2 : 1)
+ .put("percentage", DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getPercentage() / 100.0)
+ .put("floor", DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getDungeonName());
+ DungeonsGuide.sendDebugChat(new ChatComponentText(payload.toString()));
+
+ try {
+ String target = StaticResourceCache.INSTANCE.getResource(StaticResourceCache.DATA_COLLECTION).get().getValue();
+ if (FeatureRegistry.ETC_COLLECT_SCORE.isEnabled() && !target.contains("falsefalsefalsefalse")) {
+ DungeonsGuide.getDungeonsGuide().getStompConnection().send(new StompPayload().payload(payload.toString()).header("destination", target.replace("false", "").trim()));
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ public void tick() {
+ if (waitCnt < 5) {
+ waitCnt++;
+ return;
+ }
+ if (bugged) return;
+ ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.getStackInSlot(8);
+ byte[] mapData;
+ if (stack == null || !(stack.getItem() instanceof ItemMap)) {
+ mapData = lastMapData;
+ } else {
+ MapData mapData1 = ((ItemMap)stack.getItem()).getMapData(stack, context.getWorld());
+ if (mapData1 == null) mapData = lastMapData;
+ else {
+ mapData = mapData1.colors;
+ lastMapData2 = mapData1;
+
+ if (isThereDifference(lastMapData, mapData)) {
+ stabilizationTick =0;
+ context.createEvent(new DungeonMapUpdateEvent(mapData));
+ } else {
+ stabilizationTick++;
+ }
+
+ if (stabilizationTick > 20) {
+ if (doorDimension == null) buildMap(mapData);
+ else processMap(mapData);
+
+ if (context.isEnded()) {
+ processFinishedMap(mapData);
+ }
+ }
+ lastMapData = mapData;
+ }
+
+ }
+
+
+ if (lastMapData2 != null && mapIconToPlayerMap.size() < context.getPlayers().size() && initialized) {
+ label: for (Map.Entry<String, Vec4b> stringVec4bEntry : lastMapData2.mapDecorations.entrySet()) {
+ if (mapIconToPlayerMap.containsValue(stringVec4bEntry.getKey())) continue;
+ int x = stringVec4bEntry.getValue().func_176112_b() /2 + 64;
+ int y = stringVec4bEntry.getValue().func_176113_c() /2 + 64;
+ BlockPos mapPos = mapPointToWorldPoint(new Point(x, y));
+ String potentialPlayer = null;
+ for (String player : context.getPlayers()) { // check nearby players
+ if (mapIconToPlayerMap.containsKey(player)) continue;
+ EntityPlayer entityPlayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(player);
+ if (entityPlayer == null || entityPlayer.isInvisible()) continue;
+ BlockPos pos = entityPlayer.getPosition();
+ int dx = mapPos.getX() - pos.getX();
+ int dz = mapPos.getZ() - pos.getZ();
+ if (dx * dx + dz * dz < 100) {
+ if (potentialPlayer != null) continue label;
+ potentialPlayer = player;
+ }
+ }
+ if (potentialPlayer == null) continue;
+
+ for (Map.Entry<String, Vec4b> stringVec4bEntry2 : lastMapData2.mapDecorations.entrySet()) { // check nearby markers
+ if (mapIconToPlayerMap.containsValue(stringVec4bEntry.getKey())) continue;
+ if (stringVec4bEntry.getKey().equals(stringVec4bEntry2.getKey())) continue;
+ int x2 = stringVec4bEntry2.getValue().func_176112_b() /2 + 64;
+ int y2 = stringVec4bEntry2.getValue().func_176113_c() /2 + 64;
+ int dx = x2 - x;
+ int dy = y2 - y;
+ if (dx * dx + dy * dy < 100) {
+ continue label;
+ }
+ }
+ mapIconToPlayerMap.put(potentialPlayer, stringVec4bEntry.getKey());
+ }
+ }
+
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java
new file mode 100644
index 00000000..c9a8ac9a
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/AbstractAction.java
@@ -0,0 +1,57 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent;
+import net.minecraftforge.event.entity.living.LivingDeathEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+
+public abstract class AbstractAction implements Action {
+ @Override
+ public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+
+ }
+
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+
+ }
+
+ @Override
+ public void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+
+ }
+
+ @Override
+ public void onRenderScreen(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties) {
+
+ }
+
+ @Override
+ public void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+
+ }
+
+ @Override
+ public void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties) {
+
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java
new file mode 100755
index 00000000..2be05ff8
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/Action.java
@@ -0,0 +1,40 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent;
+import net.minecraftforge.event.entity.living.LivingDeathEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+
+import java.util.Set;
+
+public interface Action {
+ Set<Action> getPreRequisites(DungeonRoom dungeonRoom);
+
+ void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties);
+ void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRoute.ActionRouteProperties actionRouteProperties);
+ void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRoute.ActionRouteProperties actionRouteProperties);
+ void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag);
+ void onRenderScreen(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties);
+ void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties);
+
+ boolean isComplete(DungeonRoom dungeonRoom);
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java
new file mode 100755
index 00000000..b9307e0c
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionBreakWithSuperBoom.java
@@ -0,0 +1,101 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.BlockRendererDispatcher;
+import net.minecraft.client.renderer.GlStateManager;
+import net.minecraft.client.renderer.Tessellator;
+import net.minecraft.client.renderer.WorldRenderer;
+import net.minecraft.client.renderer.texture.TextureMap;
+import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
+import net.minecraft.entity.Entity;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionBreakWithSuperBoom extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+
+ public ActionBreakWithSuperBoom(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return target.getBlock(dungeonRoom) == Blocks.air;
+ }
+
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ Minecraft.getMinecraft().renderEngine.bindTexture(TextureMap.locationBlocksTexture);
+
+ BlockPos blockpos = target.getBlockPos(dungeonRoom);
+
+ Entity viewing_from = Minecraft.getMinecraft().getRenderViewEntity();
+
+ double x_fix = viewing_from.lastTickPosX + ((viewing_from.posX - viewing_from.lastTickPosX) * partialTicks);
+ double y_fix = viewing_from.lastTickPosY + ((viewing_from.posY - viewing_from.lastTickPosY) * partialTicks);
+ double z_fix = viewing_from.lastTickPosZ + ((viewing_from.posZ - viewing_from.lastTickPosZ) * partialTicks);
+
+ GlStateManager.pushMatrix();
+ GlStateManager.translate(-x_fix, -y_fix, -z_fix);
+ GlStateManager.disableLighting();
+ GlStateManager.enableAlpha();
+ GlStateManager.disableDepth();
+ GlStateManager.depthMask(false);
+ GlStateManager.enableBlend();
+
+ Tessellator tessellator = Tessellator.getInstance();
+ WorldRenderer vertexbuffer = tessellator.getWorldRenderer();
+ vertexbuffer.begin(7, DefaultVertexFormats.BLOCK);
+
+ BlockRendererDispatcher blockrendererdispatcher = Minecraft.getMinecraft().getBlockRendererDispatcher();
+ blockrendererdispatcher.getBlockModelRenderer().renderModel(Minecraft.getMinecraft().theWorld,
+ blockrendererdispatcher.getBlockModelShapes().getModelForState(Blocks.tnt.getDefaultState()),
+ Blocks.tnt.getDefaultState(), blockpos, vertexbuffer, false);
+ tessellator.draw();
+
+ GlStateManager.enableLighting();
+ GlStateManager.popMatrix();
+
+ RenderUtils.highlightBlock(blockpos, new Color(0, 255,255,50), partialTicks, true);
+ RenderUtils.drawTextAtWorld("Superboom", blockpos.getX() + 0.5f, blockpos.getY() + 0.5f, blockpos.getZ() + 0.5f, 0xFFFFFF00, 0.03f, false, false, partialTicks);
+ }
+
+ @Override
+ public String toString() {
+ return "BreakWithSuperboom\n- target: "+target.toString();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java
new file mode 100755
index 00000000..f88a3826
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionChangeState.java
@@ -0,0 +1,71 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDummy;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionChangeState extends AbstractAction{
+ @EqualsAndHashCode.Exclude
+ private Set<Action> preRequisite2 = new HashSet<Action>();
+
+ private String mechanicName;
+ private String state;
+
+ public ActionChangeState(String mechanicName, String state) {
+ this.mechanicName = mechanicName;
+ this.state = state;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ Set<Action> set = new HashSet<Action>();
+ set.addAll(preRequisite2);
+ DungeonMechanic mechanic = dungeonRoom.getMechanics().get(mechanicName);
+ if (mechanic!= null)
+ set.addAll(mechanic.getAction(state, dungeonRoom));
+ return set;
+ }
+ @Override
+ public String toString() {
+ return "ChangeState\n- target: "+mechanicName+"\n- state: "+state;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ DungeonMechanic mechanic = dungeonRoom.getMechanics().get(mechanicName);
+ if (state.equalsIgnoreCase("navigate"))
+ return true;
+ if (mechanic== null)
+ return false;
+ if (mechanic instanceof DungeonSecret && ((DungeonSecret) mechanic).getSecretType() != DungeonSecret.SecretType.CHEST)
+ return true;
+ if (mechanic instanceof DungeonDummy)
+ return true;
+ return mechanic.getCurrentState(dungeonRoom).equalsIgnoreCase(state);
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java
new file mode 100755
index 00000000..a903bcee
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClick.java
@@ -0,0 +1,78 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.BlockPos;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionClick extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+ private Predicate<ItemStack> predicate = Predicates.alwaysTrue();
+
+ private boolean clicked = false;
+
+ public ActionClick(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return clicked;
+ }
+
+ @Override
+ public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+ if (clicked) return;
+ if (target.getBlockPos(dungeonRoom).equals(event.pos) &&
+ (predicate == null || predicate.apply(event.entityLiving.getHeldItem()))) {
+ clicked = true;
+ }
+ }
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true);
+ RenderUtils.drawTextAtWorld("Click", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks);
+ }
+
+
+ @Override
+ public String toString() {
+ return "Click\n- target: "+target.toString()+"\n- predicate: "+predicate.getClass().getSimpleName();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java
new file mode 100755
index 00000000..24bad024
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionClickSet.java
@@ -0,0 +1,91 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.BlockPos;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionClickSet extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPointSet target;
+ private Predicate<ItemStack> predicate = Predicates.alwaysTrue();
+
+ public ActionClickSet(OffsetPointSet target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public String toString() {
+ return "ClickSet\n- targets size: "+target.getOffsetPointList().size()+"\n- predicate: "+predicate.getClass().getSimpleName();
+ }
+
+ private boolean clicked = false;
+ @Override
+ public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+ if (clicked) return;
+ for (OffsetPoint pt2: target.getOffsetPointList()) {
+ if (pt2.getBlockPos(dungeonRoom).equals(event.pos) &&
+ (predicate == null || predicate.apply(event.entityLiving.getHeldItem()))) {
+ clicked = true;
+ }
+ }
+
+ }
+
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ float xAcc = 0;
+ float yAcc = 0;
+ float zAcc = 0;
+ int size = target.getOffsetPointList().size();
+ for (OffsetPoint offsetPoint : target.getOffsetPointList()) {
+ BlockPos pos = offsetPoint.getBlockPos(dungeonRoom);
+ xAcc += pos.getX() + 0.5f;
+ yAcc += pos.getY()+ 0.5f;
+ zAcc += pos.getZ()+ 0.5f;
+ RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), new Color(0, 255,255,50),partialTicks, true);
+ }
+
+ RenderUtils.drawTextAtWorld("Click", xAcc / size, yAcc / size, zAcc / size, 0xFFFFFF00, 0.02f, false, false, partialTicks);
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return clicked;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java
new file mode 100644
index 00000000..646c2171
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionComplete.java
@@ -0,0 +1,41 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+
+import java.util.Collections;
+import java.util.Set;
+
+public class ActionComplete extends AbstractAction {
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return Collections.emptySet();
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return "Completed";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java
new file mode 100755
index 00000000..9d246fc8
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionDropItem.java
@@ -0,0 +1,71 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.entity.item.EntityItem;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Data
+public class ActionDropItem extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+ private Predicate<EntityItem> predicate = Predicates.alwaysTrue();
+
+ public ActionDropItem(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+ List<EntityItem> item = dungeonRoom.getContext().getWorld().getEntitiesWithinAABB(EntityItem.class,
+ AxisAlignedBB.fromBounds(pos.getX(), pos.getY(), pos.getZ(), pos.getX()+1, pos.getY() + 1, pos.getZ() + 1));
+ if (item.size() == 0) return false;
+ return (predicate == null || predicate.apply(item.get(0)));
+ }
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true);
+ RenderUtils.drawTextAtWorld("Drop Item", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks);
+ }
+
+ @Override
+ public String toString() {
+ return "DropItem\n- target: "+target.toString()+"\n- predicate: "+predicate.getClass().getSimpleName();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java
new file mode 100755
index 00000000..9b5a22be
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionInteract.java
@@ -0,0 +1,81 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.Vec3;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionInteract extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+ private Predicate<Entity> predicate = Predicates.alwaysFalse();
+ private int radius;
+
+ public ActionInteract(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return interacted;
+ }
+
+ private boolean interacted = false;
+ @Override
+ public void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+ if (interacted) return;
+
+ Vec3 spawnLoc = DungeonActionManager.getSpawnLocation().get(event.getEntity().getEntityId());
+ if (spawnLoc == null) return;
+ if (target.getBlockPos(dungeonRoom).distanceSq(spawnLoc.xCoord, spawnLoc.yCoord, spawnLoc.zCoord) > radius * radius) return;
+ if (!predicate.apply(event.getEntity())) return;
+ interacted = true;
+ }
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true);
+ RenderUtils.drawTextAtWorld("Interact", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks);
+ }
+
+ @Override
+ public String toString() {
+ return "InteractEntity\n- target: "+target.toString()+"\n- radius: "+radius+"\n- predicate: "+(predicate == null ? "null" : predicate.getClass().getSimpleName());
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java
new file mode 100755
index 00000000..a048bdf6
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionKill.java
@@ -0,0 +1,89 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.Vec3;
+import net.minecraftforge.event.entity.living.LivingDeathEvent;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionKill extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+ private Predicate<Entity> predicate = Predicates.alwaysFalse();
+ private int radius;
+
+ public ActionKill(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ Vec3 spawn = new Vec3(target.getBlockPos(dungeonRoom));
+ for (Integer killed : DungeonActionManager.getKilleds()) {
+ if (DungeonActionManager.getSpawnLocation().get(killed) == null) continue;
+ if (DungeonActionManager.getSpawnLocation().get(killed).squareDistanceTo(spawn) < 100) {
+ return true;
+ }
+ }
+
+ return killed;
+ }
+
+ private boolean killed = false;
+ @Override
+ public void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRoute.ActionRouteProperties actionRouteProperties) {
+ if (killed) return;
+
+ Vec3 spawnLoc = DungeonActionManager.getSpawnLocation().get(event.entity.getEntityId());
+ if (spawnLoc == null) return;
+ if (target.getBlockPos(dungeonRoom).distanceSq(spawnLoc.xCoord, spawnLoc.yCoord, spawnLoc.zCoord) > radius * radius) return;
+ if (!predicate.apply(event.entity)) return;
+ killed = true;
+ }
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, new Color(0, 255,255,50),partialTicks, true);
+ RenderUtils.drawTextAtWorld("Spawn", pos.getX() + 0.5f, pos.getY() + 0.3f, pos.getZ() + 0.5f, 0xFFFFFF00, 0.02f, false, false, partialTicks);
+ }
+
+ @Override
+ public String toString() {
+ return "KillEntity\n- target: "+target.toString()+"\n- radius: "+radius+"\n- predicate: "+(predicate == null ? "null" : predicate.getClass().getSimpleName());
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java
new file mode 100755
index 00000000..6f04b44d
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMove.java
@@ -0,0 +1,112 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.Vec3;
+
+import java.util.HashSet;
+import java.util.Set;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+@Data
+public class ActionMove extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+
+ public ActionMove(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return target.getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) < 25;
+ }
+
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+
+ float distance = MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()));
+ float multiplier = distance / 120f; //mobs only render ~120 blocks away
+ if (flag) multiplier *= 2.0f;
+ float scale = 0.45f * multiplier;
+ scale *= 25.0 / 6.0;
+ if (actionRouteProperties.isBeacon()) {
+ RenderUtils.renderBeaconBeam(pos.getX(), pos.getY(), pos.getZ(), actionRouteProperties.getBeaconBeamColor(), partialTicks);
+ RenderUtils.highlightBlock(pos, actionRouteProperties.getBeaconColor(), partialTicks);
+ }
+ RenderUtils.drawTextAtWorld("Destination", pos.getX() + 0.5f, pos.getY() + 0.5f + scale, pos.getZ() + 0.5f, 0xFF00FF00, flag ? 2f : 1f, true, false, partialTicks);
+ RenderUtils.drawTextAtWorld(String.format("%.2f",MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())))+"m", pos.getX() + 0.5f, pos.getY() + 0.5f - scale, pos.getZ() + 0.5f, 0xFFFFFF00, flag ? 2f : 1f, true, false, partialTicks);
+
+ if (!FeatureRegistry.SECRET_TOGGLE_KEY.isEnabled() || !FeatureRegistry.SECRET_TOGGLE_KEY.togglePathfindStatus) {
+ if (poses != null){
+ RenderUtils.drawLinesVec3(poses, actionRouteProperties.getLineColor(), actionRouteProperties.getLineWidth(), partialTicks, true);
+ }
+ }
+ }
+
+ private int tick = -1;
+ private List<Vec3> poses;
+ private Future<List<Vec3>> latestFuture;
+
+ @Override
+ public void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties) {
+ tick = (tick+1) % Math.max(1, actionRouteProperties.getLineRefreshRate());
+ if (latestFuture != null && latestFuture.isDone()) {
+ try {
+ poses = latestFuture.get();
+ latestFuture = null;
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (tick == 0 && actionRouteProperties.isPathfind() && latestFuture == null) {
+ if (!FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() || poses == null)
+ latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000);
+ }
+ }
+
+ public void forceRefresh(DungeonRoom dungeonRoom) {
+ try {
+ if (latestFuture != null) return;
+ } catch (Exception ignored) {}
+ latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000);
+ }
+ @Override
+ public String toString() {
+ return "Move\n- target: "+target.toString();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java
new file mode 100755
index 00000000..1535d574
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionMoveNearestAir.java
@@ -0,0 +1,112 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.tree.ActionRoute;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.client.Minecraft;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.MathHelper;
+import net.minecraft.util.Vec3;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+
+@Data
+public class ActionMoveNearestAir extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+ private OffsetPoint target;
+
+ public ActionMoveNearestAir(OffsetPoint target) {
+ this.target = target;
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return target.getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) < 25;
+ }
+
+ @Override
+ public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRoute.ActionRouteProperties actionRouteProperties, boolean flag) {
+ BlockPos pos = target.getBlockPos(dungeonRoom);
+
+ float distance = MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()));
+ float multiplier = distance / 120f; //mobs only render ~120 blocks away
+ if (flag) multiplier *= 2.0f;
+ float scale = 0.45f * multiplier;
+ scale *= 25.0 / 6.0;
+ if (actionRouteProperties.isBeacon()) {
+ RenderUtils.renderBeaconBeam(pos.getX(), pos.getY(), pos.getZ(), actionRouteProperties.getBeaconBeamColor(), partialTicks);
+ RenderUtils.highlightBlock(pos, actionRouteProperties.getBeaconColor(), partialTicks);
+ }
+ RenderUtils.drawTextAtWorld("Destination", pos.getX() + 0.5f, pos.getY() + 0.5f + scale, pos.getZ() + 0.5f, 0xFF00FF00, flag ? 2f : 1f, true, false, partialTicks);
+ RenderUtils.drawTextAtWorld(String.format("%.2f",MathHelper.sqrt_double(pos.distanceSq(Minecraft.getMinecraft().thePlayer.getPosition())))+"m", pos.getX() + 0.5f, pos.getY() + 0.5f - scale, pos.getZ() + 0.5f, 0xFFFFFF00, flag ? 2f : 1f, true, false, partialTicks);
+
+ if (!FeatureRegistry.SECRET_TOGGLE_KEY.isEnabled() || !FeatureRegistry.SECRET_TOGGLE_KEY.togglePathfindStatus) {
+ if (poses != null){
+ RenderUtils.drawLinesVec3(poses, actionRouteProperties.getLineColor(), actionRouteProperties.getLineWidth(), partialTicks, true);
+ }
+ }
+ }
+
+ private int tick = -1;
+ private List<Vec3> poses;
+ private Future<List<Vec3>> latestFuture;
+ @Override
+ public void onTick(DungeonRoom dungeonRoom, ActionRoute.ActionRouteProperties actionRouteProperties) {
+ tick = (tick+1) % Math.max(1, actionRouteProperties.getLineRefreshRate());
+ if (latestFuture != null && latestFuture.isDone()) {
+ try {
+ poses = latestFuture.get();
+ latestFuture = null;
+ } catch (InterruptedException | ExecutionException e) {
+ e.printStackTrace();
+ }
+ }
+
+ if (tick == 0 && actionRouteProperties.isPathfind() && latestFuture == null) {
+ if (!FeatureRegistry.SECRET_FREEZE_LINES.isEnabled() || poses == null)
+ latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000);
+ }
+ }
+
+
+ public void forceRefresh(DungeonRoom dungeonRoom) {
+ try {
+ if (latestFuture != null) return;
+ } catch (Exception ignored) {}
+ latestFuture = dungeonRoom.createEntityPathTo(dungeonRoom.getContext().getWorld(), Minecraft.getMinecraft().thePlayer, target.getBlockPos(dungeonRoom), Integer.MAX_VALUE, 10000);
+ }
+ @Override
+ public String toString() {
+ return "MoveNearestAir\n- target: "+target.toString();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java
new file mode 100755
index 00000000..a2527b8b
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/ActionRoot.java
@@ -0,0 +1,48 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions;
+
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import lombok.Data;
+
+import java.util.HashSet;
+import java.util.Set;
+
+@Data
+public class ActionRoot extends AbstractAction {
+ private Set<Action> preRequisite = new HashSet<Action>();
+
+ public ActionRoot() {
+ }
+
+ @Override
+ public Set<Action> getPreRequisites(DungeonRoom dungeonRoom) {
+ return preRequisite;
+ }
+
+ @Override
+ public boolean isComplete(DungeonRoom dungeonRoom) {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "Action Root";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java
new file mode 100644
index 00000000..bba5fb4d
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionRoute.java
@@ -0,0 +1,124 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions.tree;
+
+import kr.syeyoung.dungeonsguide.config.types.AColor;
+import kr.syeyoung.dungeonsguide.dungeon.actions.*;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.events.PlayerInteractEntityEvent;
+import lombok.Data;
+import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import net.minecraftforge.event.entity.living.LivingDeathEvent;
+import net.minecraftforge.event.entity.player.PlayerInteractEvent;
+
+import java.util.List;
+
+public class ActionRoute {
+ @Getter
+ private final String mechanic;
+ @Getter
+ private final String state;
+
+ @Getter
+ private int current;
+ @Getter
+ private final List<Action> actions;
+
+ private final DungeonRoom dungeonRoom;
+
+ @Getter
+ private final ActionRouteProperties actionRouteProperties;
+
+ public ActionRoute(DungeonRoom dungeonRoom, String mechanic, String state, ActionRouteProperties actionRouteProperties) {
+ this.mechanic = mechanic;
+ this.state = state;
+ this.actionRouteProperties = actionRouteProperties;
+
+ ActionChangeState actionChangeState = new ActionChangeState(mechanic, state);
+ ActionTree tree= ActionTree.buildActionTree(actionChangeState, dungeonRoom);
+ actions = ActionTreeUtil.linearifyActionTree(tree);
+ actions.add(new ActionComplete());
+ current = 0;
+ this.dungeonRoom = dungeonRoom;
+ }
+
+ public Action next() {
+ current ++;
+ if (current >= actions.size()) current = actions.size() - 1;
+ return actions.get(current);
+ }
+
+ public Action prev() {
+ current --;
+ if (current < 0) current = 0;
+ return actions.get(current);
+ }
+
+ public Action getCurrentAction() {
+ return actions.get(current);
+ }
+
+
+
+ public void onPlayerInteract(PlayerInteractEvent event) {
+ getCurrentAction().onPlayerInteract(dungeonRoom, event, actionRouteProperties );
+ }
+ public void onLivingDeath(LivingDeathEvent event) {
+ getCurrentAction().onLivingDeath(dungeonRoom, event, actionRouteProperties );
+ }
+ public void onRenderWorld(float partialTicks, boolean flag) {
+ if (current -1 >= 0 && (
+ (actions.get(current-1) instanceof ActionMove && ((ActionMove) actions.get(current-1)).getTarget().getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) >= 25)
+ || (actions.get(current-1) instanceof ActionMoveNearestAir && ((ActionMoveNearestAir) actions.get(current-1)).getTarget().getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) >= 25))) actions.get(current-1).onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag );
+ getCurrentAction().onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag);
+ }
+
+ public void onRenderScreen(float partialTicks) {
+ getCurrentAction().onRenderScreen(dungeonRoom, partialTicks, actionRouteProperties);
+ }
+
+ public void onTick() {
+ Action current = getCurrentAction();
+
+ current.onTick(dungeonRoom, actionRouteProperties);
+ if (this.current -1 >= 0 && (actions.get(this.current-1) instanceof ActionMove || actions.get(this.current-1) instanceof ActionMoveNearestAir)) actions.get(this.current-1).onTick(dungeonRoom, actionRouteProperties );
+
+ if (dungeonRoom.getMechanics().get(mechanic).getCurrentState(dungeonRoom).equals(state)) {
+ this.current = actions.size() - 1;
+ }
+
+ if (current.isComplete(dungeonRoom))
+ next();
+ }
+
+ public void onLivingInteract(PlayerInteractEntityEvent event) { getCurrentAction().onLivingInteract(dungeonRoom, event, actionRouteProperties ); }
+
+ @Data
+ public static class ActionRouteProperties {
+ private boolean pathfind;
+ private int lineRefreshRate;
+ private AColor lineColor;
+ private float lineWidth;
+
+ private boolean beacon;
+ private AColor beaconColor;
+ private AColor beaconBeamColor;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java
new file mode 100755
index 00000000..0fdb97f6
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTree.java
@@ -0,0 +1,83 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions.tree;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionRoot;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+@Data
+public class ActionTree implements Cloneable {
+ @EqualsAndHashCode.Exclude
+ private Set<ActionTree> parent;
+ private Action current;
+ private Set<ActionTree> children;
+
+ @Override
+ public int hashCode() { return current == null ? 0 : current.hashCode(); }
+
+
+ public static ActionTree buildActionTree(Set<Action> actions, DungeonRoom dungeonRoom) {
+ ActionRoot root = new ActionRoot();
+ root.setPreRequisite(actions);
+ ActionTree tree = new ActionTree();
+ tree.setParent(new HashSet<ActionTree>());
+ tree.setCurrent(root);
+ HashSet<ActionTree> set = new HashSet();
+ for (Action action : actions) {
+ set.add(buildActionTree(tree, action, dungeonRoom, new HashMap<Action, ActionTree>()));
+ }
+ tree.setChildren(set);
+ return tree;
+ }
+ public static ActionTree buildActionTree(Action actions, DungeonRoom dungeonRoom) {
+ return buildActionTree(null, actions, dungeonRoom, new HashMap<Action, ActionTree>());
+ }
+
+
+
+ private static ActionTree buildActionTree(ActionTree parent, Action action, DungeonRoom dungeonRoom, Map<Action, ActionTree> alreadyBuilt) {
+ if (action == null) return null;
+ if (alreadyBuilt.containsKey(action)) {
+ ActionTree tree = alreadyBuilt.get(action);
+ tree.getParent().add(parent);
+ return tree;
+ }
+
+ ActionTree tree = new ActionTree();
+ alreadyBuilt.put(action, tree);
+ tree.setParent(new HashSet<ActionTree>());
+ if (parent != null)
+ tree.getParent().add(parent);
+ tree.setCurrent(action);
+ HashSet<ActionTree> set = new HashSet();
+ for (Action action2 : action.getPreRequisites(dungeonRoom)) {
+ set.add(buildActionTree(tree, action2, dungeonRoom, alreadyBuilt));
+ }
+ tree.setChildren(set);
+ return tree;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java
new file mode 100644
index 00000000..4054f00d
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/actions/tree/ActionTreeUtil.java
@@ -0,0 +1,83 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.actions.tree;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+
+import java.util.*;
+
+public class ActionTreeUtil {
+ public static List<Action> linearifyActionTree(ActionTree input) {
+ ActionTree tree = copyActionTree(input);
+
+ List<Action> actions = new ArrayList<Action>();
+
+ int plsHalt = 0;
+ while (tree.getChildren().size() != 0) {
+ plsHalt ++;
+ if (plsHalt > 1000000) throw new IllegalStateException("Linearifying process ran for 1 million cycle");
+ Set<ActionTree> visited = new HashSet<ActionTree>();
+ ActionTree curr = tree;
+
+ int plsHalt2 = 0;
+ while (curr.getChildren().size() != 0) {
+ plsHalt2 ++;
+ if (plsHalt2 > 1000000) throw new IllegalStateException("Finding the leaf of tree ran for 1 million cycles");
+ if (visited.contains(curr)) throw new IllegalStateException("Circular Reference Detected");
+ visited.add(curr);
+ curr = curr.getChildren().iterator().next();
+ }
+
+ plsHalt2 =0;
+ while(curr.getChildren().size() == 0) {
+ plsHalt2 ++;
+ if (plsHalt2 > 1000000) throw new IllegalStateException("Building of array ran for 1 million cycles");
+
+ actions.add(curr.getCurrent());
+ if (curr.getParent().size() == 0) break;
+ for (ActionTree parentTree:curr.getParent())
+ parentTree.getChildren().remove(curr);
+ curr = curr.getParent().iterator().next();
+ }
+ }
+ return actions;
+ }
+
+ public static ActionTree copyActionTree(ActionTree tree) {
+ Map<ActionTree, ActionTree> built = new HashMap<ActionTree, ActionTree>();
+ if (tree.getParent().size() != 0) throw new IllegalArgumentException("that is not head of tree");
+ return copyActionTree(tree, built);
+ }
+ private static ActionTree copyActionTree(ActionTree tree, Map<ActionTree, ActionTree> preBuilts) {
+ if (preBuilts.containsKey(tree)) return preBuilts.get(tree);
+
+ ActionTree clone = new ActionTree();
+ preBuilts.put(tree, clone);
+
+ clone.setCurrent(tree.getCurrent());
+ clone.setParent(new HashSet<ActionTree>());
+ clone.setChildren(new HashSet<ActionTree>());
+ for (ActionTree tree3 : tree.getChildren()) {
+ ActionTree clone3 = copyActionTree(tree3, preBuilts);
+ clone3.getParent().add(clone);
+ clone.getChildren().add(clone3);
+ }
+ return clone;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java
new file mode 100755
index 00000000..ef25fbe1
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java
@@ -0,0 +1,60 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.data;
+
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+@Getter
+@Setter
+public class DungeonRoomInfo implements Serializable {
+ private static final long serialVersionUID = -8291811286448196640L;
+
+ public DungeonRoomInfo(short shape, byte color) {
+ this.uuid = UUID.randomUUID();
+ this.name = this.uuid.toString();
+ this.shape = shape;
+ this.color = color;
+ }
+
+ private transient boolean registered;
+
+ private boolean isUserMade = false;
+
+ private short shape;
+ private byte color;
+
+ private int[][] blocks;
+
+ private UUID uuid;
+ private String name;
+
+ private String processorId = "default";
+
+ private Map<String, Object> properties = new HashMap<String, Object>();
+
+ private Map<String, DungeonMechanic> mechanics = new HashMap<String, DungeonMechanic>();
+ private int totalSecrets = -1;
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java
new file mode 100755
index 00000000..180dd76d
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java
@@ -0,0 +1,110 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.data;
+
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.VectorUtils;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import net.minecraft.block.Block;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.Vec3;
+
+import javax.vecmath.Vector2d;
+import java.io.Serializable;
+
+@Data
+@AllArgsConstructor
+public class OffsetPoint implements Cloneable, Serializable {
+ private static final long serialVersionUID = 3102336358774967540L;
+
+ private int x;
+ private int y;
+ private int z;
+
+ public OffsetPoint(DungeonRoom dungeonRoom, BlockPos pos) {
+ setPosInWorld(dungeonRoom, pos);
+ }
+ public OffsetPoint(DungeonRoom dungeonRoom, Vec3 pos) {
+ setPosInWorld(dungeonRoom, new BlockPos((int)pos.xCoord, (int)pos.yCoord, (int)pos.zCoord));
+ }
+
+
+ public void setPosInWorld(DungeonRoom dungeonRoom, BlockPos pos) {
+ Vector2d vector2d = new Vector2d(pos.getX() - dungeonRoom.getMin().getX(), pos.getZ() - dungeonRoom.getMin().getZ());
+ for (int i = 0; i < dungeonRoom.getRoomMatcher().getRotation(); i++) {
+ vector2d = VectorUtils.rotateClockwise(vector2d);
+ if (i % 2 == 0) {
+ vector2d.x += dungeonRoom.getDungeonRoomInfo().getBlocks()[0].length - 1; // + Z
+ } else {
+ vector2d.x += dungeonRoom.getDungeonRoomInfo().getBlocks().length - 1; // + X
+ }
+ }
+
+ this.x = (int) vector2d.x;
+ this.z = (int) vector2d.y;
+ this.y = pos.getY()-dungeonRoom.getMin().getY();
+ }
+
+ public BlockPos toRotatedRelBlockPos(DungeonRoom dungeonRoom) {
+ int rot = dungeonRoom.getRoomMatcher().getRotation();
+ Vector2d rot2 = new Vector2d(x,z);
+ for (int i = 0; i < dungeonRoom.getRoomMatcher().getRotation(); i++) {
+ rot2 = VectorUtils.rotateCounterClockwise(rot2);
+ if (i % 2 == 0) {
+ rot2.y += dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() + 1; // + Z
+ } else {
+ rot2.y += dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1; // + X
+ }
+ }
+
+ return new BlockPos(rot2.x, y, rot2.y);
+ }
+
+ public Block getBlock(DungeonRoom dungeonRoom) {
+ BlockPos relBp = toRotatedRelBlockPos(dungeonRoom);
+
+ Block b = dungeonRoom.getRelativeBlockAt(relBp.getX(), relBp.getY(), relBp.getZ());
+ return b;
+ }
+ public BlockPos getBlockPos(DungeonRoom dungeonRoom) {
+ BlockPos relBp = toRotatedRelBlockPos(dungeonRoom);
+ return dungeonRoom.getRelativeBlockPosAt(relBp.getX(), relBp.getY(), relBp.getZ());
+ }
+
+ public int getData(DungeonRoom dungeonRoom) {
+ BlockPos relBp = toRotatedRelBlockPos(dungeonRoom);
+
+ int b = dungeonRoom.getRelativeBlockDataAt(relBp.getX(), relBp.getY(), relBp.getZ());
+ return b;
+ }
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ return new OffsetPoint(x,y,z);
+ }
+
+ @Override
+ public String toString() {
+ return "OffsetPoint{x=" + x +
+ ", y=" + y +
+ ", z=" + z +
+ '}';
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java
new file mode 100755
index 00000000..c674fdbc
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java
@@ -0,0 +1,39 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.data;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+@Data
+public class OffsetPointSet implements Cloneable, Serializable {
+ private List<OffsetPoint> offsetPointList = new ArrayList<OffsetPoint>();
+
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ OffsetPointSet ops = new OffsetPointSet();
+ for (OffsetPoint offsetPoint : offsetPointList) {
+ ops.offsetPointList.add((OffsetPoint) offsetPoint.clone());
+ }
+ return ops;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java
new file mode 100755
index 00000000..39eacbc1
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombDataProvider.java
@@ -0,0 +1,172 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.doorfinder;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.*;
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.*;
+import net.minecraft.entity.item.EntityArmorStand;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.world.World;
+
+import javax.vecmath.Vector2d;
+import java.util.Collection;
+import java.util.Set;
+
+public class CatacombDataProvider implements DungeonSpecificDataProvider {
+
+ private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,1), new Vector2d(0, -1), new Vector2d(1, 0), new Vector2d(-1 , 0));
+
+ @Override
+ public BlockPos findDoor(World w, String dungeonName) {
+ Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() {
+ @Override
+ public boolean apply(EntityArmorStand input) {
+ return input.getName().equals("§bMort");
+ }
+ });
+
+ if (armorStand.size() != 0) {
+ EntityArmorStand mort = armorStand.iterator().next();
+ BlockPos pos = mort.getPosition();
+ pos = pos.add(0, 3, 0);
+ for (int i = 0; i < 5; i++) {
+ for (Vector2d vector2d:directions) {
+ BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i);
+ if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) {
+ return pos.add(vector2d.x * (i + 2), -2, vector2d.y * (i+2));
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Vector2d findDoorOffset(World w, String dungeonName) {
+ Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() {
+ @Override
+ public boolean apply(EntityArmorStand input) {
+ return input.getName().equals("§bMort");
+ }
+ });
+
+ if (armorStand.size() != 0) {
+ EntityArmorStand mort = armorStand.iterator().next();
+ BlockPos pos = mort.getPosition();
+ pos = pos.add(0, 3, 0);
+ for (int i = 0; i < 5; i++) {
+ for (Vector2d vector2d:directions) {
+ BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i);
+ if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) {
+ return vector2d;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ /*
+ *
+ * */
+
+ @Override
+ public BossfightProcessor createBossfightProcessor(World w, String dungeonName) {
+ String floor = dungeonName.substring(14).trim();
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Floor: "+floor+ " Building bossfight processor"));
+ if (floor.equals("F1")) {
+ return new BossfightProcessorBonzo();
+ } else if (floor.equals("F2")) {
+ return new BossfightProcessorScarf();
+ } else if (floor.equals("F3")) {
+ return new BossfightProcessorProf();
+ } else if (floor.equals("F4")) {
+ return new BossfightProcessorThorn();
+ } else if (floor.equals("F5")) {
+ return new BossfightProcessorLivid(false);
+ } else if (floor.equals("F6")) {
+ return new BossfightProcessorSadan();
+ } else if (floor.equals("F7")) {
+ return new BossfightProcessorNecron();
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isTrapSpawn(String dungeonName) {
+ String floor = dungeonName.substring(14).trim();
+ if (floor.equals("F3")) {
+ return true;
+ } else if (floor.equals("F4")) {
+ return true;
+ } else if (floor.equals("F5")) {
+ return true;
+ } else if (floor.equals("F6")) {
+ return true;
+ } else return floor.equals("F7");
+ }
+
+ @Override
+ public double secretPercentage(String dungeonName) {
+ String floor = dungeonName.substring(14).trim();
+ if (floor.equals("F1")) {
+ return 0.3;
+ } else if (floor.equals("F2")) {
+ return 0.4;
+ } else if (floor.equals("F3")) {
+ return 0.5;
+ } else if (floor.equals("F4")) {
+ return 0.6;
+ } else if (floor.equals("F5")) {
+ return 0.7;
+ } else if (floor.equals("F6")) {
+ return 0.85;
+ } else if (floor.equals("F7")) {
+ return 1.0;
+ } else if (floor.equals("E")) {
+ return 0.3;
+ }
+ return 1.0;
+ }
+
+ @Override
+ public int speedSecond(String dungeonName) {
+ String floor = dungeonName.substring(14).trim();
+ if (floor.equals("F1")) {
+ return 600;
+ } else if (floor.equals("F2")) {
+ return 600;
+ } else if (floor.equals("F3")) {
+ return 600;
+ } else if (floor.equals("F4")) {
+ return 600;
+ } else if (floor.equals("F5")) {
+ return 720;
+ } else if (floor.equals("F6")) {
+ return 600;
+ } else if (floor.equals("F7")) {
+ return 720;
+ }
+ return 600;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java
new file mode 100755
index 00000000..9d1f63b9
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/CatacombMasterDataProvider.java
@@ -0,0 +1,127 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.doorfinder;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.*;
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor;
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessorLivid;
+import net.minecraft.entity.item.EntityArmorStand;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.world.World;
+
+import javax.vecmath.Vector2d;
+import java.util.Collection;
+import java.util.Set;
+
+public class CatacombMasterDataProvider implements DungeonSpecificDataProvider {
+
+ private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,1), new Vector2d(0, -1), new Vector2d(1, 0), new Vector2d(-1 , 0));
+
+ @Override
+ public BlockPos findDoor(World w, String dungeonName) {
+ Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() {
+ @Override
+ public boolean apply(EntityArmorStand input) {
+ return input.getName().equals("§bMort");
+ }
+ });
+
+ if (armorStand.size() != 0) {
+ EntityArmorStand mort = armorStand.iterator().next();
+ BlockPos pos = mort.getPosition();
+ pos = pos.add(0, 3, 0);
+ for (int i = 0; i < 5; i++) {
+ for (Vector2d vector2d:directions) {
+ BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i);
+ if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) {
+ return pos.add(vector2d.x * (i + 2), -2, vector2d.y * (i+2));
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Vector2d findDoorOffset(World w, String dungeonName) {
+ Collection<EntityArmorStand> armorStand = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() {
+ @Override
+ public boolean apply(EntityArmorStand input) {
+ return input.getName().equals("§bMort");
+ }
+ });
+
+ if (armorStand.size() != 0) {
+ EntityArmorStand mort = armorStand.iterator().next();
+ BlockPos pos = mort.getPosition();
+ pos = pos.add(0, 3, 0);
+ for (int i = 0; i < 5; i++) {
+ for (Vector2d vector2d:directions) {
+ BlockPos test = pos.add(vector2d.x * i, 0, vector2d.y * i);
+ if (w.getChunkFromBlockCoords(test).getBlock(test) == Blocks.iron_bars) {
+ return vector2d;
+ }
+ }
+ }
+ }
+ return null;
+ }
+ /*
+ *
+ * */
+
+ @Override
+ public BossfightProcessor createBossfightProcessor(World w, String dungeonName) {
+ String floor = dungeonName.substring(14).trim();
+ DungeonsGuide.sendDebugChat(new ChatComponentText("Floor: Master mode "+floor+ " Building bossfight processor"));
+ if (floor.equals("M5")) {
+ return new BossfightProcessorLivid(true);
+ }
+ return null;
+ }
+
+ @Override
+ public boolean isTrapSpawn(String dungeonName) {
+ String floor = dungeonName.substring(14).trim();
+ if (floor.equals("M3")) {
+ return true;
+ } else if (floor.equals("M4")) {
+ return true;
+ } else if (floor.equals("M5")) {
+ return true;
+ } else if (floor.equals("M6")) {
+ return true;
+ } else return floor.equals("M7");
+ }
+
+ @Override
+ public double secretPercentage(String dungeonName) {
+ return 1.0;
+ }
+
+ @Override
+ public int speedSecond(String dungeonName) {
+ return 480;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java
new file mode 100755
index 00000000..d0b61120
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonDoor.java
@@ -0,0 +1,81 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.doorfinder;
+
+import com.google.common.collect.Sets;
+import lombok.Getter;
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+
+import java.util.Set;
+
+@Getter
+public class DungeonDoor {
+ private final World w;
+ private final BlockPos position;
+ private EDungeonDoorType type;
+ private boolean isZDir;
+
+ private static final Set<Block> legalBlocks = Sets.newHashSet(Blocks.coal_block, Blocks.barrier, Blocks.monster_egg, Blocks.air, Blocks.stained_hardened_clay);
+
+ public DungeonDoor(World world, BlockPos pos, EDungeonDoorType type) {
+ this.w = world;
+ this.position = pos;
+ Block itshouldbeall = world.getChunkFromBlockCoords(pos).getBlock(pos);
+
+ if (type == EDungeonDoorType.WITHER && itshouldbeall == Blocks.air) type = EDungeonDoorType.WITHER_FAIRY;
+ this.type = type;
+ boolean exist = type.isExist();
+
+ for (int x = -1; x<=1; x++)
+ for (int y = -1; y<=1; y++)
+ for (int z = -1; z<=1; z++) {
+ BlockPos pos2 = pos.add(x,y,z);
+ Block block = world.getChunkFromBlockCoords(pos2).getBlock(pos2);
+ if (itshouldbeall != block) exist = false;
+ }
+ if (exist) {
+ BlockPos ZCheck = pos.add(0,0,2);
+ isZDir = world.getChunkFromBlockCoords(ZCheck).getBlock(ZCheck) == Blocks.air;
+
+ if (isZDir) {
+ for (int x = -1; x<=1; x++)
+ for (int y = -1; y<=1; y++)
+ for (int z = -2; z<=2; z+=4) {
+ BlockPos pos2 = pos.add(x,y,z);
+ Block block = world.getChunkFromBlockCoords(pos2).getBlock(pos2);
+ if (block != Blocks.air) exist = false;
+ }
+ } else {
+ for (int x = -2; x<=2; x+=4)
+ for (int y = -1; y<=1; y++)
+ for (int z = -1; z<=1; z++) {
+ BlockPos pos2 = pos.add(x,y,z);
+ Block block = world.getChunkFromBlockCoords(pos2).getBlock(pos2);
+ if (block != Blocks.air) exist = false;
+ }
+ }
+ }
+ if (!exist) {
+ isZDir = false;
+ }
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java
new file mode 100755
index 00000000..4145188c
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProvider.java
@@ -0,0 +1,38 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.doorfinder;
+
+import kr.syeyoung.dungeonsguide.roomprocessor.bossfight.BossfightProcessor;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+
+import javax.vecmath.Vector2d;
+
+public interface DungeonSpecificDataProvider {
+ BlockPos findDoor(World w, String dungeonName);
+ Vector2d findDoorOffset(World w, String dungeonName);
+
+ BossfightProcessor createBossfightProcessor(World w, String dungeonName);
+
+ boolean isTrapSpawn(String dungeonName);
+
+ double secretPercentage(String dungeonName);
+
+ int speedSecond(String dungeonName);
+} \ No newline at end of file
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java
new file mode 100755
index 00000000..7421728e
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java
@@ -0,0 +1,39 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.doorfinder;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Pattern;
+
+public class DungeonSpecificDataProviderRegistry {
+ public static final Map<Pattern, DungeonSpecificDataProvider> doorFinders = new HashMap<Pattern, DungeonSpecificDataProvider>();
+
+ static {
+ doorFinders.put(Pattern.compile("The Catacombs (?:F[0-9]|E)"), new CatacombDataProvider());
+ doorFinders.put(Pattern.compile("The Catacombs (?:M[0-9])"), new CatacombMasterDataProvider());
+ }
+
+ public static DungeonSpecificDataProvider getDoorFinder(String dungeonName) {
+ for (Map.Entry<Pattern, DungeonSpecificDataProvider> doorFinderEntry :doorFinders.entrySet()){
+ if (doorFinderEntry.getKey().matcher(dungeonName).matches()) return doorFinderEntry.getValue();
+ }
+ return null;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java
new file mode 100644
index 00000000..3a07629e
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/EDungeonDoorType.java
@@ -0,0 +1,33 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.doorfinder;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+@AllArgsConstructor
+@Getter
+public enum EDungeonDoorType {
+ NONE(false, false, false,"?"), ENTRANCE(true, false, false, "entrance"), WITHER(true, true,true,"withergate"),WITHER_FAIRY(true, false,true,"wither-fairy-gate"), BLOOD(true, true,true, "bloodgate"), UNOPEN(true, false, false,"gate");
+
+ private boolean exist;
+ private boolean keyRequired;
+ private boolean headToBlood;
+ private String name;
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java
new file mode 100644
index 00000000..9e16498b
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonCryptBrokenEvent.java
@@ -0,0 +1,34 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class DungeonCryptBrokenEvent implements DungeonEventData {
+ private int prevCrypts;
+ private int newCrypts;
+
+ @Override
+ public String getEventName() {
+ return "CRYPTS_CHANGE";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java
new file mode 100644
index 00000000..bbb2481d
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonDeathEvent.java
@@ -0,0 +1,35 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class DungeonDeathEvent implements DungeonEventData {
+ private String playerName;
+ private String message;
+ private int cnt;
+
+ @Override
+ public String getEventName() {
+ return "PLAYER_DEATH";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java
new file mode 100644
index 00000000..a62997bf
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEvent.java
@@ -0,0 +1,41 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+public class DungeonEvent implements Serializable {
+ private long UTCTime = System.currentTimeMillis();
+ private long realTimeElapsed;
+ private long skyblockTimeElapsed;
+
+ private String eventName;
+ private DungeonEventData data;
+
+ public DungeonEvent(DungeonEventData eventData){
+ this.data = eventData;
+ this.realTimeElapsed = FeatureRegistry.DUNGEON_REALTIME.getTimeElapsed();
+ this.skyblockTimeElapsed = FeatureRegistry.DUNGEON_SBTIME.getTimeElapsed();
+ this.eventName = eventData.getEventName();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java
new file mode 100644
index 00000000..a75d0f02
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventData.java
@@ -0,0 +1,25 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import java.io.Serializable;
+
+public interface DungeonEventData extends Serializable {
+ String getEventName();
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java
new file mode 100644
index 00000000..3e431107
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonEventHolder.java
@@ -0,0 +1,32 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.Set;
+
+@Data
+public class DungeonEventHolder implements Serializable {
+ private long date;
+ private Set<String> players;
+ private List<DungeonEvent> eventDataList;
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java
new file mode 100644
index 00000000..a29d2f01
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonMapUpdateEvent.java
@@ -0,0 +1,33 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class DungeonMapUpdateEvent implements DungeonEventData {
+ private byte[] map;
+
+ @Override
+ public String getEventName() {
+ return "MAP_UPDATE";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java
new file mode 100644
index 00000000..4db127d6
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonNodataEvent.java
@@ -0,0 +1,28 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class DungeonNodataEvent implements DungeonEventData {
+ private String eventName;
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java
new file mode 100644
index 00000000..88d6377f
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonPuzzleFailureEvent.java
@@ -0,0 +1,33 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class DungeonPuzzleFailureEvent implements DungeonEventData {
+ private String playerName;
+ private String message;
+ @Override
+ public String getEventName() {
+ return "PUZZLE_FAILURE";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java
new file mode 100644
index 00000000..8cec640c
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonRoomDiscoverEvent.java
@@ -0,0 +1,44 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.awt.*;
+import java.util.UUID;
+
+@Data
+@AllArgsConstructor
+public class DungeonRoomDiscoverEvent implements DungeonEventData {
+ private Point unitPt;
+ private int rotation;
+ private SerializableBlockPos min;
+ private SerializableBlockPos max;
+ private int shape;
+ private int color;
+ private UUID roomUID;
+ private String roomName;
+ private String roomProc;
+
+ @Override
+ public String getEventName() {
+ return "ROOM_DISCOVER";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java
new file mode 100644
index 00000000..702d61ba
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonSecretCountChangeEvent.java
@@ -0,0 +1,36 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class DungeonSecretCountChangeEvent implements DungeonEventData {
+ private int prevCount;
+ private int newCount;
+ private int totalSecret;
+ private boolean sureTotalSecret;
+
+ @Override
+ public String getEventName() {
+ return "SECRET_CNT_CHANGE";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java
new file mode 100644
index 00000000..16cb9661
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/DungeonStateChangeEvent.java
@@ -0,0 +1,39 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+import java.awt.*;
+
+@Data
+@AllArgsConstructor
+public class DungeonStateChangeEvent implements DungeonEventData {
+ private Point unitPt;
+ private String roomName;
+ private DungeonRoom.RoomState from;
+ private DungeonRoom.RoomState to;
+
+ @Override
+ public String getEventName() {
+ return "ROOM_STATE_CHANGE";
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java
new file mode 100644
index 00000000..ab1031e7
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/events/SerializableBlockPos.java
@@ -0,0 +1,36 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.events;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.io.Serializable;
+
+@Data @AllArgsConstructor
+public class SerializableBlockPos implements Serializable {
+ private int x, y, z;
+
+ public SerializableBlockPos(BlockPos pos) {
+ this.x = pos.getX();
+ this.y = pos.getY();
+ this.z = pos.getZ();
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java
new file mode 100755
index 00000000..9f11cde9
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonBreakableWall.java
@@ -0,0 +1,157 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionBreakWithSuperBoom;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+@Data
+public class DungeonBreakableWall implements DungeonMechanic, RouteBlocker {
+ private static final long serialVersionUID = 1161593374765852217L;
+ private OffsetPointSet secretPoint = new OffsetPointSet();
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+
+ int leastY = Integer.MAX_VALUE;
+ OffsetPoint thatPt = null;
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getY() < leastY) {
+ thatPt = offsetPoint;
+ leastY = offsetPoint.getY();
+ }
+ }
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(thatPt);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+
+ if (!"open".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for breakable wall");
+ if (!isBlocking(dungeonRoom)) {
+ return Collections.emptySet();
+ }
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionBreakWithSuperBoom actionClick;
+ preRequisites.add(actionClick = new ActionBreakWithSuperBoom(getRepresentingPoint(dungeonRoom)));
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+
+ int leastY = Integer.MAX_VALUE;
+ OffsetPoint thatPt = null;
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getY() < leastY) {
+ thatPt = offsetPoint;
+ leastY = offsetPoint.getY();
+ }
+ }
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(thatPt);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ if (secretPoint.getOffsetPointList().isEmpty()) return;
+ OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0);
+ BlockPos pos = firstpt.getBlockPos(dungeonRoom);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks);
+ }
+ }
+
+ @Override
+ public boolean isBlocking(DungeonRoom dungeonRoom) {
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true;
+ }
+ return false;
+ }
+
+ public DungeonBreakableWall clone() throws CloneNotSupportedException {
+ DungeonBreakableWall dungeonSecret = new DungeonBreakableWall();
+ dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ Block b = Blocks.air;
+ if (!secretPoint.getOffsetPointList().isEmpty())
+ b = secretPoint.getOffsetPointList().get(0).getBlock(dungeonRoom);
+
+ return b == Blocks.air ?"open" :"closed";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return isBlocking(dungeonRoom) ? Sets.newHashSet("navigate", "open") : Sets.newHashSet("navigate");
+ }
+
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("open", "closed");
+ }
+
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint.getOffsetPointList().size() == 0 ? null : secretPoint.getOffsetPointList().get(secretPoint.getOffsetPointList().size() / 2);
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java
new file mode 100755
index 00000000..79ab6fcf
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDoor.java
@@ -0,0 +1,129 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.List;
+import java.util.*;
+
+@Data
+public class DungeonDoor implements DungeonMechanic, RouteBlocker {
+ private static final long serialVersionUID = -1011605722415475761L;
+ private OffsetPointSet secretPoint = new OffsetPointSet();
+ private List<String> openPreRequisite = new ArrayList<String>();
+ private List<String> closePreRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (!("open".equalsIgnoreCase(state) || "closed".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for door");
+ if (state.equalsIgnoreCase(getCurrentState(dungeonRoom))) return Collections.emptySet();
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ if (state.equalsIgnoreCase("open")) {
+ for (String str : openPreRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ } else {
+ for (String str : closePreRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ if (secretPoint.getOffsetPointList().isEmpty()) return;
+ OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0);
+ BlockPos pos = firstpt.getBlockPos(dungeonRoom);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks);
+ }
+ }
+
+ @Override
+ public boolean isBlocking(DungeonRoom dungeonRoom) {
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true;
+ }
+ return false;
+ }
+
+ public DungeonDoor clone() throws CloneNotSupportedException {
+ DungeonDoor dungeonSecret = new DungeonDoor();
+ dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone();
+ dungeonSecret.openPreRequisite = new ArrayList<String>(openPreRequisite);
+ dungeonSecret.closePreRequisite = new ArrayList<String>(closePreRequisite);
+ return dungeonSecret;
+ }
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return isBlocking(dungeonRoom) ?"closed":"open";
+ }
+
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ String currentStatus = getCurrentState(dungeonRoom);
+ if (currentStatus.equalsIgnoreCase("closed"))
+ return Collections.singleton("open");
+ else if (currentStatus.equalsIgnoreCase("open"))
+ return Collections.singleton("closed");
+ return Collections.emptySet();
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("open", "closed");
+ }
+
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ int leastY = Integer.MAX_VALUE;
+ OffsetPoint thatPt = null;
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getY() < leastY) {
+ thatPt = offsetPoint;
+ leastY = offsetPoint.getY();
+ }
+ }
+ return thatPt;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java
new file mode 100755
index 00000000..79f079c1
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonDummy.java
@@ -0,0 +1,108 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionClick;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Data
+public class DungeonDummy implements DungeonMechanic {
+ private static final long serialVersionUID = -8449664812034435765L;
+ private OffsetPoint secretPoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+// if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ if (state.equalsIgnoreCase("navigate")){
+ ActionMove actionMove = new ActionMove(secretPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ } else if (state.equalsIgnoreCase("click")) {
+ ActionClick actionClick = new ActionClick(secretPoint);
+ preRequisites.add(actionClick);
+ preRequisites = actionClick.getPreRequisite();
+
+ ActionMove actionMove = new ActionMove(secretPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld("D-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+
+ public DungeonDummy clone() throws CloneNotSupportedException {
+ DungeonDummy dungeonSecret = new DungeonDummy();
+ dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return "no-state";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("navigate", "click");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("no-state","navigate,click");
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java
new file mode 100755
index 00000000..1c110bb5
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonFairySoul.java
@@ -0,0 +1,105 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionInteract;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates.PredicateArmorStand;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.List;
+import java.util.*;
+
+@Data
+public class DungeonFairySoul implements DungeonMechanic {
+ private static final long serialVersionUID = 156412742320519783L;
+ private OffsetPoint secretPoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionInteract actionClick= new ActionInteract(secretPoint);
+ actionClick.setPredicate(PredicateArmorStand.INSTANCE);
+ actionClick.setRadius(3);
+ preRequisites.add(actionClick);
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+ ActionMove actionMove = new ActionMove(secretPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld("F-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+
+ public DungeonFairySoul clone() throws CloneNotSupportedException {
+ DungeonFairySoul dungeonSecret = new DungeonFairySoul();
+ dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return "no-state";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("no-state","navigate");
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java
new file mode 100755
index 00000000..f0edc4a6
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonJournal.java
@@ -0,0 +1,98 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Data
+public class DungeonJournal implements DungeonMechanic {
+ private static final long serialVersionUID = 4117372070037496743L;
+ private OffsetPoint secretPoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionMove actionMove = new ActionMove(secretPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld("J-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+
+ public DungeonJournal clone() throws CloneNotSupportedException {
+ DungeonJournal dungeonSecret = new DungeonJournal();
+ dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return "no-state";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("no-state","navigate");
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java
new file mode 100755
index 00000000..5bc1f650
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonLever.java
@@ -0,0 +1,130 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.*;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.List;
+import java.util.*;
+
+@Data
+public class DungeonLever implements DungeonMechanic {
+ private OffsetPoint leverPoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+ private String triggering = "";
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equals(getCurrentState(dungeonRoom))) return Collections.emptySet();
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+
+ if (!("triggered".equalsIgnoreCase(state) || "untriggered".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ if (!state.equalsIgnoreCase(getCurrentState(dungeonRoom))){
+ ActionClick actionClick;
+ preRequisites.add(actionClick = new ActionClick(leverPoint));
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+ ActionMove actionMove = new ActionMove(leverPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getLeverPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+ public DungeonLever clone() throws CloneNotSupportedException {
+ DungeonLever dungeonSecret = new DungeonLever();
+ dungeonSecret.leverPoint = (OffsetPoint) leverPoint.clone();
+ dungeonSecret.triggering = triggering;
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ if (triggering == null) triggering = "null";
+ DungeonMechanic mechanic = dungeonRoom.getMechanics().get(triggering);
+ if (mechanic == null)
+ {
+ return "undeterminable";
+ } else {
+ String state = mechanic.getCurrentState(dungeonRoom);
+ if ("open".equalsIgnoreCase(state)) {
+ return "triggered";
+ } else {
+ return "untriggered";
+ }
+ }
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ String currentStatus = getCurrentState(dungeonRoom);
+ if (currentStatus.equalsIgnoreCase("untriggered"))
+ return Sets.newHashSet("navigate", "triggered");
+ else if (currentStatus.equalsIgnoreCase("triggered"))
+ return Sets.newHashSet("navigate","untriggered");
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("triggered", "untriggered");
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return leverPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java
new file mode 100755
index 00000000..677a5489
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonMechanic.java
@@ -0,0 +1,40 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+
+import java.awt.*;
+import java.io.Serializable;
+import java.util.Set;
+
+public interface DungeonMechanic extends Serializable {
+ Set<Action> getAction(String state, DungeonRoom dungeonRoom);
+
+ void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks);
+
+ String getCurrentState(DungeonRoom dungeonRoom);
+
+ Set<String> getPossibleStates(DungeonRoom dungeonRoom);
+ Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom);
+
+ OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom);
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java
new file mode 100755
index 00000000..e1fc4bfc
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonNPC.java
@@ -0,0 +1,107 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionInteract;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates.PredicateArmorStand;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+@Data
+public class DungeonNPC implements DungeonMechanic {
+ private static final long serialVersionUID = -89487601113028763L;
+ private OffsetPoint secretPoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionInteract actionClick= new ActionInteract(secretPoint);
+ actionClick.setPredicate(PredicateArmorStand.INSTANCE);
+ actionClick.setRadius(3);
+ preRequisites.add(actionClick);
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+ ActionMove actionMove = new ActionMove(secretPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld("F-"+name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+
+ public DungeonNPC clone() throws CloneNotSupportedException {
+ DungeonNPC dungeonSecret = new DungeonNPC();
+ dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return "no-state";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("no-state","navigate");
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java
new file mode 100755
index 00000000..b97f84d0
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayDoor.java
@@ -0,0 +1,134 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.List;
+import java.util.*;
+
+@Data
+public class DungeonOnewayDoor implements DungeonMechanic, RouteBlocker {
+ private static final long serialVersionUID = -1810891721127873330L;
+ private OffsetPointSet secretPoint = new OffsetPointSet();
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+ if (!("open".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for door");
+ if (!isBlocking(dungeonRoom)) {
+ return Collections.emptySet();
+ }
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ if (secretPoint.getOffsetPointList().isEmpty()) return;
+ OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0);
+ BlockPos pos = firstpt.getBlockPos(dungeonRoom);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks);
+ }
+ }
+
+ @Override
+ public boolean isBlocking(DungeonRoom dungeonRoom) {
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true;
+ }
+ return false;
+ }
+
+ public DungeonOnewayDoor clone() throws CloneNotSupportedException {
+ DungeonOnewayDoor dungeonSecret = new DungeonOnewayDoor();
+ dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return isBlocking(dungeonRoom) ?"closed":"open";
+ }
+
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ String currentStatus = getCurrentState(dungeonRoom);
+ if (currentStatus.equalsIgnoreCase("closed"))
+ return Sets.newHashSet("navigate", "open");
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("open", "closed");
+ }
+
+
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ int leastY = Integer.MAX_VALUE;
+ OffsetPoint thatPt = null;
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getY() < leastY) {
+ thatPt = offsetPoint;
+ leastY = offsetPoint.getY();
+ }
+ }
+ return thatPt;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java
new file mode 100755
index 00000000..8403efca
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonOnewayLever.java
@@ -0,0 +1,129 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.*;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+@Data
+public class DungeonOnewayLever implements DungeonMechanic {
+ private static final long serialVersionUID = -3203171200265540652L;
+ private OffsetPoint leverPoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+ private String triggering = "";
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equals(getCurrentState(dungeonRoom))) return Collections.emptySet();
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+ if (!("triggered".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionClick actionClick;
+ preRequisites.add(actionClick = new ActionClick(leverPoint));
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+ ActionMove actionMove = new ActionMove(leverPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getLeverPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+ public DungeonOnewayLever clone() throws CloneNotSupportedException {
+ DungeonOnewayLever dungeonSecret = new DungeonOnewayLever();
+ dungeonSecret.leverPoint = (OffsetPoint) leverPoint.clone();
+ dungeonSecret.triggering = triggering;
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ if (triggering == null) triggering = "null";
+ DungeonMechanic mechanic = dungeonRoom.getMechanics().get(triggering);
+ if (mechanic == null)
+ {
+ return "undeterminable";
+ } else {
+ String state = mechanic.getCurrentState(dungeonRoom);
+ if ("open".equalsIgnoreCase(state)) {
+ return "triggered";
+ } else {
+ return "untriggered";
+ }
+ }
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ String currentStatus = getCurrentState(dungeonRoom);
+ if (currentStatus.equalsIgnoreCase("untriggered"))
+ return Sets.newHashSet("navigate", "triggered");
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("triggered", "untriggered");
+ }
+
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return leverPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java
new file mode 100755
index 00000000..8d79d924
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonPressurePlate.java
@@ -0,0 +1,132 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.*;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+@Data
+public class DungeonPressurePlate implements DungeonMechanic {
+ private static final long serialVersionUID = 7450034718355390645L;
+ private OffsetPoint platePoint = new OffsetPoint(0,0,0);
+ private List<String> preRequisite = new ArrayList<String>();
+ private String triggering = "";
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equals(getCurrentState(dungeonRoom))) return Collections.emptySet();
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+ if (!("triggered".equalsIgnoreCase(state) || "untriggered".equalsIgnoreCase(state))) throw new IllegalArgumentException(state+" is not valid state for secret");
+ if (state.equalsIgnoreCase(getCurrentState(dungeonRoom))) return Collections.emptySet();
+
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ if ("triggered".equalsIgnoreCase(state)) {
+ ActionDropItem actionClick;
+ preRequisites.add(actionClick = new ActionDropItem(platePoint));
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+ ActionMove actionMove = new ActionMove(platePoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getPlatePoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+ public DungeonPressurePlate clone() throws CloneNotSupportedException {
+ DungeonPressurePlate dungeonSecret = new DungeonPressurePlate();
+ dungeonSecret.platePoint = (OffsetPoint) platePoint.clone();
+ dungeonSecret.triggering = triggering;
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ if (triggering == null) triggering = "null";
+ DungeonMechanic mechanic = dungeonRoom.getMechanics().get(triggering);
+ if (mechanic == null)
+ {
+ return "undeterminable";
+ } else {
+ String state = mechanic.getCurrentState(dungeonRoom);
+ if ("open".equalsIgnoreCase(state)) {
+ return "triggered";
+ } else {
+ return "untriggered";
+ }
+ }
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ String currentStatus = getCurrentState(dungeonRoom);
+ if (currentStatus.equalsIgnoreCase("triggered"))
+ return Sets.newHashSet("navigate", "untriggered");
+ else if (currentStatus.equalsIgnoreCase("untriggered"))
+ return Sets.newHashSet("navigate", "triggered");
+ return Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("triggered", "untriggered");
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return platePoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java
new file mode 100644
index 00000000..6b0d58f8
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonRoomDoor.java
@@ -0,0 +1,98 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMove;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Getter;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DungeonRoomDoor implements DungeonMechanic {
+ @Getter
+ private final DungeonDoor doorfinder;
+ private OffsetPoint offsetPoint;
+
+ public DungeonRoomDoor(DungeonRoom dungeonRoom, DungeonDoor doorfinder) {
+ this.doorfinder = doorfinder;
+ if (doorfinder.isZDir()) {
+ if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(0,0,2)))
+ offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(0,0,2));
+ else if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(0,0,-2)))
+ offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(0,0,-2));
+ } else {
+ if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(2,0,0)))
+ offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(2,0,0));
+ else if (dungeonRoom.canAccessAbsolute(doorfinder.getPosition().add(-2,0,0)))
+ offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition().add(-2,0,0));
+ }
+ if (offsetPoint == null) {
+ offsetPoint = new OffsetPoint(dungeonRoom, doorfinder.getPosition());
+ }
+ }
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (!"navigate".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret");
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionMove actionMove = new ActionMove(offsetPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = offsetPoint.getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return doorfinder.getType().isKeyRequired() ? "key" : "normal";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("navigate");
+ }
+
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("key-open", "key-closed", "normal");
+ }
+
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return offsetPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java
new file mode 100755
index 00000000..b03d5b3a
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonSecret.java
@@ -0,0 +1,239 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.*;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.DungeonActionManager;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates.PredicateBat;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.pathfinding.NodeProcessorDungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.Getter;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.client.Minecraft;
+import net.minecraft.init.Blocks;
+import net.minecraft.tileentity.TileEntityChest;
+import net.minecraft.util.BlockPos;
+import net.minecraft.util.Vec3;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+@Data
+public class DungeonSecret implements DungeonMechanic {
+ private static final long serialVersionUID = 8784808599222706537L;
+
+ private OffsetPoint secretPoint = new OffsetPoint(0,0,0);
+ private SecretType secretType = SecretType.CHEST;
+ private List<String> preRequisite = new ArrayList<String>();
+
+ public void tick(DungeonRoom dungeonRoom) {
+ if (secretType == SecretType.CHEST) {
+ BlockPos pos = secretPoint.getBlockPos(dungeonRoom);
+ IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos);
+ if (blockState.getBlock() == Blocks.chest || blockState.getBlock() == Blocks.trapped_chest) {
+ TileEntityChest chest = (TileEntityChest) dungeonRoom.getContext().getWorld().getTileEntity(pos);
+ if (chest.numPlayersUsing > 0) {
+ dungeonRoom.getRoomContext().put("c-"+pos.toString(), 2);
+ } else {
+ dungeonRoom.getRoomContext().put("c-"+pos.toString(), 1);
+ }
+ }
+ } else if (secretType == SecretType.ESSENCE) {
+ BlockPos pos = secretPoint.getBlockPos(dungeonRoom);
+ IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos);
+ if (blockState.getBlock() == Blocks.skull) {
+ dungeonRoom.getRoomContext().put("e-"+pos.toString(), true);
+ }
+ } else if (secretType == SecretType.ITEM_DROP) {
+ Vec3 pos = new Vec3(secretPoint.getBlockPos(dungeonRoom));
+ Vec3 player = Minecraft.getMinecraft().thePlayer.getPositionVector();
+ if (player.squareDistanceTo(pos) < 16) {
+ Vec3 vec3 = pos.subtract(player).normalize();
+ for (int i = 0; i < player.distanceTo(pos); i++) {
+ Vec3 vec = player.addVector(vec3.xCoord * i, vec3.yCoord * i, vec3.zCoord * i);
+ BlockPos bpos = new BlockPos(vec);
+ IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(bpos);
+ if (!NodeProcessorDungeonRoom.isValidBlock(blockState))
+ return;
+ }
+ dungeonRoom.getRoomContext().put("i-" + pos, true);
+ }
+ }
+ }
+
+ public SecretStatus getSecretStatus(DungeonRoom dungeonRoom) {
+ if (secretType == SecretType.CHEST) {
+ BlockPos pos = secretPoint.getBlockPos(dungeonRoom);
+ IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos);
+ if (dungeonRoom.getRoomContext().containsKey("c-"+pos.toString()))
+ return ((int)dungeonRoom.getRoomContext().get("c-"+pos.toString()) == 2 || blockState.getBlock() == Blocks.air) ? SecretStatus.FOUND : SecretStatus.CREATED;
+
+ if (blockState.getBlock() == Blocks.air) {
+ return SecretStatus.DEFINITELY_NOT;
+ } else if (blockState.getBlock() != Blocks.chest && blockState.getBlock() != Blocks.trapped_chest) {
+ return SecretStatus.ERROR;
+ } else {
+ TileEntityChest chest = (TileEntityChest) dungeonRoom.getContext().getWorld().getTileEntity(pos);
+ if (chest.numPlayersUsing > 0) {
+ return SecretStatus.FOUND;
+ } else{
+ return SecretStatus.CREATED;
+ }
+ }
+ } else if (secretType == SecretType.ESSENCE) {
+ BlockPos pos = secretPoint.getBlockPos(dungeonRoom);
+ IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(pos);
+ if (blockState.getBlock() == Blocks.skull) {
+ dungeonRoom.getRoomContext().put("e-"+pos.toString(), true);
+ return SecretStatus.DEFINITELY_NOT;
+ } else {
+ if (dungeonRoom.getRoomContext().containsKey("e-"+pos.toString()))
+ return SecretStatus.FOUND;
+ return SecretStatus.NOT_SURE;
+ }
+ } else if (secretType == SecretType.BAT) {
+ Vec3 spawn = new Vec3(secretPoint.getBlockPos(dungeonRoom));
+ for (Integer killed : DungeonActionManager.getKilleds()) {
+ if (DungeonActionManager.getSpawnLocation().get(killed) == null) continue;
+ if (DungeonActionManager.getSpawnLocation().get(killed).squareDistanceTo(spawn) < 100) {
+ return SecretStatus.FOUND;
+ }
+ }
+ return SecretStatus.NOT_SURE;
+ } else {
+ Vec3 pos = new Vec3(secretPoint.getBlockPos(dungeonRoom));
+ if (dungeonRoom.getRoomContext().containsKey("i-"+ pos))
+ return SecretStatus.FOUND;
+ Vec3 player = Minecraft.getMinecraft().thePlayer.getPositionVector();
+ if (player.squareDistanceTo(pos) < 16) {
+ Vec3 vec3 = pos.subtract(player).normalize();
+ for (int i = 0; i < player.distanceTo(pos); i++) {
+ Vec3 vec = player.addVector(vec3.xCoord * i, vec3.yCoord * i, vec3.zCoord * i);
+ BlockPos bpos = new BlockPos(vec);
+ IBlockState blockState = dungeonRoom.getContext().getWorld().getBlockState(bpos);
+ if (!NodeProcessorDungeonRoom.isValidBlock(blockState))
+ return SecretStatus.NOT_SURE;
+ }
+ dungeonRoom.getRoomContext().put("i-" + pos, true);
+ }
+ return SecretStatus.NOT_SURE;
+ }
+ }
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+ if (!"found".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for secret");
+ if (state.equals("found") && getSecretStatus(dungeonRoom) == SecretStatus.FOUND) return new HashSet<>();
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ if (secretType == SecretType.CHEST || secretType == SecretType.ESSENCE) {
+ ActionClick actionClick;
+ preRequisites.add(actionClick = new ActionClick(secretPoint));
+ preRequisites = actionClick.getPreRequisite();
+ } else if (secretType == SecretType.BAT) {
+ ActionKill actionKill;
+ preRequisites.add(actionKill = new ActionKill(secretPoint));
+ actionKill.setPredicate(PredicateBat.INSTANCE);
+ actionKill.setRadius(10);
+ preRequisites = actionKill.getPreRequisite();
+ }
+ {
+ ActionMove actionMove = new ActionMove(secretPoint);
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ BlockPos pos = getSecretPoint().getBlockPos(dungeonRoom);
+ RenderUtils.highlightBlock(pos, color,partialTicks);
+ RenderUtils.drawTextAtWorld(getSecretType().name(), pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.375f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ }
+
+ public enum SecretType {
+ BAT, CHEST, ITEM_DROP, ESSENCE
+ }
+
+ @AllArgsConstructor
+ @Getter
+ public enum SecretStatus {
+ DEFINITELY_NOT("definitely_not"), NOT_SURE("not_sure"), CREATED("created"), FOUND("found"), ERROR("error");
+
+ private final String stateName;
+ }
+
+ public DungeonSecret clone() throws CloneNotSupportedException {
+ DungeonSecret dungeonSecret = new DungeonSecret();
+ dungeonSecret.secretPoint = (OffsetPoint) secretPoint.clone();
+ dungeonSecret.secretType = secretType;
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ return getSecretStatus(dungeonRoom).getStateName();
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ SecretStatus status = getSecretStatus(dungeonRoom);
+ if (status == SecretStatus.FOUND) return Sets.newHashSet("navigate");
+ else return Sets.newHashSet("found", "navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("found"/*, "definitely_not", "not_sure", "created", "error"*/);
+ }
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java
new file mode 100755
index 00000000..e4dc79cb
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/DungeonTomb.java
@@ -0,0 +1,137 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.actions.Action;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionBreakWithSuperBoom;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionChangeState;
+import kr.syeyoung.dungeonsguide.dungeon.actions.ActionMoveNearestAir;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import lombok.Data;
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+@Data
+public class DungeonTomb implements DungeonMechanic, RouteBlocker {
+ private static final long serialVersionUID = -7347076019472222115L;
+ private OffsetPointSet secretPoint = new OffsetPointSet();
+ private List<String> preRequisite = new ArrayList<String>();
+
+
+ @Override
+ public Set<Action> getAction(String state, DungeonRoom dungeonRoom) {
+ if (state.equalsIgnoreCase("navigate")) {
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(getRepresentingPoint(dungeonRoom));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ return base;
+ }
+ if (!"open".equalsIgnoreCase(state)) throw new IllegalArgumentException(state+" is not valid state for tomb");
+ if (!isBlocking(dungeonRoom)) {
+ return Collections.emptySet();
+ }
+ Set<Action> base;
+ Set<Action> preRequisites = base = new HashSet<Action>();
+ {
+ ActionBreakWithSuperBoom actionClick;
+ preRequisites.add(actionClick = new ActionBreakWithSuperBoom(secretPoint.getOffsetPointList().get(0)));
+ preRequisites = actionClick.getPreRequisite();
+ }
+ {
+ ActionMoveNearestAir actionMove = new ActionMoveNearestAir(secretPoint.getOffsetPointList().get(0));
+ preRequisites.add(actionMove);
+ preRequisites = actionMove.getPreRequisite();
+ }
+ {
+ for (String str : preRequisite) {
+ if (str.isEmpty()) continue;
+ ActionChangeState actionChangeState = new ActionChangeState(str.split(":")[0], str.split(":")[1]);
+ preRequisites.add(actionChangeState);
+ }
+ }
+ return base;
+ }
+
+ @Override
+ public void highlight(Color color, String name, DungeonRoom dungeonRoom, float partialTicks) {
+ if (secretPoint.getOffsetPointList().isEmpty()) return;
+ OffsetPoint firstpt = secretPoint.getOffsetPointList().get(0);
+ BlockPos pos = firstpt.getBlockPos(dungeonRoom);
+ RenderUtils.drawTextAtWorld(name, pos.getX() +0.5f, pos.getY()+0.75f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+ RenderUtils.drawTextAtWorld(getCurrentState(dungeonRoom), pos.getX() +0.5f, pos.getY()+0.25f, pos.getZ()+0.5f, 0xFFFFFFFF, 0.03f, false, true, partialTicks);
+
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ RenderUtils.highlightBlock(offsetPoint.getBlockPos(dungeonRoom), color,partialTicks);
+ }
+ }
+
+ @Override
+ public boolean isBlocking(DungeonRoom dungeonRoom) {
+ for (OffsetPoint offsetPoint : secretPoint.getOffsetPointList()) {
+ if (offsetPoint.getBlock(dungeonRoom) != Blocks.air) return true;
+ }
+ return false;
+ }
+
+ public DungeonTomb clone() throws CloneNotSupportedException {
+ DungeonTomb dungeonSecret = new DungeonTomb();
+ dungeonSecret.secretPoint = (OffsetPointSet) secretPoint.clone();
+ dungeonSecret.preRequisite = new ArrayList<String>(preRequisite);
+ return dungeonSecret;
+ }
+
+ @Override
+ public String getCurrentState(DungeonRoom dungeonRoom) {
+ Block b = Blocks.air;
+ if (!secretPoint.getOffsetPointList().isEmpty())
+ b = secretPoint.getOffsetPointList().get(0).getBlock(dungeonRoom);
+ return b == Blocks.air ?"open" :"closed";
+ }
+
+ @Override
+ public Set<String> getPossibleStates(DungeonRoom dungeonRoom) {
+ return isBlocking(dungeonRoom) ? Sets.newHashSet("open", "navigate") : Sets.newHashSet("navigate");
+ }
+ @Override
+ public Set<String> getTotalPossibleStates(DungeonRoom dungeonRoom) {
+ return Sets.newHashSet("open", "closed");
+ }
+
+
+ @Override
+ public OffsetPoint getRepresentingPoint(DungeonRoom dungeonRoom) {
+ return secretPoint.getOffsetPointList().size() == 0 ? null : secretPoint.getOffsetPointList().get(0);
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java
new file mode 100755
index 00000000..e12d1269
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/RouteBlocker.java
@@ -0,0 +1,25 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics;
+
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+
+public interface RouteBlocker {
+ boolean isBlocking(DungeonRoom dungeonRoom);
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java
new file mode 100755
index 00000000..a4eddefe
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateArmorStand.java
@@ -0,0 +1,44 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates;
+
+import com.google.common.base.Predicate;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.item.EntityArmorStand;
+import org.jetbrains.annotations.Nullable;
+
+
+public class PredicateArmorStand implements Predicate<Entity> {
+
+ public static final PredicateArmorStand INSTANCE = new PredicateArmorStand();
+
+ @Override
+ public boolean apply(@Nullable Entity input) {
+ return input instanceof EntityArmorStand;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+ @Override
+ public boolean equals(Object o) {
+ return o == this || o != null && (o.getClass() == this.getClass());
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java
new file mode 100755
index 00000000..b7fae7a8
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateBat.java
@@ -0,0 +1,44 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates;
+
+import com.google.common.base.Predicate;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.passive.EntityBat;
+import org.jetbrains.annotations.Nullable;
+
+
+public class PredicateBat implements Predicate<Entity> {
+
+ public static final PredicateBat INSTANCE = new PredicateBat();
+
+ @Override
+ public boolean apply(@Nullable Entity input) {
+ return input instanceof EntityBat;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+ @Override
+ public boolean equals(Object o) {
+ return o == this || o != null && (o.getClass() == this.getClass());
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java
new file mode 100755
index 00000000..d4cce7f1
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/mechanics/predicates/PredicateSuperBoom.java
@@ -0,0 +1,43 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.mechanics.predicates;
+
+import com.google.common.base.Predicate;
+import net.minecraft.item.ItemStack;
+import org.jetbrains.annotations.Nullable;
+
+public class PredicateSuperBoom implements Predicate<ItemStack> {
+
+ public static final PredicateSuperBoom INSTANCE = new PredicateSuperBoom();
+
+ @Override
+ public boolean apply(@Nullable ItemStack input) {
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o == this || o != null && (o.getClass() == this.getClass());
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java
new file mode 100755
index 00000000..83dbb889
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java
@@ -0,0 +1,380 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.roomfinder;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.EDungeonDoorType;
+import kr.syeyoung.dungeonsguide.dungeon.events.DungeonStateChangeEvent;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonMechanic;
+import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonRoomDoor;
+import kr.syeyoung.dungeonsguide.features.impl.secret.FeaturePathfindStrategy;
+import kr.syeyoung.dungeonsguide.dungeon.DungeonContext;
+import kr.syeyoung.dungeonsguide.dungeon.MapProcessor;
+import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor;
+import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
+import kr.syeyoung.dungeonsguide.roomedit.EditingContext;
+import kr.syeyoung.dungeonsguide.roomprocessor.ProcessorFactory;
+import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor;
+import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+import net.minecraft.block.Block;
+import net.minecraft.block.state.IBlockState;
+import net.minecraft.entity.Entity;
+import net.minecraft.pathfinding.PathEntity;
+import net.minecraft.pathfinding.PathFinder;
+import net.minecraft.pathfinding.PathPoint;
+import net.minecraft.util.*;
+import net.minecraft.world.ChunkCache;
+import net.minecraft.world.IBlockAccess;
+import net.minecraft.world.World;
+
+import javax.vecmath.Vector2d;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledFuture;
+import java.util.concurrent.TimeUnit;
+
+@Getter
+public class DungeonRoom {
+ private final List<Point> unitPoints;
+ private final short shape;
+ private final byte color;
+
+ private final BlockPos min;
+ private final BlockPos max;
+ private final Point minRoomPt;
+
+ private final DungeonContext context;
+
+ private final List<DungeonDoor> doors = new ArrayList<DungeonDoor>();
+
+ private DungeonRoomInfo dungeonRoomInfo;
+
+ private final int unitWidth; // X
+ private final int unitHeight; // Z
+
+ @Setter
+ private int totalSecrets = -1;
+ private RoomState currentState = RoomState.DISCOVERED;
+
+ private Map<String, DungeonMechanic> cached = null;
+
+ @Getter
+ private World cachedWorld;
+ public Map<String, DungeonMechanic> getMechanics() {
+ if (cached == null || EditingContext.getEditingContext() != null) {
+ cached = new HashMap<String, DungeonMechanic>(dungeonRoomInfo.getMechanics());
+ int index = 0;
+ for (DungeonDoor door : doors) {
+ if (door.getType().isExist()) cached.put((door.getType().getName())+"-"+(++index), new DungeonRoomDoor(this, door));
+ }
+ }
+ return cached;
+ }
+
+ public void setCurrentState(RoomState currentState) {
+ context.createEvent(new DungeonStateChangeEvent(unitPoints.get(0), dungeonRoomInfo.getName(), this.currentState, currentState));
+ this.currentState = currentState;
+ }
+
+ private Map<BlockPos, AStarFineGrid> activeBetterAStar = new HashMap<>();
+ private Map<BlockPos, AStarCornerCut> activeBetterAStarCornerCut = new HashMap<>();
+ private Map<BlockPos, ThetaStar> activeThetaStar = new HashMap<>();
+
+ public ScheduledFuture<List<Vec3>> createEntityPathTo(IBlockAccess blockaccess, Entity entityIn, BlockPos targetPos, float dist, int timeout) {
+ FeaturePathfindStrategy.PathfindStrategy pathfindStrategy = FeatureRegistry.SECRET_PATHFIND_STRATEGY.getPathfindStrat();
+ if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.JPS_LEGACY) {
+ ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> {
+ BlockPos min = new BlockPos(getMin().getX(), 0, getMin().getZ());
+ BlockPos max= new BlockPos(getMax().getX(), 255, getMax().getZ());
+ JPSPathfinder pathFinder = new JPSPathfinder(this);
+ pathFinder.pathfind(entityIn.getPositionVector(), new Vec3(targetPos).addVector(0.5, 0.5, 0.5), 1.5f,timeout);
+ return pathFinder.getRoute();
+ }, 0, TimeUnit.MILLISECONDS);
+ return sf;
+ } else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.A_STAR_FINE_GRID) {
+ ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> {
+ AStarFineGrid pathFinder =
+ activeBetterAStar.computeIfAbsent(targetPos, (pos) -> new AStarFineGrid(this, new Vec3(pos.getX(), pos.getY(), pos.getZ()).addVector(0.5, 0.5, 0.5)));
+ pathFinder.pathfind(entityIn.getPositionVector(),timeout);
+ return pathFinder.getRoute();
+ }, 0, TimeUnit.MILLISECONDS);
+ return sf;
+ }else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.A_STAR_DIAGONAL) {
+ ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> {
+ AStarCornerCut pathFinder =
+ activeBetterAStarCornerCut.computeIfAbsent(targetPos, (pos) -> new AStarCornerCut(this, new Vec3(pos.getX(), pos.getY(), pos.getZ()).addVector(0.5, 0.5, 0.5)));
+ pathFinder.pathfind(entityIn.getPositionVector(),timeout);
+ return pathFinder.getRoute();
+ }, 0, TimeUnit.MILLISECONDS);
+ return sf;
+ } else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.THETA_STAR) {
+ ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> {
+ ThetaStar pathFinder =
+ activeThetaStar.computeIfAbsent(targetPos, (pos) -> new ThetaStar(this, new Vec3(pos.getX(), pos.getY(), pos.getZ()).addVector(0.5, 0.5, 0.5)));
+ pathFinder.pathfind(entityIn.getPositionVector(),timeout);
+ return pathFinder.getRoute();
+ }, 0, TimeUnit.MILLISECONDS);
+ return sf;
+ } else {
+ ScheduledFuture<List<Vec3>> sf = asyncPathFinder.schedule(() -> {
+ PathFinder pathFinder = new PathFinder(nodeProcessorDungeonRoom);
+ PathEntity latest = pathFinder.createEntityPathTo(blockaccess, entityIn, targetPos, dist);
+ if (latest != null) {
+ List<Vec3> poses = new ArrayList<>();
+ for (int i = 0; i < latest.getCurrentPathLength(); i++) {
+ PathPoint pathPoint = latest.getPathPointFromIndex(i);
+ poses.add(new Vec3(getMin().add(pathPoint.xCoord, pathPoint.yCoord, pathPoint.zCoord)).addVector(0.5,0.5,0.5));
+ }
+ return poses;
+ }
+ return new ArrayList<>();
+ }, 0, TimeUnit.MILLISECONDS);
+ return sf;
+ }
+ }
+
+ private static final ScheduledExecutorService asyncPathFinder = Executors.newScheduledThreadPool(4);
+ @Getter
+ private final NodeProcessorDungeonRoom nodeProcessorDungeonRoom;
+
+ @Getter
+ private final Map<String, Object> roomContext = new HashMap<String, Object>();
+
+ @AllArgsConstructor
+ @Getter
+ public enum RoomState {
+ DISCOVERED(0), COMPLETE_WITHOUT_SECRETS(0), FINISHED(0), FAILED(-14);
+ private final int scoreModifier;
+ }
+
+ private RoomProcessor roomProcessor;
+
+ public DungeonRoom(List<Point> points, short shape, byte color, BlockPos min, BlockPos max, DungeonContext context, Set<Tuple<Vector2d, EDungeonDoorType>> doorsAndStates) {
+ this.unitPoints = points;
+ this.shape = shape;
+ this.color = color;
+ this.min = min;
+ this.max = max;
+ this.context = context;
+
+ minRoomPt = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE);
+ for (Point pt : unitPoints) {
+ if (pt.x < minRoomPt.x) minRoomPt.x = pt.x;
+ if (pt.y < minRoomPt.y) minRoomPt.y = pt.y;
+ }
+ unitWidth = (int) Math.ceil(max.getX() - min.getX() / 32.0);
+ unitHeight = (int) Math.ceil(max.getZ() - min.getZ() / 32.0);
+
+
+ ChunkCache chunkCache = new ChunkCache(getContext().getWorld(), min.add(-3, 0, -3), max.add(3,0,3), 0);
+ this.cachedWorld = new CachedWorld(chunkCache);
+
+
+
+ minx = min.getX() * 2; miny = 0; minz = min.getZ() * 2;
+ maxx = max.getX() * 2 + 2; maxy = 255 * 2 + 2; maxz = max.getZ() * 2 + 2;
+
+ lenx = maxx - minx;
+ leny = maxy - miny;
+ lenz = maxz - minz;
+ arr = new long[lenx *leny * lenz * 2 / 8];;
+
+ buildDoors(doorsAndStates);
+ buildRoom();
+ nodeProcessorDungeonRoom = new NodeProcessorDungeonRoom(this);
+ updateRoomProcessor();
+
+
+ }
+
+ private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,16), new Vector2d(0, -16), new Vector2d(16, 0), new Vector2d(-16 , 0));
+
+ private void buildDoors(Set<Tuple<Vector2d, EDungeonDoorType>> doorsAndStates) {
+ Set<Tuple<BlockPos, EDungeonDoorType>> positions = new HashSet<>();
+ BlockPos pos = context.getMapProcessor().roomPointToWorldPoint(minRoomPt).add(16,0,16);
+ for (Tuple<Vector2d, EDungeonDoorType> doorsAndState : doorsAndStates) {
+ Vector2d vector2d = doorsAndState.getFirst();
+ BlockPos neu = pos.add(vector2d.x * 32, 0, vector2d.y * 32);
+ positions.add(new Tuple<>(neu, doorsAndState.getSecond()));
+ }
+
+ for (Tuple<BlockPos, EDungeonDoorType> door : positions) {
+ doors.add(new DungeonDoor(context.getWorld(), door.getFirst(), door.getSecond()));
+ }
+ }
+
+ private RoomMatcher roomMatcher = null;
+ private void buildRoom() {
+ if (roomMatcher == null)
+ roomMatcher = new RoomMatcher(this);
+ DungeonRoomInfo dungeonRoomInfo = roomMatcher.match();
+ if (dungeonRoomInfo == null) {
+ dungeonRoomInfo = roomMatcher.createNew();
+ if (color == 18) dungeonRoomInfo.setProcessorId("bossroom");
+ }
+ this.dungeonRoomInfo = dungeonRoomInfo;
+ totalSecrets = dungeonRoomInfo.getTotalSecrets();
+ }
+
+ public void updateRoomProcessor() {
+ RoomProcessorGenerator roomProcessorGenerator = ProcessorFactory.getRoomProcessorGenerator(dungeonRoomInfo.getProcessorId());
+ if (roomProcessorGenerator == null) this.roomProcessor = null;
+ else this.roomProcessor = roomProcessorGenerator.createNew(this);
+ }
+
+ public Block getAbsoluteBlockAt(int x, int y, int z) {
+ // validate x y z's
+ BlockPos pos = new BlockPos(x,y,z);
+ if (canAccessAbsolute(pos)) {
+ return cachedWorld.getBlockState(pos).getBlock();
+ }
+ return null;
+ }
+
+ public Block getRelativeBlockAt(int x, int y, int z) {
+ // validate x y z's
+ if (canAccessRelative(x,z)) {
+ BlockPos pos = new BlockPos(x,y,z).add(min.getX(),min.getY(),min.getZ());
+ return cachedWorld.getBlockState(pos).getBlock();
+ }
+ return null;
+ }
+
+ public BlockPos getRelativeBlockPosAt(int x, int y, int z) {
+ BlockPos pos = new BlockPos(x,y,z).add(min.getX(),min.getY(),min.getZ());
+ return pos;
+ }
+
+ public int getRelativeBlockDataAt(int x, int y, int z) {
+ // validate x y z's
+ if (canAccessRelative(x,z)) {
+ BlockPos pos = new BlockPos(x,y,z).add(min.getX(),min.getY(),min.getZ());
+ IBlockState iBlockState = cachedWorld.getBlockState(pos);
+ return iBlockState.getBlock().getMetaFromState(iBlockState);
+ }
+ return -1;
+ }
+
+ public int getAbsoluteBlockDataAt(int x, int y, int z) {
+ // validate x y z's
+ BlockPos pos = new BlockPos(x,y,z);
+ if (canAccessAbsolute(pos)) {
+ IBlockState iBlockState = cachedWorld.getBlockState(pos);
+ return iBlockState.getBlock().getMetaFromState(iBlockState);
+ }
+ return -1;
+ }
+
+ public boolean canAccessAbsolute(BlockPos pos) {
+ MapProcessor mapProcessor = this.context.getMapProcessor();
+ Point roomPt = mapProcessor.worldPointToRoomPoint(pos);
+ roomPt.translate(-minRoomPt.x, -minRoomPt.y);
+
+ return (shape >>(roomPt.y *4 +roomPt.x) & 0x1) > 0;
+ }
+ public boolean canAccessRelative(int x, int z) {
+ return x>= 0 && z >= 0 && (shape >>((z/32) *4 +(x/32)) & 0x1) > 0;
+ }
+
+
+
+ long arr[];
+ // These values are doubled
+ private final int minx, miny, minz, maxx, maxy, maxz;
+ private final int lenx, leny, lenz;
+ private static final float playerWidth = 0.3f;
+ public boolean isBlocked(int x,int y, int z) {
+ if (x < minx || z < minz || x >= maxx || z >= maxz || y < miny || y >= maxy) return true;
+ int dx = x - minx, dy = y - miny, dz = z - minz;
+ int bitIdx = dx * leny * lenz + dy * lenz + dz;
+ int location = bitIdx / 4;
+ int bitStart = (2 * (bitIdx % 4));
+ long theBit = arr[location];
+ if (((theBit >> bitStart) & 0x2) > 0) return ((theBit >> bitStart) & 1) > 0;
+ float wX = x / 2.0f, wY = y / 2.0f, wZ = z / 2.0f;
+
+
+ AxisAlignedBB bb = AxisAlignedBB.fromBounds(wX - playerWidth, wY, wZ - playerWidth, wX + playerWidth, wY + 1.9f, wZ + playerWidth);
+
+ int i = MathHelper.floor_double(bb.minX);
+ int j = MathHelper.floor_double(bb.maxX + 1.0D);
+ int k = MathHelper.floor_double(bb.minY);
+ int l = MathHelper.floor_double(bb.maxY + 1.0D);
+ int i1 = MathHelper.floor_double(bb.minZ);
+ int j1 = MathHelper.floor_double(bb.maxZ + 1.0D);
+ BlockPos.MutableBlockPos blockPos = new BlockPos.MutableBlockPos();
+
+ List<AxisAlignedBB> list = new ArrayList<>();
+ for (int k1 = i; k1 < j; ++k1) {
+ for (int l1 = i1; l1 < j1; ++l1) {
+ for (int i2 = k - 1; i2 < l; ++i2) {
+ blockPos.set(k1, i2, l1);
+ IBlockState iblockstate1 = cachedWorld.getBlockState(blockPos);
+ Block b = iblockstate1.getBlock();
+ if (!b.getMaterial().blocksMovement())continue;
+ if (b.isFullCube() && i2 == k-1) continue;
+ if (iblockstate1.equals( NodeProcessorDungeonRoom.preBuilt)) continue;
+ if (b.isFullCube()) {
+ theBit |= (3L << bitStart);
+ arr[location] = theBit;
+ return true;
+ }
+ try {
+ b.addCollisionBoxesToList(cachedWorld, blockPos, iblockstate1, bb, list, null);
+ } catch (Exception e) {
+ return true;
+ }
+ if (list.size() > 0) {
+ theBit |= (3L << bitStart);
+ arr[location] = theBit;
+ return true;
+ }
+ }
+ }
+ }
+ theBit |= 2L << bitStart;
+ arr[location] = theBit;
+ return false;
+ }
+
+
+ public void resetBlock(BlockPos pos) {
+ for (int x = -1; x <= 1; x++) {
+ for (int y = -1; y <= 1; y++) {
+ for (int z = -1; z <= 1; z++) {
+ resetBlock(pos.getX()*2 + x, pos.getY()*2 + y, pos.getZ()*2 + z);
+ }
+ }
+ }
+ }
+ private void resetBlock(int x, int y, int z) {
+ if (x < minx || z < minz || x >= maxx || z >= maxz || y < miny || y >= maxy) return;
+ int dx = x - minx, dy = y - miny, dz = z - minz;
+ int bitIdx = dx * leny * lenz + dy * lenz + dz;
+ int location = bitIdx / 4;
+ arr[location] = 0;
+ }
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java
new file mode 100755
index 00000000..a97efa43
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoomInfoRegistry.java
@@ -0,0 +1,142 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.roomfinder;
+
+import com.google.common.io.Files;
+import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo;
+import kr.syeyoung.dungeonsguide.launcher.Main;
+import lombok.Getter;
+import net.minecraft.client.Minecraft;
+import org.apache.commons.io.IOUtils;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+import javax.crypto.NoSuchPaddingException;
+import java.io.*;
+import java.nio.charset.Charset;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.*;
+
+public class DungeonRoomInfoRegistry {
+ @Getter
+ private static final List<DungeonRoomInfo> registered = new ArrayList<DungeonRoomInfo>();
+ private static final Map<Short, List<DungeonRoomInfo>> shapeMap = new HashMap<Short, List<DungeonRoomInfo>>();
+ private static final Map<UUID, DungeonRoomInfo> uuidMap = new HashMap<UUID, DungeonRoomInfo>();
+
+ public static void register(DungeonRoomInfo dungeonRoomInfo) {
+ if (dungeonRoomInfo == null) throw new NullPointerException("what the fak parameter is noll?");
+ if (uuidMap.containsKey(dungeonRoomInfo.getUuid())) {
+ DungeonRoomInfo dri1 = uuidMap.get(dungeonRoomInfo.getUuid());
+ registered.remove(dri1);
+ shapeMap.get(dri1.getShape()).remove(dri1);
+ uuidMap.remove(dri1.getUuid());
+ }
+ dungeonRoomInfo.setRegistered(true);
+ registered.add(dungeonRoomInfo);
+ uuidMap.put(dungeonRoomInfo.getUuid(), dungeonRoomInfo);
+ List<DungeonRoomInfo> roomInfos = shapeMap.get(dungeonRoomInfo.getShape());
+ if (roomInfos == null) roomInfos = new ArrayList<DungeonRoomInfo>();
+ roomInfos.add(dungeonRoomInfo);
+ shapeMap.put(dungeonRoomInfo.getShape(), roomInfos);
+ }
+
+
+ public static List<DungeonRoomInfo> getByShape(Short shape) {
+ List<DungeonRoomInfo> dungeonRoomInfos = shapeMap.get(shape);
+ return dungeonRoomInfos == null ? Collections.emptyList() : dungeonRoomInfos;
+ }
+
+ public static DungeonRoomInfo getByUUID(UUID uid) {
+ return uuidMap.get(uid);
+ }
+
+ public static void unregister(DungeonRoomInfo dungeonRoomInfo) {
+ if (!dungeonRoomInfo.isRegistered()) throw new IllegalStateException("what tha fak? that is not registered one");
+ if (!uuidMap.containsKey(dungeonRoomInfo.getUuid())) throw new IllegalStateException("what tha fak? that is not registered one, but you desperately wanted to trick this program");
+ dungeonRoomInfo.setRegistered(false);
+ registered.remove(dungeonRoomInfo);
+ shapeMap.get(dungeonRoomInfo.getShape()).remove(dungeonRoomInfo);
+ uuidMap.remove(dungeonRoomInfo.getUuid());
+ }
+
+ public static void saveAll(File dir) {
+ dir.mkdirs();
+ boolean isDev = Minecraft.getMinecraft().getSession().getPlayerID().replace("-","").equals("e686fe0aab804a71ac7011dc8c2b534c");
+ String nameidstring = "name,uuid,processsor,secrets";
+ String ids = "";
+ for (DungeonRoomInfo dungeonRoomInfo : registered) {
+ try {
+ if (!dungeonRoomInfo.isUserMade() && !isDev) continue;
+ FileOutputStream fos = new FileOutputStream(new File(dir, dungeonRoomInfo.getUuid().toString() + ".roomdata"));
+ ObjectOutputStream oos = new ObjectOutputStream(fos);
+ oos.writeObject(dungeonRoomInfo);
+ oos.flush();
+ oos.close();
+
+ nameidstring += "\n"+dungeonRoomInfo.getName()+","+dungeonRoomInfo.getUuid() +","+dungeonRoomInfo.getProcessorId()+","+dungeonRoomInfo.getTotalSecrets();
+ ids += "roomdata/"+dungeonRoomInfo.getUuid() +".roomdata\n";
+ } catch (Exception e) {e.printStackTrace();}
+ }
+
+ try {
+ Files.write(nameidstring, new File(dir, "roomidmapping.csv"), Charset.defaultCharset());
+ Files.write(ids, new File(dir, "datas.txt"), Charset.defaultCharset());
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void loadAll(File dir) throws BadPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, IOException, IllegalBlockSizeException, NoSuchPaddingException, InvalidKeyException {
+ registered.clear();
+ shapeMap.clear();
+ uuidMap.clear();
+ try {
+ List<String> lines = IOUtils.readLines(Main.class.getResourceAsStream("/roomdata/datas.txt"));
+ for (String name : lines) {
+ if (!name.endsWith(".roomdata")) continue;
+ try {
+ InputStream fis = Main.class.getResourceAsStream("/"+name);
+ ObjectInputStream ois = new ObjectInputStream(fis);
+ DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject();
+ ois.close();
+ fis.close();
+ register(dri);
+ } catch (Exception e) {
+ System.out.println(name);
+ e.printStackTrace();
+ }
+ }
+ } catch (Exception e) {e.printStackTrace();}
+ for (File f : dir.listFiles()) {
+ if (!f.getName().endsWith(".roomdata")) continue;
+ try {
+ InputStream fis = new FileInputStream(f);
+ ObjectInputStream ois = new ObjectInputStream(fis);
+ DungeonRoomInfo dri = (DungeonRoomInfo) ois.readObject();
+ ois.close();
+ fis.close();
+ register(dri);
+ } catch (Exception e) {
+ System.out.println(f.getName());e.printStackTrace();}
+ }
+ }
+
+}
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java
new file mode 100755
index 00000000..f0da1f35
--- /dev/null
+++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java
@@ -0,0 +1,154 @@
+/*
+ * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
+ * Copyright (C) 2021 cyoung06
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package kr.syeyoung.dungeonsguide.dungeon.roomfinder;
+
+import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo;
+import kr.syeyoung.dungeonsguide.utils.ArrayUtils;
+import kr.syeyoung.dungeonsguide.utils.ShortUtils;
+import lombok.Getter;
+import net.minecraft.block.Block;
+import net.minecraft.init.Blocks;
+import net.minecraft.world.World;
+
+import java.util.List;
+
+public class RoomMatcher {
+ private final DungeonRoom dungeonRoom;
+
+ @Getter
+ private DungeonRoomInfo match;
+ @Getter
+ private int rotation; // how much the "found room" has to rotate clockwise to match the given dungeon room info. !
+ private boolean triedMatch = false;
+
+ private final World w;
+
+ public RoomMatcher(DungeonRoom dungeonRoom) {
+ this.dungeonRoom = dungeonRoom;
+ w = dungeonRoom.getContext().getWorld();
+ }
+
+ public DungeonRoomInfo match() {
+ if (triedMatch) return match;
+
+ int zz = dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() + 1;
+ int xx = dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1;
+ for (int z = 0; z < zz; z ++) {
+ for (int x = 0; x < xx; x++) {
+ if (x % 8 == 0 && z % 8 == 0 && dungeonRoom.getContext().getWorld().getChunkFromBlockCoords(dungeonRoom.getRelativeBlockPosAt(x, 0, z)).isEmpty()) {
+ throw new IllegalStateException("chunk is not loaded");
+
+ }
+ }
+ }
+
+ triedMatch = true;
+ int lowestcost = 10;
+ int lowestRot = 0;
+ DungeonRoomInfo bestMatch = null;
+ for (int rotation = 0; rotation < 4; rotation++) {
+ short shape = dungeonRoom.getShape();
+ for (int j = 0; j<rotation; j++)
+ shape = ShortUtils.rotateClockwise(shape);
+ shape = ShortUtils.topLeftifyInt(shape);
+
+ List<DungeonRoomInfo> roomInfoList = DungeonRoomInfoRegistry.getByShape(shape);
+ for (DungeonRoomInfo roomInfo : roomInfoList) {
+ int cost = tryMatching(roomInfo, rotation);
+ if (cost == 0) {
+ match = roomInfo;
+ this.rotation = rotation;
+ return match;
+ }
+ if (cost < lowestcost) {
+ lowestcost = cost;
+ bestMatch = roomInfo;
+ lowestRot = rotation;
+ }
+ }
+ }
+ match = bestMatch;
+ this.rotation = lowestRot;
+ return bestMatch;
+ }
+
+ private int tryMatching(DungeonRoomInfo dungeonRoomInfo, int rotation) {
+ if (dungeonRoomInfo.getColor() != dungeonRoom.getColor()) return Integer.MAX_VALUE;
+
+ int[][] res = dungeonRoomInfo.getBlocks();
+ for (int i = 0; i < rotation; i++)
+ res = ArrayUtils.rotateCounterClockwise(res);
+
+ int wrongs = 0;
+ for (int z = 0; z < res.length; z ++) {
+ for (int x = 0; x < res[0].length; x++) {
+ int data = res[z][x];
+ if (data == -1) continue;
+ Block b = dungeonRoom.getRelativeBlockAt(x,0,z);
+
+ if (b == null || Block.getIdFromBlock(b) != data) {
+ wrongs++;
+
+ if (wrongs > 10) return wrongs;
+ }
+ }
+ }
+ return wrongs;
+ }
+
+ private static final int offset = 3;
+ public DungeonRoomInfo createNew() {
+ DungeonRoomInfo roomInfo = new DungeonRoomInfo(dungeonRoom.getShape(), dungeonRoom.getColor());
+
+ int maxX = dungeonRoom.getMax().getX();
+ int maxZ = dungeonRoom.getMax().getZ();
+ int minX = dungeonRoom.getMin().getX();
+ int minZ = dungeonRoom.getMin().getZ();
+ int widthX = maxX - minX + 2;
+ int heightZ = maxZ - minZ + 2;
+ int[][] data = new int[dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() +2][dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 2];
+
+ for (int z = 0; z < data.length; z++) {
+ for (int x = 0; x < data[0].length; x++) {
+// if (!(offset < x && widthX - offset > x && offset < z && heightZ - offset > z)) {
+// data[z][x] = -1;
+// continue;
+// }
+ if (!(dungeonRoom.canAccessRelative(x + offset, z + offset)
+ && dungeonRoom.canAccessRelative(x - offset -1 , z - offset-1)
+ && dungeonRoom.canAccessRelative(x + offset , z - offset-1)
+ && dungeonRoom.canAccessRelative(x - offset -1 , z + offset))) {
+ data[z][x] = -1;
+ continue;
+ }
+
+ Block b = dungeonRoom.getRelativeBlockAt(x,0,z);
+ if (b == null || b == Blocks.chest || b == Blocks.trapped_chest) {
+ data[z][x] = -1;
+ } else {
+ data[z][x] = Block.getIdFromBlock(b);
+ }
+ }
+ }
+
+ roomInfo.setBlocks(data);
+ roomInfo.setUserMade(true);
+ return roomInfo;
+ }
+}