diff options
author | syeyoung <cyoung06@naver.com> | 2022-05-21 21:18:14 +0900 |
---|---|---|
committer | syeyoung <cyoung06@naver.com> | 2022-05-21 21:28:52 +0900 |
commit | 20dd3f99a7b139b5848128246c622fd9cfefa478 (patch) | |
tree | 78e5f84ad22fd53876d488f6b58c3528aebe6501 /mod/src/main/java/kr/syeyoung/dungeonsguide/dungeon | |
parent | 50de034c046c4ddea033b73793c8825ecb5bb86f (diff) | |
download | Skyblock-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')
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; + } +} |