diff options
Diffstat (limited to 'src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon')
151 files changed, 17425 insertions, 0 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonActionContext.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonActionContext.java new file mode 100644 index 00000000..f9541a3d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonActionContext.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.mod.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 DungeonActionContext { + @Getter + private static final Map<Integer, Vec3> spawnLocation = new HashMap<>(); + + @Getter + private static final List<Integer> killeds = new ArrayList<>(); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java new file mode 100755 index 00000000..32a668c0 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonContext.java @@ -0,0 +1,218 @@ +/* + * 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.mod.dungeon; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonSpecificDataProvider; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonSpecificDataProviderRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonCryptBrokenEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonNodataEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonPuzzleFailureEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonSecretCountChangeEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightProcessor; +import kr.syeyoung.dungeonsguide.mod.events.impl.BossroomEnterEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.TabListUtil; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.client.Minecraft; +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.List; +import java.util.*; + +public class DungeonContext { + /** + * This is static because its used in the constructor, + * it means we cannot set the name without having an object, + * and we cannot create an object without the name + * so its static :) + */ + @Getter @Setter + private static String dungeonName; + @Getter + @Setter + public int percentage; + @Getter + private final World world; + @Getter + private final MapProcessor mapProcessor; + + @Getter + @Setter + private BlockPos dungeonMin; + + @Getter + private final Map<Point, DungeonRoom> roomMapper = new HashMap<>(); + @Getter + private final List<DungeonRoom> dungeonRoomList = new ArrayList<>(); + + @Getter + private final List<RoomProcessor> globalRoomProcessors = new ArrayList<>(); + + @Getter + private final Map<String, Integer> deaths = new HashMap<>(); + @Getter + private final List<String[]> milestoneReached = new ArrayList<>(); + @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<>(); + + @Getter + private final List<DungeonEvent> events = new ArrayList<>(); + + public DungeonContext(World world) { + this.world = world; + createEvent(new DungeonNodataEvent("DUNGEON_CONTEXT_CREATION")); + mapProcessor = new MapProcessor(this); + DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(getDungeonName()); + if (doorFinder != null) { + trapRoomGen = doorFinder.isTrapSpawn(getDungeonName()); + + secretPercentage = doorFinder.secretPercentage(getDungeonName()); + maxSpeed = doorFinder.speedSecond(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() { + + + 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(getDungeonName()); + if (doorFinder != null) { + bossfightProcessor = doorFinder.createBossfightProcessor(world, getDungeonName()); + } else { + ChatTransmitter.sendDebugChat(new ChatComponentText("Error:: Null Data Providier")); + } + } + + players.clear(); + players.addAll(TabListUtil.getPlayersInDungeon()); + + + 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)); + ChatTransmitter.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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java new file mode 100644 index 00000000..96a951fd --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/DungeonFacade.java @@ -0,0 +1,35 @@ +package kr.syeyoung.dungeonsguide.mod.dungeon; + +import kr.syeyoung.dungeonsguide.Main; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.mod.events.listener.DungeonListener; +import lombok.Getter; +import lombok.Setter; +import net.minecraftforge.common.MinecraftForge; + +import javax.crypto.BadPaddingException; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import java.io.IOException; +import java.security.InvalidAlgorithmParameterException; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; + +public class DungeonFacade { + + @Getter + @Setter + private DungeonContext context; + + public void init() { + DungeonListener dgEventListener = new DungeonListener(); + MinecraftForge.EVENT_BUS.register(dgEventListener); + + try { + DungeonRoomInfoRegistry.loadAll(Main.getConfigDir()); + } catch (BadPaddingException | InvalidKeyException | NoSuchPaddingException | IllegalBlockSizeException | + IOException | NoSuchAlgorithmException | InvalidAlgorithmParameterException e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/MapProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/MapProcessor.java new file mode 100755 index 00000000..9c2462ea --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/MapProcessor.java @@ -0,0 +1,535 @@ +/* + * 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.mod.dungeon; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import com.google.common.collect.Sets; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.EDungeonDoorType; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.SerializableBlockPos; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonMapUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonRoomDiscoverEvent; +import kr.syeyoung.dungeonsguide.mod.dungeon.map.DungeonMapData; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.MapUtils; +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 org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import javax.vecmath.Vector2d; +import java.awt.*; +import java.util.List; +import java.util.Queue; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +public class MapProcessor { + + 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 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 static final Minecraft mc = Minecraft.getMinecraft(); + private final DungeonContext context; + @Getter + private final BiMap<String, String> mapIconToPlayerMap = HashBiMap.create(); + private final List<Point> roomsFound = new ArrayList<>(); + Logger logger = LogManager.getLogger("MapProcessor"); + /** + * If the player on the map is closer than value this it won't save it + * this should be done with render-distance but whateva + */ + int clossnessDistance = 50; + @Getter + @Setter + private Dimension unitRoomDimension; + @Getter @Setter + private Dimension doorDimensions; // width: width of door, height: gap between rooms + @Getter + @Setter + private Point topLeftMapPoint; + @Setter + private boolean bugged = false; + @Getter + private boolean initialized = false; + @Getter + private int undiscoveredRoom = 0; + private boolean processed = false; + @Getter + private MapData latestMapData; + private int waitDelay = 0; + private boolean processlock; + + public MapProcessor(DungeonContext context) { + this.context = context; + } + + private static void error(String prefix) { + ChatTransmitter.addToQueue(new ChatComponentText(ChatTransmitter.prefix + prefix)); + } + + + ExecutorService es = Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("Dg-MapProcessor-%d").build()); + + + int processMapThroddle; + + public void tick() { + if (waitDelay < 5) { + waitDelay++; + return; + } + if (bugged) { + return; + } + ItemStack stack = Minecraft.getMinecraft().thePlayer.inventory.getStackInSlot(8); + + if (stack == null || !(stack.getItem() instanceof ItemMap)) { + return; + } + + MapData mapData = ((ItemMap) stack.getItem()).getMapData(stack, mc.theWorld); + + if (mapData != null) { + + if(processMapThroddle > 5 && !processlock){ + processMapData(mapData.colors); + processMapThroddle = 0; + } + processMapThroddle++; + + } + + latestMapData = mapData; + + if (latestMapData != null && mapIconToPlayerMap.size() < context.getPlayers().size() && initialized) { + getPlayersFromMap(latestMapData); + } + + } + + private void processMapData(byte[] mapColorData) { + + // i just cant get this to work sad + if (isThereDifference(latestMapData.colors, mapColorData)) { + context.createEvent(new DungeonMapUpdateEvent(mapColorData)); + + es.execute(() -> { + processlock = true; + if (doorDimensions == null || !initialized) { + assembleMap(mapColorData); + } else { + processMap(mapColorData); + } + + if (context.isEnded()) { + processFinishedMap(mapColorData); + } + processlock = false; + }); + + } + + } + + void assembleMap(final byte[] mapData){ + DungeonMapData data = new DungeonMapData(context, Minecraft.getMinecraft()); + + data.eat(mapData); + + bugged = data.bugged; + + unitRoomDimension = data.unitRoomDimension; + + topLeftMapPoint = data.topLeftMapPoint; + + initialized = data.initialized; + + doorDimensions = data.doorDimensions; + + } + + + public static Point mapPointToRoomPoint(Point mapPoint, Point topLeftMapPoint, Dimension unitRoomDimension, Dimension doorDimensions) { + int x = (int) ((mapPoint.x - topLeftMapPoint.x) / ((double) unitRoomDimension.width + doorDimensions.height)); + int y = (int) ((mapPoint.y - topLeftMapPoint.y) / ((double) unitRoomDimension.height + doorDimensions.height)); + return new Point(x, y); + } + + public BlockPos mapPointToWorldPoint(Point mapPoint) { + int x = (int) ((mapPoint.x - topLeftMapPoint.x) / ((double) unitRoomDimension.width + doorDimensions.height) * 32 + context.getDungeonMin().getX()); + int y = (int) ((mapPoint.y - topLeftMapPoint.y) / ((double) unitRoomDimension.height + doorDimensions.height) * 32 + context.getDungeonMin().getZ()); + return new BlockPos(x, 70, y); + } + + public Point roomPointToMapPoint(Point roomPoint) { + return new Point(roomPoint.x * (unitRoomDimension.width + doorDimensions.height) + topLeftMapPoint.x, roomPoint.y * (unitRoomDimension.height + doorDimensions.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 + doorDimensions.height)), topLeftMapPoint.y + (int) ((worldPoint.zCoord - context.getDungeonMin().getZ()) / 32.0f * (unitRoomDimension.height + doorDimensions.height))); + } + + public Vector2d worldPointToMapPointFLOAT(Vec3 worldPoint) { + if (context.getDungeonMin() == null) return null; + double x = topLeftMapPoint.x + ((worldPoint.xCoord - context.getDungeonMin().getX()) / 32.0f * (unitRoomDimension.width + doorDimensions.height)); + double y = topLeftMapPoint.y + ((worldPoint.zCoord - context.getDungeonMin().getZ()) / 32.0f * (unitRoomDimension.height + doorDimensions.height)); + return new Vector2d(x, y); + } + + private void processMap(byte[] mapData) { + int roomHeight = (int) ((128.0 - topLeftMapPoint.y) / (unitRoomDimension.height + doorDimensions.height)); + int roomWidth = (int) ((128.0 - topLeftMapPoint.x) / (unitRoomDimension.width + doorDimensions.height)); + if (MapUtils.getMapColorAt(mapData, 0, 0) != 0) return; + undiscoveredRoom = 0; + for (int y = 0; y <= roomHeight; y++) { + for (int x = 0; x <= roomWidth; 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.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 room = buildRoom(mapData, new Point(x, y)); + + + // USELESS DEBUG CODE + context.createEvent(new DungeonRoomDiscoverEvent(room.getUnitPoints().get(0), room.getRoomMatcher().getRotation(), new SerializableBlockPos(room.getMin()), new SerializableBlockPos(room.getMax()), room.getShape(), room.getColor(), room.getDungeonRoomInfo().getUuid(), room.getDungeonRoomInfo().getName(), room.getDungeonRoomInfo().getProcessorId())); + ChatTransmitter.sendDebugChat(new ChatComponentText("New Map discovered! shape: " + room.getShape() + " color: " + room.getColor() + " unitPos: " + x + "," + y)); + ChatTransmitter.sendDebugChat(new ChatComponentText("New Map discovered! mapMin: " + room.getMin() + " mapMx: " + room.getMax())); + StringBuilder builder = new StringBuilder(); + for (int dy = 0; dy < 4; dy++) { + builder.append("\n"); + for (int dx = 0; dx < 4; dx++) { + boolean isSet = ((room.getShape() >> (dy * 4 + dx)) & 0x1) != 0; + builder.append(isSet ? "O" : "X"); + } + } + ChatTransmitter.sendDebugChat(new ChatComponentText("Shape visual: " + builder)); + // END + + + context.getDungeonRoomList().add(room); + for (Point p : room.getUnitPoints()) { + roomsFound.add(p); + context.getRoomMapper().put(p, room); + } + if (room.getRoomProcessor() != null && room.getRoomProcessor().readGlobalChat()) { + context.getGlobalRoomProcessors().add(room.getRoomProcessor()); + } + } else if (color == 85) { + undiscoveredRoom++; + } + + } + } + } + + private DungeonRoom buildRoom(byte[] mapData, Point unitPoint) { + Queue<Point[]> toCheck = new LinkedList<>(); + toCheck.add(new Point[]{unitPoint, unitPoint}); // requestor, target + Set<Point> checked = new HashSet<>(); + List<Point> ayConnected = new ArrayList<>(); + + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + int maxX = 0; + int 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; + int 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 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); + int 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)); + } + + } + + + return new DungeonRoom(ayConnected, shape, unit1, roomPointToWorldPoint(new Point(minX, minY)), roomPointToWorldPoint(new Point(maxX + 1, maxY + 1)).add(-1, 0, -1), context, doorsAndStates); + + } + + private boolean checkIfConnected(byte[] mapData, Point unitPoint1, Point unitPoint2) { + if (unitPoint1 == unitPoint2) return true; + if (unitPoint1.equals(unitPoint2)) return true; + + + Point high; + if (unitPoint2.y > unitPoint1.y) { + high = unitPoint2; + } else { + if (unitPoint2.x > unitPoint1.x) { + high = unitPoint2; + } else { + high = unitPoint1; + } + } + + Point low; + if (high == unitPoint2) { + low = unitPoint1; + } else { + low = 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[] colorData, byte[] colorData1) { + + return true; +// boolean equals = Arrays.equals(colorData1, colorData); +// +// boolean foundDIffrentThen0 = false; +// +// +// for (byte colorDatum : colorData) { +// if(colorDatum != 0){ +// foundDIffrentThen0 = true; +// break; +// } +// } +// +// +// return !(equals && foundDIffrentThen0); + } + + 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); + + + FeatureRegistry.ETC_COLLECT_SCORE.collectDungeonRunData(mapData, context); + + } + + private void getPlayersFromMap(MapData mapdata) { + + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("Getting players from map"); + + for (Map.Entry<String, Vec4b> stringVec4bEntry : mapdata.mapDecorations.entrySet()) { + String mapDecString = stringVec4bEntry.getKey(); + Vec4b vec4 = stringVec4bEntry.getValue(); + + if (!mapIconToPlayerMap.containsValue(mapDecString)) { + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("mapIconToPlayerMap dosent have Player"); + + int x = vec4.func_176112_b() / 2 + 64; + int y = vec4.func_176113_c() / 2 + 64; + BlockPos mapPos = mapPointToWorldPoint(new Point(x, y)); + String potentialPlayer = null; + + for (String player : context.getPlayers()) { + if (DungeonsGuide.getDungeonsGuide().verbose) + logger.info("Player: {} isNear: {} ", player, isPlayerNear(player, mapPos)); +// if (!mapIconToPlayerMap.containsKey(player) && isPlayerNear(player, mapPos)) { + if (!mapIconToPlayerMap.containsKey(player)) { + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("Potential profile is: " + player); + potentialPlayer = player; + break; + } + } + + + if (potentialPlayer != null) { + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("potentialPlayer is not null"); + boolean shouldSave = true; + + for (Map.Entry<String, Vec4b> vec4bEntry : mapdata.mapDecorations.entrySet()) { +// String aaa = vec4bEntry.getKey(); + Vec4b bbb = vec4bEntry.getValue(); + +// if (mapIconToPlayerMap.containsValue(aaa) || mapDecString.equals(aaa)) { +// shouldSave = false; +// break; +// } +// else { + int x2 = bbb.func_176112_b() / 2 + 64; + int y2 = bbb.func_176113_c() / 2 + 64; + int dx = x2 - x; + int dy = y2 - y; + if (dx * dx + dy * dy < clossnessDistance) { + shouldSave = false; + break; + } +// } + } + + if (shouldSave) { + if (DungeonsGuide.getDungeonsGuide().verbose) + logger.info("added {} to mapIconPlayerMap with {}", potentialPlayer, stringVec4bEntry.getKey()); + if (mapIconToPlayerMap.containsKey(potentialPlayer)) { + mapIconToPlayerMap.replace(potentialPlayer, stringVec4bEntry.getKey()); + } else { + mapIconToPlayerMap.put(potentialPlayer, stringVec4bEntry.getKey()); + } + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("mapIconToPlayerMap:"); + if (DungeonsGuide.getDungeonsGuide().verbose) + mapIconToPlayerMap.forEach((key, value) -> logger.info(" {}: {}", key, value)); + } else { + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("shouldSave is false"); + } + + + } else { + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("potentialPlayer is null"); + } + + } else { + if (DungeonsGuide.getDungeonsGuide().verbose) logger.info("mapIconToPlayerMap has player "); + } + } + + + } + + private boolean isPlayerNear(String player, BlockPos mapPos) { + EntityPlayer entityPlayer = Minecraft.getMinecraft().theWorld.getPlayerEntityByName(player); + + if (entityPlayer != null && !entityPlayer.isInvisible()) { + BlockPos pos = entityPlayer.getPosition(); + int dx = mapPos.getX() - pos.getX(); + int dz = mapPos.getZ() - pos.getZ(); + return dx * dx + dz * dz < clossnessDistance; + + } + + return false; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/AbstractAction.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/AbstractAction.java new file mode 100644 index 00000000..d465fd47 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/AbstractAction.java @@ -0,0 +1,61 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.util.Set; + +public abstract class AbstractAction { + public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRouteProperties actionRouteProperties){ + + } + + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, ActionRouteProperties actionRouteProperties, boolean flag) { + + } + + public void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRouteProperties actionRouteProperties) { + + } + + public void onRenderScreen(DungeonRoom dungeonRoom, float partialTicks, ActionRouteProperties actionRouteProperties) { + + } + + public void onLivingInteract(DungeonRoom dungeonRoom, PlayerInteractEntityEvent event, ActionRouteProperties actionRouteProperties) { + + } + + public void onTick(DungeonRoom dungeonRoom, ActionRouteProperties actionRouteProperties) { + + } + + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return null; + } + + public boolean isComplete(DungeonRoom dungeonRoom) { + return false; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionBreakWithSuperBoom.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionBreakWithSuperBoom.java new file mode 100755 index 00000000..baab261f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionBreakWithSuperBoom.java @@ -0,0 +1,103 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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 +@EqualsAndHashCode(callSuper=false) +public class ActionBreakWithSuperBoom extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<AbstractAction>(); + private OffsetPoint target; + + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return false; + } + + public ActionBreakWithSuperBoom(OffsetPoint target) { + this.target = target; + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionChangeState.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionChangeState.java new file mode 100755 index 00000000..634129c6 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionChangeState.java @@ -0,0 +1,75 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDummy; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.dunegonmechanic.DungeonMechanic; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.HashSet; +import java.util.Set; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ActionChangeState extends AbstractAction { + @EqualsAndHashCode.Exclude + private Set<AbstractAction> preRequisite2 = new HashSet<AbstractAction>(); + + private String mechanicName; + private String state; + + public ActionChangeState(String mechanicName, String state) { + this.mechanicName = mechanicName; + this.state = state; + } + + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + Set<AbstractAction> set = new HashSet<>(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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionClick.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionClick.java new file mode 100755 index 00000000..c9ffb81c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionClick.java @@ -0,0 +1,82 @@ +/* + * 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.mod.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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 +@EqualsAndHashCode(callSuper=false) +public class ActionClick extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<AbstractAction>(); + private OffsetPoint target; + private Predicate<ItemStack> predicate = Predicates.alwaysTrue(); + + private boolean clicked = false; + + public ActionClick(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return clicked; + } + + @Override + public void onPlayerInteract(DungeonRoom dungeonRoom, PlayerInteractEvent event, ActionRouteProperties actionRouteProperties) { + if (clicked) return; + if (target.getBlockPos(dungeonRoom).equals(event.pos) && + (predicate == null || predicate.apply(event.entityLiving.getHeldItem()))) { + clicked = true; + ChatTransmitter.sendDebugChat("ACTION FINISHED: CLICK"); + } + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionClickSet.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionClickSet.java new file mode 100755 index 00000000..01f5b9b2 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionClickSet.java @@ -0,0 +1,90 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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; +import java.util.function.Predicate; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ActionClickSet extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<>(); + private OffsetPointSet target; + private Predicate<ItemStack> predicate = stack -> true; + + public ActionClickSet(OffsetPointSet target) { + this.target = target; + } + + @Override + public Set<AbstractAction> 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, ActionRouteProperties actionRouteProperties) { + if (clicked) return; + for (OffsetPoint pt2: target.getOffsetPointList()) { + if (pt2.getBlockPos(dungeonRoom).equals(event.pos) && predicate.test(event.entityLiving.getHeldItem())) { + clicked = true; + } + } + + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionComplete.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionComplete.java new file mode 100644 index 00000000..32d6bfc3 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; + +import java.util.Collections; +import java.util.Set; + +public class ActionComplete extends AbstractAction { + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return Collections.emptySet(); + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return false; + } + + @Override + public String toString() { + return "Completed"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionDropItem.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionDropItem.java new file mode 100755 index 00000000..0c94e5ae --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionDropItem.java @@ -0,0 +1,82 @@ +/* + * 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.mod.dungeon.actions; + +import com.google.common.base.Predicate; +import com.google.common.base.Predicates; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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 +@EqualsAndHashCode(callSuper = false) +public class ActionDropItem extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<>(); + private OffsetPoint target; + private Predicate<EntityItem> predicate = Predicates.alwaysTrue(); + + public ActionDropItem(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + BlockPos secretLocation = target.getBlockPos(dungeonRoom); + List<EntityItem> item = dungeonRoom.getContext().getWorld().getEntitiesWithinAABB(EntityItem.class, + AxisAlignedBB.fromBounds( + secretLocation.getX(), + secretLocation.getY(), + secretLocation.getZ(), + secretLocation.getX() + 1, + secretLocation.getY() + 1, + secretLocation.getZ() + 1)); + if (item.isEmpty()) { + return false; + } + return (predicate == null || predicate.apply(item.get(0))); + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionInteract.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionInteract.java new file mode 100755 index 00000000..b41e1b7a --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionInteract.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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonActionContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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; +import java.util.function.Predicate; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ActionInteract extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<>(); + private OffsetPoint target; + private Predicate<Entity> predicate = entity -> false; + private int radius; + + public ActionInteract(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<AbstractAction> 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, ActionRouteProperties actionRouteProperties) { + if (interacted) return; + + Vec3 spawnLoc = DungeonActionContext.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.test(event.getEntity())) { + return; + } + interacted = true; + } + + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, 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.test(null) ? "null" : predicate.getClass().getSimpleName()); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionKill.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionKill.java new file mode 100755 index 00000000..94569ad1 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionKill.java @@ -0,0 +1,90 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonActionContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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; +import java.util.function.Predicate; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ActionKill extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<AbstractAction>(); + private OffsetPoint target; + private Predicate<Entity> predicate = entity -> false; + private int radius; + + public ActionKill(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + Vec3 spawn = new Vec3(target.getBlockPos(dungeonRoom)); + for (Integer killed : DungeonActionContext.getKilleds()) { + if (DungeonActionContext.getSpawnLocation().get(killed) == null) continue; + if (DungeonActionContext.getSpawnLocation().get(killed).squareDistanceTo(spawn) < 100) { + return true; + } + } + + return killed; + } + + private boolean killed = false; + @Override + public void onLivingDeath(DungeonRoom dungeonRoom, LivingDeathEvent event, ActionRouteProperties actionRouteProperties) { + if (killed) return; + + Vec3 spawnLoc = DungeonActionContext.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.test(event.entity)) return; + killed = true; + } + @Override + public void onRenderWorld(DungeonRoom dungeonRoom, float partialTicks, 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.test(null) ? "null" : predicate.getClass().getSimpleName()); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java new file mode 100755 index 00000000..f499032d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMove.java @@ -0,0 +1,122 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Data; +import lombok.EqualsAndHashCode; +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 +@EqualsAndHashCode(callSuper=false) +public class ActionMove extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<>(); + private OffsetPoint target; + + public ActionMove(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<AbstractAction> 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, ActionRouteProperties actionRouteProperties, boolean flag) { + draw(dungeonRoom, partialTicks, actionRouteProperties, flag, target, poses); + } + + static void draw(DungeonRoom dungeonRoom, float partialTicks, ActionRouteProperties actionRouteProperties, boolean flag, OffsetPoint target, List<Vec3> poses) { + 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()) { + if(!FeatureRegistry.RENDER_BREACONS.isEnabled()){ + RenderUtils.renderBeaconBeam(pos.getX(), pos.getY(), pos.getZ(), actionRouteProperties.getBeaconBeamColor(), partialTicks); + } + RenderUtils.highlightBlock(pos, actionRouteProperties.getBeaconColor(), partialTicks); + } + if(!FeatureRegistry.RENDER_DESTENATION_TEXT.isEnabled()){ + 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, 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) { + if (latestFuture == null) { + 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java new file mode 100755 index 00000000..54e8b1a8 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionMoveNearestAir.java @@ -0,0 +1,92 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import lombok.Data; +import lombok.EqualsAndHashCode; +import net.minecraft.client.Minecraft; +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 +@EqualsAndHashCode(callSuper=false) +public class ActionMoveNearestAir extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<>(); + private OffsetPoint target; + + public ActionMoveNearestAir(OffsetPoint target) { + this.target = target; + } + + @Override + public Set<AbstractAction> 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, ActionRouteProperties actionRouteProperties, boolean flag) { + ActionMove.draw(dungeonRoom, partialTicks, actionRouteProperties, flag, target, poses); + } + + private int tick = -1; + private List<Vec3> poses; + private Future<List<Vec3>> latestFuture; + @Override + public void onTick(DungeonRoom dungeonRoom, 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) { + if (latestFuture == null) { + 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionRoot.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionRoot.java new file mode 100755 index 00000000..23b9fdce --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/ActionRoot.java @@ -0,0 +1,47 @@ +/* + * 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.mod.dungeon.actions; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.HashSet; +import java.util.Set; + +@Data +@EqualsAndHashCode(callSuper=false) +public class ActionRoot extends AbstractAction { + private Set<AbstractAction> preRequisite = new HashSet<>(); + + @Override + public Set<AbstractAction> getPreRequisites(DungeonRoom dungeonRoom) { + return preRequisite; + } + + @Override + public boolean isComplete(DungeonRoom dungeonRoom) { + return true; + } + + @Override + public String toString() { + return "Action Root"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionRoute.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionRoute.java new file mode 100644 index 00000000..17cea18d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionRoute.java @@ -0,0 +1,136 @@ +/* + * 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.mod.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +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<AbstractAction> 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; + + System.out.println("Creating Action Route with mechanic:" + mechanic + " State:" + state); + ActionChangeState actionChangeState = new ActionChangeState(mechanic, state); + ActionTree tree= ActionTree.buildActionTree(actionChangeState, dungeonRoom); + actions = ActionTreeUtil.linearifyActionTree(tree); + actions.add(new ActionComplete()); + ChatTransmitter.sendDebugChat("Created ActionRoute with " + actions.size() + " steps"); + ChatTransmitter.sendDebugChat("========== STEPS =========="); + for (AbstractAction action : actions) { + ChatTransmitter.sendDebugChat(action.toString()); + } + ChatTransmitter.sendDebugChat("=========== END ==========="); + + + current = 0; + this.dungeonRoom = dungeonRoom; + } + + public AbstractAction next() { + current ++; + if (current >= actions.size()) { + current = actions.size() - 1; + } + return getCurrentAction(); + } + + public AbstractAction prev() { + current --; + if (current < 0) { + current = 0; + } + return getCurrentAction(); + } + + public AbstractAction 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) { + AbstractAction abstractAction = actions.get(current - 1); + if(((abstractAction instanceof ActionMove && ((ActionMove) abstractAction).getTarget().getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) >= 25) + || (abstractAction instanceof ActionMoveNearestAir && ((ActionMoveNearestAir) abstractAction).getTarget().getBlockPos(dungeonRoom).distanceSq(Minecraft.getMinecraft().thePlayer.getPosition()) >= 25))){ + abstractAction.onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag ); + } + } + getCurrentAction().onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag); + + + getCurrentAction().onRenderWorld(dungeonRoom, partialTicks, actionRouteProperties, flag); + } + + public void onRenderScreen(float partialTicks) { + getCurrentAction().onRenderScreen(dungeonRoom, partialTicks, actionRouteProperties); + } + + public void onTick() { + AbstractAction currentAction = getCurrentAction(); + + currentAction.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 (currentAction.isComplete(dungeonRoom)) { + next(); + } + } + + public void onLivingInteract(PlayerInteractEntityEvent event) { + getCurrentAction().onLivingInteract(dungeonRoom, event, actionRouteProperties ); + } + +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionRouteProperties.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionRouteProperties.java new file mode 100644 index 00000000..df32e718 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionRouteProperties.java @@ -0,0 +1,16 @@ +package kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import lombok.Data; + +@Data +public 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionTree.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionTree.java new file mode 100755 index 00000000..99846fc7 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionTree.java @@ -0,0 +1,94 @@ +/* + * 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.mod.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.AbstractAction; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.ActionRoot; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +@Data +public class ActionTree implements Cloneable { + @EqualsAndHashCode.Exclude + private Set<ActionTree> parent; + private AbstractAction current; + private Set<ActionTree> children; + + @Override + public int hashCode() { return current == null ? 0 : current.hashCode(); } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ActionTree that = (ActionTree) o; + return Objects.equals(parent, that.parent) && Objects.equals(current, that.current) && Objects.equals(children, that.children); + } + + public static ActionTree buildActionTree(Set<AbstractAction> actions, DungeonRoom dungeonRoom) { + ActionRoot root = new ActionRoot(); + root.setPreRequisite(actions); + ActionTree tree = new ActionTree(); + tree.setParent(new HashSet<>()); + tree.setCurrent(root); + HashSet<ActionTree> set = new HashSet<>(); + for (AbstractAction action : actions) { + set.add(buildActionTree(tree, action, dungeonRoom, new HashMap<>())); + } + tree.setChildren(set); + return tree; + } + public static ActionTree buildActionTree(AbstractAction actions, DungeonRoom dungeonRoom) { + return buildActionTree(null, actions, dungeonRoom, new HashMap<>()); + } + + + + private static ActionTree buildActionTree(ActionTree parent, @NotNull AbstractAction action,@NotNull DungeonRoom dungeonRoom, @NotNull Map<AbstractAction, ActionTree> alreadyBuilt) { + 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<>()); + if (parent != null) { + tree.getParent().add(parent); + } + tree.setCurrent(action); + HashSet<ActionTree> set = new HashSet<>(); + + Set<AbstractAction> preRequisites = action.getPreRequisites(dungeonRoom); + if(preRequisites != null){ + for (AbstractAction action2 : preRequisites) { + ActionTree e = buildActionTree(tree, action2, dungeonRoom, alreadyBuilt); + set.add(e); + } + } + + tree.setChildren(set); + return tree; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionTreeUtil.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/actions/tree/ActionTreeUtil.java new file mode 100644 index 00000000..18c17c17 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/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.mod.dungeon.actions.tree; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.AbstractAction; + +import java.util.*; + +public class ActionTreeUtil { + public static List<AbstractAction> linearifyActionTree(ActionTree input) { + ActionTree tree = copyActionTree(input); + + List<AbstractAction> actions = new ArrayList<AbstractAction>(); + + 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonDoor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonDoor.java new file mode 100755 index 00000000..15004dcc --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonDoor.java @@ -0,0 +1,87 @@ +/* + * 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.mod.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 final 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonSpecificDataProvider.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonSpecificDataProvider.java new file mode 100755 index 00000000..b34986eb --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonSpecificDataProvider.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.mod.dungeon.doorfinder; + +import kr.syeyoung.dungeonsguide.mod.dungeon.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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java new file mode 100755 index 00000000..48b24120 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/DungeonSpecificDataProviderRegistry.java @@ -0,0 +1,42 @@ +/* + * 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.mod.dungeon.doorfinder; + +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.catacombs.impl.NormalModeDataProvider; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.catacombs.impl.MasterModeDataProvider; + +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<>(); + + static { + doorFinders.put(Pattern.compile("The Catacombs (?:F[0-9]|E)"), new NormalModeDataProvider()); + doorFinders.put(Pattern.compile("The Catacombs (?:M[0-9])"), new MasterModeDataProvider()); + } + + 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/EDungeonDoorType.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/EDungeonDoorType.java new file mode 100644 index 00000000..05915a1a --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/EDungeonDoorType.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.mod.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 final boolean exist; + private final boolean keyRequired; + private final boolean headToBlood; + private final String name; +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/CatacombsDataProvider.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/CatacombsDataProvider.java new file mode 100644 index 00000000..b9052353 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/CatacombsDataProvider.java @@ -0,0 +1,75 @@ +package kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.catacombs; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonSpecificDataProvider; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import javax.vecmath.Vector2d; +import java.util.Collection; +import java.util.Set; + +public abstract class CatacombsDataProvider 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)); + + @Nullable + static Vector2d getVector2d(World w, Collection<EntityArmorStand> armorStand, Set<Vector2d> directions) { + 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; + } + + public static Collection<EntityArmorStand> getMorts(World w){ + return w.getEntities(EntityArmorStand.class, input -> input.getName().equals("§bMort")); + } + + /** + * This gets all morts checks for iron bars near him + * and based on iron bars determine the door location + * + * @param w World that we are going to look for the door in + * world is explicitly specified instead of mc.theWorld bc we can use cached worlds + * @param dungeonName dungeon type eg master mode, currently unused + * @return Block pos of the dungeon entrance + */ + public BlockPos findDoor(World w, String dungeonName) { + Collection<EntityArmorStand> armorStand = getMorts(w); + + if (!armorStand.isEmpty()) { + 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; + } + + public Vector2d findDoorOffset(World w, String dungeonName) { + Collection<EntityArmorStand> armorStand = getMorts(w); + + if (!armorStand.isEmpty()) { + return getVector2d(w, armorStand, directions); + } + return null; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/impl/MasterModeDataProvider.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/impl/MasterModeDataProvider.java new file mode 100755 index 00000000..ab3f5df3 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/impl/MasterModeDataProvider.java @@ -0,0 +1,64 @@ +/* + * 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.mod.dungeon.doorfinder.catacombs.impl; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.catacombs.CatacombsDataProvider; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.BossfightProcessorLivid; +import net.minecraft.util.ChatComponentText; +import net.minecraft.world.World; + +public class MasterModeDataProvider extends CatacombsDataProvider { + + + @Override + public BossfightProcessor createBossfightProcessor(World w, String dungeonName) { + String floor = dungeonName.substring(14).trim(); + ChatTransmitter.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(); + switch (floor) { + case "M3": + case "M4": + case "M5": + case "M6": + return true; + default: + return floor.equals("M7"); + } + } + + @Override + public double secretPercentage(String dungeonName) { + return 1.0; + } + + @Override + public int speedSecond(String dungeonName) { + return 480; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/impl/NormalModeDataProvider.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/impl/NormalModeDataProvider.java new file mode 100755 index 00000000..880cf473 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/doorfinder/catacombs/impl/NormalModeDataProvider.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.mod.dungeon.doorfinder.catacombs.impl; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.catacombs.CatacombsDataProvider; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bossfight.*; +import net.minecraft.util.ChatComponentText; +import net.minecraft.world.World; + +public class NormalModeDataProvider extends CatacombsDataProvider { + + + @Override + public BossfightProcessor createBossfightProcessor(World w, String dungeonName) { + String floor = dungeonName.substring(14).trim(); + ChatTransmitter.sendDebugChat(new ChatComponentText("Floor: "+floor+ " Building bossfight processor")); + switch (floor) { + case "F1": + return new BossfightProcessorBonzo(); + case "F2": + return new BossfightProcessorScarf(); + case "F3": + return new BossfightProcessorProf(); + case "F4": + return new BossfightProcessorThorn(); + case "F5": + return new BossfightProcessorLivid(false); + case "F6": + return new BossfightProcessorSadan(); + case "F7": + return new BossfightProcessorNecron(); + default: + return null; + } + } + + @Override + public boolean isTrapSpawn(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + switch (floor) { + case "F3": + case "F4": + case "F5": + case "F6": + return true; + default: + return floor.equals("F7"); + } + } + + @Override + public double secretPercentage(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + switch (floor) { + case "F1": + case "E": + return 0.3; + case "F2": + return 0.4; + case "F3": + return 0.5; + case "F4": + return 0.6; + case "F5": + return 0.7; + case "F6": + return 0.85; + default: + return 1.0; + } + } + + @Override + public int speedSecond(String dungeonName) { + String floor = dungeonName.substring(14).trim(); + switch (floor) { + case "F5": + case "F7": + return 720; + default: + return 600; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/DungeonEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/DungeonEvent.java new file mode 100644 index 00000000..0e71a65e --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/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.mod.dungeon.events; + +import kr.syeyoung.dungeonsguide.mod.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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/DungeonEventData.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/DungeonEventData.java new file mode 100644 index 00000000..812e1488 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/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.mod.dungeon.events; + +import java.io.Serializable; + +public interface DungeonEventData extends Serializable { + String getEventName(); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/DungeonEventHolder.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/DungeonEventHolder.java new file mode 100644 index 00000000..58799f80 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/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.mod.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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/SerializableBlockPos.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/SerializableBlockPos.java new file mode 100644 index 00000000..d70ba2c2 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/SerializableBlockPos.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.mod.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; + private int y; + private int z; + + public SerializableBlockPos(BlockPos pos) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonCryptBrokenEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonCryptBrokenEvent.java new file mode 100644 index 00000000..c2a4f71e --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonCryptBrokenEvent.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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonDeathEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonDeathEvent.java new file mode 100644 index 00000000..09877b80 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonDeathEvent.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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonMapUpdateEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonMapUpdateEvent.java new file mode 100644 index 00000000..023902c8 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonMapUpdateEvent.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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonNodataEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonNodataEvent.java new file mode 100644 index 00000000..531f5990 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonNodataEvent.java @@ -0,0 +1,29 @@ +/* + * 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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class DungeonNodataEvent implements DungeonEventData { + private String eventName; +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonPuzzleFailureEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonPuzzleFailureEvent.java new file mode 100644 index 00000000..64621339 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonPuzzleFailureEvent.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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonRoomDiscoverEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonRoomDiscoverEvent.java new file mode 100644 index 00000000..09fd64a5 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonRoomDiscoverEvent.java @@ -0,0 +1,46 @@ +/* + * 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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.SerializableBlockPos; +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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonSecretCountChangeEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonSecretCountChangeEvent.java new file mode 100644 index 00000000..21ea853c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonSecretCountChangeEvent.java @@ -0,0 +1,37 @@ +/* + * 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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonStateChangeEvent.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonStateChangeEvent.java new file mode 100644 index 00000000..f1cb1167 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/events/impl/DungeonStateChangeEvent.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.mod.dungeon.events.impl; + +import kr.syeyoung.dungeonsguide.mod.dungeon.events.DungeonEventData; +import kr.syeyoung.dungeonsguide.mod.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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/map/DungeonMapData.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/map/DungeonMapData.java new file mode 100644 index 00000000..9687d554 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/map/DungeonMapData.java @@ -0,0 +1,121 @@ +package kr.syeyoung.dungeonsguide.mod.dungeon.map; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.MapProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonSpecificDataProvider; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonSpecificDataProviderRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonNodataEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.DungeonContextInitializationEvent; +import kr.syeyoung.dungeonsguide.mod.utils.MapUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraftforge.common.MinecraftForge; + +import javax.vecmath.Vector2d; +import java.awt.*; +import java.util.Set; + +public class DungeonMapData { + 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 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)); + public Dimension unitRoomDimension; + public boolean bugged; + public Dimension doorDimensions; + public Point topLeftMapPoint; + private final DungeonContext context; + private final Minecraft mc; + public boolean initialized; + + public DungeonMapData(DungeonContext context, Minecraft mc) { + this.context = context; + this.mc = mc; + } + + + public void eat(final byte[] mapData){ + final Point firstRoom = MapUtils.findFirstColorWithIn(mapData, (byte) 30, new Rectangle(0, 0, 128, 128)); + // Determine room dimension + int width = MapUtils.getWidthOfColorAt(mapData, (byte) 30, firstRoom); + int height = MapUtils.getHeightOfColorAt(mapData, (byte) 30, firstRoom); + unitRoomDimension = new Dimension(width, height); + Vector2d doorDir = null; + Point midfirstRoom = new Point(firstRoom.x + unitRoomDimension.width / 2, firstRoom.y + unitRoomDimension.height / 2); + final int halfWidth = unitRoomDimension.width / 2 + 2; + for (Vector2d v : directions) { + byte color = MapUtils.getMapColorAt(mapData, (int) (v.x * halfWidth + midfirstRoom.x), (int) (v.y * halfWidth + midfirstRoom.y)); + if (color != 0) { + doorDir = v; + break; + } + } + + if (doorDir == null) { + bugged = true; + return; + } + + Point basePoint = new Point(firstRoom.x, firstRoom.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) { + 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))); + doorDimensions = new Dimension(doorWidth, gap); + + // Determine Top Left + int topLeftX = firstRoom.x; + int topLeftY = firstRoom.y; + while (topLeftX >= unitRoomDimension.width + doorDimensions.height) + topLeftX -= unitRoomDimension.width + doorDimensions.height; + while (topLeftY >= unitRoomDimension.height + doorDimensions.height) + topLeftY -= unitRoomDimension.height + doorDimensions.height; + topLeftMapPoint = new Point(topLeftX, topLeftY); + // determine door location based on npc, and determine map min from there + DungeonSpecificDataProvider doorFinder = DungeonSpecificDataProviderRegistry.getDoorFinder(DungeonContext.getDungeonName()); + if (doorFinder == null) { + bugged = true; + return; + } + BlockPos door = doorFinder.findDoor(mc.theWorld, DungeonContext.getDungeonName()); + if (door == null) { + bugged = true; + return; + } + + ChatTransmitter.sendDebugChat(new ChatComponentText("door Pos:" + door)); + + Point unitPoint = MapProcessor.mapPointToRoomPoint(firstRoom, topLeftMapPoint, unitRoomDimension, doorDimensions); + unitPoint.translate(unitPoint.x + 1, unitPoint.y + 1); + unitPoint.translate((int) doorDir.x, (int) doorDir.y); + + Vector2d offset = doorFinder.findDoorOffset(mc.theWorld, DungeonContext.getDungeonName()); + boolean axisMatch = doorDir.equals(offset); + + int worldX = unitPoint.x * 16; + int worldY = unitPoint.y * 16; + BlockPos worldMin = door.add(-worldX, 0, -worldY); + context.setDungeonMin(worldMin); + + ChatTransmitter.sendDebugChat(new ChatComponentText("Found Green room:" + firstRoom)); + ChatTransmitter.sendDebugChat(new ChatComponentText("Axis match:" + axisMatch)); + ChatTransmitter.sendDebugChat(new ChatComponentText("World Min:" + context.getDungeonMin())); + ChatTransmitter.sendDebugChat(new ChatComponentText("Dimension:" + unitRoomDimension)); + ChatTransmitter.sendDebugChat(new ChatComponentText("top Left:" + topLeftMapPoint)); + ChatTransmitter.sendDebugChat(new ChatComponentText("door dimension:" + doorDimensions)); + context.createEvent(new DungeonNodataEvent("MAP_PROCESSOR_INIT")); + initialized = true; + MinecraftForge.EVENT_BUS.post(new DungeonContextInitializationEvent()); + + + } + +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarCornerCut.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarCornerCut.java new file mode 100644 index 00000000..f6ac1777 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarCornerCut.java @@ -0,0 +1,189 @@ +/* + * 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.mod.dungeon.pathfinding; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class AStarCornerCut { + private final BlockPos min, max; + private final World world; + + int lastSx, lastSy, lastSz; + final int dx, dy, dz; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public AStarCornerCut(DungeonRoom dungeonRoom, Vec3 destination) { + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + + this.dx = (int) (destination.xCoord * 2); + this.dy = (int) (destination.yCoord * 2); + this.dz = (int) (destination.zCoord * 2); + destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); + } + + private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); + + private Node openNode(int x, int y, int z) + { + Node.Coordinate coordinate = new Node.Coordinate(x,y,z); + Node node = this.nodeMap.get(coordinate); + + if (node == null) + { + node = new Node(coordinate); + this.nodeMap.put(coordinate, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); + + private int pfindIdx = 0; + + public boolean pathfind(Vec3 from, long timeout) { + pfindIdx ++; + if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) + open.clear(); + + this.lastSx = (int) Math.round(from.xCoord * 2); + this.lastSy = (int) Math.round(from.yCoord * 2); + this.lastSz = (int) Math.round(from.zCoord * 2); + + Node startNode = openNode(dx, dy, dz); + Node goalNode = openNode(lastSx, lastSy, lastSz); + + if (goalNode.parent != null) { + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + startNode.g = 0; + startNode.f = 0; + goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; + + + open.add(startNode); + + long end = System.currentTimeMillis() + timeout; + + while (!open.isEmpty()) { + if (System.currentTimeMillis() > end) { + return false; + } + + Node n = open.poll(); + if (n.lastVisited == pfindIdx) continue; + n.lastVisited = pfindIdx; + + if (n == goalNode) { + // route = reconstructPath(startNode) + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + for (int z = -1; z <= 1; z++) {for (int y = -1; y <= 1; y ++) { for(int x = -1; x <= 1; x++) { + if (x == 0 && y == 0 && z == 0) continue; + Node neighbor = openNode(n.coordinate.x +x, n.coordinate.y +y, n.coordinate.z + z); + + // check blocked. + if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && + destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && + destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination + || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked + continue; + } + if (neighbor.lastVisited == pfindIdx) continue; + + + float gScore = n.g + MathHelper.sqrt_float(x*x + y*y + z*z); // altho it's sq, it should be fine + if (gScore < neighbor.g ) { + neighbor.parent = n; + neighbor.g = gScore; + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } else if (neighbor.lastVisited != pfindIdx) { + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } + }}} + } + return true; + } + + private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + @RequiredArgsConstructor + @Data + public static final class Node { + @Data + @RequiredArgsConstructor + public static final class Coordinate { + private final int x, y, z; + } + private final Coordinate coordinate; + + private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; + private int lastVisited; + + @EqualsAndHashCode.Exclude + private Node parent; + + public static long makeHash(int x, int y, int z) + { + return y & 32767L | ((short)x & 32767L) << 16 | ((short)z & 32767L) << 32; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarFineGrid.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarFineGrid.java new file mode 100644 index 00000000..8cb49a10 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/AStarFineGrid.java @@ -0,0 +1,182 @@ +/* + * 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.mod.dungeon.pathfinding; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class AStarFineGrid { + private final BlockPos min, max; + private final World world; + + int lastSx, lastSy, lastSz; + final int dx, dy, dz; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public AStarFineGrid(DungeonRoom dungeonRoom, Vec3 destination) { + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + + this.dx = (int) (destination.xCoord * 2); + this.dy = (int) (destination.yCoord * 2); + this.dz = (int) (destination.zCoord * 2); + destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); + } + + private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); + + private Node openNode(int x, int y, int z) + { + Node.Coordinate coordinate = new Node.Coordinate(x,y,z); + Node node = this.nodeMap.get(coordinate); + + if (node == null) + { + node = new Node(coordinate); + this.nodeMap.put(coordinate, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); + + private int pfindIdx = 0; + + public boolean pathfind(Vec3 from, long timeout) { + pfindIdx ++; + if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) + open.clear(); + + this.lastSx = (int) Math.round(from.xCoord * 2); + this.lastSy = (int) Math.round(from.yCoord * 2); + this.lastSz = (int) Math.round(from.zCoord * 2); + + Node startNode = openNode(dx, dy, dz); + Node goalNode = openNode(lastSx, lastSy, lastSz); + startNode.g = 0; + startNode.f = 0; + goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; + if (goalNode.parent != null) { + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + open.add(startNode); + + long end = System.currentTimeMillis() + timeout; + + while (!open.isEmpty()) { + if (System.currentTimeMillis() > end) { + return false; + } + + Node n = open.poll(); + if (n.lastVisited == pfindIdx) continue; + n.lastVisited = pfindIdx; + + if (n == goalNode) { + // route = reconstructPath(startNode) + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + for (EnumFacing value : EnumFacing.VALUES) { + Node neighbor = openNode(n.coordinate.x + value.getFrontOffsetX(), n.coordinate.y + value.getFrontOffsetY(), n.coordinate.z + value.getFrontOffsetZ()); + + // check blocked. + if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && + destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && + destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination + || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked + continue; + } + + float gScore = n.g + 1; // altho it's sq, it should be fine + if (gScore < neighbor.g) { + neighbor.parent = n; + neighbor.g = gScore; + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } else if (neighbor.lastVisited != pfindIdx) { + neighbor.f = gScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } + } + } + return true; + } + + private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + @RequiredArgsConstructor + @Data + public static final class Node { + @Data + @RequiredArgsConstructor + public static final class Coordinate { + private final int x, y, z; + } + private final Coordinate coordinate; + + private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; + private int lastVisited; + + @EqualsAndHashCode.Exclude + private Node parent; + + public static long makeHash(int x, int y, int z) + { + return y & 32767L | ((short)x & 32767L) << 16 | ((short)z & 32767L) << 32; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/CachedWorld.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/CachedWorld.java new file mode 100644 index 00000000..9d9644c6 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/CachedWorld.java @@ -0,0 +1,85 @@ +/* + * 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.mod.dungeon.pathfinding; + +import net.minecraft.block.state.IBlockState; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.*; +import net.minecraft.world.chunk.IChunkProvider; + +public class CachedWorld extends World { + private ChunkCache chunkCache; + + public CachedWorld(ChunkCache chunkCache) { + super(null, null, new WorldProviderSurface(), null, true); + this.chunkCache = chunkCache; + } + + @Override + protected IChunkProvider createChunkProvider() { + return null; + } + + @Override + protected int getRenderDistanceChunks() { + return 999; + } + + @Override + public boolean extendedLevelsInChunkCache() { + return chunkCache.extendedLevelsInChunkCache(); + } + + @Override + public TileEntity getTileEntity(BlockPos pos) { + return chunkCache.getTileEntity(pos); + } + + @Override + public int getCombinedLight(BlockPos pos, int lightValue) { + return chunkCache.getCombinedLight(pos, lightValue); + } + + @Override + public IBlockState getBlockState(BlockPos pos) { + return chunkCache.getBlockState(pos); + } + + @Override + public int getLightFor(EnumSkyBlock type, BlockPos pos) { + return chunkCache.getLightFor(type, pos); + } + + @Override + public boolean isAirBlock(BlockPos pos) { + return chunkCache.isAirBlock(pos); + } + + @Override + public int getStrongPower(BlockPos pos, EnumFacing direction) { + return chunkCache.getStrongPower(pos, direction); + } + + @Override + public boolean isSideSolid(BlockPos pos, EnumFacing side, boolean _default) { + return chunkCache.isSideSolid(pos, side, _default); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/JPSPathfinder.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/JPSPathfinder.java new file mode 100644 index 00000000..0a4e1b7d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/JPSPathfinder.java @@ -0,0 +1,306 @@ +/* + * 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.mod.dungeon.pathfinding; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class JPSPathfinder { + private final BlockPos min, max; + private final World world; + + private Vec3 start; + private Vec3 destination; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public JPSPathfinder(DungeonRoom dungeonRoom){ + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + } + + private IntHashMap<Node> nodeMap = new IntHashMap(); + + private Node openNode(int x, int y, int z) + { + int i = Node.makeHash(x, y, z); + Node node = this.nodeMap.lookup(i); + + if (node == null) + { + node = new Node(x, y, z); + this.nodeMap.addKey(i, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.z)); + + private int tx, ty, tz; + + private Node addNode(Node parent, Node jumpPt, boolean addToOpen) { + float ng = parent.g + distSq(jumpPt.x - parent.x, jumpPt.y - parent.y, jumpPt.z - parent.z); + + if (ng < jumpPt.g) { + if (addToOpen) + open.remove(jumpPt); + jumpPt.g = ng; + jumpPt.h = jumpPt.h == -1 ? distSq(tx - jumpPt.x, ty - jumpPt.y, tz - jumpPt.z) : jumpPt.h; + jumpPt.f = jumpPt.h + jumpPt.g; + jumpPt.parent = parent; + if (addToOpen) + open.add(jumpPt); + } + return jumpPt; + } + + + long arr[]; + + public boolean pathfind(Vec3 from, Vec3 to, float within, long timeout) { + route.clear(); nodeMap.clearMap(); + + { + from = new Vec3(((int)(from.xCoord * 2)) / 2.0, ((int)(from.yCoord * 2)) / 2.0, ((int)(from.zCoord* 2)) / 2.0); + to = new Vec3(((int)(to.xCoord * 2)) / 2.0, ((int)(to.yCoord * 2)) / 2.0, ((int)(to.zCoord* 2)) / 2.0); + } + + this.start = from; this.destination = to; + tx = (int)(to.xCoord * 2); + ty = (int)(to.yCoord * 2); + tz = (int)(to.zCoord * 2); + + destinationBB = AxisAlignedBB.fromBounds((to.xCoord - within)* 2, (to.yCoord - within) * 2, (to.zCoord - within) * 2, (to.xCoord + within) * 2, (to.yCoord + within)* 2, (to.zCoord + within) *2); + open.clear(); + Node start; + open.add(start = openNode((int)from.xCoord * 2 + 1, (int)from.yCoord * 2, (int)from.zCoord * 2+1)); + start.g = 0; start.f = 0; start.h = (float) from.squareDistanceTo(to); + + Node end = null; float minDist = Float.MAX_VALUE; + long forceEnd = System.currentTimeMillis() + timeout + 999999999L; + while(!open.isEmpty()) { + if (forceEnd < System.currentTimeMillis() && timeout != -1) break; + Node n = open.poll(); + n.closed= true; + if (minDist > n.h) { + minDist = n.h; + end = n; + } + if (n.x > destinationBB.minX && n.x < destinationBB.maxX && n.y > destinationBB.minY && n.y < destinationBB.maxY && n.z > destinationBB.minZ && n.z < destinationBB.maxZ) { + break; + } + + for (Node neighbor : getNeighbors(n.parent == null ? n : n.parent, n)) { + Node jumpPT = expand(n.x, n.y, n.z, neighbor.x - n.x, neighbor.y - n.y, neighbor.z - n.z); + if (jumpPT == null || jumpPT.closed) continue; + + addNode(n, jumpPT, true); + } + } + + if (end == null) return false; + Node p = end; + while (p != null) { + route.addLast(new Vec3(p.x / 2.0f, p.y / 2.0f + 0.1, p.z / 2.0f)); + p = p.parent; + } + + + return true; + } + + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + public Set<Node> getNeighbors(Node prevN, Node n) { +// if (true) throw new RuntimeException("ah"); + int dx = MathHelper.clamp_int(n.x - prevN.x, -1, 1); + int dy = MathHelper.clamp_int(n.y - prevN.y, -1, 1); + int dz = MathHelper.clamp_int(n.z - prevN.z, -1, 1); + int x = n.x, y = n.y, z = n.z; + int nx = n.x + dx, ny = n.y + dy, nz = n.z + dz; + + Set<Node> nexts = new HashSet<>(); + int determinant = Math.abs(dx) + Math.abs(dy) + Math.abs(dz); + if (determinant == 0) { + for (int i = -1; i <= 1; i++) + for (int j = -1; j <= 1; j++) + for (int k = -1; k <= 1; k++) { + if (i == 0 && j == 0 && k == 0) continue; + nexts.add(openNode(x+i, y+j, z+k)); + } + } else if (determinant == 1) { + nexts.add(openNode(nx,ny,nz)); + for (int i = -1; i<=1; i++) { + for (int j = - 1; j<=1; j++) { + if (i == 0 && j == 0) continue; + if (dx != 0 && dungeonRoom.isBlocked(x, y + i, z + j)) nexts.add(openNode(nx,y+i,z+j)); + if (dy != 0 && dungeonRoom.isBlocked(x + i, y, z + j)) nexts.add(openNode(x+i,ny,z+j)); + if (dz != 0 && dungeonRoom.isBlocked(x + i, y + j, z)) nexts.add(openNode(x+i,y+j,nz)); + } + } + } else if (determinant == 2) { + if (dz != 0) nexts.add(openNode(x,y,nz)); + if (dy != 0) nexts.add(openNode(x,ny,z)); + if (dx != 0) nexts.add(openNode(nx,y,z)); + nexts.add(openNode(nx,ny,nz)); + if (dx == 0) { + if (dungeonRoom.isBlocked(x, y, z-dz)) { + nexts.add(openNode(x, ny, z-dz)); + if (dungeonRoom.isBlocked(x+1, y, z-dz)) nexts.add(openNode(x+1, ny, z-dz)); + if (dungeonRoom.isBlocked(x-1, y, z-dz)) nexts.add(openNode(x-1, ny, z-dz)); + } + if (dungeonRoom.isBlocked(x, y-dy, z)) { + nexts.add(openNode(x, y-dy, nz)); + if (dungeonRoom.isBlocked(x+1, y-dy, z)) nexts.add(openNode(x+1, y-dy, nz)); + if (dungeonRoom.isBlocked(x-1, y-dy, z)) nexts.add(openNode(x+1, y-dy, nz)); + } + } else if (dy == 0) { + if (dungeonRoom.isBlocked(x, y, z-dz)) { + nexts.add(openNode(nx, y, z-dz)); + if (dungeonRoom.isBlocked(x, y+1, z-dz)) nexts.add(openNode(nx, y+1, z-dz)); + if (dungeonRoom.isBlocked(x, y-1, z-dz)) nexts.add(openNode(nx, y-1, z-dz)); + } + if (dungeonRoom.isBlocked(x-dx, y, z)) { + nexts.add(openNode(x-dx, y, nz)); + if (dungeonRoom.isBlocked(x-dx, y+1, z)) nexts.add(openNode(x-dx, y+1, nz)); + if (dungeonRoom.isBlocked(x-dx, y-1, z)) nexts.add(openNode(x-dx, y-1, nz)); + } + } else if (dz == 0) { + if (dungeonRoom.isBlocked(x, y-dy, z)) { + nexts.add(openNode(nx, y-dy, z)); + if (dungeonRoom.isBlocked(x, y-dy, z+1)) nexts.add(openNode(nx, y-dy, z+1)); + if (dungeonRoom.isBlocked(x, y-dy, z-1)) nexts.add(openNode(nx, y-dy, z-1)); + } + if (dungeonRoom.isBlocked(x-dx, y, z)) { + nexts.add(openNode(x-dx, ny, z)); + if (dungeonRoom.isBlocked(x-dx, y, z+1)) nexts.add(openNode(x-dx, ny, z+1)); + if (dungeonRoom.isBlocked(x-dx, y, z-1)) nexts.add(openNode(x-dx, ny, z-1)); + } + } + } else if (determinant == 3) { + nexts.add(openNode(x,y,nz)); + nexts.add(openNode(x,ny,z)); + nexts.add(openNode(nx,y,z)); + nexts.add(openNode(nx,y,nz)); + nexts.add(openNode(x,ny,nz)); + nexts.add(openNode(nx,ny,z)); + nexts.add(openNode(nx,ny,nz)); + + if (dungeonRoom.isBlocked(x,y,z-dz)) { + nexts.add(openNode(x,ny,z-dz)); + nexts.add(openNode(nx,ny,z-dz)); + nexts.add(openNode(nx,y,z-dz)); + } + if (dungeonRoom.isBlocked(x-dx,y,z)) { + nexts.add(openNode(x-dx,ny,nz)); + nexts.add(openNode(x-dx,ny,z)); + nexts.add(openNode(x-dx,y,nz)); + } + if (dungeonRoom.isBlocked(x,y-dy,z)) { + nexts.add(openNode(x,y-dy,nz)); + nexts.add(openNode(nx,y-dy,z)); + nexts.add(openNode(nx,y-dy,nz)); + } + } + return nexts; + } + + public Node expand(int x, int y, int z, int dx, int dy, int dz) { + while(true) { + int nx = x + dx, ny = y + dy, nz = z + dz; + if (dungeonRoom.isBlocked(nx, ny, nz)) return null; + + if (nx > destinationBB.minX && nx < destinationBB.maxX && ny > destinationBB.minY && ny < destinationBB.maxY && nz > destinationBB.minZ && nz < destinationBB.maxZ) return openNode(nx,ny,nz); + + int determinant = Math.abs(dx) + Math.abs(dy) + Math.abs(dz); + if (determinant == 1) { + for (int i = -1; i<=1; i++) { + for (int j = - 1; j<=1; j++) { + if (i == 0 && j == 0) continue; + if (dx != 0 && dungeonRoom.isBlocked(nx, ny + i, nz + j) && !dungeonRoom.isBlocked(nx+dx, ny + i, nz + j)) return openNode(nx,ny,nz); + if (dy != 0 && dungeonRoom.isBlocked(nx + i, ny, nz + j) && !dungeonRoom.isBlocked(nx + i, ny+dy, nz + j)) return openNode(nx,ny,nz); + if (dz != 0 && dungeonRoom.isBlocked(nx + i, ny + j , nz) && !dungeonRoom.isBlocked(nx + i, ny + j , nz+dz)) return openNode(nx,ny,nz); + } + } + } else if (determinant == 2) { + for (EnumFacing value : EnumFacing.VALUES) { + if (value.getFrontOffsetX() == dx || value.getFrontOffsetY() == dy || value.getFrontOffsetZ() == dz) continue; + int tx = nx + value.getFrontOffsetX(); + int ty = ny + value.getFrontOffsetY(); + int tz = nz + value.getFrontOffsetZ(); + if (dungeonRoom.isBlocked(tx, ty, tz)) return openNode(nx, ny, nz); + } + if (dx != 0 && expand(nx, ny, nz, dx, 0,0) != null) return openNode(nx,ny,nz); + if (dy != 0 && expand(nx, ny, nz, 0, dy,0) != null) return openNode(nx,ny,nz); + if (dz != 0 && expand(nx, ny, nz, 0, 0,dz) != null) return openNode(nx,ny,nz); + } else if (determinant == 3) { + if (dungeonRoom.isBlocked(x, ny, nz ) || dungeonRoom.isBlocked(nx, y , nz) || dungeonRoom.isBlocked(nx, ny, z)) return openNode(nx,ny,nz); + if (expand(nx, ny, nz, dx, 0, 0) != null || + expand(nx, ny, nz, dx, dy, 0) != null || + expand(nx, ny, nz, dx, 0, dz) != null || + expand(nx, ny, nz, 0, dy, 0) != null || + expand(nx, ny, nz, 0, dy, dz) != null || + expand(nx, ny, nz, 0, 0, dz) != null) return openNode(nx,ny,nz); + } + x = nx; y = ny; z = nz; + } + } + + @RequiredArgsConstructor + @Data + public static final class Node { + private final int x, y, z; + + private float f, g = Float.MAX_VALUE, h = -1; + private boolean closed; + + @EqualsAndHashCode.Exclude + private Node parent; + + public static int makeHash(int x, int y, int z) + { + return y & 255 | (x & 32767) << 8 | (z & 32767) << 24 | (x < 0 ? Integer.MIN_VALUE : 0) | (z < 0 ? 32768 : 0); + } + + public Node close() { + this.closed = true; + return this; + } + + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/NodeProcessorDungeonRoom.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/NodeProcessorDungeonRoom.java new file mode 100644 index 00000000..cdce6cf4 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/NodeProcessorDungeonRoom.java @@ -0,0 +1,144 @@ +/* + * 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.mod.dungeon.pathfinding; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.init.Blocks; +import net.minecraft.pathfinding.PathPoint; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3i; +import net.minecraft.world.World; +import net.minecraft.world.pathfinder.NodeProcessor; + +import java.util.Set; + +public class NodeProcessorDungeonRoom extends NodeProcessor { + private final DungeonRoom dungeonRoom; + private final BlockPos sub; + + public NodeProcessorDungeonRoom(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + sub = dungeonRoom.getMax().subtract(dungeonRoom.getMin()); + } + + @Override + public PathPoint getPathPointTo(Entity entityIn) { + return openPoint((int) entityIn.posX - dungeonRoom.getMin().getX(), (int) entityIn.posY - dungeonRoom.getMin().getY(), + (int) entityIn.posZ - dungeonRoom.getMin().getZ()); + } + + @Override + public PathPoint getPathPointToCoords(Entity entityIn, double x, double y, double z) { + return openPoint((int) x - dungeonRoom.getMin().getX(), (int) y - dungeonRoom.getMin().getY(), + (int) z - dungeonRoom.getMin().getZ()); + } + + private static final EnumFacing[] values2 = new EnumFacing[] { + EnumFacing.DOWN, EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.UP + }; + + + + @Override + public int findPathOptions(PathPoint[] pathOptions, Entity entityIn, PathPoint currentPoint, PathPoint targetPoint, float maxDistance) { + + int i = 0; + for (EnumFacing ef : values2) { + Vec3i dir = ef.getDirectionVec(); + int newX = currentPoint.xCoord + dir.getX(); + int newY = currentPoint.yCoord + dir.getY(); + int newZ = currentPoint.zCoord + dir.getZ(); + + if (newX < 0 || newZ < 0) continue; + if (newX > sub.getX() || newZ > sub.getZ()) continue; + + BlockPos add1 = dungeonRoom.getMin().add(newX, newY, newZ); + World playerWorld = entityIn.getEntityWorld(); + + IBlockState curr = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(add1); + + + IBlockState up = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(dungeonRoom.getMin().add(newX, newY + 1, newZ)); + + if (isValidBlock(curr) && isValidBlock(up)) { + PathPoint pt = openPoint(newX, newY, newZ); + if (pt.visited) continue; + pathOptions[i++] = pt; + continue; + } + + if (curr.getBlock() == Blocks.air) { + if (up.getBlock() == Blocks.stone_slab + || up.getBlock() == Blocks.wooden_slab + || up.getBlock() == Blocks.stone_slab2) { + IBlockState up2 = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(dungeonRoom.getMin().add(newX, newY - 1, newZ)); + if (up2.getBlock() == Blocks.stone_slab + || up2.getBlock() == Blocks.wooden_slab + || up2.getBlock() == Blocks.stone_slab2) { + PathPoint pt = openPoint(newX, newY, newZ); + if (pt.visited) continue; + pathOptions[i++] = pt; + continue; + } + } + } + + if (dir.getY() == 0 + && curr.getBlock() == Blocks.iron_bars + && up.getBlock() == Blocks.air + && DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(new BlockPos(currentPoint.xCoord, currentPoint.yCoord, currentPoint.zCoord)).getBlock() != Blocks.iron_bars) { + + boolean theFlag = false; + if (dir.getZ() == 0) { + if (DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState( + add1.add(0, 0, 1)).getBlock() == Blocks.air || + DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(add1.add(0, 0, -1)).getBlock() == Blocks.air) { + theFlag = true; + } + } else if (dir.getX() == 0) { + if (DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(add1.add(-1, 0, 0)).getBlock() == Blocks.air || + DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(add1.add(1, 0, 0)).getBlock() == Blocks.air) { + theFlag = true; + } + } + if (theFlag) { + PathPoint pt = openPoint(newX, newY, newZ); + if (pt.visited) continue; + pathOptions[i++] = pt; + } + } + } + return i; + } + + public static final Set<Block> allowed = Sets.newHashSet(Blocks.air, Blocks.water, Blocks.lava, Blocks.flowing_water, Blocks.flowing_lava, Blocks.vine, Blocks.ladder + , Blocks.standing_sign, Blocks.wall_sign, Blocks.trapdoor, Blocks.iron_trapdoor, Blocks.wooden_button, Blocks.stone_button, Blocks.fire, + Blocks.torch, Blocks.rail, Blocks.golden_rail, Blocks.activator_rail, Blocks.detector_rail, Blocks.carpet, Blocks.redstone_torch); + public static final IBlockState preBuilt = Blocks.stone.getStateFromMeta(2); + + public static boolean isValidBlock(IBlockState state) { + return state.equals(preBuilt) || allowed.contains(state.getBlock()); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/ThetaStar.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/ThetaStar.java new file mode 100644 index 00000000..4a4cf786 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/pathfinding/ThetaStar.java @@ -0,0 +1,209 @@ +/* + * 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.mod.dungeon.pathfinding; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.*; +import net.minecraft.util.*; +import net.minecraft.world.World; + +import java.util.*; + +public class ThetaStar { + private final BlockPos min, max; + private final World world; + + int lastSx, lastSy, lastSz; + final int dx, dy, dz; + private DungeonRoom dungeonRoom; + + @Getter + private AxisAlignedBB destinationBB; + + public ThetaStar(DungeonRoom dungeonRoom, Vec3 destination) { + this.min = new BlockPos(dungeonRoom.getMinx(), 0, dungeonRoom.getMinz()); + this.max = new BlockPos(dungeonRoom.getMaxx(), 255, dungeonRoom.getMaxz()); + + this.world = dungeonRoom.getCachedWorld(); + this.dungeonRoom = dungeonRoom; + + this.dx = (int) (destination.xCoord * 2); + this.dy = (int) (destination.yCoord * 2); + this.dz = (int) (destination.zCoord * 2); + destinationBB = AxisAlignedBB.fromBounds(dx-2, dy-2, dz-2, dx+2, dy+2, dz+2); + } + + private Map<Node.Coordinate, Node> nodeMap = new HashMap<>(); + + private Node openNode(int x, int y, int z) + { + Node.Coordinate coordinate = new Node.Coordinate(x,y,z); + Node node = this.nodeMap.get(coordinate); + + if (node == null) + { + node = new Node(coordinate); + this.nodeMap.put(coordinate, node); + } + + return node; + } + + @Getter + private LinkedList<Vec3> route = new LinkedList<>(); + + @Getter + private PriorityQueue<Node> open = new PriorityQueue<>(Comparator.comparing((Node a) -> a == null ? Float.MAX_VALUE : a.f).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.x).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.y).thenComparing(a -> a == null ? Float.MAX_VALUE : a.coordinate.z)); + + private int pfindIdx = 0; + + public boolean pathfind(Vec3 from, long timeout) { + + pfindIdx ++; + if (lastSx != (int)Math.round(from.xCoord * 2) || lastSy != (int)Math.round(from.yCoord*2) || lastSz != (int)Math.round(from.zCoord * 2)) + open.clear(); + + this.lastSx = (int) Math.round(from.xCoord * 2); + this.lastSy = (int) Math.round(from.yCoord * 2); + this.lastSz = (int) Math.round(from.zCoord * 2); + if (dungeonRoom.isBlocked(lastSx, lastSy, lastSz)) return false; + + Node startNode = openNode(dx, dy, dz); + Node goalNode = openNode(lastSx, lastSy, lastSz); + startNode.g = 0; + startNode.f = 0; + goalNode.g = Integer.MAX_VALUE; goalNode.f = Integer.MAX_VALUE; + if (goalNode.parent != null) { + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + open.add(startNode); + + long end = System.currentTimeMillis() + timeout; + + while (!open.isEmpty()) { + if (System.currentTimeMillis() > end) { + return false; + } + Node n = open.poll(); + if (n.lastVisited == pfindIdx) continue; + n.lastVisited = pfindIdx; + + if (n == goalNode) { + // route = reconstructPath(startNode) + LinkedList<Vec3> route = new LinkedList<>(); + Node curr =goalNode; + while(curr.parent != null) { + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + curr = curr.parent; + } + route.addLast(new Vec3(curr.coordinate.x / 2.0, curr.coordinate.y / 2.0 + 0.1, curr.coordinate.z/ 2.0)); + this.route = route; + return true; + } + + for (EnumFacing value : EnumFacing.VALUES) { + Node neighbor = openNode(n.coordinate.x + value.getFrontOffsetX(), n.coordinate.y + value.getFrontOffsetY(), n.coordinate.z + value.getFrontOffsetZ()); + + // check blocked. + if (!((destinationBB.minX <= neighbor.coordinate.x && neighbor.coordinate.x <= destinationBB.maxX && + destinationBB.minY <= neighbor.coordinate.y && neighbor.coordinate.y <= destinationBB.maxY && + destinationBB.minZ <= neighbor.coordinate.z && neighbor.coordinate.z <= destinationBB.maxZ) // near destination + || !dungeonRoom.isBlocked(neighbor.coordinate.x, neighbor.coordinate.y, neighbor.coordinate.z))) { // not blocked + continue; + } + if (neighbor.lastVisited == pfindIdx) continue; + + boolean flag = false; + if (n. parent != null) { + float tempGScore = n.parent.g + distSq(n.parent.coordinate.x - neighbor.coordinate.x, n.parent.coordinate.y - neighbor.coordinate.y, n.parent.coordinate.z - neighbor.coordinate.z); + if (tempGScore < neighbor.g && lineofsight(n.parent, neighbor)) { + neighbor.parent = n.parent; + neighbor.g = tempGScore; + neighbor.f = tempGScore + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + flag = true; + } + } + if (!flag) { + float gScore = n.g + 1; // altho it's sq, it should be fine + if (gScore < neighbor.g) { + neighbor.parent = n; + neighbor.g = gScore; + neighbor.f = gScore +distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } else if (neighbor.lastVisited != pfindIdx) { + neighbor.f = neighbor.g + distSq(goalNode.coordinate.x - neighbor.coordinate.x, goalNode.coordinate.y - neighbor.coordinate.y, goalNode.coordinate.z - neighbor.coordinate.z); + open.add(neighbor); + } + } + } + } + return true; + } + + private boolean lineofsight(Node a, Node b) { + if (a == null || b == null) return false; + float sx = a.coordinate.x, sy = a.coordinate.y, sz = a.coordinate.z; + int ex = b.coordinate.x, ey = b.coordinate.y, ez = b.coordinate.z; + + float dx = ex - sx, dy = ey - sy, dz = ez - sz; + float len = distSq(dx, dy, dz); + dx /= len; dy /= len; dz /= len; + + for (int d = 0; d <= len; d += 1) { + if (dungeonRoom.isBlocked(Math.round(sx), (int) Math.ceil(sy), Math.round(sz))) return false; + if (dungeonRoom.isBlocked(Math.round(sx)+1, (int) Math.ceil(sy), Math.round(sz)+1)) return false; + if (dungeonRoom.isBlocked(Math.round(sx)-1, (int) Math.ceil(sy), Math.round(sz)-1)) return false; + if (dungeonRoom.isBlocked(Math.round(sx)+1, (int) Math.ceil(sy), Math.round(sz)-1)) return false; + if (dungeonRoom.isBlocked(Math.round(sx)-1, (int) Math.ceil(sy), Math.round(sz)+1)) return false; + sx += dx; sy += dy; sz += dz; + } + return true; + } + + private int manhatten(int x, int y, int z) {return Math.abs(x)+ Math.abs(y)+ Math.abs(z);} + private float distSq(float x, float y, float z) { + return MathHelper.sqrt_float(x * x + y * y + z * z); + } + + @Data + public static final class Node { + @Data + public static final class Coordinate { + private final int x, y, z; + } + + private final Coordinate coordinate; + + private float f = Float.MAX_VALUE, g = Float.MAX_VALUE; + private int lastVisited; + + @EqualsAndHashCode.Exclude + @ToString.Exclude + private Node parent; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/EditingContext.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/EditingContext.java new file mode 100755 index 00000000..8f5fec3f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/EditingContext.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.mod.dungeon.roomedit; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.gui.GuiDungeonRoomEdit; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; + +import java.util.Stack; + +public class EditingContext { + + private static EditingContext editingContext; + + public static void createEditingContext(DungeonRoom dungeonRoom) { + editingContext = new EditingContext(dungeonRoom); + } + + public static EditingContext getEditingContext() { + return editingContext; + } + + public static void endEditingSession() { + editingContext = null; + Minecraft.getMinecraft().displayGuiScreen(null); + } + + + private EditingContext(DungeonRoom dungeonRoom) { + this.room = dungeonRoom; + } + + @Getter + private final DungeonRoom room; + + @Getter + private final Stack<GuiScreen> guiStack = new Stack<GuiScreen>(); + + public boolean isEditingSecrets() { + return guiDungeonRoomEdit.isEditingSelected(); + } + public void endEditing() { + guiDungeonRoomEdit.endEditing(); + } + + private GuiDungeonRoomEdit guiDungeonRoomEdit; + @Getter + private GuiScreen current; + + public void openGui(GuiScreen gui) { + if (gui instanceof GuiDungeonRoomEdit) guiDungeonRoomEdit = (GuiDungeonRoomEdit) gui; + guiStack.push(current); + this.current = gui; + Minecraft.getMinecraft().displayGuiScreen(gui); + } + + public void goBack() { + current = guiStack.pop(); + Minecraft.getMinecraft().displayGuiScreen(current); + } + + public void reopen() { + Minecraft.getMinecraft().displayGuiScreen(current); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/Parameter.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/Parameter.java new file mode 100755 index 00000000..850cbe11 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/Parameter.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.mod.dungeon.roomedit; + +import lombok.Data; + +@Data +public class Parameter { + private String name; + private Object previousData; + private Object newData; + + public Parameter(String name, Object previousData, Object newData) { + this.name = name; this.previousData = previousData; this.newData = newData; + } + + private Runnable onSetNewData; + + public void setNewData(Object newData) { + this.newData = newData; + if (onSetNewData != null) onSetNewData.run(); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonAddSet.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonAddSet.java new file mode 100755 index 00000000..4e4b5da4 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonAddSet.java @@ -0,0 +1,136 @@ +/* + * 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.mod.dungeon.roomedit.gui; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.gui.MGui; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditOffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class GuiDungeonAddSet extends MGui { + + private final ValueEditOffsetPointSet valueEditOffsetPointSet; + + private final MButton add; + private final MButton back; + + + @Getter + private final OffsetPoint start; + @Getter + private final OffsetPoint end; + + public void onWorldRender(float partialTicks) { + for (OffsetPoint pos:getBlockPoses()) { + RenderUtils.highlightBlock(pos.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,255,50), partialTicks); + } + RenderUtils.highlightBlock(start.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(255,0,0,100), partialTicks); + RenderUtils.highlightBlock(end.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,0,100), partialTicks); + } + + public List<OffsetPoint> getBlockPoses() { + int minX = Math.min(start.getX(), end.getX()); + int minY = Math.min(start.getY(), end.getY()); + int minZ = Math.min(start.getZ(), end.getZ()); + int maxX = Math.max(start.getX(), end.getX()); + int maxY = Math.max(start.getY(), end.getY()); + int maxZ = Math.max(start.getZ(), end.getZ()); + + List<OffsetPoint> offsetPoints = new ArrayList<OffsetPoint>(); + for (int z = minZ; z <= maxZ; z++) { + for (int x = minX; x <=maxX; x++) { + for (int y = maxY; y >= minY; y --) { + offsetPoints.add(new OffsetPoint(x,y,z)); + } + } + } + return offsetPoints; + } + + public void add() { + valueEditOffsetPointSet.addAll(getBlockPoses()); + } + + public GuiDungeonAddSet(final ValueEditOffsetPointSet processorParameterEditPane) { + this.valueEditOffsetPointSet = processorParameterEditPane; + getMainPanel().setBackgroundColor(new Color(17, 17, 17, 179)); + { + start = new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + end = new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + } + { + MValue mValue = new MValue(start, Collections.emptyList()); + mValue.setBounds(new Rectangle(0,0,150,20)); + getMainPanel().add(mValue); + MValue mValue2 = new MValue(end,Collections.emptyList()); + mValue2.setBounds(new Rectangle(0,20,150,20)); + getMainPanel().add(mValue2); + } + { + add = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,parentHeight - 20, parentWidth / 2, 20)); + } + }; + add.setText("Add"); + add.setBackgroundColor(Color.red); + add.setOnActionPerformed(new Runnable() { + @Override + public void run() { + add(); + EditingContext.getEditingContext().goBack(); + } + }); + + back = new MButton(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(parentWidth / 2,parentHeight - 20, parentWidth / 2, 20)); + } + }; + back.setText("Go back"); + back.setBackgroundColor(Color.green); + back.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().goBack(); + } + }); + getMainPanel().add(add); + getMainPanel().add(back); + } + } + + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(10, Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),200,300)); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonParameterEdit.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonParameterEdit.java new file mode 100755 index 00000000..0f2764de --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonParameterEdit.java @@ -0,0 +1,173 @@ +/* + * 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.mod.dungeon.roomedit.gui; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MGui; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.panes.DynamicEditor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditRegistry; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; + +public class GuiDungeonParameterEdit extends MGui { + + private final Parameter parameter; + private final DungeonRoom dungeonRoom; + + private String classSelection; + + private final MPanel currentValueEdit; + + private final MButton save; + private final MButton delete; + + @Getter + private ValueEdit valueEdit; + + public GuiDungeonParameterEdit(final MParameter parameter2, final DynamicEditor processorParameterEditPane) { + dungeonRoom = EditingContext.getEditingContext().getRoom(); + getMainPanel().setBackgroundColor(new Color(17, 17, 17, 179)); + this.parameter = parameter2.getParameter(); + { + MTextField mTextField = new MTextField() { + @Override + public void edit(String str) { + parameter.setName(str); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Name", mTextField); + + mTextField.setText(parameter.getName()); + mLabelAndElement.setBounds(new Rectangle(0,0,200, 20)); + getMainPanel().add(mLabelAndElement); + } + { + classSelection = parameter.getNewData() == null ?"null" : parameter.getNewData().getClass().getName(); + final MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(processorParameterEditPane.allowedClass(), classSelection) { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 20, parentWidth,20)); + } + + @Override + public String selectionToDisplay(String selection) { + String[] split = selection.split("\\."); + return super.selectionToDisplay(split[split.length - 1]); + } + }; + + mStringSelectionButton.setOnUpdate(new Runnable() { + @Override + public void run() { + classSelection = mStringSelectionButton.getSelected(); + updateClassSelection(); + } + }); + mStringSelectionButton.setBounds(new Rectangle(0,20,150,20)); + getMainPanel().add(mStringSelectionButton); + } + { + currentValueEdit = new MPanel(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 40, parentWidth,parentHeight - 60)); + } + }; + getMainPanel().add(currentValueEdit); + } + { + delete = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,parentHeight - 20, parentWidth / 2, 20)); + } + }; + delete.setText("Delete"); + delete.setBackgroundColor(Color.red); + delete.setOnActionPerformed(new Runnable() { + @Override + public void run() { + processorParameterEditPane.delete(parameter2); + EditingContext.getEditingContext().goBack(); + } + }); + + save = new MButton(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(parentWidth / 2,parentHeight - 20, parentWidth / 2, 20)); + } + }; + save.setText("Go back"); + save.setBackgroundColor(Color.green); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().goBack(); + } + }); + getMainPanel().add(delete); + getMainPanel().add(save); + } + updateClassSelection(); + } + + public void updateClassSelection() { + currentValueEdit.getChildComponents().clear(); + + ValueEditCreator valueEditCreator = ValueEditRegistry.getValueEditMap(classSelection); + + if (!classSelection.equals(parameter.getNewData() == null ?"null" :parameter.getNewData().getClass().getName())) { + parameter.setNewData(valueEditCreator.createDefaultValue(parameter)); + parameter.setPreviousData(valueEditCreator.cloneObj(parameter.getNewData())); + } + + MPanel valueEdit = (MPanel) valueEditCreator.createValueEdit(parameter); + if (valueEdit == null) { + MLabel valueEdit2 = new MLabel() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 0, parentWidth,20)); + } + }; + valueEdit2.setText("No Value Edit"); + valueEdit2.setBounds(new Rectangle(0,0,150,20)); + valueEdit = valueEdit2; + this.valueEdit = null; + } else{ + this.valueEdit = (ValueEdit) valueEdit; + } + valueEdit.resize0(currentValueEdit.getBounds().width, currentValueEdit.getBounds().height); + currentValueEdit.add(valueEdit); + } + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(10, Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),200,300)); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonRoomEdit.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonRoomEdit.java new file mode 100755 index 00000000..181ff640 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonRoomEdit.java @@ -0,0 +1,68 @@ +/* + * 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.mod.dungeon.roomedit.gui; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MGui; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTabbedPane; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.panes.*; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; + +public class GuiDungeonRoomEdit extends MGui { + + private final DungeonRoom room; + + private final MTabbedPane tabbedPane; + @Getter + private final SecretEditPane sep; + + public GuiDungeonRoomEdit(DungeonRoom room) { + this.room = room; + + MTabbedPane tabbedPane = new MTabbedPane(); + getMainPanel().add(tabbedPane); + tabbedPane.setBackground2(new Color(17, 17, 17, 179)); + + + tabbedPane.addTab("General", new GeneralEditPane(room)); + tabbedPane.addTab("Match", new RoomDataDisplayPane(room)); + tabbedPane.addTab("Secrets", sep = new SecretEditPane(room)); + tabbedPane.addTab("Actions", new ActionDisplayPane(room)); + tabbedPane.addTab("Test", new RoommatchingPane(room)); + tabbedPane.addTab("Proc.Params", new ProcessorParameterEditPane(room)); + this.tabbedPane = tabbedPane; + } + + public boolean isEditingSelected() { + return "Secrets".equals(tabbedPane.getSelectedKey()); + } + public void endEditing() { + tabbedPane.setSelectedKey("General"); + } + + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(Math.min((Minecraft.getMinecraft().displayWidth - 500) / 2, Minecraft.getMinecraft().displayWidth), Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),500,300)); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonValueEdit.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonValueEdit.java new file mode 100755 index 00000000..af4657f5 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/gui/GuiDungeonValueEdit.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.mod.dungeon.roomedit.gui; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MGui; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditRegistry; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; +import java.util.List; + +public class GuiDungeonValueEdit extends MGui { + private DungeonRoom dungeonRoom; + + + private MPanel currentValueEdit; + + private MButton save; + + @Getter + private ValueEdit valueEdit; + + private List<MPanel> addons; + + private Object editingObj; + + public GuiDungeonValueEdit(final Object object, final List<MPanel> addons) { + try { + dungeonRoom = EditingContext.getEditingContext().getRoom(); + this.addons = addons; + this.editingObj = object; + getMainPanel().setBackgroundColor(new Color(17, 17, 17, 179)); + { + currentValueEdit = new MPanel() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 0, parentWidth, parentHeight - 20 - addons.size() * 20)); + } + }; + getMainPanel().add(currentValueEdit); + } + + for (MPanel addon : addons) { + getMainPanel().add(addon); + } + { + save = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, parentHeight - 20, parentWidth, 20)); + } + }; + save.setText("Go back"); + save.setBackgroundColor(Color.green); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().goBack(); + } + }); + getMainPanel().add(save); + } + updateClassSelection(); + } catch (Exception e){} + } + + public void updateClassSelection() { + currentValueEdit.getChildComponents().clear(); + + ValueEditCreator valueEditCreator = ValueEditRegistry.getValueEditMap(editingObj == null ?"null":editingObj.getClass().getName()); + + MPanel valueEdit = (MPanel) valueEditCreator.createValueEdit(new Parameter("", editingObj, editingObj)); + if (valueEdit == null) { + MLabel valueEdit2 = new MLabel() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0, 0, parentWidth,20)); + } + }; + valueEdit2.setText("No Value Edit"); + valueEdit2.setBounds(new Rectangle(0,0,150,20)); + valueEdit = valueEdit2; + this.valueEdit = null; + } else{ + this.valueEdit = (ValueEdit) valueEdit; + } + valueEdit.resize0(currentValueEdit.getBounds().width, currentValueEdit.getBounds().height); + currentValueEdit.add(valueEdit); + } + @Override + public void initGui() { + super.initGui(); + // update bounds + getMainPanel().setBounds(new Rectangle(10, Math.min((Minecraft.getMinecraft().displayHeight - 300) / 2, Minecraft.getMinecraft().displayHeight),200,300)); + + + for (int i = 0; i < addons.size(); i++) { + addons.get(i).setBounds(new Rectangle(0, getMainPanel().getBounds().height - (i+1) * 20 - 20, getMainPanel().getBounds().width, 20)); + } + save.setBounds(new Rectangle(0 ,getMainPanel().getBounds().height - 20, getMainPanel().getBounds().width, 20)); + } + +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditBreakableWall.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditBreakableWall.java new file mode 100755 index 00000000..bcde40b9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditBreakableWall.java @@ -0,0 +1,143 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonBreakableWall; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.init.Blocks; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Collections; + +public class ValueEditBreakableWall extends MPanel implements ValueEdit<DungeonBreakableWall> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonBreakableWall dungeonBreakableWall; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MButton updateOnlyAir; + + public ValueEditBreakableWall(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonBreakableWall = (DungeonBreakableWall) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Wall Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonBreakableWall.getSecretPoint(), Collections.emptyList()); + add(value); + + updateOnlyAir = new MButton(); + updateOnlyAir.setText("Update Air"); + updateOnlyAir.setBackgroundColor(Color.green); + updateOnlyAir.setForeground(Color.black); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(updateOnlyAir); + updateOnlyAir.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPointSet ofs = dungeonBreakableWall.getSecretPoint(); + List<OffsetPoint> filtered = new ArrayList<OffsetPoint>(); + for (OffsetPoint offsetPoint : ofs.getOffsetPointList()) { + if (offsetPoint.getBlock(EditingContext.getEditingContext().getRoom()) != Blocks.air) continue; + filtered.add(offsetPoint); + } + dungeonBreakableWall.getSecretPoint().setOffsetPointList(filtered); + } + }); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonBreakableWall.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonBreakableWall.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonBreakableWall.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditBreakableWall> { + + @Override + public ValueEditBreakableWall createValueEdit(Parameter parameter) { + return new ValueEditBreakableWall(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonBreakableWall(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonBreakableWall)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditDoor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditDoor.java new file mode 100755 index 00000000..b2a30bfb --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditDoor.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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDoor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.init.Blocks; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class ValueEditDoor extends MPanel implements ValueEdit<DungeonDoor> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonDoor dungeonDoor; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite_par; + private final MTextField preRequisite2; + private final MLabelAndElement preRequisite2_par; + private final MButton updateOnlyAir; + + public ValueEditDoor(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonDoor = (DungeonDoor) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Wall Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonDoor.getSecretPoint(), Collections.emptyList()); + add(value); + + updateOnlyAir = new MButton(); + updateOnlyAir.setText("Update Air"); + updateOnlyAir.setBackgroundColor(Color.green); + updateOnlyAir.setForeground(Color.black); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(updateOnlyAir); + updateOnlyAir.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPointSet ofs = dungeonDoor.getSecretPoint(); + List<OffsetPoint> filtered = new ArrayList<OffsetPoint>(); + for (OffsetPoint offsetPoint : ofs.getOffsetPointList()) { + if (offsetPoint.getBlock(EditingContext.getEditingContext().getRoom()) != Blocks.air) continue; + filtered.add(offsetPoint); + } + dungeonDoor.getSecretPoint().setOffsetPointList(filtered); + } + }); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonDoor.setOpenPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonDoor.getOpenPreRequisite(), ",")); + preRequisite_par = new MLabelAndElement("Open Req.",preRequisite); + preRequisite_par.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite_par); + + preRequisite2 = new MTextField() { + @Override + public void edit(String str) { + dungeonDoor.setClosePreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite2.setText(TextUtils.join(dungeonDoor.getClosePreRequisite(), ",")); + preRequisite2_par = new MLabelAndElement("Close Req.",preRequisite2); + preRequisite2_par.setBounds(new Rectangle(0,80,getBounds().width,20)); + add(preRequisite2_par); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite_par.setBounds(new Rectangle(0,60,getBounds().width,20)); + preRequisite2_par.setBounds(new Rectangle(0,80,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonDoor.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditDoor> { + + @Override + public ValueEditDoor createValueEdit(Parameter parameter) { + return new ValueEditDoor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonDoor(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonDoor)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditDummy.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditDummy.java new file mode 100755 index 00000000..64808dda --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditDummy.java @@ -0,0 +1,121 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonDummy; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditDummy extends MPanel implements ValueEdit<DungeonDummy> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonDummy dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditDummy(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonDummy) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Dummy Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditDummy> { + + @Override + public ValueEditDummy createValueEdit(Parameter parameter) { + return new ValueEditDummy(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonDummy(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonDummy)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditFairySoul.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditFairySoul.java new file mode 100755 index 00000000..3bd69eb9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditFairySoul.java @@ -0,0 +1,118 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonFairySoul; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditFairySoul extends MPanel implements ValueEdit<DungeonFairySoul> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonFairySoul dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditFairySoul(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonFairySoul) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("FairySoul Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditFairySoul> { + + @Override + public ValueEditFairySoul createValueEdit(Parameter parameter) { + return new ValueEditFairySoul(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonFairySoul(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonFairySoul)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditJournal.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditJournal.java new file mode 100755 index 00000000..1123050e --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditJournal.java @@ -0,0 +1,122 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonJournal; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + + +public class ValueEditJournal extends MPanel implements ValueEdit<DungeonJournal> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonJournal dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditJournal(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonJournal) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Journal Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditJournal> { + + @Override + public ValueEditJournal createValueEdit(Parameter parameter) { + return new ValueEditJournal(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonJournal(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonJournal)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditLever.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditLever.java new file mode 100755 index 00000000..080be185 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditLever.java @@ -0,0 +1,133 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonLever; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditLever extends MPanel implements ValueEdit<DungeonLever> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonLever dungeonLever; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MTextField target; + private final MLabelAndElement target2; + + public ValueEditLever(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonLever = (DungeonLever) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonLever.getLeverPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonLever.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + + + target = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setTriggering(str); + } + }; + target.setText(dungeonLever.getTriggering()); + target2 = new MLabelAndElement("Target",target); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(target2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonLever.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditLever> { + + @Override + public ValueEditLever createValueEdit(Parameter parameter) { + return new ValueEditLever(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonLever(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonLever)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditNPC.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditNPC.java new file mode 100755 index 00000000..20608f8e --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditNPC.java @@ -0,0 +1,121 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonNPC; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditNPC extends MPanel implements ValueEdit<DungeonNPC> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonNPC dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditNPC(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonNPC) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("NPC Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditNPC> { + + @Override + public ValueEditNPC createValueEdit(Parameter parameter) { + return new ValueEditNPC(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonNPC(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonNPC)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditOnewayDoor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditOnewayDoor.java new file mode 100755 index 00000000..ffeba48d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditOnewayDoor.java @@ -0,0 +1,143 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonOnewayDoor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.init.Blocks; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +public class ValueEditOnewayDoor extends MPanel implements ValueEdit<DungeonOnewayDoor> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonOnewayDoor dungeonDoor; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MButton updateOnlyAir; + + public ValueEditOnewayDoor(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonDoor = (DungeonOnewayDoor) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Wall Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonDoor.getSecretPoint(), Collections.emptyList()); + add(value); + + updateOnlyAir = new MButton(); + updateOnlyAir.setText("Update Air"); + updateOnlyAir.setBackgroundColor(Color.green); + updateOnlyAir.setForeground(Color.black); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(updateOnlyAir); + updateOnlyAir.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPointSet ofs = dungeonDoor.getSecretPoint(); + List<OffsetPoint> filtered = new ArrayList<OffsetPoint>(); + for (OffsetPoint offsetPoint : ofs.getOffsetPointList()) { + if (offsetPoint.getBlock(EditingContext.getEditingContext().getRoom()) != Blocks.air) continue; + filtered.add(offsetPoint); + } + dungeonDoor.getSecretPoint().setOffsetPointList(filtered); + } + }); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonDoor.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonDoor.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + updateOnlyAir.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonDoor.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditOnewayDoor> { + + @Override + public ValueEditOnewayDoor createValueEdit(Parameter parameter) { + return new ValueEditOnewayDoor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonOnewayDoor(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonOnewayDoor)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditOnewayLever.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditOnewayLever.java new file mode 100755 index 00000000..a315b736 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditOnewayLever.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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonOnewayLever; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditOnewayLever extends MPanel implements ValueEdit<DungeonOnewayLever> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonOnewayLever dungeonLever; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MTextField target; + private final MLabelAndElement target2; + + + public ValueEditOnewayLever(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonLever = (DungeonOnewayLever) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonLever.getLeverPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonLever.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + + + target = new MTextField() { + @Override + public void edit(String str) { + dungeonLever.setTriggering(str); + } + }; + target.setText(dungeonLever.getTriggering()); + target2 = new MLabelAndElement("Target",target); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(target2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonLever.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditOnewayLever> { + + @Override + public ValueEditOnewayLever createValueEdit(Parameter parameter) { + return new ValueEditOnewayLever(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonOnewayLever(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonOnewayLever)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditPressurePlate.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditPressurePlate.java new file mode 100755 index 00000000..dac3d196 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditPressurePlate.java @@ -0,0 +1,136 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonPressurePlate; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditPressurePlate extends MPanel implements ValueEdit<DungeonPressurePlate> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonPressurePlate dungeonPressureplate; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + private final MTextField target; + private final MLabelAndElement target2; + + + public ValueEditPressurePlate(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonPressureplate = (DungeonPressurePlate) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonPressureplate.getPlatePoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonPressureplate.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonPressureplate.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + + + target = new MTextField() { + @Override + public void edit(String str) { + dungeonPressureplate.setTriggering(str); + } + }; + target.setText(dungeonPressureplate.getTriggering()); + target2 = new MLabelAndElement("Target",target); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(target2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + target2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonPressureplate.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditPressurePlate> { + + @Override + public ValueEditPressurePlate createValueEdit(Parameter parameter) { + return new ValueEditPressurePlate(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonPressurePlate(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonPressurePlate)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditSecret.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditSecret.java new file mode 100755 index 00000000..165105aa --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditSecret.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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditSecret extends MPanel implements ValueEdit<DungeonSecret> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonSecret dungeonSecret; + + private final MLabel label; + private final MValue<OffsetPoint> value; + private final MStringSelectionButton selectionButton; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditSecret(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonSecret = (DungeonSecret) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Secret Point"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonSecret.getSecretPoint(), Collections.emptyList()); + add(value); + + selectionButton = new MStringSelectionButton(Arrays.asList("CHEST", "BAT", "ITEM_DROP", "ESSENCE"), dungeonSecret.getSecretType().name()); + selectionButton.setOnUpdate(new Runnable() { + @Override + public void run() { + dungeonSecret.setSecretType(DungeonSecret.SecretType.valueOf(selectionButton.getSelected())); + } + }); + add(selectionButton); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonSecret.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonSecret.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + selectionButton.setBounds(new Rectangle(0,40,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,60,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonSecret.highlight(new Color(0,255,0,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditSecret> { + + @Override + public ValueEditSecret createValueEdit(Parameter parameter) { + return new ValueEditSecret(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonSecret(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonSecret)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditTomb.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditTomb.java new file mode 100755 index 00000000..2604b873 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/mechanicedit/ValueEditTomb.java @@ -0,0 +1,118 @@ +/* + * 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.mod.dungeon.roomedit.mechanicedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonTomb; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEdit; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; + +import java.awt.*; +import java.util.Arrays; +import java.util.Collections; + +public class ValueEditTomb extends MPanel implements ValueEdit<DungeonTomb> { + private Parameter parameter; + + // scroll pane + // just create + // add set + private final DungeonTomb dungeonTomb; + + private final MLabel label; + private final MValue<OffsetPointSet> value; + private final MTextField preRequisite; + private final MLabelAndElement preRequisite2; + + public ValueEditTomb(final Parameter parameter2) { + this.parameter = parameter2; + this.dungeonTomb = (DungeonTomb) parameter2.getNewData(); + + + label = new MLabel(); + label.setText("Tomb Points"); + label.setAlignment(MLabel.Alignment.LEFT); + add(label); + + value = new MValue(dungeonTomb.getSecretPoint(), Collections.emptyList()); + add(value); + + preRequisite = new MTextField() { + @Override + public void edit(String str) { + dungeonTomb.setPreRequisite(Arrays.asList(str.split(","))); + } + }; + preRequisite.setText(TextUtils.join(dungeonTomb.getPreRequisite(), ",")); + preRequisite2 = new MLabelAndElement("Req.",preRequisite); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(preRequisite2); + } + + @Override + public void onBoundsUpdate() { + label.setBounds(new Rectangle(0,0,getBounds().width, 20)); + value.setBounds(new Rectangle(0,20,getBounds().width, 20)); + preRequisite2.setBounds(new Rectangle(0,40,getBounds().width,20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + dungeonTomb.highlight(new Color(0,255,255,50), parameter.getName(), EditingContext.getEditingContext().getRoom(), partialTicks); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditTomb> { + + @Override + public ValueEditTomb createValueEdit(Parameter parameter) { + return new ValueEditTomb(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new DungeonTomb(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((DungeonTomb)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ActionDisplayPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ActionDisplayPane.java new file mode 100755 index 00000000..2c886ac9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ActionDisplayPane.java @@ -0,0 +1,82 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.ActionChangeState; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionTree; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; + +import java.awt.*; + +public class ActionDisplayPane extends MPanel { + private final DungeonRoom dungeonRoom; + + private ActionTreeDisplayPane displayPane; + + private final MTextField textField; + private final MButton calculate; + public ActionDisplayPane(final DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + + { + textField = new MTextField(); + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + add(textField); + } + { + calculate = new MButton(); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + calculate.setText("calculate"); + calculate.setOnActionPerformed(new Runnable() { + @Override + public void run() { + try { + remove(displayPane); + + String text = textField.getText(); + String target = text.split(":")[0]; + String state = text.split(":")[1]; + ActionChangeState actionChangeState = new ActionChangeState(target, state); + ActionTree tree= ActionTree.buildActionTree(actionChangeState, dungeonRoom); + + displayPane = new ActionTreeDisplayPane(dungeonRoom, tree); + displayPane.setBounds(new Rectangle(0,25,getBounds().width,getBounds().height-25)); + add(displayPane); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }); + add(calculate); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void onBoundsUpdate() { + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ActionTreeDisplayPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ActionTreeDisplayPane.java new file mode 100755 index 00000000..bcc75a98 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ActionTreeDisplayPane.java @@ -0,0 +1,216 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.AbstractAction; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionTree; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionTreeUtil; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import org.lwjgl.opengl.GL11; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class ActionTreeDisplayPane extends MPanel { + + private int offsetX = 0; + private int offsetY = 0; + + private float scale; + + private final DungeonRoom dungeonRoom; + private final ActionTree tree; + private List<AbstractAction> linearified; + public ActionTreeDisplayPane(DungeonRoom dungeonRoom, ActionTree tree) { + this.dungeonRoom = dungeonRoom; + this.tree = tree; + try { + this.linearified = ActionTreeUtil.linearifyActionTree(tree); + } catch (Exception e) { + linearified = new ArrayList<AbstractAction>(); + e.printStackTrace(); + } + scale = 1.0f; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + GlStateManager.pushMatrix(); + GlStateManager.translate(offsetX, offsetY, 0); + GlStateManager.scale(scale,scale,1); + int x = renderTree(tree, 5, 5, Minecraft.getMinecraft().fontRendererObj, null, new HashMap<ActionTree, Point>()); + renderLinearified(linearified, x, 5, fr); + GlStateManager.popMatrix(); + } + + public int renderTree(ActionTree actionTree, int x, int y, FontRenderer fr, Point drawLineFrom, HashMap<ActionTree, Point> drawmPoints) { + if (drawmPoints.containsKey(actionTree)) { + // recursive, fu + Point pt = drawmPoints.get(actionTree); + + GlStateManager.pushMatrix(); + + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(770, 771); + GlStateManager.enableBlend(); + GL11.glLineWidth(1); + GlStateManager.color(1, 0, 0, 1); + GL11.glBegin(2); + GL11.glVertex2d(drawLineFrom.x, drawLineFrom.y); + GL11.glVertex2d(pt.x, pt.y); + GL11.glEnd(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + + return 0; + } + + Dimension dim = renderAction(actionTree.getCurrent(), x, y, fr); + if (drawLineFrom != null) { + GlStateManager.pushMatrix(); + + + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(770, 771); + GlStateManager.enableBlend(); + GL11.glLineWidth(1); + GlStateManager.color(1, 1, 1, 1); + GL11.glBegin(2); + GL11.glVertex2d(drawLineFrom.x, drawLineFrom.y); + GL11.glVertex2d(x + dim.width / 2, y); + GL11.glEnd(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + + } + Point pt = new Point(x + dim.width / 2, y + dim.height); + + drawmPoints.put(actionTree, new Point(x + dim.width / 2, y + dim.height / 2)); + int xOff = 0; + for (ActionTree tree:actionTree.getChildren()) { + xOff += renderTree(tree, x + xOff, y + dim.height + 10, fr, pt, drawmPoints) + 10; + } + return Math.max(xOff, dim.width); + } + + public void renderLinearified(List<AbstractAction> actions, int x, int y, FontRenderer fr) { + Point lastPt = null; + int y2 = y; + + for (AbstractAction action : actions) { + Dimension dim = renderAction(action, x, y2, fr); + if (lastPt != null) { + GlStateManager.pushMatrix(); + + + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(770, 771); + GlStateManager.enableBlend(); + GL11.glLineWidth(1); + GlStateManager.color(1, 1, 1, 1); + GL11.glBegin(2); + GL11.glVertex2d(lastPt.x, lastPt.y); + GL11.glVertex2d(x + dim.width / 2, y2); + GL11.glEnd(); + GlStateManager.disableBlend(); + GlStateManager.enableTexture2D(); + GlStateManager.enableDepth(); + GlStateManager.disableBlend(); + GlStateManager.popMatrix(); + + } + lastPt = new Point(x + dim.width / 2, y2 + dim.height); + + y2 += dim.height + 10; + } + } + + public Dimension renderAction(AbstractAction action, int x, int y, FontRenderer fr) { + String[] lines = action.toString().split("\n"); + int maxWidth = 0; + for (String line : lines) { + if (fr.getStringWidth(line) > maxWidth) maxWidth= fr.getStringWidth(line); + } + int offset = 2; + int height = (fr.FONT_HEIGHT + offset) * lines.length; + + Gui.drawRect(x,y,x + maxWidth +10, y + height + 10, 0xff000000); + Gui.drawRect(x+1,y+1,x + maxWidth +8, y + height + 8, 0xff4d4d4d); + for (int i = 0; i < lines.length; i++) { + fr.drawString(lines[i], x + 5, y + 5 + i*(fr.FONT_HEIGHT + offset), 0xffffffff); + } + + return new Dimension(maxWidth + 10, height + 10); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,25,parentWidth,parentHeight-25)); + } + + + private int lastX; + private int lastY; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int dX = absMouseX - lastX; + int dY = absMouseY - lastY; + offsetX += dX; + offsetY += dY; + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseScrolled0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (scrollAmount > 0) scale += 0.1; + if (scrollAmount < 0) scale -= 0.1; + + if (scale < 0) scale = 0.1f; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/DynamicEditor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/DynamicEditor.java new file mode 100755 index 00000000..5be67660 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/DynamicEditor.java @@ -0,0 +1,29 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.gui.elements.MParameter; + +import java.util.List; + +public interface DynamicEditor { + void delete(MParameter parameter); + + List<String> allowedClass(); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/GeneralEditPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/GeneralEditPane.java new file mode 100755 index 00000000..a60797e8 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/GeneralEditPane.java @@ -0,0 +1,286 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.Main; +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.ProcessorFactory; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.tileentity.TileEntity; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; + +import java.awt.*; +import java.io.*; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.UUID; +import java.util.zip.GZIPOutputStream; + +public class GeneralEditPane extends MPanel { + private final DungeonRoom dungeonRoom; + + private final MLabelAndElement uuid; + private final MLabelAndElement name; + private final MLabelAndElement secrets; + + private final MLabelAndElement shape; + private final MLabelAndElement rotation; + private final MLabelAndElement shape2; + + private MButton save; + private final MButton end; + private final MButton schematic; + + private final MLabelAndElement roomProcessor; + + public GeneralEditPane(final DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + { + MLabel la; + uuid = new MLabelAndElement("Room UUID: ", la = new MLabel()); + la.setText(dungeonRoom.getDungeonRoomInfo().getUuid().toString()); + uuid.setBounds(new Rectangle(0,0,getBounds().width, 20)); + add(uuid); + } + { + MTextField la = new MTextField() { + @Override + public void edit(String str) { + dungeonRoom.getDungeonRoomInfo().setName(str); + } + }; + name = new MLabelAndElement("Room Name: ", la); + la.setText(dungeonRoom.getDungeonRoomInfo().getName()); + name.setBounds(new Rectangle(0,20,getBounds().width, 20)); + add(name); + } + { + final MIntegerSelectionButton la = new MIntegerSelectionButton(dungeonRoom.getDungeonRoomInfo().getTotalSecrets()); + la.setOnUpdate(new Runnable() { + @Override + public void run() { + dungeonRoom.getDungeonRoomInfo().setTotalSecrets(la.getData()); + } + }); + secrets = new MLabelAndElement("Room Secrets: ", la); + secrets.setBounds(new Rectangle(0,40,getBounds().width, 20)); + add(secrets); + } + + { + MLabel la; + shape = new MLabelAndElement("Room Shape: ", la = new MLabel()); + la.setText(dungeonRoom.getDungeonRoomInfo().getShape()+""); + shape.setBounds(new Rectangle(0,60,getBounds().width, 20)); + add(shape); + } + + { + MLabel la; + rotation = new MLabelAndElement("Found Room Rotation: ", la = new MLabel()); + la.setText(dungeonRoom.getRoomMatcher().getRotation()+""); + rotation.setBounds(new Rectangle(0,80,getBounds().width, 20)); + add(rotation); + } + { + MLabel la; + shape2 = new MLabelAndElement("Found Room Shape: ", la = new MLabel()); + la.setText(dungeonRoom.getShape()+""); + shape2.setBounds(new Rectangle(0,100,getBounds().width, 20)); + add(shape2); + } + { + final MStringSelectionButton mStringSelectionButton = new MStringSelectionButton(new ArrayList<String>(ProcessorFactory.getProcessors()), dungeonRoom.getDungeonRoomInfo().getProcessorId()); + roomProcessor = new MLabelAndElement("Room Processor: ", mStringSelectionButton); + roomProcessor.setBounds(new Rectangle(0,120,getBounds().width, 20)); + add(roomProcessor); + + mStringSelectionButton.setOnUpdate(new Runnable() { + @Override + public void run() { + dungeonRoom.getDungeonRoomInfo().setProcessorId(mStringSelectionButton.getSelected()); + dungeonRoom.updateRoomProcessor(); + } + }); + } + { + end = new MButton(); + end.setText("End Editing Session"); + end.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.endEditingSession(); + } + }); + end.setBackgroundColor(Color.green); + end.setBounds(new Rectangle(0,140,getBounds().width, 20)); + add(end); + } + { + schematic = new MButton(); + schematic.setText("Save Schematic"); + schematic.setOnActionPerformed(new Runnable() { + @Override + public void run() { + try { + NBTTagCompound nbtTagCompound2 = createNBT(); + + File f=new File(Main.getConfigDir(), "schematics/"+ + dungeonRoom.getDungeonRoomInfo().getName()+"-"+dungeonRoom.getDungeonRoomInfo().getUuid().toString()+"-"+ UUID.randomUUID()+".schematic"); + + Method method = null; + try { + method = NBTTagCompound.class.getDeclaredMethod("write", DataOutput.class); + method.setAccessible(true); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + return; + } + FileOutputStream fos = new FileOutputStream(f); + DataOutputStream dataoutputstream = new DataOutputStream(new BufferedOutputStream(new GZIPOutputStream(fos))); + + try + { + dataoutputstream.writeByte(nbtTagCompound2.getId()); + + dataoutputstream.writeUTF("Schematic"); + method.invoke(nbtTagCompound2, dataoutputstream); + } + finally + { + dataoutputstream.close(); + } + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §fSaved to "+f.getName())); + } catch (Throwable e) { + e.printStackTrace(); + } + + } + }); + schematic.setBackgroundColor(Color.orange); + schematic.setBounds(new Rectangle(0,180,getBounds().width, 20)); + add(schematic); + } + { + if (dungeonRoom.getDungeonRoomInfo().isRegistered()) return; + save = new MButton(); + save.setText("Save RoomData"); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + DungeonRoomInfoRegistry.register(dungeonRoom.getDungeonRoomInfo()); + remove(save); + } + }); + save.setBackgroundColor(Color.green); + save.setBounds(new Rectangle(0,10,getBounds().width, 20)); + add(save); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void onBoundsUpdate() { + if (save != null) + save.setBounds(new Rectangle(0,160,getBounds().width, 20)); + end.setBounds(new Rectangle(1,140,getBounds().width-2, 20)); + if (schematic != null) + schematic.setBounds(new Rectangle(0,180,getBounds().width, 20)); + } + + private NBTTagCompound createNBT() { + NBTTagCompound compound = new NBTTagCompound(); + compound.setShort("Width", (short) (dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1)); + compound.setShort("Height", (short) 255); + compound.setShort("Length", (short) (dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() + 1)); + int size =compound.getShort("Width") * compound.getShort("Height") * compound.getShort("Length"); + + byte[] blocks = new byte[size]; + byte[] meta = new byte[size]; + byte[] extra = new byte[size]; + byte[] extranibble = new byte[(int) Math.ceil(size / 2.0)]; + + boolean extraEx = false; + NBTTagList tileEntitiesList = new NBTTagList(); + for (int x = 0; x < compound.getShort("Width"); x++) { + for (int y = 0; y < compound.getShort("Height"); y++) { + for (int z = 0; z < compound.getShort("Length"); z++) { + int index = x + (y * compound.getShort("Length") + z) * compound.getShort("Width"); + BlockPos pos = dungeonRoom.getRelativeBlockPosAt(x,y - 70,z); + IBlockState blockState = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(pos); + boolean acc = dungeonRoom.canAccessRelative(x,z); + int id = Block.getIdFromBlock(blockState.getBlock()); + blocks[index] = acc ? (byte) id : 0; + meta[index] = acc ? (byte) blockState.getBlock().getMetaFromState(blockState) : 0; + if ((extra[index] = (byte) ((acc ? id : 0) >> 8)) > 0) { + extraEx = true; + } + + if (blockState.getBlock().hasTileEntity(blockState)) { + TileEntity tileEntity = dungeonRoom.getContext().getWorld().getTileEntity(pos); + try { + final NBTTagCompound tileEntityCompound = new NBTTagCompound(); + tileEntity.writeToNBT(tileEntityCompound); + tileEntitiesList.appendTag(tileEntityCompound); + } catch (final Exception e) { + final BlockPos tePos = tileEntity.getPos(); + + blocks[index] = (byte) 7; + meta[index] = 0; + extra[index] = 0; + } + } + } + } + } + for (int i = 0; i < extranibble.length; i++) { + if (i * 2 + 1 < extra.length) { + extranibble[i] = (byte) ((extra[i * 2 + 0] << 4) | extra[i * 2 + 1]); + } else { + extranibble[i] = (byte) (extra[i * 2 + 0] << 4); + } + } + + + compound.setByteArray("Blocks", blocks); + compound.setByteArray("Data", meta); + compound.setString("Materials", "Alpha"); + if (extraEx) { + compound.setByteArray("AddBlocks", extranibble); + } + compound.setTag("Entities", new NBTTagList()); + compound.setTag("TileEntities", tileEntitiesList); + + return compound; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ProcessorParameterEditPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ProcessorParameterEditPane.java new file mode 100755 index 00000000..5b907fb7 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/ProcessorParameterEditPane.java @@ -0,0 +1,144 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MParameter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditRegistry; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class ProcessorParameterEditPane extends MPanel implements DynamicEditor { + private final DungeonRoom dungeonRoom; + + private MButton save; + private MButton create; + private final List<MParameter> parameters = new ArrayList<MParameter>(); + + public ProcessorParameterEditPane(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + buildElements(); + } + + public void buildElements() { + { + create = new MButton(); + create.setText("Create New Parameter"); + create.setBackgroundColor(Color.cyan); + create.setBounds(new Rectangle(0,0,100,20)); + create.setOnActionPerformed(new Runnable() { + @Override + public void run() { + MParameter parameter; + parameters.add(parameter = new MParameter(new Parameter(UUID.randomUUID().toString(), null, null), ProcessorParameterEditPane.this)); + parameter.setParent(ProcessorParameterEditPane.this); + parameter.setBounds(new Rectangle(0,0,getBounds().width, 20)); + } + }); + + save = new MButton(); + save.setText("Save"); + save.setBackgroundColor(Color.green); + save.setBounds(new Rectangle(0,0,100,20)); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + DungeonRoomInfo dungeonRoomInfo = dungeonRoom.getDungeonRoomInfo(); + dungeonRoomInfo.getProperties().clear(); + + for (MParameter parameter : parameters) { + Parameter real = parameter.getParameter(); + + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(real.getNewData() == null ? "null" :real.getNewData().getClass().getName()); + + real.setPreviousData(vec.cloneObj(real.getNewData())); + dungeonRoomInfo.getProperties().put(real.getName(), real.getNewData()); + } + } + }); + create.setParent(this); save.setParent(this); + } + { + for (Map.Entry<String, Object> en : dungeonRoom.getDungeonRoomInfo().getProperties().entrySet()) { + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(en.getValue() == null ? "null" :en.getValue().getClass().getName()); + + MParameter mParameter = new MParameter(new Parameter(en.getKey(), vec.cloneObj(en.getValue()), vec.cloneObj(en.getValue())), this); + mParameter.setBounds(new Rectangle(0,0,getBounds().width,20)); + parameters.add(mParameter); + mParameter.setParent(this); + } + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + + public void delete(MParameter parameter) { + parameters.remove(parameter); + } + + @Override + public List<String> allowedClass() { + return ValueEditRegistry.getClassesSupported(); + } + + + @Override + public List<MPanel> getChildComponents() { + ArrayList<MPanel> panels = new ArrayList<MPanel>(parameters); + panels.add(create); + panels.add(save); + return panels; + } + + private int offsetY = 0; + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int heights = 0; + for (MPanel panel:getChildComponents()) { + panel.setPosition(new Point(0, -offsetY + heights)); + heights += panel.getBounds().height; + } + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (scrollAmount > 0) offsetY -= 20; + else if (scrollAmount < 0) offsetY += 20; + if (offsetY < 0) offsetY = 0; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoomDataDisplayPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoomDataDisplayPane.java new file mode 100755 index 00000000..f2ae85c3 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoomDataDisplayPane.java @@ -0,0 +1,126 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.awt.*; + +public class RoomDataDisplayPane extends MPanel { + + private int offsetX = 0; + private int offsetY = 0; + + private int selectedX = -1; + private int selectedY = -1; + + private final DungeonRoom dungeonRoom; + public RoomDataDisplayPane(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + int[][] blocks = dungeonRoom.getDungeonRoomInfo().getBlocks(); + // draw Axis; + Gui.drawRect(0,0,10,10,0x77777777); + clip(clip.x + 10, clip.y, clip.width - 10, 10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int x = 0; x < blocks[0].length; x++) { + fr.drawString(x+"", x * 16 +10 + offsetX, 0, 0xFFFFFFFF); + } + clip(clip.x, clip.y +10, 10, clip.height-10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int z = 0; z < blocks.length; z++) { + fr.drawString(z+"", 2, z * 16 + 10 + offsetY, 0xFFFFFFFF); + } + + int hoverX = (relMousex0 - offsetX - 10) / 16; + int hoverY = (relMousey0 - offsetY - 10) / 16; + // draw Content + clip(clip.x + 10, clip.y +10, clip.width - 10, clip.height - 10); + for (int z = 0; z < blocks.length; z++) { + for (int x = 0; x < blocks[z].length; x++) { + int data = blocks[z][x]; + if (z == selectedY && x == selectedX){ + Gui.drawRect(x *16 +10+offsetX, z *16 +10 + offsetY, x *16 +26 +offsetX, z *16 +26 + offsetY, 0xAA707070); + } else if (z == hoverY && x == hoverX) { + Gui.drawRect(x *16 +10+offsetX, z *16 +10 + offsetY, x *16 +26 +offsetX, z *16 +26 + offsetY, 0xAA505050); + } + + + if (data == -1) fr.drawString("X", x *16 +10 + offsetX, z *16 +10 + offsetY,0xFFFFFF); + else drawItemStack(new ItemStack(Item.getItemFromBlock(Block.getBlockById(data)), 1), x * 16 +10 + offsetX, z *16 +10 + offsetY); + } + } + + } + private void drawItemStack(ItemStack stack, int x, int y) + { + Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, x, y); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void keyPressed(char typedChar, int keyCode) { + int[][] blocks = dungeonRoom.getDungeonRoomInfo().getBlocks(); + if (selectedX != -1 && selectedY != -1 && selectedY < blocks.length && selectedX < blocks[0].length) { + dungeonRoom.getDungeonRoomInfo().getBlocks()[selectedY][selectedX] = -1; + } + } + + private int lastX; + private int lastY; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + lastX = absMouseX; + lastY = absMouseY; + + if (lastAbsClip.contains(absMouseX, absMouseY)) { + selectedX = (relMouseX - offsetX - 10) / 16; + selectedY = (relMouseY - offsetY - 10) / 16; + } + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int dX = absMouseX - lastX; + int dY = absMouseY - lastY; + offsetX += dX; + offsetY += dY; + lastX = absMouseX; + lastY = absMouseY; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoomMatchDisplayPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoomMatchDisplayPane.java new file mode 100755 index 00000000..b7023c4b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoomMatchDisplayPane.java @@ -0,0 +1,152 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoomInfoRegistry; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTooltip; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTooltipText; +import kr.syeyoung.dungeonsguide.mod.utils.ArrayUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.Gui; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; + +import java.awt.*; +import java.util.Arrays; +import java.util.UUID; + +public class RoomMatchDisplayPane extends MPanel { + + private int offsetX = 0; + private int offsetY = 0; + + private final DungeonRoom dungeonRoom; + + private final int[][] currentBlocks; + private int[][] targetBlocks; + public RoomMatchDisplayPane(DungeonRoom dungeonRoom, UUID uid, int rotation) { + this.dungeonRoom = dungeonRoom; + + currentBlocks = dungeonRoom.getRoomMatcher().createNew().getBlocks(); + targetBlocks = DungeonRoomInfoRegistry.getByUUID(uid).getBlocks(); + for (int i = 0; i < rotation; i++) + targetBlocks = ArrayUtils.rotateCounterClockwise(targetBlocks); + } + + MTooltip mTooltip; + int lastTooltipX = -1, lastTooltipZ = -1; + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle clip) { + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + int height = Math.max(currentBlocks.length, targetBlocks.length); + int width = Math.max(currentBlocks[0].length, targetBlocks[0].length); + + // draw Axis; + Gui.drawRect(0,0,10,10,0x77777777); + clip(clip.x + 10, clip.y, clip.width - 10, 10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int x = 0; x < width; x++) { + fr.drawString(x+"", x * 16 +10 + offsetX, 0, 0xFFFFFFFF); + } + clip(clip.x, clip.y +10, 10, clip.height-10); + Gui.drawRect(0,0,getBounds().width, getBounds().height, 0x77777777); + for (int z = 0; z < height; z++) { + fr.drawString(z+"", 2, z * 16 + 10 + offsetY, 0xFFFFFFFF); + } + + int hoverX = (relMousex0 - offsetX - 10) / 16; + int hoverY = (relMousey0 - offsetY - 10) / 16; + // draw Content + clip(clip.x + 10, clip.y +10, clip.width - 10, clip.height - 10); + boolean tooltiped=false; + for (int z = 0; z < height; z++) { + for (int x = 0; x < width; x++) { + int data1; + try { data1 = currentBlocks[z][x]; } catch (Exception e) { + data1 = -2; + } + int data2; + try { data2 = targetBlocks[z][x]; } catch (Exception e) { + data2 = -2; + } + + if (z == hoverY && x == hoverX) { + Gui.drawRect(x *16 +10+offsetX, z *16 +10 + offsetY, x *16 +26 +offsetX, z *16 +26 + offsetY, 0xAA505050); + } + + if (data1 == data2) drawItemStack(new ItemStack(Item.getItemFromBlock(Block.getBlockById(data1)), 1), x * 16 +10 + offsetX, z *16 +10 + offsetY); + else if (data2 == -1 || data1 == -1) { + drawItemStack(new ItemStack(Item.getItemFromBlock(Block.getBlockById(data1 == -1 ? data2 : data1)), 1), x * 16 +10 + offsetX, z *16 +10 + offsetY); + fr.drawString("S", x *16 +10 + offsetX, z *16 +10 + offsetY,0xFFFFFF00); + } else { + fr.drawString("N", x *16 +10 + offsetX, z *16 +10 + offsetY,0xFFFF0000); + } + if (z == hoverY && x == hoverX) { + tooltiped = true; + if (lastTooltipX != x || lastTooltipZ != z){ + if (mTooltip != null) mTooltip.close(); + mTooltip = new MTooltipText(Arrays.asList("Expected "+data2 +" But found "+data1)); + mTooltip.open(this); + } + } + } + } + if (!tooltiped && mTooltip != null) { + mTooltip.close(); + mTooltip = null; + } + + } + private void drawItemStack(ItemStack stack, int x, int y) + { + Minecraft.getMinecraft().getRenderItem().renderItemAndEffectIntoGUI(stack, x, y); + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + private int lastX; + private int lastY; + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + lastX = absMouseX; + lastY = absMouseY; + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int dX = absMouseX - lastX; + int dY = absMouseY - lastY; + offsetX += dX; + offsetY += dY; + lastX = absMouseX; + lastY = absMouseY; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoommatchingPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoommatchingPane.java new file mode 100755 index 00000000..964c450b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/RoommatchingPane.java @@ -0,0 +1,84 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; + +import java.awt.*; +import java.util.UUID; + +public class RoommatchingPane extends MPanel { + private final DungeonRoom dungeonRoom; + + private RoomMatchDisplayPane displayPane; + + private final MTextField textField; + private final MButton calculate; + public RoommatchingPane(final DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + + { + textField = new MTextField(); + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + add(textField); + } + { + calculate = new MButton(); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + calculate.setText("match"); + calculate.setOnActionPerformed(new Runnable() { + @Override + public void run() { + try { + remove(displayPane); + + String text = textField.getText(); + String target = text.split(":")[0]; + String state = text.split(":")[1]; + + UUID uid = UUID.fromString(target); + int rotation = Integer.parseInt(state) % 4; + + + displayPane = new RoomMatchDisplayPane(dungeonRoom, uid, rotation); + displayPane.setBounds(new Rectangle(0,25,getBounds().width,getBounds().height-25)); + add(displayPane); + } catch (Throwable t) { + t.printStackTrace(); + } + } + }); + add(calculate); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void onBoundsUpdate() { + textField.setBounds(new Rectangle(0,0,getBounds().width - 100, 20)); + calculate.setBounds(new Rectangle(getBounds().width - 100,0,100, 20)); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/SecretEditPane.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/SecretEditPane.java new file mode 100755 index 00000000..5c52e770 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/panes/SecretEditPane.java @@ -0,0 +1,156 @@ +/* + * 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.mod.dungeon.roomedit.panes; + +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.dunegonmechanic.DungeonMechanic; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MParameter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditCreator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.valueedit.ValueEditRegistry; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; + +public class SecretEditPane extends MPanel implements DynamicEditor { + private final DungeonRoom dungeonRoom; + + private MButton save; + private MButton create; + private final List<MParameter> parameters = new ArrayList<MParameter>(); + + private final List<String> allowedClasses = new ArrayList<String>(); + + public SecretEditPane(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + buildElements(); + + for (String clazz : ValueEditRegistry.getClassesSupported()) { + if (clazz.contains("mechanics") || clazz.equals("null")) { + allowedClasses.add(clazz); + } + } + } + + public void createNewMechanic(String uid, DungeonMechanic data) { + MParameter parameter; + parameters.add(parameter = new MParameter(new Parameter(uid, data, data), SecretEditPane.this)); + parameter.setBounds(new Rectangle(0,0,getBounds().width, 20)); + parameter.setParent(SecretEditPane.this); + } + + public void buildElements() { + { + create = new MButton(); + create.setText("Create New Mechanic"); + create.setBackgroundColor(Color.cyan); + create.setBounds(new Rectangle(0,0,100,20)); + create.setOnActionPerformed(new Runnable() { + @Override + public void run() { + createNewMechanic(UUID.randomUUID().toString(), null); + } + }); + + save = new MButton(); + save.setText("Save"); + save.setBackgroundColor(Color.green); + save.setBounds(new Rectangle(0,0,100,20)); + save.setOnActionPerformed(new Runnable() { + @Override + public void run() { + DungeonRoomInfo dungeonRoomInfo = dungeonRoom.getDungeonRoomInfo(); + dungeonRoomInfo.getMechanics().clear(); + + for (MParameter parameter : parameters) { + Parameter real = parameter.getParameter(); + + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(real.getNewData() == null ? "null" :real.getNewData().getClass().getName()); + + real.setPreviousData(vec.cloneObj(real.getNewData())); + dungeonRoomInfo.getMechanics().put(real.getName(), (DungeonMechanic) real.getNewData()); + } + } + }); + create.setParent(this); save.setParent(this); + } + { + for (Map.Entry<String, DungeonMechanic> en : dungeonRoom.getDungeonRoomInfo().getMechanics().entrySet()) { + ValueEditCreator vec = ValueEditRegistry.getValueEditMap(en.getValue() == null ? "null" :en.getValue().getClass().getName()); + + MParameter mParameter = new MParameter(new Parameter(en.getKey(), vec.cloneObj(en.getValue()), vec.cloneObj(en.getValue())), this); + mParameter.setBounds(new Rectangle(0,0,getBounds().width,20)); + parameters.add(mParameter); + mParameter.setParent(this); + } + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + + public void delete(MParameter parameter) { + parameters.remove(parameter); + } + + @Override + public List<String> allowedClass() { + return allowedClasses; + } + + @Override + public List<MPanel> getChildComponents() { + ArrayList<MPanel> panels = new ArrayList<MPanel>(parameters); + panels.add(create); + panels.add(save); + return panels; + } + + private int offsetY = 0; + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int heights = 0; + for (MPanel panel:getChildComponents()) { + panel.setPosition(new Point(0, -offsetY + heights)); + heights += panel.getBounds().height; + } + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (scrollAmount > 0) offsetY -= 20; + else if (scrollAmount < 0) offsetY += 20; + if (offsetY < 0) offsetY = 0; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEdit.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEdit.java new file mode 100755 index 00000000..d52094de --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEdit.java @@ -0,0 +1,27 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; + +public interface ValueEdit<T extends Object> { + void setParameter(Parameter parameter); + + void renderWorld(float partialTicks); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditAColor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditAColor.java new file mode 100755 index 00000000..c42fa423 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditAColor.java @@ -0,0 +1,339 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MColor; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class ValueEditAColor extends MPanel implements ValueEdit<AColor> { + private Parameter parameter; + private final MFloatSelectionButton h; + private final MFloatSelectionButton s; + private final MFloatSelectionButton v; + private final MFloatSelectionButton a; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditAColor(final Parameter parameter2) { + this.parameter = parameter2; + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getPreviousData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",color); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getNewData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",color); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + + Color color = (Color) parameter2.getNewData(); + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsv); + alpha = color.getAlpha() / 255.0f; + + { + h = new MFloatSelectionButton(hsv[0] * 360); + h.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[0] = h.getData() / 360; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("H", h); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + s = new MFloatSelectionButton(hsv[1] * 100); + s.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[1] = s.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("S", s); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + v = new MFloatSelectionButton(hsv[2] * 100); + v.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[2] = v.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("V", v); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + a = new MFloatSelectionButton(alpha * 100); + a.setOnUpdate(new Runnable() { + @Override + public void run() { + alpha = a.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("A", a); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + private final float[] hsv = new float[3]; + private float alpha = 0; + + public void update() { + if (hsv[2] > 1) hsv[2] = 1; + if (hsv[2] < 0) hsv[2] = 0; + if (hsv[1] > 1) hsv[1] = 1; + if (hsv[1] < 0) hsv[1] = 0; + parameter.setNewData(new AColor(Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]) & 0xffffff | (MathHelper.clamp_int((int)(alpha * 255), 0, 255) << 24), true )); + h.setData((float) Math.floor(hsv[0] * 360)); + s.setData((float) Math.floor(hsv[1] * 100)); + v.setData((float) Math.floor(hsv[2] * 100)); + a.setData((float) Math.floor(alpha * 100)); + h.updateSelected(); + s.updateSelected(); + v.updateSelected(); + a.updateSelected(); + } + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + // draw CoolRect + int width = getBounds().width - 60; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int shademodel = GL11.glGetInteger(GL11.GL_SHADE_MODEL); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.enableBlend(); + GlStateManager.disableDepth(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + +// worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); + + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], 1); + float r = (rgb >> 16 & 255) / 255.0f; + float g = (rgb >> 8 & 255) / 255.0f; + float b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(25+width ,45, 0); + GlStateManager.color(0,0,0,alpha);GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(25+width , 45+width, 0); + + GlStateManager.color(0,0,0,alpha); GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(10+width , 45 + width, 0); + GlStateManager.color(r,g,b,alpha);GL11.glVertex3i(25+width , 45+width, 0); + GL11.glEnd(); + rgb = Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]); + r = (rgb >> 16 & 255) / 255.0f; + g = (rgb >> 8 & 255) / 255.0f; + b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(r,g,b,0);GL11.glVertex3i(50+width ,45, 0); + GlStateManager.color(r,g,b,0);GL11.glVertex3i(35+width , 45, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(50+width , 45+width, 0); + +// GlStateManager.color(r,g,b,0); GL11.glVertex3i(35+width , 45, 0); +// GlStateManager.color(r,g,b,1);GL11.glVertex3i(35+width , 45 + width, 0); +// GlStateManager.color(r,g,b,1);GL11.glVertex3i(50+width , 45+width, 0); + GL11.glEnd(); + + + float radius = width/2f; + float cx = 5 + radius; + float cy = 45 + radius; + + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GlStateManager.color(1,1,1,alpha); + GL11.glVertex3f(cx,cy,0); + for (int i = 0; i <= 360; i++) { + float rad = 3.141592653f * i / 180; + int rgb2 = Color.HSBtoRGB(i / 360f, 1, hsv[2]); + float r2 = (rgb2 >> 16 & 255) / 255.0f; + float g2 = (rgb2 >> 8 & 255) / 255.0f; + float b2 = (rgb2 & 255) / 255.0f; + GlStateManager.color(r2,g2,b2, alpha); + GL11.glVertex3f(MathHelper.sin(rad) * radius + cx, MathHelper.cos(rad) * radius + cy, 0); + } + GL11.glEnd(); + GlStateManager.shadeModel(shademodel); + + GlStateManager.color(1,1,1,1); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + float rad2 = 2 * 3.141592653f * hsv[0] ; + float x = 5 + radius + (MathHelper.sin(rad2)) * hsv[1] * radius; + float y = 45 + radius + (MathHelper.cos(rad2))* hsv[1] * radius; + for (int i = 0; i < 100; i++) { + float rad = 2 * 3.141592653f * (i / 100f); + worldrenderer.pos(MathHelper.sin(rad) * 2 + x, MathHelper.cos(rad) * 2 + y, 0).endVertex(); + } + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(8+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + worldrenderer.pos(27+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(33+width, 45 + (alpha) * width, 0.5).endVertex(); + worldrenderer.pos(52+width, 45 + (alpha) * width, 0.5).endVertex(); + tessellator.draw(); + + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.color(1,1,1,1); + GlStateManager.color(1,1,1,1); + } + private int selected = 0; + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + int width = getBounds().width - 60; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + selected = 0; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (dx * dx + dy * dy <= radius * radius) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.sqrt_float(dx * dx + dy * dy) / radius; + selected = 1; + } + } + { + if (10+width <= relMouseX && relMouseX <= 25 + width && + 45 <= relMouseY && relMouseY <= 45 + width) { + hsv[2] = (relMouseY - 45) / (float)width; + selected = 2; + } + } + { + if (35+width <= relMouseX && relMouseX <= 50 + width && + 45 <= relMouseY && relMouseY <= 45 + width) { + alpha = (relMouseY - 45) / (float)width; + selected = 3; + } + } + update(); + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int width = getBounds().width - 60; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (selected == 1) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.clamp_float(MathHelper.sqrt_float(dx * dx + dy * dy) / radius, 0, 1); + } + } + { + if (selected == 2) { + hsv[2] = MathHelper.clamp_float((relMouseY - 45) / (float)width, 0, 1); + } + if (selected == 3) { + alpha = MathHelper.clamp_float((relMouseY - 45) / (float)width, 0, 1); + } + } + update(); + } + + @Override + public void onBoundsUpdate() { + int cnt = 0; + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); cnt++; + if (cnt > 2) { + panel.setPosition(new Point(0, getBounds().width + (cnt - 3) * 20)); + } + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditAColor> { + + @Override + public ValueEditAColor createValueEdit(Parameter parameter) { + return new ValueEditAColor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new AColor(255,0,0,255); + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditBoolean.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditBoolean.java new file mode 100755 index 00000000..639afc20 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditBoolean.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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MStringSelectionButton; + +import java.awt.*; +import java.util.Arrays; + +public class ValueEditBoolean extends MPanel implements ValueEdit<Boolean> { + private Parameter parameter; + + + public ValueEditBoolean(Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + boolean newData = (Boolean) parameter.getNewData(); + final MStringSelectionButton textField = new MStringSelectionButton(Arrays.asList("true", "false"), Boolean.toString(newData)); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + parameter.setNewData(Boolean.valueOf(textField.getSelected())); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditBoolean> { + + @Override + public ValueEditBoolean createValueEdit(Parameter parameter) { + return new ValueEditBoolean(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return true; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditColor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditColor.java new file mode 100755 index 00000000..5ef977a1 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditColor.java @@ -0,0 +1,287 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.Tessellator; +import net.minecraft.client.renderer.WorldRenderer; +import net.minecraft.client.renderer.vertex.DefaultVertexFormats; +import net.minecraft.util.MathHelper; +import org.lwjgl.opengl.GL11; + +import java.awt.*; + +public class ValueEditColor extends MPanel implements ValueEdit<Color> { + private Parameter parameter; + private final MFloatSelectionButton h; + private final MFloatSelectionButton s; + private final MFloatSelectionButton v; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditColor(final Parameter parameter2) { + this.parameter = parameter2; + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getPreviousData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",color); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + MColor color = new MColor() { + @Override + public Color getColor() { + return (Color) parameter2.getNewData(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",color); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + + Color color = (Color) parameter2.getNewData(); + Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsv); + + { + h = new MFloatSelectionButton(hsv[0] * 360); + h.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[0] = h.getData() / 360; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("H", h); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + s = new MFloatSelectionButton(hsv[1] * 100); + s.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[1] = s.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("S", s); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + v = new MFloatSelectionButton(hsv[2] * 100); + v.setOnUpdate(new Runnable() { + @Override + public void run() { + hsv[2] = v.getData() / 100; + update(); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("V", v); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + private final float[] hsv = new float[3]; + + public void update() { + if (hsv[2] > 1) hsv[2] = 1; + if (hsv[2] < 0) hsv[2] = 0; + if (hsv[1] > 1) hsv[1] = 1; + if (hsv[1] < 0) hsv[1] = 0; + parameter.setNewData(new Color(Color.HSBtoRGB(hsv[0], hsv[1], hsv[2]))); + h.setData((float) Math.floor(hsv[0] * 360)); + s.setData((float) Math.floor(hsv[1] * 100)); + v.setData((float) Math.floor(hsv[2] * 100)); + h.updateSelected(); + s.updateSelected(); + v.updateSelected(); + } + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + // draw CoolRect + int width = getBounds().width - 30; + Tessellator tessellator = Tessellator.getInstance(); + WorldRenderer worldrenderer = tessellator.getWorldRenderer(); + int shademodel = GL11.glGetInteger(GL11.GL_SHADE_MODEL); + GlStateManager.shadeModel(GL11.GL_SMOOTH); + GlStateManager.enableBlend(); + GlStateManager.disableTexture2D(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); +// worldrenderer.begin(GL11.GL_TRIANGLES, DefaultVertexFormats.POSITION_COLOR); + + int rgb = Color.HSBtoRGB(hsv[0], hsv[1], 1); + float r = (rgb >> 16 & 255) / 255.0f; + float g = (rgb >> 8 & 255) / 255.0f; + float b = (rgb & 255) / 255.0f; + GL11.glBegin(GL11.GL_TRIANGLES); + GlStateManager.color(0,0,0,1);GL11.glVertex3i(25+width ,45, 0); + GlStateManager.color(0,0,0,1);GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 45+width, 0); + + GlStateManager.color(0,0,0,1); GL11.glVertex3i(10+width , 45, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(10+width , 45 + width, 0); + GlStateManager.color(r,g,b,1);GL11.glVertex3i(25+width , 45+width, 0); + GL11.glEnd(); + + float radius = width/2f; + float cx = 5 + radius; + float cy = 45 + radius; + + GL11.glBegin(GL11.GL_TRIANGLE_FAN); + GlStateManager.color(1,1,1,1); + GL11.glVertex3f(cx,cy,0); + for (int i = 0; i <= 360; i++) { + float rad = 3.141592653f * i / 180; + int rgb2 = Color.HSBtoRGB(i / 360f, 1, hsv[2]); + float r2 = (rgb2 >> 16 & 255) / 255.0f; + float g2 = (rgb2 >> 8 & 255) / 255.0f; + float b2 = (rgb2 & 255) / 255.0f; + GlStateManager.color(r2,g2,b2, 1); + GL11.glVertex3f(MathHelper.sin(rad) * radius + cx, MathHelper.cos(rad) * radius + cy, 0); + } + GL11.glEnd(); + GlStateManager.shadeModel(shademodel); + + GlStateManager.color(1,1,1,1); + worldrenderer.begin(GL11.GL_LINE_LOOP, DefaultVertexFormats.POSITION); + float rad2 = 2 * 3.141592653f * hsv[0] ; + float x = 5 + radius + (MathHelper.sin(rad2)) * hsv[1] * radius; + float y = 45 + radius + (MathHelper.cos(rad2))* hsv[1] * radius; + for (int i = 0; i < 100; i++) { + float rad = 2 * 3.141592653f * (i / 100f); + worldrenderer.pos(MathHelper.sin(rad) * 2 + x, MathHelper.cos(rad) * 2 + y, 0).endVertex(); + } + tessellator.draw(); + + worldrenderer.begin(GL11.GL_LINES, DefaultVertexFormats.POSITION); + worldrenderer.pos(8+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + worldrenderer.pos(27+width, 45 + (hsv[2]) * width, 0.5).endVertex(); + tessellator.draw(); + + GlStateManager.enableTexture2D(); + GlStateManager.disableBlend(); + GlStateManager.color(1,1,1,1); + GlStateManager.color(1,1,1,1); + } + private int selected = 0; + + @Override + public void mouseClicked(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int mouseButton) { + int width = getBounds().width - 30; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + selected = 0; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (dx * dx + dy * dy <= radius * radius) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.sqrt_float(dx * dx + dy * dy) / radius; + selected = 1; + } + } + { + if (10+width <= relMouseX && relMouseX <= 25 + width && + 45 <= relMouseY && relMouseY <= 45 + width) { + hsv[2] = (relMouseY - 45) / (float)width; + selected = 2; + } + } + update(); + } + + @Override + public void mouseClickMove(int absMouseX, int absMouseY, int relMouseX, int relMouseY, int clickedMouseButton, long timeSinceLastClick) { + int width = getBounds().width - 30; + float radius = width / 2f; + float circleX = 5 + radius; + float circleY = 45 + radius; + { + // check circle + float dx = relMouseX - circleX; + float dy = circleY - relMouseY; + if (selected == 1) { + double theta = (MathHelper.atan2(dy, dx) / Math.PI * 180 + 90) % 360; + hsv[0] = (float) theta / 360f; + hsv[1] = MathHelper.clamp_float(MathHelper.sqrt_float(dx * dx + dy * dy) / radius, 0, 1); + } + } + { + if (selected == 2) { + hsv[2] = MathHelper.clamp_float((relMouseY - 45) / (float)width, 0, 1); + } + } + update(); + } + + @Override + public void onBoundsUpdate() { + int cnt = 0; + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); cnt++; + if (cnt > 2) { + panel.setPosition(new Point(0, getBounds().width + (cnt - 2) * 20)); + } + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditColor> { + + @Override + public ValueEditColor createValueEdit(Parameter parameter) { + return new ValueEditColor(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return Color.red; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditCreator.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditCreator.java new file mode 100755 index 00000000..5d37040b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditCreator.java @@ -0,0 +1,29 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; + +public interface ValueEditCreator<T extends ValueEdit> { + T createValueEdit(Parameter parameter); + + Object createDefaultValue(Parameter parameter); + + Object cloneObj(Object object); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditFloat.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditFloat.java new file mode 100755 index 00000000..e44adab1 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditFloat.java @@ -0,0 +1,99 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MFloatSelectionButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; + +import java.awt.*; + +public class ValueEditFloat extends MPanel implements ValueEdit<Float> { + private Parameter parameter; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditFloat(final Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + float newData = (Float) parameter.getNewData(); + final MFloatSelectionButton textField = new MFloatSelectionButton(newData); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + parameter.setNewData(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditFloat> { + + @Override + public ValueEditFloat createValueEdit(Parameter parameter) { + return new ValueEditFloat(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return 0.0f; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditInteger.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditInteger.java new file mode 100755 index 00000000..4b93a30d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditInteger.java @@ -0,0 +1,99 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MIntegerSelectionButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; + +import java.awt.*; + +public class ValueEditInteger extends MPanel implements ValueEdit<Integer> { + private Parameter parameter; + + + @Override + public void renderWorld(float partialTicks) { + + } + public ValueEditInteger(final Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + int newData = (Integer) parameter.getNewData(); + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + parameter.setNewData(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditInteger> { + + @Override + public ValueEditInteger createValueEdit(Parameter parameter) { + return new ValueEditInteger(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return 0; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditNull.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditNull.java new file mode 100755 index 00000000..0868470e --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditNull.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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; + +public class ValueEditNull implements ValueEditCreator { + @Override + public ValueEdit createValueEdit(Parameter parameter) { + return null; + } + + @Override + public Cloneable createDefaultValue(Parameter parameter) { + return null; + } + + @Override + public Object cloneObj(Object object) { + return null; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditOffsetPoint.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditOffsetPoint.java new file mode 100755 index 00000000..813ac68a --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditOffsetPoint.java @@ -0,0 +1,163 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.*; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.player.EntityPlayer; +import net.minecraft.util.BlockPos; +import java.awt.*; + +public class ValueEditOffsetPoint extends MPanel implements ValueEdit<String> { + private Parameter parameter; + + @Override + public void renderWorld(float partialTicks) { + RenderUtils.highlightBlock(((OffsetPoint)parameter.getPreviousData()).getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(255,0,0,150), partialTicks); + RenderUtils.highlightBlock(((OffsetPoint)parameter.getNewData()).getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,0,150), partialTicks); + } + + public ValueEditOffsetPoint(final Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + OffsetPoint newData = (OffsetPoint) parameter.getNewData(); + { + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData.getX()); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + ((OffsetPoint) parameter.getNewData()).setX(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("x",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData.getY()); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + ((OffsetPoint) parameter.getNewData()).setY(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("y",textField); + mLabelAndElement.setBounds(new Rectangle(0,40,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MIntegerSelectionButton textField = new MIntegerSelectionButton(newData.getZ()); + textField.setOnUpdate(new Runnable() { + @Override + public void run() { + ((OffsetPoint) parameter.getNewData()).setZ(textField.getData()); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("z",textField); + mLabelAndElement.setBounds(new Rectangle(0,60,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MLabel setToHEre = new MLabel() { + @Override + public String getText() { + OffsetPoint offsetPoint = (OffsetPoint) parameter.getNewData(); + return Block.getIdFromBlock(offsetPoint.getBlock(EditingContext.getEditingContext().getRoom())) + + ":" + offsetPoint.getData(EditingContext.getEditingContext().getRoom()); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("newPt",setToHEre); + mLabelAndElement.setBounds(new Rectangle(0,80,getBounds().width,20)); + add(mLabelAndElement); + } + { + final MButton setToHEre2 = new MButton(); + setToHEre2.setText("Set to here"); + setToHEre2.setBackgroundColor(Color.green); + setToHEre2.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EntityPlayer player = Minecraft.getMinecraft().thePlayer; + BlockPos pos = new BlockPos(player.posX, player.posY, player.posZ); + ((OffsetPoint)parameter2.getNewData()).setPosInWorld(EditingContext.getEditingContext().getRoom(),pos ); + } + }); + MLabelAndElement mLabelAndElement = new MLabelAndElement("set",setToHEre2); + mLabelAndElement.setBounds(new Rectangle(0,100,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditOffsetPoint> { + + @Override + public ValueEditOffsetPoint createValueEdit(Parameter parameter) { + return new ValueEditOffsetPoint(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((OffsetPoint)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditOffsetPointSet.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditOffsetPointSet.java new file mode 100755 index 00000000..cd6351bd --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditOffsetPointSet.java @@ -0,0 +1,250 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MButton; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MValue; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.gui.GuiDungeonAddSet; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.Getter; +import net.minecraft.client.Minecraft; + +import java.awt.*; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ValueEditOffsetPointSet extends MPanel implements ValueEdit<OffsetPointSet> { + private Parameter parameter; + + // scroll pane + // just create + // add set + + private final MPanel scroll; + @Getter + private final List<MPanel> MParameters = new ArrayList<MPanel>(); + + private final MButton add; + private final MButton addSet; + + public void delete(OffsetPoint offsetPoint) { + ((OffsetPointSet)parameter.getNewData()).getOffsetPointList().remove(offsetPoint); + Iterator<MPanel> iterator = MParameters.iterator(); + while (iterator.hasNext()) { + MValue panel = (MValue) iterator.next(); + if (panel.getData() == offsetPoint) { + iterator.remove(); + break; + } + } + + } + + public ValueEditOffsetPointSet(final Parameter parameter2) { + this.parameter = parameter2; + { + scroll = new MPanel() { + private int offsetY = 0; + + @Override + public List<MPanel> getChildComponents() { + return MParameters; + } + + @Override + public void render(int absMousex, int absMousey, int relMousex0, int relMousey0, float partialTicks, Rectangle scissor) { + int heights = 0; + for (MPanel panel:getChildComponents()) { + panel.setPosition(new Point(0, -offsetY + heights)); + heights += panel.getBounds().height; + } + } + + @Override + public boolean mouseClicked0(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int mouseButton) { + if (!getBounds().contains(relMouseX0, relMouseY0)) { + return false; + } + + int relMousex = relMouseX0 - getBounds().x; + int relMousey = relMouseY0 - getBounds().y; + + boolean noClip = true; + boolean focusedOverall = false; + for (MPanel childComponent : getChildComponents()) { + if (childComponent.mouseClicked0(absMouseX, absMouseY, relMousex, relMousey, mouseButton)) { + noClip = false; + focusedOverall = true; + } + } + + if (getBounds().contains(relMouseX0, relMouseY0) && noClip) { + isFocused = true; + focusedOverall = true; + } else { + isFocused = false; + } + + mouseClicked(absMouseX, absMouseY, relMousex, relMousey, mouseButton); + return focusedOverall; + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10)); + } + + @Override + public void mouseScrolled(int absMouseX, int absMouseY, int relMouseX0, int relMouseY0, int scrollAmount) { + if (new Rectangle(new Point(0,0), getSize()).contains(relMouseX0, relMouseY0)) { + if (scrollAmount >0) offsetY += 20; + else if (scrollAmount < 0) offsetY -= 20; + if (offsetY <0) offsetY = 0; + } + } + }; + scroll.setBounds(new Rectangle(0,0,getBounds().width, getBounds().height-20)); + add(scroll); + } + + { + add = new MButton() { + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(0,parentHeight - 20, parentWidth / 2, 20)); + } + }; + add.setText("Add"); + add.setBackgroundColor(Color.green); + add.setOnActionPerformed(new Runnable() { + @Override + public void run() { + OffsetPoint offsetPoint = new OffsetPoint(EditingContext.getEditingContext().getRoom(), Minecraft.getMinecraft().thePlayer.getPosition()); + MValue mValue; + MParameters.add(mValue = new MValue(offsetPoint, buildAddonsFor(offsetPoint))); + ((OffsetPointSet)parameter.getNewData()).getOffsetPointList().add(offsetPoint); + mValue.setSize(new Dimension(getBounds().width, 20)); + } + }); + + addSet = new MButton(){ + @Override + public void resize(int parentWidth, int parentHeight) { + setBounds(new Rectangle(parentWidth / 2,parentHeight - 20, parentWidth / 2, 20)); + } + }; + addSet.setText("Add Set"); + addSet.setBackgroundColor(Color.cyan); + addSet.setOnActionPerformed(new Runnable() { + @Override + public void run() { + EditingContext.getEditingContext().openGui(new GuiDungeonAddSet(ValueEditOffsetPointSet.this)); + } + }); + add(add); + add(addSet); + } + for (OffsetPoint offsetPoint : ((OffsetPointSet)parameter.getNewData()).getOffsetPointList()) { + MParameters.add(new MValue(offsetPoint, buildAddonsFor(offsetPoint))); + } + } + + public List<MPanel> buildAddonsFor(final OffsetPoint offsetPoint) { + ArrayList<MPanel> panels = new ArrayList<MPanel>(); + MButton mButton = new MButton(); + mButton.setText("Delete"); + mButton.setForeground(Color.white); + mButton.setBackgroundColor(Color.red); + mButton.setOnActionPerformed(new Runnable() { + @Override + public void run() { + delete(offsetPoint); + } + }); + panels.add(mButton); + return panels; + } + + @Override + public void onBoundsUpdate() { + scroll.setBounds(new Rectangle(0,0,getBounds().width, getBounds().height-20)); + add.setBounds(new Rectangle(0,getBounds().height-20,getBounds().width / 2, 20)); + addSet.setBounds(new Rectangle(getBounds().width / 2,getBounds().height-20,getBounds().width / 2, 20)); + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void renderWorld(float partialTicks) { + for (OffsetPoint offsetPoint :((OffsetPointSet)parameter.getNewData()).getOffsetPointList()) { + RenderUtils.highlightBlock(offsetPoint.getBlockPos(EditingContext.getEditingContext().getRoom()), new Color(0,255,255,50), partialTicks); + } + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public void addAll(List<OffsetPoint> blockPoses) { + ((OffsetPointSet)parameter.getNewData()).getOffsetPointList().addAll(blockPoses); + for (OffsetPoint blockPose : blockPoses) { + MParameters.add(new MValue(blockPose, buildAddonsFor(blockPose))); + } + } + + public static class Generator implements ValueEditCreator<ValueEditOffsetPointSet> { + + @Override + public ValueEditOffsetPointSet createValueEdit(Parameter parameter) { + return new ValueEditOffsetPointSet(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return new OffsetPointSet(); + } + + @Override + public Object cloneObj(Object object) { + try { + return ((OffsetPointSet)object).clone(); + } catch (CloneNotSupportedException e) { + e.printStackTrace(); + } + assert false; + return null; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditRegistry.java new file mode 100755 index 00000000..af368f2c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditRegistry.java @@ -0,0 +1,70 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.mechanicedit.*; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ValueEditRegistry { + private static final Map<String, ValueEditCreator> valueEditMap = new HashMap<String, ValueEditCreator>(); + + public static ValueEditCreator getValueEditMap(String className) { + return valueEditMap.get(className); + } + + public static List<String> getClassesSupported() { + return new ArrayList<String>(valueEditMap.keySet()); + } + + static { + valueEditMap.put("null", new ValueEditNull()); + valueEditMap.put(String.class.getName(), new ValueEditString.Generator()); + valueEditMap.put(Boolean.class.getName(), new ValueEditBoolean.Generator()); + valueEditMap.put(Integer.class.getName(), new ValueEditInteger.Generator()); + valueEditMap.put(Float.class.getName(), new ValueEditFloat.Generator()); + valueEditMap.put(OffsetPoint.class.getName(), new ValueEditOffsetPoint.Generator()); + valueEditMap.put(OffsetPointSet.class.getName(), new ValueEditOffsetPointSet.Generator()); + valueEditMap.put(Color.class.getName(), new ValueEditColor.Generator()); + valueEditMap.put(AColor.class.getName(), new ValueEditAColor.Generator()); + + + valueEditMap.put(DungeonSecret.class.getName(), new ValueEditSecret.Generator()); + valueEditMap.put(DungeonFairySoul.class.getName(), new ValueEditFairySoul.Generator()); + valueEditMap.put(DungeonNPC.class.getName(), new ValueEditNPC.Generator()); + valueEditMap.put(DungeonTomb.class.getName(), new ValueEditTomb.Generator()); + valueEditMap.put(DungeonBreakableWall.class.getName(), new ValueEditBreakableWall.Generator()); + valueEditMap.put(DungeonJournal.class.getName(), new ValueEditJournal.Generator()); + valueEditMap.put(DungeonDummy.class.getName(), new ValueEditDummy.Generator()); + + valueEditMap.put(DungeonPressurePlate.class.getName(), new ValueEditPressurePlate.Generator()); + valueEditMap.put(DungeonOnewayLever.class.getName(), new ValueEditOnewayLever.Generator()); + valueEditMap.put(DungeonLever.class.getName(), new ValueEditLever.Generator()); + valueEditMap.put(DungeonDoor.class.getName(), new ValueEditDoor.Generator()); + valueEditMap.put(DungeonOnewayDoor.class.getName(), new ValueEditOnewayDoor.Generator()); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditString.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditString.java new file mode 100755 index 00000000..0d2b3697 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomedit/valueedit/ValueEditString.java @@ -0,0 +1,99 @@ +/* + * 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.mod.dungeon.roomedit.valueedit; + +import kr.syeyoung.dungeonsguide.mod.gui.MPanel; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.Parameter; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabel; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MLabelAndElement; +import kr.syeyoung.dungeonsguide.mod.gui.elements.MTextField; + +import java.awt.*; + +public class ValueEditString extends MPanel implements ValueEdit<String> { + private Parameter parameter; + + @Override + public void renderWorld(float partialTicks) { + + } + + public ValueEditString(Parameter parameter2) { + this.parameter = parameter2; + { + MLabel label = new MLabel() { + @Override + public String getText() { + return parameter.getPreviousData().toString(); + } + }; + MLabelAndElement mLabelAndElement = new MLabelAndElement("Prev",label); + mLabelAndElement.setBounds(new Rectangle(0,0,getBounds().width,20)); + add(mLabelAndElement); + } + { + String newData = (String) parameter.getNewData(); + MTextField textField = new MTextField() { + @Override + public void edit(String str) { + parameter.setNewData(str); + } + }; + textField.setText(newData); + MLabelAndElement mLabelAndElement = new MLabelAndElement("New",textField); + mLabelAndElement.setBounds(new Rectangle(0,20,getBounds().width,20)); + add(mLabelAndElement); + } + } + + @Override + public void onBoundsUpdate() { + for (MPanel panel :getChildComponents()){ + panel.setSize(new Dimension(getBounds().width, 20)); + } + } + + @Override + public void setParameter(Parameter parameter) { + this.parameter = parameter; + } + + @Override + public void resize(int parentWidth, int parentHeight) { + this.setBounds(new Rectangle(0,0,parentWidth, parentHeight)); + } + + public static class Generator implements ValueEditCreator<ValueEditString> { + + @Override + public ValueEditString createValueEdit(Parameter parameter) { + return new ValueEditString(parameter); + } + + @Override + public Object createDefaultValue(Parameter parameter) { + return "default"; + } + + @Override + public Object cloneObj(Object object) { + return object; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/DungeonRoom.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/DungeonRoom.java new file mode 100755 index 00000000..5834d67e --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/DungeonRoom.java @@ -0,0 +1,381 @@ +/* + * 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.mod.dungeon.roomfinder; + +import com.google.common.collect.Sets; +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.MapProcessor; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonDoor; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.EDungeonDoorType; +import kr.syeyoung.dungeonsguide.mod.dungeon.events.impl.DungeonStateChangeEvent; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.dunegonmechanic.DungeonMechanic; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonRoomDoor; +import kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding.*; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.ProcessorFactory; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.features.impl.secret.FeaturePathfindStrategy; +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.List; +import java.util.*; +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<>(); + + 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 final World cachedWorld; + public Map<String, DungeonMechanic> getMechanics() { + if (cached == null || EditingContext.getEditingContext() != null) { + cached = new HashMap<>(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 final Map<BlockPos, AStarFineGrid> activeBetterAStar = new HashMap<>(); + private final Map<BlockPos, AStarCornerCut> activeBetterAStarCornerCut = new HashMap<>(); + private final 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) { + return 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); + } else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.A_STAR_FINE_GRID) { + return 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); + }else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.A_STAR_DIAGONAL) { + return 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); + } else if (pathfindStrategy == FeaturePathfindStrategy.PathfindStrategy.THETA_STAR) { + return 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); + } else { + return 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); + } + } + + private static final ScheduledExecutorService asyncPathFinder = Executors.newScheduledThreadPool(4); + @Getter + private final NodeProcessorDungeonRoom nodeProcessorDungeonRoom; + + @Getter + private final Map<String, Object> roomContext = new HashMap<>(); + + @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; + private final int miny; + private final int minz; + private final int maxx; + private final int maxy; + private final int 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/DungeonRoomInfoRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/DungeonRoomInfoRegistry.java new file mode 100755 index 00000000..72000d38 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/DungeonRoomInfoRegistry.java @@ -0,0 +1,163 @@ +/* + * 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.mod.dungeon.roomfinder; + +import com.google.common.io.Files; +import com.google.gson.Gson; +import kr.syeyoung.dungeonsguide.Main; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import org.apache.commons.io.IOUtils; +import org.jetbrains.annotations.NotNull; + +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>(); + + static Gson gson = new Gson(); + + public static void register(@NotNull DungeonRoomInfo dungeonRoomInfo) { + +// System.out.println("Loading room: " + dungeonRoomInfo.getUuid()); +// +// File file = new File(Main.getConfigDir() + "/" + "rooms" + "/" + dungeonRoomInfo.getUuid() + ".json"); +// if(!file.exists()){ +// try { +// FileUtils.writeStringToFile(file, gson.toJson(dungeonRoomInfo)); +// } catch (IOException e) { +// throw new RuntimeException(e); +// } +// } + + + + 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<>(); + } + 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"); + StringBuilder nameidstring = new StringBuilder("name,uuid,processsor,secrets"); + StringBuilder ids = new StringBuilder(); + 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.append("\n").append(dungeonRoomInfo.getName()).append(",").append(dungeonRoomInfo.getUuid()).append(",").append(dungeonRoomInfo.getProcessorId()).append(",").append(dungeonRoomInfo.getTotalSecrets()); + ids.append("roomdata/").append(dungeonRoomInfo.getUuid()).append(".roomdata\n"); + } catch (Exception e) {e.printStackTrace();} + } + + try { + Files.write(nameidstring.toString(), new File(dir, "roomidmapping.csv"), Charset.defaultCharset()); + Files.write(ids.toString(), 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/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/RoomMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/RoomMatcher.java new file mode 100755 index 00000000..994a19d8 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomfinder/RoomMatcher.java @@ -0,0 +1,145 @@ +/* + * 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.mod.dungeon.roomfinder; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo; +import kr.syeyoung.dungeonsguide.mod.utils.ArrayUtils; +import kr.syeyoung.dungeonsguide.mod.utils.ShortUtils; +import lombok.Getter; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.ChatComponentText; + +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; + + + public RoomMatcher(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + } + + 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()) { + ChatTransmitter.sendDebugChat(new ChatComponentText("Chunk Not loaded in Room Matcher")); + } + } + } + + 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[][] 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 (!(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; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/GeneralRoomProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/GeneralRoomProcessor.java new file mode 100755 index 00000000..22cdb20c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/GeneralRoomProcessor.java @@ -0,0 +1,448 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.DungeonActionContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.ActionComplete; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.ActionMove; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.ActionMoveNearestAir; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRoute; +import kr.syeyoung.dungeonsguide.mod.dungeon.actions.tree.ActionRouteProperties; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.dunegonmechanic.DungeonMechanic; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonRoomDoor; +import kr.syeyoung.dungeonsguide.dungeon.mechanics.DungeonSecret; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.events.impl.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.pathfinding.NodeProcessorDungeonRoom; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.EditingContext; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.gui.GuiDungeonAddSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomedit.gui.GuiDungeonRoomEdit; +import kr.syeyoung.dungeonsguide.mod.utils.VectorUtils; +import lombok.Getter; +import lombok.Setter; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.passive.EntityBat; +import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.util.*; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; + +public class GeneralRoomProcessor implements RoomProcessor { + + @Getter + @Setter + private DungeonRoom dungeonRoom; + public GeneralRoomProcessor(DungeonRoom dungeonRoom) { + this.dungeonRoom = dungeonRoom; + } + private boolean ticked = false; + + + @Override + public void tick() { + if (!ticked && FeatureRegistry.SECRET_AUTO_START.isEnabled()) { + searchForNextTarget(); + }else if (!ticked && FeatureRegistry.SECRET_PATHFIND_ALL.isEnabled()) { + for (Map.Entry<String, DungeonMechanic> value : getDungeonRoom().getDungeonRoomInfo().getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonSecret && ((DungeonSecret) value.getValue()).getSecretStatus(dungeonRoom) != DungeonSecret.SecretStatus.FOUND) { + DungeonSecret dungeonSecret = (DungeonSecret) value.getValue(); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isBat() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.BAT) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_BAT.getRouteProperties()); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isChest() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.CHEST) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_CHEST.getRouteProperties()); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isEssence() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.ESSENCE) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_ESSENCE.getRouteProperties()); + if (FeatureRegistry.SECRET_PATHFIND_ALL.isItemdrop() && dungeonSecret.getSecretType() == DungeonSecret.SecretType.ITEM_DROP) + pathfind(value.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_PATHFINDALL_ITEM_DROP.getRouteProperties()); + } + } + } else if (!ticked && FeatureRegistry.SECRET_BLOOD_RUSH.isEnabled()) { + for (Map.Entry<String, DungeonMechanic> value : getDungeonRoom().getMechanics().entrySet()) { + if (value.getValue() instanceof DungeonRoomDoor) { + DungeonRoomDoor dungeonDoor = (DungeonRoomDoor) value.getValue(); + if (dungeonDoor.getDoorfinder().getType().isHeadToBlood()) { + pathfind(value.getKey(), "navigate", FeatureRegistry.SECRET_BLOOD_RUSH_LINE_PROPERTIES.getRouteProperties()); + } + } + } + } + ticked = true; + + Set<String> toRemove = new HashSet<>(); + path.entrySet().forEach(a -> { + a.getValue().onTick(); + if (a.getValue().getCurrentAction() instanceof ActionComplete) + toRemove.add(a.getKey()); + }); + toRemove.forEach(path::remove); + + + for (DungeonMechanic value : dungeonRoom.getMechanics().values()) { + if (value instanceof DungeonSecret) ((DungeonSecret) value).tick(dungeonRoom); + } + + if (toRemove.contains("AUTO-BROWSE") && FeatureRegistry.SECRET_AUTO_BROWSE_NEXT.isEnabled()) { + searchForNextTarget(); + } + } + private final Set<String> visited = new HashSet<String>(); + + public void searchForNextTarget() { + if (getDungeonRoom().getCurrentState() == DungeonRoom.RoomState.FINISHED) { + cancelAll(); + return; + } + + BlockPos pos = Minecraft.getMinecraft().thePlayer.getPosition(); + + double lowestCost = 99999999999999.0; + Map.Entry<String, DungeonMechanic> lowestWeightMechanic = null; + for (Map.Entry<String, DungeonMechanic> mech: dungeonRoom.getMechanics().entrySet()) { + if (!(mech.getValue() instanceof DungeonSecret)) continue; + if (visited.contains(mech.getKey())) continue; + if (((DungeonSecret) mech.getValue()).getSecretStatus(getDungeonRoom()) != DungeonSecret.SecretStatus.FOUND) { + double cost = 0; + if (((DungeonSecret) mech.getValue()).getSecretType() == DungeonSecret.SecretType.BAT && + ((DungeonSecret) mech.getValue()).getPreRequisite().size() == 0) { + cost += -100000000; + } + if (mech.getValue().getRepresentingPoint(getDungeonRoom()) == null) continue; + BlockPos blockpos = mech.getValue().getRepresentingPoint(getDungeonRoom()).getBlockPos(getDungeonRoom()); + + cost += blockpos.distanceSq(pos); + cost += ((DungeonSecret) mech.getValue()).getPreRequisite().size() * 100; + + if (cost < lowestCost) { + lowestCost = cost; + lowestWeightMechanic = mech; + } + } + } + if (lowestWeightMechanic != null) { + visited.add(lowestWeightMechanic.getKey()); + pathfind("AUTO-BROWSE", lowestWeightMechanic.getKey(), "found", FeatureRegistry.SECRET_LINE_PROPERTIES_AUTOPATHFIND.getRouteProperties()); + } else { + visited.clear(); + } + } + + @Override + public void drawScreen(float partialTicks) { + path.values().forEach(a -> { + a.onRenderScreen(partialTicks); + }); + + if (FeatureRegistry.ADVANCED_ROOMEDIT.isEnabled() && FeatureRegistry.DEBUG.isEnabled()) { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + + if (Minecraft.getMinecraft().objectMouseOver == null) return; + Entity en = Minecraft.getMinecraft().objectMouseOver.entityHit; + if (en == null) return; + + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + if (DungeonActionContext.getSpawnLocation().containsKey(en.getEntityId())) { + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Spawned at " + DungeonActionContext.getSpawnLocation().get(en.getEntityId()), sr.getScaledWidth() / 2, sr.getScaledHeight() / 2, 0xFFFFFFFF); + } + } + } + + @Override + public void drawWorld(float partialTicks) { + if (FeatureRegistry.DEBUG.isEnabled() && (EditingContext.getEditingContext() != null && EditingContext.getEditingContext().getCurrent() instanceof GuiDungeonRoomEdit)) { + for (Map.Entry<String, DungeonMechanic> value : dungeonRoom.getMechanics().entrySet()) { + if (value.getValue() == null) continue; + value.getValue().highlight(new Color(0,255,255,50), value.getKey(), dungeonRoom, partialTicks); + } + } + + + ActionRoute finalSmallest = getBestFit(partialTicks); + path.values().forEach(a -> { + a.onRenderWorld(partialTicks, finalSmallest == a); + }); + } + + private ActionRoute getBestFit(float partialTicks) { + + ActionRoute smallest = null; + double smallestTan = 0.002; + for (ActionRoute value : path.values()) { + BlockPos target; + if (value.getCurrentAction() instanceof ActionMove) { + target = ((ActionMove) value.getCurrentAction()).getTarget().getBlockPos(dungeonRoom); + } else if (value.getCurrentAction() instanceof ActionMoveNearestAir) { + target = ((ActionMoveNearestAir) value.getCurrentAction()).getTarget().getBlockPos(dungeonRoom); + } else if (value.getCurrent() >= 1 && value.getActions().get(value.getCurrent()-1) instanceof ActionMove) { + target = ((ActionMove)value.getActions().get(value.getCurrent()-1)).getTarget().getBlockPos(dungeonRoom); + } else if (value.getCurrent() >= 1 && value.getActions().get(value.getCurrent()-1) instanceof ActionMoveNearestAir) { + target = ((ActionMoveNearestAir)value.getActions().get(value.getCurrent()-1)).getTarget().getBlockPos(dungeonRoom); + } else continue; + + if (value.getActionRouteProperties().getLineRefreshRate() != -1 && value.getActionRouteProperties().isPathfind() && !FeatureRegistry.SECRET_FREEZE_LINES.isEnabled()) continue; + + Entity e = Minecraft.getMinecraft().getRenderViewEntity(); + + double vectorV = VectorUtils.distSquared(e.getLook(partialTicks), e.getPositionEyes(partialTicks), new Vec3(target).addVector(0.5,0.5,0.5)); + + if (vectorV < smallestTan) { + smallest = value; + smallestTan = vectorV; + } + } + return smallest; + } + + @Override + public void chatReceived(IChatComponent chat) { + if (lastChest != null && chat.getFormattedText().equals("§r§cThis chest has already been searched!§r")) { + getDungeonRoom().getRoomContext().put("c-"+lastChest.toString(), 2); + lastChest = null; + } + } + + private int stack = 0; + private long secrets2 = 0; + @Override + public void actionbarReceived(IChatComponent chat) { + if (!DungeonsGuide.getDungeonsGuide().getSkyblockStatus().isOnDungeon()) return; + if (dungeonRoom.getTotalSecrets() == -1) { + ChatTransmitter.sendDebugChat(new ChatComponentText(chat.getFormattedText().replace('§', '&') + " - received")); + } + if (!chat.getFormattedText().contains("/")) return; + BlockPos pos = Minecraft.getMinecraft().thePlayer.getPosition(); + + DungeonContext context = DungeonsGuide.getDungeonsGuide().getDungeonFacade().getContext(); + Point pt1 = context.getMapProcessor().worldPointToRoomPoint(pos.add(2, 0, 2)); + Point pt2 = context.getMapProcessor().worldPointToRoomPoint(pos.add(-2, 0, -2)); + if (!pt1.equals(pt2)) { + stack = 0; + secrets2 = -1; + return; + } + BlockPos pos2 = dungeonRoom.getMin().add(5, 0, 5); + + String text = chat.getFormattedText(); + int secretsIndex = text.indexOf("Secrets"); + int secrets = 0; + if (secretsIndex != -1) { + int theindex = 0; + for (int i = secretsIndex; i >= 0; i--) { + if (text.startsWith("§7", i)) { + theindex = i; + } + } + String it = text.substring(theindex + 2, secretsIndex - 1); + + secrets = Integer.parseInt(it.split("/")[1]); + } + + if (secrets2 == secrets) stack++; + else { + stack = 0; + secrets2 = secrets; + } + + if (stack == 4 && dungeonRoom.getTotalSecrets() != secrets) { + dungeonRoom.setTotalSecrets(secrets); + if (FeatureRegistry.DUNGEON_INTERMODCOMM.isEnabled()) + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pchat $DG-Comm " + pos2.getX() + "/" + pos2.getZ() + " " + secrets); + } + } + + @Override + public boolean readGlobalChat() { + return false; + } + + @Getter + private Map<String, ActionRoute> path = new HashMap<>(); + + public ActionRoute getPath(String id){ + return path.get(id); + } + + public String pathfind(String mechanic, String state, ActionRouteProperties actionRouteProperties) { + String str = UUID.randomUUID().toString(); + pathfind(str, mechanic, state, actionRouteProperties); + return str; + } + public void pathfind(String id, String mechanic, String state, ActionRouteProperties actionRouteProperties) { + path.put(id, new ActionRoute(getDungeonRoom(), mechanic, state, actionRouteProperties)); + } + public void cancelAll() { + path.clear(); + } + public void cancel(String id) { + path.remove(id); + } + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand && + updateEvent.entityLiving.getName() != null && + updateEvent.entityLiving.getName().contains("Mimic") && + !dungeonRoom.getContext().isGotMimic()) { + dungeonRoom.getContext().setGotMimic(true); +// Minecraft.getMinecraft().thePlayer.sendChatMessage("/pc $DG-Mimic"); + } + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + if (FeatureRegistry.SECRET_NEXT_KEY.isEnabled() && FeatureRegistry.SECRET_NEXT_KEY.<Integer>getParameter("key").getValue() == keyInputEvent.getKey()) { + searchForNextTarget(); + } else if (FeatureRegistry.SECRET_CREATE_REFRESH_LINE.getKeybind() == keyInputEvent.getKey() && FeatureRegistry.SECRET_CREATE_REFRESH_LINE.isEnabled()) { + ActionRoute actionRoute = getBestFit(0); + // actually do force refresh because of force freeze pathfind + if (actionRoute.getCurrentAction() instanceof ActionMove) { + ActionMove ac = (ActionMove) actionRoute.getCurrentAction(); + ac.forceRefresh(getDungeonRoom()); + } else if (actionRoute.getCurrentAction() instanceof ActionMoveNearestAir) { + ActionMoveNearestAir ac = (ActionMoveNearestAir) actionRoute.getCurrentAction(); + ac.forceRefresh(getDungeonRoom()); + } else if (actionRoute.getCurrent() >= 1 && actionRoute.getActions().get(actionRoute.getCurrent()-1) instanceof ActionMove) { + ((ActionMove)actionRoute.getActions().get(actionRoute.getCurrent()-1)).forceRefresh(dungeonRoom); + } else if (actionRoute.getCurrent() >= 1 && actionRoute.getActions().get(actionRoute.getCurrent()-1) instanceof ActionMoveNearestAir) { + ((ActionMoveNearestAir)actionRoute.getActions().get(actionRoute.getCurrent()-1)).forceRefresh(dungeonRoom); + } + + if (FeatureRegistry.SECRET_CREATE_REFRESH_LINE.isPathfind() && !actionRoute.getActionRouteProperties().isPathfind()) { + actionRoute.getActionRouteProperties().setPathfind(true); + actionRoute.getActionRouteProperties().setLineRefreshRate(FeatureRegistry.SECRET_CREATE_REFRESH_LINE.getRefreshRate()); + } + } + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + path.values().forEach(a -> { + a.onLivingInteract(event); + }); + } + + private boolean last = false; + private BlockPos lastChest; + @Override + public void onInteractBlock(PlayerInteractEvent event) { + path.values().forEach(a -> { + a.onPlayerInteract(event); + }); + + if (event.pos != null) { + IBlockState iBlockState = event.world.getBlockState(event.pos); + if (iBlockState.getBlock() == Blocks.chest || iBlockState.getBlock() == Blocks.trapped_chest) + lastChest = event.pos; + } + + if (event.entityPlayer.getHeldItem() != null && + event.entityPlayer.getHeldItem().getItem() == Items.stick && + FeatureRegistry.ADVANCED_ROOMEDIT.isEnabled() && + FeatureRegistry.DEBUG.isEnabled()) { + EditingContext ec = EditingContext.getEditingContext(); + if (ec == null) return; + if (!(ec.getCurrent() instanceof GuiDungeonAddSet)) return; + GuiDungeonAddSet gdas = (GuiDungeonAddSet) ec.getCurrent(); + if (event.action == PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) { + if (last) + gdas.getEnd().setPosInWorld(getDungeonRoom(), event.pos); + else + gdas.getStart().setPosInWorld(getDungeonRoom(), event.pos); + + last = !last; + } + } + } + + @Override + public void onEntityDeath(LivingDeathEvent deathEvent) { + path.values().forEach(a -> { + a.onLivingDeath(deathEvent); + }); + if (EditingContext.getEditingContext() != null && EditingContext.getEditingContext().getRoom() == getDungeonRoom()) { + if (deathEvent.entity instanceof EntityBat) { + for (GuiScreen screen : EditingContext.getEditingContext().getGuiStack()) { + if (screen instanceof GuiDungeonRoomEdit) { + DungeonSecret secret = new DungeonSecret(); + secret.setSecretType(DungeonSecret.SecretType.BAT); + secret.setSecretPoint(new OffsetPoint(dungeonRoom, + DungeonActionContext.getSpawnLocation().get(deathEvent.entity.getEntityId()) + )); + ((GuiDungeonRoomEdit) screen).getSep().createNewMechanic("BAT-"+ UUID.randomUUID(), + secret); + return; + } + } + if (EditingContext.getEditingContext().getCurrent() instanceof GuiDungeonRoomEdit) { + DungeonSecret secret = new DungeonSecret(); + secret.setSecretType(DungeonSecret.SecretType.BAT); + secret.setSecretPoint(new OffsetPoint(dungeonRoom, + DungeonActionContext.getSpawnLocation().get(deathEvent.entity.getEntityId()) + )); + ((GuiDungeonRoomEdit) EditingContext.getEditingContext().getCurrent()).getSep().createNewMechanic("BAT-"+ UUID.randomUUID(), + secret); + } + } + } + } + @Override + public void onBlockUpdate(BlockUpdateEvent blockUpdateEvent) { + for (Tuple<BlockPos, IBlockState> updatedBlock : blockUpdateEvent.getUpdatedBlocks()) { + if (updatedBlock.getSecond().equals(NodeProcessorDungeonRoom.preBuilt)) continue; + dungeonRoom.resetBlock(updatedBlock.getFirst()); + } + } + + public static class Generator implements RoomProcessorGenerator<GeneralRoomProcessor> { + @Override + public GeneralRoomProcessor createNew(DungeonRoom dungeonRoom) { + GeneralRoomProcessor defaultRoomProcessor = new GeneralRoomProcessor(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/ProcessorFactory.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/ProcessorFactory.java new file mode 100755 index 00000000..1c61a45d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/ProcessorFactory.java @@ -0,0 +1,65 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.boxpuzzle.RoomProcessorBoxSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.icefill.RoomProcessorIcePath2; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.RoomProcessorWaterPuzzle; + +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +public class ProcessorFactory { + private static final Map<String, RoomProcessorGenerator> map = new HashMap<>(); + + public static RoomProcessorGenerator getRoomProcessorGenerator(String processorId) { + return map.get(processorId); + } + + public static void registerRoomProcessor(String processorId, RoomProcessorGenerator generator) { + map.put(processorId, generator); + } + + public static Set<String> getProcessors() { + return map.keySet(); + } + + static { + registerRoomProcessor("default", new GeneralRoomProcessor.Generator()); + registerRoomProcessor("button_5", new RoomProcessorButtonSolver.Generator()); + registerRoomProcessor("puzzle_water_solver", new RoomProcessorWaterPuzzle.Generator()); + registerRoomProcessor("puzzle_teleport_solver", new RoomProcessorTeleportMazeSolver.Generator()); + registerRoomProcessor("puzzle_riddle_solver", new RoomProcessorRiddle.Generator()); + registerRoomProcessor("puzzle_creeper_solver", new RoomProcessorCreeperSolver.Generator()); + registerRoomProcessor("puzzle_tictactoe_solver", new RoomProcessorTicTacToeSolver.Generator()); + + registerRoomProcessor("puzzle_blaze_solver", new RoomProcessorBlazeSolver.Generator()); + + + registerRoomProcessor("puzzle_silverfish", new RoomProcessorIcePath.Generator()); // done + registerRoomProcessor("puzzle_icefill", new RoomProcessorIcePath2.Generator()); + registerRoomProcessor("puzzle_box", new RoomProcessorBoxSolver.Generator()); + registerRoomProcessor("puzzle_trivia", new RoomProcessorTrivia.Generator()); + registerRoomProcessor("puzzle_bombdefuse", new RoomProcessorBombDefuseSolver.Generator()); + + registerRoomProcessor("bossroom", new RoomProcessorRedRoom.Generator()); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessor.java new file mode 100755 index 00000000..96b9fb72 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessor.java @@ -0,0 +1,49 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.events.impl.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +public interface RoomProcessor { + void tick(); + void drawScreen(float partialTicks); + void drawWorld(float partialTicks); + void chatReceived(IChatComponent chat); + void actionbarReceived(IChatComponent chat); + + boolean readGlobalChat(); + + void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event); + void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent); + void onEntityDeath(LivingDeathEvent deathEvent); + + void onKeybindPress(KeyBindPressedEvent keyInputEvent); + + void onInteract(PlayerInteractEntityEvent event); + void onInteractBlock(PlayerInteractEvent event); + + void onBlockUpdate(BlockUpdateEvent blockUpdateEvent); +}
\ No newline at end of file diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorBlazeSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorBlazeSolver.java new file mode 100755 index 00000000..f36fd71b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorBlazeSolver.java @@ -0,0 +1,201 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.entity.monster.EntityBlaze; +import net.minecraft.util.*; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +public class RoomProcessorBlazeSolver extends GeneralRoomProcessor { + + private boolean highToLow = false; + + private List<EntityArmorStand> entityList = new ArrayList<EntityArmorStand>(); + private List<EntityBlaze> blazeList = new ArrayList<>(); + private EntityArmorStand next; + private EntityBlaze nextBlaze, theoneafterit; + public RoomProcessorBlazeSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + Object highToLow = dungeonRoom.getDungeonRoomInfo().getProperties().get("order"); + if (highToLow == null) this.highToLow = false; + else this.highToLow = (Boolean) highToLow; + } + + @Override + public void tick() { + super.tick(); + + DungeonRoom dungeonRoom = getDungeonRoom(); + World w = dungeonRoom.getContext().getWorld(); + final BlockPos low = dungeonRoom.getMin(); + final BlockPos high = dungeonRoom.getMax(); + entityList = new ArrayList<EntityArmorStand>(w.getEntities(EntityArmorStand.class, input -> { + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ() && input.getName().toLowerCase().contains("blaze"); + })); + blazeList = new ArrayList<EntityBlaze>(w.getEntities(EntityBlaze.class, input -> { + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ(); + })); + + Comparator<EntityArmorStand> comparator = Comparator.comparingInt(a -> { + String name = a.getName(); + String colorGone = TextUtils.stripColor(name); + String health2 = TextUtils.keepIntegerCharactersOnly(colorGone.split("/")[1]); + try { + return Integer.parseInt(health2); + } catch (Exception e) {return -1;} + }); + if (highToLow) { + entityList.sort(comparator.reversed()); + } else { + entityList.sort(comparator); + } + + if (entityList.size() > 0) { + next = entityList.get(0); + nextBlaze = blazeList.stream().min(Comparator.comparingDouble(e -> e.getDistanceSqToEntity(next))).orElse(null); + } else { + next = null; + nextBlaze = null; + } + if (entityList.size() > 1) { + EntityArmorStand thenextone = entityList.get(1); + theoneafterit = blazeList.stream().min(Comparator.comparingDouble(e -> e.getDistanceSqToEntity(thenextone))).orElse(null); + } else { + theoneafterit = null; + } + } + + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_BLAZE.isEnabled()) return; + if (next == null) return; + Vec3 pos = next.getPositionEyes(partialTicks); + RenderUtils.drawTextAtWorld("NEXT", (float)pos.xCoord, (float)pos.yCoord, (float)pos.zCoord, 0xFFFF0000, 0.5f, true, false, partialTicks); + + 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); + + + for (EntityBlaze entity : blazeList) { + GlStateManager.pushMatrix(); + float f = entity.prevRotationYaw + (entity.rotationYaw - entity.prevRotationYaw) * partialTicks; + double x = entity.prevPosX + (entity.posX - entity.prevPosX) * partialTicks; + double y = entity.prevPosY + (entity.posY - entity.prevPosY) * partialTicks; + double z = entity.prevPosZ + (entity.posZ - entity.prevPosZ) * partialTicks; + + + GL11.glEnable(GL11.GL_STENCIL_TEST); + GL11.glClearStencil(0); + GlStateManager.disableDepth(); + GL11.glClear(GL11.GL_STENCIL_BUFFER_BIT); + + GL11.glStencilMask(0xFF); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_REPLACE, GL11.GL_REPLACE); + + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + + GlStateManager.colorMask(false, false, false, false); + Minecraft.getMinecraft().getRenderManager().doRenderEntity(entity, x,y,z,f,partialTicks, true); + GlStateManager.colorMask(true, true, true, true); + + GlStateManager.popMatrix(); + + + GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + +// Gui.drawRect(-9999,-9999, 9999, 9999, 0xFFFFFFFF); + + boolean border = true; + + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-0.8,0, -0.8, 0.8, 2, 0.8), FeatureRegistry.SOLVER_BLAZE.getBlazeColor(), partialTicks, false); + if (entity == theoneafterit) { + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-0.8,0, -0.8, 0.8, 2, 0.8), FeatureRegistry.SOLVER_BLAZE.getNextUpBlazeColor(), partialTicks, false); + } else if (entity == nextBlaze) + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-0.8,0, -0.8, 0.8, 2, 0.8), FeatureRegistry.SOLVER_BLAZE.getNextBlazeColor(), partialTicks, false); + + GlStateManager.color(1,1,1,1); + + + if (FeatureRegistry.SOLVER_BLAZE.<AColor>getParameter("blazeborder").getValue().getAlpha() > 0x10) { + GL11.glStencilFunc(GL11.GL_NOTEQUAL, 3, 0x01); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_REPLACE, GL11.GL_REPLACE); + GlStateManager.pushMatrix(); + + GlStateManager.translate(-x_fix, -y_fix, -z_fix); + GlStateManager.translate(x, y + 0.7, z); + GlStateManager.scale(1.1f, 1.1f, 1.1f); + + GlStateManager.colorMask(false, false, false, false); + Minecraft.getMinecraft().getRenderManager().doRenderEntity(entity, 0, -0.7, 0, f, partialTicks, true); + GlStateManager.colorMask(true, true, true, true); + + GlStateManager.popMatrix(); + + + + GL11.glStencilFunc(GL11.GL_EQUAL, 3, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_KEEP); + + RenderUtils.highlightBox(entity, AxisAlignedBB.fromBounds(-1, 0, -1, 1, 2, 1), FeatureRegistry.SOLVER_BLAZE.<AColor>getParameter("blazeborder").getValue(), partialTicks, false); + + + } + GL11.glDisable(GL11.GL_STENCIL_TEST); + GlStateManager.enableDepth(); + GlStateManager.popMatrix(); + } + } + + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorBlazeSolver> { + @Override + public RoomProcessorBlazeSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorBlazeSolver defaultRoomProcessor = new RoomProcessorBlazeSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorButtonSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorButtonSolver.java new file mode 100644 index 00000000..709922a0 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorButtonSolver.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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.BlockPos; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.awt.*; +import java.util.Arrays; + +public class RoomProcessorButtonSolver extends GeneralRoomProcessor { + public RoomProcessorButtonSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + OffsetPointSet ops = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("buttons"); + if (ops == null) { + bugged = true; + return; + } + + buttons = new BlockPos[12]; + woods = new BlockPos[12]; + for (int i = 0; i < ops.getOffsetPointList().size(); i++) { + buttons[i] = ops.getOffsetPointList().get(i).getBlockPos(dungeonRoom); + woods[i] = buttons[i].add(0,-1,0); + } + } + + private boolean bugged; + + private BlockPos[] buttons; + private BlockPos[] woods; + + private long clicked; + private int clickedButton = -1; + + private final int[] result = new int[12]; + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + super.onInteractBlock(event); + if (bugged) return; + + if (event.action != PlayerInteractEvent.Action.RIGHT_CLICK_BLOCK) return; + for (int i = 0; i < buttons.length; i++) { + if (event.pos.equals(buttons[i])) { + clicked = System.currentTimeMillis(); + clickedButton = i; + return; + } + } + } + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (bugged) return; + + if (clickedButton == -1) return; + if (clicked + 500 < System.currentTimeMillis()) return; + + String msg = chat.getFormattedText(); + if (msg.equals("§r§cThis button doesn't seem to do anything...§r")) { + result[clickedButton] = -1; + clickedButton = -1; + } else if (msg.equals("§r§aThis button seems connected to something§r")) { + Arrays.fill(result, -1); + if (clickedButton % 4 != 0) result[clickedButton - 1] = 1; + if (clickedButton % 4 != 3) result[clickedButton + 1] = 1; + clickedButton = -1; + } else if (msg.equals("§r§aClick! you Hear the sound of a door opening§r")) { + Arrays.fill(result, -1); + result[clickedButton] = 2; + clickedButton = -1; + } else if (msg.equals("§r§aWrong button, looks like the system reset!§r")) { + Arrays.fill(result, 0); + clickedButton = -1; + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (bugged) return; + if (Minecraft.getMinecraft().thePlayer.getPosition().distanceSq(woods[6]) > 100) return; + + + for (int i = 0; i < woods.length; i++) { + int data = result[i]; + BlockPos pos = woods[i]; + + if (data == 0) { + RenderUtils.highlightBlock(pos, new Color(0, 255, 255, 50), partialTicks, false); + } else if (data == -1) { + RenderUtils.highlightBlock(pos, new Color(255, 0, 0, 50), partialTicks, false); + } else if (data == 1) { + RenderUtils.highlightBlock(pos, new Color(0, 255, 0, 50), partialTicks, false); + } else if (data == 2) { + RenderUtils.highlightBlock(pos, new Color(0, 255, 0, 100), partialTicks, false); + } + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorButtonSolver> { + @Override + public RoomProcessorButtonSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorButtonSolver defaultRoomProcessor = new RoomProcessorButtonSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorCreeperSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorCreeperSolver.java new file mode 100755 index 00000000..b2c236c8 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorCreeperSolver.java @@ -0,0 +1,148 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.ArrayList; +import java.util.List; + +public class RoomProcessorCreeperSolver extends GeneralRoomProcessor { + + private final List<BlockPos[]> poses = new ArrayList<BlockPos[]>(); + + private final boolean bugged = false; + + public RoomProcessorCreeperSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + findCreeperAndDoPoses(); + } + + private boolean check(AxisAlignedBB axis, Vec3 vec) { + if (vec == null) return false; + return axis.isVecInside(vec); + } + + private void findCreeperAndDoPoses() { + World w = getDungeonRoom().getContext().getWorld(); + List<BlockPos> prismarines = new ArrayList<BlockPos>(); + final BlockPos low = getDungeonRoom().getMin().add(0,-2,0); + final BlockPos high = getDungeonRoom().getMax().add(0,20,0); + final AxisAlignedBB axis = AxisAlignedBB.fromBounds( + low.getX() + 17, low.getY() + 7, low.getZ() + 17, + low.getX() + 16, low.getY() + 10.5, low.getZ() + 16 + ); + + for (BlockPos pos : BlockPos.getAllInBox(low, high)) { + Block b = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(pos).getBlock(); + if (b == Blocks.prismarine || b == Blocks.sea_lantern) { + for (EnumFacing face:EnumFacing.VALUES) { + if (w.getBlockState(pos.offset(face)).getBlock() == Blocks.air) { + prismarines.add(pos); + break; + } + } + } + } + double offset = 0.1; + + while (prismarines.size() > 1) { + BlockPos first = prismarines.get(0); + BlockPos highestMatch = null; + int highestDist = 0; + label: for (int i = 1; i < prismarines.size(); i++) { + BlockPos second = prismarines.get(i); + + if (second.distanceSq(first) < highestDist) continue; + + Vec3 startLoc = new Vec3(first).addVector(0.5,0.5,0.5); + Vec3 dest = new Vec3(second).addVector(0.5,0.5,0.5); + if (check(axis, startLoc.getIntermediateWithYValue(dest, axis.minY+offset)) || + check(axis, startLoc.getIntermediateWithYValue(dest, axis.maxY-offset)) || + check(axis, startLoc.getIntermediateWithXValue(dest, axis.minX+offset)) || + check(axis, startLoc.getIntermediateWithXValue(dest, axis.maxX-offset)) || + check(axis, startLoc.getIntermediateWithZValue(dest, axis.minZ+offset)) || + check(axis, startLoc.getIntermediateWithZValue(dest, axis.maxZ-offset))) { + highestDist = (int) second.distanceSq(first); + highestMatch = second; + } + + } + + + if (highestMatch == null) { + prismarines.remove(first); + } else { + prismarines.remove(first); + prismarines.remove(highestMatch); + poses.add(new BlockPos[] {first, highestMatch}); + } + } + } + + @Override + public void tick() { + super.tick(); + if (bugged) { + findCreeperAndDoPoses(); + } + } + + private static final Color[] colors = new Color[] {Color.red, Color.orange, Color.green, Color.cyan, Color.blue, Color.pink, Color.yellow, Color.darkGray, Color.lightGray}; + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_CREEPER.isEnabled()) return; + World w = getDungeonRoom().getContext().getWorld(); + for (int i = 0; i < poses.size(); i++) { + BlockPos[] poset = poses.get(i); + Color color = colors[i % colors.length]; + boolean oneIsConnected = w.getChunkFromBlockCoords(poset[0]).getBlock(poset[0]) != Blocks.sea_lantern && + w.getChunkFromBlockCoords(poset[1]).getBlock(poset[1]) != Blocks.sea_lantern; + RenderUtils.drawLine(new Vec3(poset[0].getX() +0.5, poset[0].getY() +0.5, poset[0].getZ()+0.5), + new Vec3(poset[1].getX() +0.5, poset[1].getY() +0.5, poset[1].getZ()+0.5), oneIsConnected ? new Color(0,0,0,50) : color, partialTicks, true); + } + final BlockPos low = getDungeonRoom().getMin(); + final AxisAlignedBB axis = AxisAlignedBB.fromBounds( + low.getX() + 17, low.getY() + 5, low.getZ() + 17, + low.getX() + 16, low.getY() + 8.5, low.getZ() + 16 + ); + RenderUtils.highlightBox(axis, new Color(0x4400FF00, true), partialTicks, false); + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorCreeperSolver> { + @Override + public RoomProcessorCreeperSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorCreeperSolver defaultRoomProcessor = new RoomProcessorCreeperSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorGenerator.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorGenerator.java new file mode 100755 index 00000000..969424d9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorGenerator.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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; + +public interface RoomProcessorGenerator<T extends RoomProcessor> { + T createNew(DungeonRoom dungeonRoom); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorIcePath.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorIcePath.java new file mode 100755 index 00000000..df902858 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorIcePath.java @@ -0,0 +1,234 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.minecraft.entity.Entity; +import net.minecraft.entity.monster.EntitySilverfish; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class RoomProcessorIcePath extends GeneralRoomProcessor { + + private int[][] map; + private OffsetPoint[][] map2; + private final Set<OffsetPoint> endNode = new HashSet<OffsetPoint>(); + + private final List<BlockPos> solution = new ArrayList<BlockPos>(); + + private BlockPos lastSilverfishLoc; + private int sameTick; + + private Entity silverfish; + + private boolean err; + + public RoomProcessorIcePath(DungeonRoom dungeonRoom) { + super(dungeonRoom); + findSilverFishanddoStuff(); + } + + public void findSilverFishanddoStuff() { + final BlockPos low = getDungeonRoom().getMin(); + final BlockPos high = getDungeonRoom().getMax(); + List<EntitySilverfish> silverfishs = getDungeonRoom().getContext().getWorld().getEntities(EntitySilverfish.class, new Predicate<EntitySilverfish>() { + @Override + public boolean apply(@Nullable EntitySilverfish input) { + if (input.isInvisible()) return false; + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ(); + } + }); + + if (!silverfishs.isEmpty()) silverfish = silverfishs.get(0); + if (silverfishs.isEmpty()) { + err = true; + return; + } + try { + buildMap(); + err = false; + } catch (Exception e) { + e.printStackTrace(); + err = true; + return; + } + } + + private void buildMap() { + int width = (Integer) getDungeonRoom().getDungeonRoomInfo().getProperties().get("width"); + int height = (Integer) getDungeonRoom().getDungeonRoomInfo().getProperties().get("height"); + OffsetPointSet ops = (OffsetPointSet) getDungeonRoom().getDungeonRoomInfo().getProperties().get("board"); + OffsetPointSet endNodes = (OffsetPointSet) getDungeonRoom().getDungeonRoomInfo().getProperties().get("endnodes"); + map2 = new OffsetPoint[width][height]; + map = new int[width][height]; + for (int y = 0; y < height; y ++) { + for (int x =0; x < width; x++) { + OffsetPoint op = ops.getOffsetPointList().get(y * width + x); + map2[y][x] = op; + map[y][x] = op.getBlock(getDungeonRoom()) == Blocks.air ? 0 : 1; + } + } + endNode.addAll(endNodes.getOffsetPointList()); + } + + public void tick() { + super.tick(); + if (err || silverfish.isDead) { + findSilverFishanddoStuff(); + if (err) return; + } + if (silverfish.getPosition().equals(lastSilverfishLoc)) { + if (sameTick < 10) { + sameTick ++; + return; + } else if (sameTick == 10) { + sameTick ++; + Point silverfish = getPointOfSilverFishOnMap(this.silverfish.getPosition()); + List<Point> tempSol = solve(map, silverfish.x, silverfish.y, new Predicate<Point>() { + @Override + public boolean apply(@Nullable Point input) { + return endNode.contains(map2[input.y][input.x]); + } + }); + { + solution.clear(); + for (Point point : tempSol) { + solution.add(map2[point.y][point.x].getBlockPos(getDungeonRoom())); + } + } + + } + } else { + sameTick = 0; + } + + lastSilverfishLoc = silverfish.getPosition(); + } + + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_SILVERFISH.isEnabled()) return; + if (!err) + RenderUtils.drawLines(solution, FeatureRegistry.SOLVER_SILVERFISH.getLineColor(),FeatureRegistry.SOLVER_SILVERFISH.getLineWidth(), partialTicks, true); + } + + public Point getPointOfSilverFishOnMap(BlockPos blockPos) { + for (int y = 0; y < map.length; y ++) { + for (int x = 0; x < map[0].length; x++) { + if (map2[y][x].getBlockPos(getDungeonRoom()).equals(blockPos)) + return new Point(x,y); + } + } + return null; + } + + + // Taken from https://stackoverflow.com/a/55271133 and modified to suit our needs + // Answer by ofekp (https://stackoverflow.com/users/4295037/ofekp) + public static List<Point> solve(int[][] board, int startX, int startY, Predicate<Point> finishLinePredicate) { + Point startPoint = new Point(startX, startY); + + LinkedList<Point> queue = new LinkedList<Point>(); + Point[][] boardSearch = new Point[board.length][board[0].length]; + + queue.addLast(new Point(startX, startY)); + boardSearch[startY][startX] = startPoint; + + while (queue.size() != 0) { + Point currPos = queue.pollFirst(); + for (Direction dir : Direction.values()) { + Point nextPos = move(board, boardSearch, currPos, dir); + if (nextPos != null) { + queue.addLast(nextPos); + boardSearch[nextPos.y][nextPos.x] = new Point(currPos.x, currPos.y); + if (finishLinePredicate.apply(nextPos)) { + List<Point> route = new ArrayList<Point>(); + Point tmp = currPos; + route.add(nextPos); + route.add(currPos); + while (tmp != startPoint) { + tmp = boardSearch[tmp.y][tmp.x]; + route.add(tmp); + } + return route; + } + } + } + } + return Collections.emptyList(); + } + + public static Point move(int[][] board, Point[][] boardSearch, Point currPos, Direction dir) { + int x = currPos.x; + int y = currPos.y; + + int diffX = dir.dx; + int diffY = dir.dy; + + int i = 1; + while (x + i * diffX >= 0 && x + i * diffX < board[0].length + && y + i * diffY >= 0 && y + i * diffY < board.length + && board[y + i * diffY][x + i * diffX] != 1) { + i++; + } + i--; + + if (boardSearch[y + i * diffY][x + i * diffX] != null) { + return null; + } + + return new Point(x + i * diffX, y + i * diffY); + } + + @Getter + @AllArgsConstructor + public enum Direction { + LEFT(-1,0), + RIGHT(1,0), + UP(0,-1), + DOWN(0,1); + + int dx, dy; + } + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorIcePath> { + @Override + public RoomProcessorIcePath createNew(DungeonRoom dungeonRoom) { + RoomProcessorIcePath defaultRoomProcessor = new RoomProcessorIcePath(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorRedRoom.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorRedRoom.java new file mode 100644 index 00000000..d171c928 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorRedRoom.java @@ -0,0 +1,121 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.doorfinder.DungeonDoor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.features.impl.boss.FeatureWarningOnPortal; +import kr.syeyoung.dungeonsguide.mod.features.text.StyledTextRenderer; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MathHelper; +import net.minecraft.util.Vec3; +import org.lwjgl.opengl.GL11; + +import javax.vecmath.Vector3f; + +public class RoomProcessorRedRoom extends GeneralRoomProcessor { + public RoomProcessorRedRoom(DungeonRoom dungeonRoom) { + super(dungeonRoom); + BlockPos basePt = dungeonRoom.getMin().add(dungeonRoom.getMax()); + this.basePt = new Vec3(basePt.getX() / 2.0f, basePt.getY() / 2.0f, basePt.getZ() / 2.0f); + } + + Vec3 basePt; + int dir = 0; + + @Override + public void tick() { + BlockPos basePt = getDungeonRoom().getMin().add(getDungeonRoom().getMax()); + this.basePt = new Vec3(basePt.getX() / 2.0f, basePt.getY() / 2.0f + 4, basePt.getZ() / 2.0f); + DungeonDoor real = null; + for (DungeonDoor door : getDungeonRoom().getDoors()) { + if (door.getType().isExist()) { + real = door;break; + } + } + if (real != null) { + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), real.getPosition()); + offsetPoint = new OffsetPoint(33- offsetPoint.getX(), offsetPoint.getY(), 33 - offsetPoint.getZ()); + BlockPos opposite =offsetPoint.getBlockPos(getDungeonRoom()); + BlockPos dir = new BlockPos(real.getPosition().subtract(opposite)); + dir = new BlockPos(MathHelper.clamp_int(dir.getX() / 10, -1, 1), 0, MathHelper.clamp_int(dir.getZ() / 10, -1, 1)); + + this.basePt = new Vec3(opposite.add(dir.getX() * 6 + dir.getZ(), 3, dir.getZ() * 6 - dir.getX())); + + if (dir.getX() > 0) this.dir = 270; + else if (dir.getX() < 0) this.dir = 90; + else if (dir.getZ() < 0) this.dir = 0; + else if (dir.getZ() > 0) this.dir = 180; + else this.dir = Integer.MIN_VALUE; + } else { + dir = Integer.MIN_VALUE; + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.BOSSFIGHT_WARNING_ON_PORTAL.isEnabled()) return; + + + FeatureWarningOnPortal featureWarningOnPortal = FeatureRegistry.BOSSFIGHT_WARNING_ON_PORTAL; + { + RenderManager renderManager = Minecraft.getMinecraft().getRenderManager(); + + Vector3f renderPos = RenderUtils.getRenderPos((float)basePt.xCoord,(float) basePt.yCoord, (float)basePt.zCoord, partialTicks); + + GlStateManager.color(1f, 1f, 1f, 0.5f); + GlStateManager.pushMatrix(); + GlStateManager.translate(renderPos.x, renderPos.y, renderPos.z); + if (dir == Integer.MIN_VALUE) + GlStateManager.rotate(-renderManager.playerViewY, 0.0f, 1.0f, 0.0f); + else + GlStateManager.rotate(dir, 0.0f, 1.0f, 0.0f); + GlStateManager.scale(-0.05f, -0.05f, 0.05f); + GlStateManager.disableLighting(); + GlStateManager.depthMask(false); GL11.glDisable(GL11.GL_DEPTH_TEST); + GlStateManager.disableDepth(); + GlStateManager.enableBlend(); + GlStateManager.blendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA); + + + StyledTextRenderer.drawTextWithStylesAssociated(featureWarningOnPortal.getText(), 0, 0,0, featureWarningOnPortal.getStylesMap(), StyledTextRenderer.Alignment.LEFT); + + GlStateManager.color(1.0f, 1.0f, 1.0f, 1.0f); + GlStateManager.depthMask(true); + GlStateManager.enableDepth(); + GlStateManager.popMatrix(); + } + } + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorRedRoom> { + @Override + public RoomProcessorRedRoom createNew(DungeonRoom dungeonRoom) { + RoomProcessorRedRoom defaultRoomProcessor = new RoomProcessorRedRoom(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorRiddle.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorRiddle.java new file mode 100755 index 00000000..f7a0b65f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorRiddle.java @@ -0,0 +1,121 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +public class RoomProcessorRiddle extends GeneralRoomProcessor { + + public RoomProcessorRiddle(DungeonRoom dungeonRoom) { + super(dungeonRoom); + } + + private static final List<Pattern> patternList = Arrays.asList( + Pattern.compile("My chest doesn't have the reward. We are all telling the truth.*"), + Pattern.compile("The reward isn't in any of our chests.*"), + Pattern.compile("The reward is not in my chest!.*"), + Pattern.compile("At least one of them is lying, and the reward is not in .+'s chest.*"), + Pattern.compile("Both of them are telling the truth. Also,.+has the reward in their chest.*"), + Pattern.compile("My chest has the reward and I'm telling the truth.*") + ); + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (!FeatureRegistry.SOLVER_RIDDLE.isEnabled()) return; + String ch2 = chat.getUnformattedText(); + if (!ch2.startsWith("§e[NPC] ")) { + return; + } + String watsaid = TextUtils.stripColor(ch2.split(":")[1]).trim(); + boolean foundMatch = false; + for (Pattern p:patternList) { + if (p.matcher(watsaid).matches()) { + foundMatch = true; + break; + } + } + if (foundMatch) { + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §eRiddle §7:: "+ch2.split(":")[0].trim()+" §fhas the reward!")); + final String name = TextUtils.stripColor(ch2.split(":")[0]).replace("[NPC] ","").trim(); + final BlockPos low = getDungeonRoom().getMin(); + final BlockPos high = getDungeonRoom().getMax(); + World w = getDungeonRoom().getContext().getWorld(); + List<EntityArmorStand> armor = w.getEntities(EntityArmorStand.class, new Predicate<EntityArmorStand>() { + @Override + public boolean apply(@Nullable EntityArmorStand input) { + BlockPos pos = input.getPosition(); + return low.getX() < pos.getX() && pos.getX() < high.getX() + && low.getZ() < pos.getZ() && pos.getZ() < high.getZ() && TextUtils.stripColor(input.getName()).equalsIgnoreCase(name); + } + }); + + if (armor != null) { + this.chest = null; + BlockPos pos = armor.get(0).getPosition(); + for (BlockPos allInBox : BlockPos.getAllInBox(pos.add(-1, 0, -1), pos.add(1, 0, 1))) { + Block b = w.getChunkFromBlockCoords(allInBox).getBlock(allInBox); + + if ((b == Blocks.chest || b == Blocks.trapped_chest)&& allInBox.distanceSq(pos) == 1 ) { + this.chest = allInBox; + return; + } + } + } + + } + } + + BlockPos chest; + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_RIDDLE.isEnabled()) return; + if (chest != null) { + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(chest.getX(), chest.getY(), chest.getZ(), chest.getX()+1, chest.getY() + 1, chest.getZ() + 1), FeatureRegistry.SOLVER_RIDDLE.getTargetColor(), partialTicks, true); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorRiddle> { + @Override + public RoomProcessorRiddle createNew(DungeonRoom dungeonRoom) { + RoomProcessorRiddle defaultRoomProcessor = new RoomProcessorRiddle(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTeleportMazeSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTeleportMazeSolver.java new file mode 100755 index 00000000..30f1d385 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTeleportMazeSolver.java @@ -0,0 +1,145 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.Vec3; +import net.minecraft.world.World; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +public class RoomProcessorTeleportMazeSolver extends GeneralRoomProcessor { + @Nullable + private BlockPos lastPlayerLocation; + + public RoomProcessorTeleportMazeSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + yLevel = dungeonRoom.getMin().getY() - 1; + } + + private final List<BlockPos> visitedPortals = new ArrayList<BlockPos>(); + + private int yLevel = 0; + private double slope1, slope2; + private double posX1, posZ1, posX2, posZ2; + private int times=0 ; + + private double intersectionX, intersectionZ; + private BlockPos intersection; + + @Override + public void tick() { + super.tick(); + + + + World w = getDungeonRoom().getContext().getWorld(); + EntityPlayerSP entityPlayerSP = Minecraft.getMinecraft().thePlayer; + BlockPos pos2 = new BlockPos(Math.floor(entityPlayerSP.posX), Math.floor(entityPlayerSP.posY), Math.floor(entityPlayerSP.posZ)); + Block b = w.getChunkFromBlockCoords(pos2).getBlock(pos2); + Vec3 lookVec = entityPlayerSP.getLookVec(); + + if (times % 4 == 1) { + posX1 = entityPlayerSP.posX; + posZ1 = entityPlayerSP.posZ; + slope1 = lookVec.zCoord / lookVec.xCoord; + times ++; + } else if (times % 4 == 3) { + posX2 = entityPlayerSP.posX; + posZ2 = entityPlayerSP.posZ; + slope2 = lookVec.zCoord / lookVec.xCoord; + + double yInt1 = posZ1 - posX1 * slope1; + double yInt2 = posZ2 - posX2 * slope2; + + intersectionX = (yInt2 - yInt1) / (slope1 - slope2); + intersectionZ = (slope1 * intersectionX + yInt1); + intersection = new BlockPos((int) intersectionX, yLevel, (int) intersectionZ); + times++; + } + + if (b == Blocks.stone_slab || b == Blocks.stone_slab2) { + boolean teleport = false; + if (lastPlayerLocation != null && lastPlayerLocation.distanceSq(pos2) < 3) { + return; + } + for (BlockPos allInBox : BlockPos.getAllInBox(lastPlayerLocation, pos2)) { + if (w.getChunkFromBlockCoords(allInBox).getBlock(allInBox) == Blocks.iron_bars) { + teleport = true; + break; + } + } + + if (teleport) { + if (times % 4 == 0) { + times ++; + } else if (times % 4 == 2){ + times++; + } + + for (BlockPos allInBox : BlockPos.getAllInBox(pos2.add(-1, 0, -1), pos2.add(1, 0, 1))) { + if (w.getChunkFromBlockCoords(allInBox).getBlock(allInBox) == Blocks.end_portal_frame) { + if (!visitedPortals.contains(allInBox)) + visitedPortals.add(allInBox); + break; + } + } + for (BlockPos allInBox : BlockPos.getAllInBox(lastPlayerLocation.add(-1, -1, -1), lastPlayerLocation.add(1, 1, 1))) { + if (w.getChunkFromBlockCoords(allInBox).getBlock(allInBox) == Blocks.end_portal_frame) { + if (!visitedPortals.contains(allInBox)) + visitedPortals.add(allInBox); + break; + } + } + } + } + + lastPlayerLocation = pos2; + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_TELEPORT.isEnabled()) return; + for (BlockPos bpos:visitedPortals) { + RenderUtils.highlightBoxAColor( AxisAlignedBB.fromBounds(bpos.getX(), bpos.getY(), bpos.getZ(), bpos.getX()+1, bpos.getY() + 1, bpos.getZ() + 1), FeatureRegistry.SOLVER_TELEPORT.getTargetColor2(), partialTicks, true); + } + + if (intersection != null) { + RenderUtils.highlightBoxAColor( AxisAlignedBB.fromBounds(intersection.getX(), intersection.getY(), intersection.getZ(), intersection.getX()+1, intersection.getY() + 1, intersection.getZ() + 1), FeatureRegistry.SOLVER_TELEPORT.getTargetColor(), partialTicks, false); + } + } + public static class Generator implements RoomProcessorGenerator<RoomProcessorTeleportMazeSolver> { + @Override + public RoomProcessorTeleportMazeSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorTeleportMazeSolver defaultRoomProcessor = new RoomProcessorTeleportMazeSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTicTacToeSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTicTacToeSolver.java new file mode 100755 index 00000000..9ee8c215 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTicTacToeSolver.java @@ -0,0 +1,214 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.item.EntityItemFrame; +import net.minecraft.init.Blocks; +import net.minecraft.item.ItemMap; +import net.minecraft.item.ItemStack; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; +import net.minecraft.world.storage.MapData; + +import java.util.List; + +public class RoomProcessorTicTacToeSolver extends GeneralRoomProcessor { + + private final OffsetPointSet board; + private byte[][] lastBoard; + public RoomProcessorTicTacToeSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + board = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("board"); + } + + // -1 com, 1 pla, 0 emp + private byte[][] buildBoardState() { + byte[][] board = new byte[3][3]; + World w= getDungeonRoom().getContext().getWorld(); + for (int x = 0; x < 3; x++) { + for (int y = 0; y < 3; y++) { + OffsetPoint op = this.board.getOffsetPointList().get(x * 3 + y); + BlockPos bpos = op.getBlockPos(getDungeonRoom()); + Block b = w.getChunkFromBlockCoords(bpos).getBlock(bpos); + if (b == Blocks.stone_button) { + board[y][x] = 0; + } else if (b == Blocks.air){ + AxisAlignedBB abab = AxisAlignedBB.fromBounds(bpos.getX() , bpos.getY(), bpos.getZ(), bpos.getX() +1, bpos.getY() +1, bpos.getZ() +1); + List<EntityItemFrame> frames = getDungeonRoom().getContext().getWorld().getEntitiesWithinAABB(EntityItemFrame.class, abab); + if (frames.isEmpty()) board[y][x] = 0; + else { + ItemStack displayedItem = frames.get(0).getDisplayedItem(); + if (displayedItem == null || displayedItem.getItem() == null || !displayedItem.getItem().isMap()) { + board[y][x] = 0; + continue; + } + MapData mapData = ((ItemMap)displayedItem.getItem()).getMapData(displayedItem, w); + byte center = mapData.colors[64 * 128+64]; + if (center == 114) + board[y][x] = -1; + else + board[y][x] = 1; + } + } + } + } + return board; + } + + private byte checkWinner(byte[][] board) { + for (int y = 0; y <3; y++) { + byte potentialWinner = board[y][0]; + if (potentialWinner == 0) continue; + boolean found = false; + for (int x = 0; x < 3; x++) { + if (potentialWinner != board[y][x]) { + found = true; + break; + } + } + if (!found) { + return potentialWinner; + } + } + for (int x = 0; x <3; x++) { + byte potentialWinner = board[0][x]; + if (potentialWinner == 0) continue; + boolean found = false; + for (int y = 0; y < 3; y++) { + if (potentialWinner != board[y][x]) { + found = true; + break; + } + } + if (!found) { + return potentialWinner; + } + } + if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[0][0] != 0) { + return board[0][0]; + } + if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[0][2] != 0) { + return board[0][2]; + } + return 0; + } + + private int chosePos = -1; + private int minimax(byte[][] board, byte player) { + byte winner = checkWinner(board); + if (winner != 0) { + return winner * player; + } + + int move = -1; + int score = -2; + for (int i = 0; i < 9; i++) { + if (board[i % 3][i / 3] == 0) { + byte[][] cloned = new byte[3][]; + for(int k = 0; k < 3; k++) + cloned[k] = board[k].clone(); + + cloned[i % 3][i/3] = player; + int scoreForMove = -minimax(cloned, (byte) -player); + if (scoreForMove > score) { + score = scoreForMove; + move = i; + } + } + } + chosePos = move; + if (move == -1) { + return 0; + } + + return score; + } + + private boolean gameEnded = false; + + @Override + public void tick() { + super.tick(); + if (board == null) return; + if (gameEnded) return; + byte[][] board = buildBoardState(); + if (checkWinner(board) != 0) { + gameEnded = true; + return; + } + if (lastBoard != null) { + boolean yesdoit = false; + label: + for (int y = 0; y < 3; y++) + for (int x = 0; x < 3; x++) + if (board[y][x] != lastBoard[y][x]) { + yesdoit = true; + break label; + } + if (!yesdoit) return; + } + lastBoard = board; + + minimax(board, (byte) 1); + if (chosePos == -1) { + gameEnded = true; + return; + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_TICTACTOE.isEnabled()) return; + if (chosePos != -1) { + BlockPos block = board.getOffsetPointList().get(chosePos).getBlockPos(getDungeonRoom()); + boolean whoseturn = false; // false => hype true => me + if (lastBoard != null) { + int ones = 0; + int negativeones = 0; + for (byte[] bytes : lastBoard) { + for (byte aByte : bytes) { + if (aByte == 1) ones++; + else if (aByte == -1) negativeones++; + } + } + whoseturn = ones < negativeones; + } + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(block.getX(), block.getY(), block.getZ(), block.getX()+1, block.getY() + 1, block.getZ() + 1), + whoseturn ? FeatureRegistry.SOLVER_TICTACTOE.getTargetColor() + : FeatureRegistry.SOLVER_TICTACTOE.getTargetColor2(), partialTicks, true); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorTicTacToeSolver> { + @Override + public RoomProcessorTicTacToeSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorTicTacToeSolver defaultRoomProcessor = new RoomProcessorTicTacToeSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTrivia.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTrivia.java new file mode 100755 index 00000000..b7956122 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/RoomProcessorTrivia.java @@ -0,0 +1,165 @@ +/* + * 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.mod.dungeon.roomprocessor; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.mod.utils.SkyblockUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import kr.syeyoung.dungeonsguide.mod.wsresource.StaticResourceCache; +import net.minecraft.util.AxisAlignedBB; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import org.apache.commons.lang3.math.NumberUtils; +import org.json.JSONObject; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class RoomProcessorTrivia extends GeneralRoomProcessor { + + public RoomProcessorTrivia(DungeonRoom dungeonRoom) { + super(dungeonRoom); + } + + + private final List<String> questionDialog = new ArrayList<String>(); + private boolean questionDialogStart = false; + + private boolean parseDialog = false; + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (!FeatureRegistry.SOLVER_KAHOOT.isEnabled()) return; + String ch2 = chat.getUnformattedText(); + if (parseDialog) { + parseDialog = false; + parseDialog(); + } + if (chat.getFormattedText().contains("§r§6§lQuestion ")) { + questionDialogStart = true; + questionDialog.clear(); + } + if (questionDialogStart && (chat.getFormattedText().startsWith("§r§r§r") || chat.getFormattedText().startsWith("§r§r§r") || chat.getFormattedText().trim().startsWith("§r§6 "))) { + questionDialog.add(chat.getFormattedText()); + } + + if (chat.getFormattedText().contains("§r§6 ⓒ")) { + questionDialogStart = false; + parseDialog = true; + } + } + public static final Pattern anwerPattern = Pattern.compile("§r§6 . §a(.+)§r"); + private void parseDialog() { + String question = TextUtils.stripColor(questionDialog.get(1)).trim(); + String answerA = getAnswer(questionDialog.get(2)); + String answerB = getAnswer(questionDialog.get(3)); + String answerC = getAnswer(questionDialog.get(4)); + match(question, answerA, answerB, answerC); + + } + String correctAnswer; + + + private String getAnswer(String answerString) { + Matcher matcher = anwerPattern.matcher(answerString.trim()); + if (!matcher.matches()) return ""; + return matcher.group(1); + } + private void match(String question, String a, String b, String c) { + StaticResourceCache.INSTANCE.getResource(StaticResourceCache.TRIVIA_ANSWERS).thenAccept(value -> { + JSONObject answersJSON = new JSONObject(value.getValue()); + + String semi_answers = answersJSON.getString(question.toLowerCase().trim()); + String theRealAnswer; + if (semi_answers == null) theRealAnswer = null; + else { + semi_answers = takeCareOfPlaceHolders(semi_answers); + String[] answers = semi_answers.split(","); + if (match(answers, a)) theRealAnswer = "A"; + else if (match(answers, b)) theRealAnswer = "B"; + else if (match(answers, c)) theRealAnswer = "C"; + else theRealAnswer = semi_answers; + } + if (theRealAnswer == null) + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §eTrivia §7:: §cCouldn't determine the answer! (no question found)")); + else if (theRealAnswer.length() >1) + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §eTrivia §7:: §cCouldn't determine the answer! ("+theRealAnswer+")")); + else + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §eTrivia §7:: "+theRealAnswer+"§f is the correct answer!")); + correctAnswer = theRealAnswer; + }); + } + + private String takeCareOfPlaceHolders(String input) { + String str = input; + if (str.contains("$year")) { + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §fuses §eInventiveTalent§7(https://github.com/InventivetalentDev)§e's Skyblock Api §fto fetch current skyblock year!")); + try { + str = str.replace("$year", SkyblockUtils.getSkyblockYear()+""); + } catch (IOException e) { + str = str.replace("$year", "Couldn't determine current skyblock year :: "+e.getMessage()); + } + } + return str; + } + private boolean match(String[] match, String match2) { + for (String s : match) { + if (NumberUtils.isNumber(s)) { + if (match2.toLowerCase().contains(s)) return true; + } else { + if (match2.equalsIgnoreCase(s)) return true; + } + } + return false; + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_KAHOOT.isEnabled()) return; + if (correctAnswer == null) return; + + OffsetPoint op = (OffsetPoint) getDungeonRoom().getDungeonRoomInfo().getProperties().get(correctAnswer); + if (op != null) { + BlockPos solution = op.getBlockPos(getDungeonRoom()); + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(solution.getX(), solution.getY(), solution.getZ(), solution.getX()+1, solution.getY() + 1, solution.getZ() + 1), FeatureRegistry.SOLVER_KAHOOT.getTargetColor(), partialTicks, false); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorTrivia> { + @Override + public RoomProcessorTrivia createNew(DungeonRoom dungeonRoom) { + RoomProcessorTrivia defaultRoomProcessor = new RoomProcessorTrivia(dungeonRoom); + return defaultRoomProcessor; + } + } + + @Override + public boolean readGlobalChat() { + return true; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/RoomProcessorBombDefuseSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/RoomProcessorBombDefuseSolver.java new file mode 100644 index 00000000..d3d7ae3b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/RoomProcessorBombDefuseSolver.java @@ -0,0 +1,441 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.DummyDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.arrow.ArrowProcessorMatcher; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.bugged.ImpossibleMatcher; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.color.ColorProcessorMatcher; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.creeper.CreeperProcessorMatcher; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.goldenpath.GoldenPathProcessorMatcher; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.maze.MazeProcessorMatcher; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.number.NumberProcessorMatcher; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.nbt.CompressedStreamTools; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import org.apache.commons.codec.binary.Base64; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +public class RoomProcessorBombDefuseSolver extends GeneralRoomProcessor { + + @Getter + private final List<ChamberSet> chambers = new ArrayList<ChamberSet>(); + @Getter + private OffsetPointSet doors; + + private static final List<BombDefuseChamberGenerator> chamberGenerators = new ArrayList<BombDefuseChamberGenerator>(); + { + chamberGenerators.add(new ArrowProcessorMatcher()); + chamberGenerators.add(new ColorProcessorMatcher()); + chamberGenerators.add(new CreeperProcessorMatcher()); + chamberGenerators.add(new NumberProcessorMatcher()); + chamberGenerators.add(new GoldenPathProcessorMatcher()); + chamberGenerators.add(new MazeProcessorMatcher()); + chamberGenerators.add(new ImpossibleMatcher()); + } + + private boolean bugged = false; + private boolean maze = false; + private boolean impossible = false; + + public RoomProcessorBombDefuseSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + if (!FeatureRegistry.SOLVER_BOMBDEFUSE.isEnabled()) { + bugged = true; + return; + } + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L1"), 1, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R1"), 1, true), null + )); + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L2"), 2, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R2"), 2, true), null + )); + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L3"), 3, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R3"), 3, true), null + )); + chambers.add(new ChamberSet( + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("L4"), 4, true), + buildChamber((OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("R4"), 4, true), null + )); + doors = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("Door"); + if (doors == null) {bugged = true; return;} + for (ChamberSet set:chambers) { + if (set.getLeft().getChamberBlocks() == null) { + bugged = true; + return; + } + if (set.getRight().getChamberBlocks() == null) { + bugged = true; + return; + } + } + + for (ChamberSet set:chambers) { + if (set.getLeft().getChamberBlocks() == null) { + bugged = true; + return; + } + if (set.getRight().getChamberBlocks() == null) { + bugged = true; + return; + } + } + + for (ChamberSet set:chambers) { + for (BombDefuseChamberGenerator bdcg:chamberGenerators) { + if (bdcg.match(set.getLeft(), set.getRight())) { + set.setChamberGen(bdcg); + set.getLeft().setProcessor(bdcg.createLeft(set.getLeft(), this)); + set.getRight().setProcessor(bdcg.createRight(set.getRight(), this)); + if (bdcg instanceof ImpossibleMatcher) impossible=true; + if (bdcg instanceof MazeProcessorMatcher) maze = true; + break; + } + } + if (set.getChamberGen() == null) { + set.setChamberGen(null); + set.getLeft().setProcessor(new DummyDefuseChamberProcessor(this, set.getLeft())); + set.getRight().setProcessor(new DummyDefuseChamberProcessor(this, set.getRight())); + } + } + + OffsetPoint warning1 = (OffsetPoint) dungeonRoom.getDungeonRoomInfo().getProperties().get("Warning"); + if (warning1 != null) warning = warning1.getBlockPos(dungeonRoom); + } + + public BDChamber buildChamber(OffsetPointSet ops, int level, boolean left) { + return new BDChamber(getDungeonRoom(), ops, left, level, null); + } + BlockPos warning; + + + public void communicate(NBTTagCompound compound) { + if (bugged) return; + try { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + DataOutputStream w = new DataOutputStream(baos); + CompressedStreamTools.writeCompressed(compound, w); + w.flush(); + byte[] bytes = baos.toByteArray(); + String str = Base64.encodeBase64String(bytes); + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pc $DG-BD " +str); + + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().onDataRecieve(compound); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().onDataRecieve(compound); + } + } catch (IOException e2) { + e2.printStackTrace(); + ChatTransmitter.sendDebugChat(new ChatComponentText("Failed to send Bomb Defuse Chat")); + } + } + + @Override + public void chatReceived(IChatComponent component) { + super.chatReceived(component); + if (bugged) return; + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().chatReceived(component); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().chatReceived(component); + } + + if (component.getFormattedText().contains("$DG-BD ")) { + try { + String data = component.getFormattedText().substring(component.getFormattedText().indexOf("$DG-BD")); + String actual = TextUtils.stripColor(data).trim().split(" ")[1]; + byte[] data2 = Base64.decodeBase64(actual); + NBTTagCompound compound = CompressedStreamTools.readCompressed(new ByteArrayInputStream(data2)); + + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().onDataRecieve(compound); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().onDataRecieve(compound); + } + } catch (Throwable t) { + t.printStackTrace(); + ChatTransmitter.sendDebugChat(new ChatComponentText("Failed to analyze Bomb Defuse Chat")); + } + } + } + + + @Override + public void tick() { + super.tick(); + if (bugged) return; + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().tick(); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().tick(); + } + } + } + } + + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + if (bugged) return; + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + if (FeatureRegistry.DEBUG.isEnabled()) { + for (ChamberSet ch : chambers) { + if (ch.getChamberGen() == null) continue; + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().drawScreen(partialTicks); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + String str = "Current: " + ch.getChamberGen().getName() + " Specific: " + ch.getLeft().getProcessor().getName(); + fr.drawString(str, 0, 0, 0xFFFFFFFF); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().drawScreen(partialTicks); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + if (ch.getChamberGen() == null || ch.getRight().getProcessor() == null) continue; + String str = "Current: " + ch.getChamberGen().getName() + " Specific: " + ch.getRight().getProcessor().getName(); + fr.drawString(str, 0, 0, 0xFFFFFFFF); + } + } + } + } + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (bugged) return; + + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos((int)Minecraft.getMinecraft().thePlayer.posX, 68, (int)Minecraft.getMinecraft().thePlayer.posZ)); + boolean found = false; + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + found = true; + ch.getLeft().getProcessor().drawWorld(partialTicks); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + found = true; + ch.getRight().getProcessor().drawWorld(partialTicks); + } + } + } + + if ((maze || impossible) && warning != null && !found) { + if (impossible) { + RenderUtils.drawTextAtWorld("Warning: This Bomb Defuse is bugged and Impossible" , warning.getX()+ 0.5f, warning.getY(), warning.getZ()+ 0.5f, 0xFF00FF00, 0.03F, false, false, partialTicks); + } else { + RenderUtils.drawTextAtWorld("Warning: This Bomb Defuse must be done with 2 people (maze)" , warning.getX()+ 0.5f, warning.getY(), warning.getZ()+ 0.5f, 0xFF00FF00, 0.03F, false, false, partialTicks); + } + } + if (warning != null && !found) { + for (int i = 0; i < 4; i++) { + BombDefuseChamberGenerator bdcg = chambers.get(i).getChamberGen(); + RenderUtils.drawTextAtWorld((i + 1) + ". " + (bdcg == null ? "null" : bdcg.getName()), warning.getX() + 0.5f, warning.getY() - ((i + 1) * 0.3f), warning.getZ() + 0.5f, 0xFF00FF00, 0.03F, false, false, partialTicks); + } + } + } + + @Override + public void actionbarReceived(IChatComponent chat) { + super.actionbarReceived(chat); + if (bugged) return; + + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().actionbarReceived(chat); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().actionbarReceived(chat); + } + } + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + super.onPostGuiRender(event); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onPostGuiRender(event); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onPostGuiRender(event); + } + } + } + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + super.onEntityUpdate(updateEvent); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onEntityUpdate(updateEvent); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { +// if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onEntityUpdate(updateEvent); +// } + } + } + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + super.onKeybindPress(keyInputEvent); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onKeybindPress(keyInputEvent); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onKeybindPress(keyInputEvent); + } + } + } + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + super.onInteract(event); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onInteract(event); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onInteract(event); + } + } + } + } + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + super.onInteractBlock(event); + if (bugged) return; + + BlockPos player = Minecraft.getMinecraft().thePlayer.getPosition(); + OffsetPoint offsetPoint = new OffsetPoint(getDungeonRoom(), new BlockPos(player.getX(), 68, player.getZ())); + for (ChamberSet ch:chambers) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) { + if (ch.getLeft().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getLeft().getProcessor().onInteractBlock(event); + } + } + if (ch.getRight() != null && ch.getRight().getProcessor() != null) { + if (ch.getRight().getChamberBlocks().getOffsetPointList().contains(offsetPoint)) { + ch.getRight().getProcessor().onInteractBlock(event); + } + } + } + } + + @Override public boolean readGlobalChat() { return true; } + + @Data + @AllArgsConstructor + public static class ChamberSet { + private BDChamber left; + private BDChamber right; + private BombDefuseChamberGenerator chamberGen; + } + + + public static class Generator implements RoomProcessorGenerator<RoomProcessorBombDefuseSolver> { + @Override + public RoomProcessorBombDefuseSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorBombDefuseSolver defaultRoomProcessor = new RoomProcessorBombDefuseSolver(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/BDChamber.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/BDChamber.java new file mode 100644 index 00000000..2dc754b1 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/BDChamber.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.mod.dungeon.roomprocessor.bombdefuse.chambers; + +import com.google.common.base.Predicate; +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.state.IBlockState; +import net.minecraft.entity.Entity; +import net.minecraft.util.BlockPos; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +@AllArgsConstructor +@Data +public class BDChamber { + private DungeonRoom room; + private OffsetPointSet chamberBlocks; + + private boolean isLeft; + private int level; + + private ChamberProcessor processor; + + // for whatever's sake, 6: z, 9: x. Starts from botoom right, left, then up + + public OffsetPoint getOffsetPoint(int x, int z) { + return chamberBlocks.getOffsetPointList().get(z * 9 + x); + } + + public BlockPos getBlockPos(int x, int y, int z) { + return getOffsetPoint(x,z).getBlockPos(room).add(0,y,0); + } + + public IBlockState getBlock(int x, int y, int z) { + BlockPos pos = getBlockPos(x,y,z); + return DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(pos); + } + + public boolean isWithinAbsolute(int x, int y, int z) { + return isWithinAbsolute(new BlockPos(x,68,z)); + } + public boolean isWithinAbsolute(BlockPos pos) { + return chamberBlocks.getOffsetPointList().contains(new OffsetPoint(room, new BlockPos(pos.getX(), 68, pos.getZ()))); + } + + + public <T extends Entity> T getEntityAt(Class<T> entity, int x, int y, int z) { + final BlockPos pos = getBlockPos(x,y,z); + return getEntityAt(entity, pos); + } + public <T extends Entity> T getEntityAt(Class<T> entity, final BlockPos pos) { + List<T> entities = room.getContext().getWorld().getEntities(entity, new Predicate<T>() { + @Override + public boolean apply(@Nullable T input) { + return input.getPosition().equals(pos); + } + }); + if (entities.size() == 0) return null; + return entities.get(0); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/BombDefuseChamberGenerator.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/BombDefuseChamberGenerator.java new file mode 100644 index 00000000..8c43ca36 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/BombDefuseChamberGenerator.java @@ -0,0 +1,30 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; + +public interface BombDefuseChamberGenerator { + boolean match(BDChamber left, BDChamber right); + + String getName(); + + ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver); + ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver); +}
\ No newline at end of file diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/ChamberProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/ChamberProcessor.java new file mode 100644 index 00000000..c4d63f42 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/ChamberProcessor.java @@ -0,0 +1,27 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessor; +import net.minecraft.nbt.NBTTagCompound; + +public interface ChamberProcessor extends RoomProcessor { + void onDataRecieve(NBTTagCompound compound); + String getName(); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/DummyDefuseChamberProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/DummyDefuseChamberProcessor.java new file mode 100644 index 00000000..d7056dbf --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/DummyDefuseChamberProcessor.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.mod.dungeon.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; + +public class DummyDefuseChamberProcessor extends GeneralDefuseChamberProcessor { + public DummyDefuseChamberProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + } + + @Override + public String getName() { + return "dummy"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/GeneralDefuseChamberProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/GeneralDefuseChamberProcessor.java new file mode 100644 index 00000000..0040bc4f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/GeneralDefuseChamberProcessor.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.mod.dungeon.roomprocessor.bombdefuse.chambers; + +import kr.syeyoung.dungeonsguide.mod.events.impl.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import lombok.Getter; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.IChatComponent; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +@Getter +public abstract class GeneralDefuseChamberProcessor implements ChamberProcessor{ + private final RoomProcessorBombDefuseSolver solver; + private final BDChamber chamber; + + public GeneralDefuseChamberProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + this.solver = solver; + this.chamber = chamber; + } + + + @Override + public void onDataRecieve(NBTTagCompound compound) { + + } + + @Override + public void tick() { + + } + + @Override + public void drawScreen(float partialTicks) { + + } + + @Override + public void drawWorld(float partialTicks) { + + } + + @Override + public void chatReceived(IChatComponent chat) { + + } + + @Override + public void onEntityDeath(LivingDeathEvent deathEvent) { + + } + + @Override + public void actionbarReceived(IChatComponent chat) { + + } + @Override + public void onBlockUpdate(BlockUpdateEvent blockUpdateEvent) { + + } + + @Override + public boolean readGlobalChat() { + return false; + } + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + + } + + protected void drawPressKey() { + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + String str = "Press "+ GameSettings.getKeyDisplayString(FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) + " to save and send solution"; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(str, (sr.getScaledWidth() - fr.getStringWidth(str)) / 2, (sr.getScaledHeight() - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + if (keyInputEvent.getKey() == FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) { + if (!getChamber().isWithinAbsolute(Minecraft.getMinecraft().thePlayer.getPosition())) { + return; + } + onSendData(); + } + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + + } + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + + } + + public void onSendData() {} +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowLeftProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowLeftProcessor.java new file mode 100644 index 00000000..94b4f78d --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowLeftProcessor.java @@ -0,0 +1,138 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.arrow; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +import java.util.HashMap; +import java.util.Map; + +public class ArrowLeftProcessor extends GeneralDefuseChamberProcessor { + public ArrowLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + for (int i = 0; i < 9; i++) { + grid[i] = chamber.getBlockPos(7,1 + (i / 3),1 + (i % 3)); + } + } + + @Override + public String getName() { + return "arrowLeft"; + } + + + private int answer = -1; + private final int[] answers = new int[9]; + private final BlockPos[] grid = new BlockPos[9]; + @Override + public void tick() { + super.tick(); + if (answer != -1) return; + for (int i = 0; i < 9; i++) + answers[i] = match(getChamber().getEntityAt(EntityArmorStand.class, grid[i].add(0, -1, 0))); + + answer = 0; + for (int i =0; i < 9; i++) { + answer = answer * 10 + answers[i]; + } + } + + @Override + public void drawScreen(float partialTicks) { + if (answer == -1) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + + if (answer == -1) return; + for (int i = 0; i < 9; i++) { + BlockPos pos = grid[i]; + int direction = answers[i]; + String charac = arrows.get(direction); + + RenderUtils.drawTextAtWorld(charac, pos.getX()+ 0.5f, pos.getY()+ 0.5f, pos.getZ()+ 0.5f, 0xFFFFFFFF, 0.05F, false, false, partialTicks); + } + } + + @Override + public void onSendData() { + if (answer == -1) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 3); + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (3 == compound.getByte("a")) { + answer = compound.getInteger("b"); + for (int i = 8; i >= 0; i--) { + answers[i] = answer % 10; + answer = answer / 10; + } + answer = compound.getInteger("b"); + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) return -1; + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(8); + private static final Map<Integer, String> arrows = new HashMap<Integer, String>(); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDczZTFmZTBmZmNkNTQ2YzIxYjYzZWFhOTEwYWI1YzkzMTMyYTY0ZTY0NDE3OWZjY2FhMjFkYzhiYzY2MCJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNThmZTI1MWE0MGU0MTY3ZDM1ZDA4MWMyNzg2OWFjMTUxYWY5NmI2YmQxNmRkMjgzNGQ1ZGM3MjM1ZjQ3NzkxZCJ9fX0=", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTc3ZWM0NGZiNzUwM2RlNmFmZTNiZGQ3ZTU4M2M3YjkzOTc5ZjU5ZjZkNjM0YjZiNmE1YWY3ZjNhMWM1ODUxNSJ9fX0=", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjJmM2EyZGZjZTBjM2RhYjdlZTEwZGIzODVlNTIyOWYxYTM5NTM0YThiYTI2NDYxNzhlMzdjNGZhOTNiIn19fQ==", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOGUxY2U5YzBkMzMyMzZmOTkyMWQyMmM0ZWM0YmY1MDkyMzdhZWY2NzZiNWQxZDJiYWNjOTNmNWE4MTk0ODAifX19", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOWI3Y2U2ODNkMDg2OGFhNDM3OGFlYjYwY2FhNWVhODA1OTZiY2ZmZGFiNmI1YWYyZDEyNTk1ODM3YTg0ODUzIn19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTI2NTFlY2QzNzgwY2Y2ZTQ1MWVjYWNjZGVlNjk3MTVjMDhjYWU3Y2Q0NTA5MDg0NDYyY2RjZDk2M2E2YjMyMiJ9fX0=", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmIwZjZlOGFmNDZhYzZmYWY4ODkxNDE5MWFiNjZmMjYxZDY3MjZhNzk5OWM2MzdjZjJlNDE1OWZlMWZjNDc3In19fQ==", 8); + + arrows.put(0, "?"); + arrows.put(1, "↖"); + arrows.put(2, "↑"); + arrows.put(3, "↗"); + arrows.put(4, "→"); + arrows.put(5, "↘"); + arrows.put(6, "↓"); + arrows.put(7, "↙"); + arrows.put(8, "←"); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowProcessorMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowProcessorMatcher.java new file mode 100644 index 00000000..82a972b2 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowProcessorMatcher.java @@ -0,0 +1,52 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.arrow; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class ArrowProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(8,1,1).getBlock() == Blocks.planks && + left.getBlock(8,1,2).getBlock() == Blocks.planks && + left.getBlock(8,1,3).getBlock() == Blocks.planks && + right.getBlock(0,1,1).getBlock() == Blocks.planks && + right.getBlock(0,1,2).getBlock() == Blocks.planks && + right.getBlock(0,1,3).getBlock() == Blocks.planks; + } + + @Override + public String getName() { + return "arrowMatch"; + } + + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new ArrowLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new ArrowRightProcessor(solver, right); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowRightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowRightProcessor.java new file mode 100644 index 00000000..9c293bc7 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/arrow/ArrowRightProcessor.java @@ -0,0 +1,126 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.arrow; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +import java.util.HashMap; +import java.util.Map; + +public class ArrowRightProcessor extends GeneralDefuseChamberProcessor { + public ArrowRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + for (int i = 0; i < 9; i++) { + grid[i] = chamber.getBlockPos(1,1 + (i / 3),1 + (2 - (i % 3))); + } + + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "arrowRight"; + } + + + private int answer = -1; + private final int[] correctAnswers = new int[9]; + private final int[] currentAnswers = new int[9]; + private final BlockPos[] grid = new BlockPos[9]; + private final BlockPos center; + @Override + public void tick() { + super.tick(); + for (int i = 0; i < 9; i++) + currentAnswers[i] = match(getChamber().getEntityAt(EntityArmorStand.class, grid[i].add(0, -1, 0))); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + + RenderUtils.drawTextAtWorld(answer == -1 ? "Answer not received yet. Visit left room to obtain solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + for (int i = 0; i < 9; i++) { + BlockPos pos = grid[i]; + int direction = correctAnswers[i]; + int direction2 = currentAnswers[i]; + String charac = arrows.get(direction); + String car2 = arrows.get(direction2); + + RenderUtils.drawTextAtWorld(car2, pos.getX()+ 0.5f, pos.getY()+ 0.6f, pos.getZ()+ 0.5f, direction == direction2 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(charac, pos.getX()+ 0.5f, pos.getY()+ 0.2f, pos.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + } + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (3 == compound.getByte("a")) { + answer = compound.getInteger("b"); + for (int i = 8; i >= 0; i--) { + correctAnswers[i] = answer % 10; + answer = answer / 10; + } + answer = compound.getInteger("b"); + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) return -1; + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(8); + private static final Map<Integer, String> arrows = new HashMap<Integer, String>(); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODY1NDI2YTMzZGY1OGI0NjVmMDYwMWRkOGI5YmVjMzY5MGIyMTkzZDFmOTUwM2MyY2FhYjc4ZjZjMjQzOCJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzA0MGZlODM2YTZjMmZiZDJjN2E5YzhlYzZiZTUxNzRmZGRmMWFjMjBmNTVlMzY2MTU2ZmE1ZjcxMmUxMCJ9fX0=", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTBlMGE0ZDQ4Y2Q4MjlhNmQ1ODY4OTA5ZDY0M2ZhNGFmZmQzOWU4YWU2Y2FhZjZlYzc5NjA5Y2Y3NjQ5YjFjIn19fQ==", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTliZjMyOTJlMTI2YTEwNWI1NGViYTcxM2FhMWIxNTJkNTQxYTFkODkzODgyOWM1NjM2NGQxNzhlZDIyYmYifX19", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzVjYmRiMjg5OTFhMTZlYjJjNzkzNDc0ZWY3ZDBmNDU4YTVkMTNmZmZjMjgzYzRkNzRkOTI5OTQxYmIxOTg5In19fQ==", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzQzNzM0NmQ4YmRhNzhkNTI1ZDE5ZjU0MGE5NWU0ZTc5ZGFlZGE3OTVjYmM1YTEzMjU2MjM2MzEyY2YifX19", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzU0Y2U4MTU3ZTcxZGNkNWI2YjE2NzRhYzViZDU1NDkwNzAyMDI3YzY3NWU1Y2RjZWFjNTVkMmZiYmQ1YSJ9fX0=", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmQ2OWUwNmU1ZGFkZmQ4NGU1ZjNkMWMyMTA2M2YyNTUzYjJmYTk0NWVlMWQ0ZDcxNTJmZGM1NDI1YmMxMmE5In19fQ==", 8); + + + arrows.put(0, "?"); + arrows.put(1, "↖"); + arrows.put(2, "↑"); + arrows.put(3, "↗"); + arrows.put(4, "→"); + arrows.put(5, "↘"); + arrows.put(6, "↓"); + arrows.put(7, "↙"); + arrows.put(8, "←"); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/bugged/ImpossibleMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/bugged/ImpossibleMatcher.java new file mode 100644 index 00000000..42a00119 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/bugged/ImpossibleMatcher.java @@ -0,0 +1,47 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.bugged; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class ImpossibleMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(1,1,1).getBlock() == Blocks.barrier; + } + + @Override + public String getName() { + return "buggedMazeMatcher"; + } + + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return null; + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return null; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorLeftProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorLeftProcessor.java new file mode 100644 index 00000000..e0291d00 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorLeftProcessor.java @@ -0,0 +1,230 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.color; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; + +public class ColorLeftProcessor extends GeneralDefuseChamberProcessor { + public ColorLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + center = chamber.getBlockPos(4,6,4); + b1p = chamber.getBlockPos(1,1,4); + b2p = chamber.getBlockPos(4,1,4); + b3p = chamber.getBlockPos(7,1,4); + } + + private final BlockPos center; + + private Block w1, w2, w3, c1, c2, c3; + private final BlockPos b1p; + private final BlockPos b2p; + private final BlockPos b3p; + private int s1, s2, s3; + private int s1t, s2t, s3t; + private boolean solutionBuilt; + + @Override + public String getName() { + return "colorRight"; + } + + @Override + public void tick() { + super.tick(); + if (solutionBuilt) return; + World w = getChamber().getRoom().getContext().getWorld(); + if ((c1 = w.getBlockState(b1p).getBlock()) == w1 && s1t < 7) { + int semi = match(getChamber().getEntityAt(EntityArmorStand.class,b1p.add(0, 1, 0))); + if (s1 == semi) { + s1t++; + } else { + s1 = semi; + s1t = 0; + } + } + if ((c2 = w.getBlockState(b2p).getBlock()) == w2 && s2t < 7) { + int semi = match(getChamber().getEntityAt(EntityArmorStand.class,b2p.add(0, 2, 0))); + if (s2 == semi) { + s2t++; + } else { + s2 = semi; + s2t = 0; + } + } + if ((c3 =w.getBlockState(b3p).getBlock()) == w3 && s3t < 7) { + int semi = match(getChamber().getEntityAt(EntityArmorStand.class,b3p.add(0, 1, 0))); + if (s3== semi) { + s3t++; + } else { + s3 = semi; + s3t = 0; + } + } + + if (s1t > 5 && s2t > 5 && s3t > 5) { + solutionBuilt = true; + } + } + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + if (solutionBuilt) + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(w1 == null ? "Request Not Received Yet" : "Building- "+w1.getLocalizedName() +" / "+w2.getLocalizedName() +" / "+w3.getLocalizedName() , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + RenderUtils.drawTextAtWorld(w1 == null ? "null" : w1.getLocalizedName(), b1p.getX()+ 0.5f, b1p.getY() + 0.2f, b1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(w2 == null ? "null" : w2.getLocalizedName(), b2p.getX()+ 0.5f, b2p.getY() + 0.2f, b2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(w3 == null ? "null" : w3.getLocalizedName(), b3p.getX()+ 0.5f, b3p.getY() + 0.2f, b3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(c1 == null ? "null" : c1.getLocalizedName(), b1p.getX()+ 0.5f, b1p.getY() + 0.6f, b1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(c2 == null ? "null" : c2.getLocalizedName(), b2p.getX()+ 0.5f, b2p.getY() + 0.6f, b2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(c3 == null ? "null" : c3.getLocalizedName(), b3p.getX()+ 0.5f, b3p.getY() + 0.6f, b3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + if (FeatureRegistry.DEBUG.isEnabled()) { + RenderUtils.drawTextAtWorld(s1 + "", b1p.getX() + 0.5f, b1p.getY() + 2.6f, b1p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s2 + "", b2p.getX() + 0.5f, b2p.getY() + 3.6f, b2p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s3 + "", b3p.getX() + 0.5f, b3p.getY() + 2.6f, b3p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + } + + RenderUtils.drawTextAtWorld(colors.get(s1), b1p.getX()+ 0.5f, b1p.getY() + 2.2f, b1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(colors.get(s2), b2p.getX()+ 0.5f, b2p.getY() + 3.2f, b2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(colors.get(s3), b3p.getX()+ 0.5f, b3p.getY() + 2.2f, b3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + if (FeatureRegistry.DEBUG.isEnabled()) { + RenderUtils.drawTextAtWorld(s1t + "", b1p.getX() + 0.5f, b1p.getY() + 1.5f, b1p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s2t + "", b2p.getX() + 0.5f, b2p.getY() + 2f, b2p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(s3t + "", b3p.getX() + 0.5f, b3p.getY() + 1.5f, b3p.getZ() + 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + } + } + + @Override + public void onSendData() { + super.onSendData(); + if (!solutionBuilt) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 7); + int answer = s1 * 10000 + s2 * 100 + s3; + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (6 == compound.getByte("a")) { + w1 = Block.getBlockById(compound.getByte("f")); + w2 = Block.getBlockById(compound.getByte("s")); + w3 = Block.getBlockById(compound.getByte("t")); + solutionBuilt = false; + s1 = s2 = s3 = s1t = s2t = s3t =0; + } + } + + private byte match(EntityArmorStand armorStand) { + if (armorStand == null) { + return 0; + } + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return (byte) (!integers.containsKey(str) ? 0 : integers.get(str)); + } + + private static final Map<String, Integer> integers = new HashMap<String, Integer>(); + private static final BiMap<Integer, String> colors = HashBiMap.create(); + static { + colors.put(0, "?"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2YzZTQwNjI5MTE3NGQyNGNkZjBmOTUzZjhhMTc0YTgyYmIzNDg5ZGNlOGY2NzlhNDQzZWYxYWFlMDE2OTA2MSJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE4MWZjYjUxYmUyYTlmODliMWFkYzlkODcyMzliYTQyOWQ2MzVmYmUwMWIzN2VjMzI5MTY0ODg3YmY2NjViIn19fQ==", 1); + colors.put(1, "blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FiMDI2M2JkZDc2ZjNlNDE4ZGJhNWJmNDgxYjkyMWNlZDM5N2Q4YjhhMzRhNTU2MWZiN2JlYWE0NmVjZTEifX19", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZhNGRkYTZkMTlhMWZlMmQ5ODhkNjVkZWM1MzQyOTUwNTMwODE2NmM5MDY3YjY4YTQ3NzBjYTVjNDM2Y2Y5NCJ9fX0=", 2); + colors.put(2, "black"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDg0Njg0MzQ0YWUwOTg1MjlmYzk0MWFhODRlMTk1YmRjYTM3NDhkNjlhY2ZlZTJiYWMxMzMyMTM1ZWRkOThjIn19fQ==", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM1ODFjMmY5Y2YzNThkN2VkYzc4ZGQ2ZmQ0YjYyNTc1MDFiYzRlNjQ1NWUzM2ZhMGNhYWUyMDdjZjAzMjFhMiJ9fX0=", 3); + colors.put(3, "green"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTllNjkxN2YyZmI0ZWEwOGU3MTMyZGYzMDk2MWQyYjVjNTIzYWJiYTE5Y2U0M2Y4MzVmYzE0YzU2OGY0In19fQ==", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMjFmNTMyMTIyNTY2YWY4OTNkYTI3ODgwYTFiNjA5NWMzNTcxMmYyOWEzNzhjZmVjYzdmZTJiMTMyOGFiNCJ9fX0=", 4); + colors.put(4, "gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODhlZmFkNzRiMjU0ZTU3Yzc5OTc2M2RjZWVlNDUxMWZhMmY4NWFlOWZhNTU2ZWFhOTdkNDViZjY3ZTBiNmIzIn19fQ==", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWZhZGY3NDFhYjc2Y2QzNjIwYWQxNjEzMDAyMDJkN2I1OWEzMzA1MWU1OTY3ZTRiNjE5NGJhYzQwYmIyODBmZiJ9fX0=", 5); + colors.put(5, "cyan"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzJlMzZmNmE2NTRkZTc0NTgzZDgwMzAxNzdhZDZlM2FjNjc1NWQ3NDM1ZDkxMjNlOGViZGZmNzRiMmQ5MGNiIn19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJjYmQ5ZjQzNjE5YWI1Y2IxYjExZjkxY2IwM2U5NTVjNmZjNmM0NThhYmY4OWFiNjEwMzEzNDZhMDkwNjEyZSJ9fX0=", 6); + colors.put(6, "brown"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjFhZjQ2ZmViZDQ1YzBmNGQ4MWU4ZmExYjY2YjI3NWQ4OWUyNzJiMmFkNTVjOTc4NTUzYTk5YzczM2UxZmYifX19", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTYzZTY2NDZmMWMwZDQxZmQzYmY1NTg0YTFjZTA0NGY1YzQ2ZDU5ODI1OGRiNDYyMTYxMTc4NTlmNTdhZjE5NyJ9fX0=", 7); + colors.put(7, "light-blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY3NDcwYTBjMThmNjg1MWU5MTQzNTM3MTllNzk1ODc3ZDI5YjMyNTJmN2U2YmQ0YTFiODY1NzY1YmQ3NGZlYiJ9fX0=", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzc0NzJkNjA4ODIxZjQ1YTg4MDUzNzZlYzBjNmZmY2I3ODExNzgyOWVhNWY5NjAwNDFjMmEwOWQxMGUwNGNiNCJ9fX0=", 8); + colors.put(8, "lime"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJiNDM4NmJjZGE4NGUzNTNjMzFkNzc4ZDNiMTFiY2QyNmZlYTQ5NGRkNjM0OTZiOGE4MmM3Yzc4YTRhZCJ9fX0=", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjk3MDEyZWQ2YTkyYjA1ZWEwZjE5NDk1MDc0ODU0NGUwNzViYWEyODc4MWNhMzczZDFiMjdlMjhjMjY5NTNjIn19fQ==", 9); + colors.put(9, "magenta"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2JmNzc5N2EyNGE2YWY4NzVmNWM4MjcxYzViOGM0MjVlMTlmMzcyYTQxNWUwNTUyZmMyNDc3NjNmMjg1OWQxIn19fQ==", 10); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMmViMjA1YTIzYzExOTZiM2VjZjIxZTY4YzA3NmI2OTZlNzYxNjNhYzhmYzRmYjlmNTMxOGMyYTVlNWIxYSJ9fX0=", 10); + colors.put(10, "orange"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmJlY2ZiMzg3OTkzNmI4OTllNDIwYmZjZDNhNzRmOGExYmY5ZGQ1NGM1OGVjN2ZiOWY4MWQ5YTVkOTg4ZSJ9fX0=", 11); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ODM2NTBlYTkyOWRiMGVhYmRmNWJjNzU1OTlkOGVmMDBkNzAzNDBjZDFjZTVlMDRhZDk1ZWY4ZWQ4M2I3MyJ9fX0=", 11); + colors.put(11, "pink"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmE5NGNiMjVkZTYyOGNhMzU5YjJmNmVhNWE4ODY4Y2JlMjY1OTVlZWRiMmJmZmI3NTA5NjdhZDFlZTE4NTAifX19", 12); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODllYzVhMzAyMjJkMDY1OWIwZGJlZTg0NGI4ZjUzZWFlNjJmZTk1YjRhMzQ0OGE5ZWY3OTBhN2FlZGIyOTZkOSJ9fX0=", 12); + colors.put(12, "purple"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODZkMzVhOTYzZDU5ODc4OTRiNmJjMjE0ZTMyOGIzOWNkMjM4MjQyNmZmOWM4ZTA4MmIwYjZhNmUwNDRkM2EzIn19fQ==", 13); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjk1M2IxMmEwOTQ2YjYyOWI0YzA4ODlkNDFmZDI2ZWQyNmZiNzI5ZDRkNTE0YjU5NzI3MTI0YzM3YmI3MGQ4ZCJ9fX0=", 13); + colors.put(13, "red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTk4YmEyYjM3NGNmYzg5NDU0YzFiOGMzMmRiNDU4YTI3MDY3NTQzOWE0OTU0OTZjOTY3NzFjOTg5MTE2MTYyIn19fQ==", 14); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTUyODhkZGM5MTFhNzVmNzdjM2E1ZDMzNjM2NWE4ZjhiMTM5ZmE1MzkzMGI0YjZlZTEzOTg3NWM4MGNlMzY2YyJ9fX0=", 14); + colors.put(14, "light-gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2ZhZjRjMjlmMWU3NDA1ZjQ2ODBjNWMyYjAzZWY5Mzg0ZjFhZWNmZTI5ODZhZDUwMTM4YzYwNWZlZmZmMmYxNSJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ZGY2MGM1MTA3NGVlZjI1NDRmZjM4Y2VhZDllMTY2NzVhZTQyNTE5MTYxMDUxODBlMWY4Y2UxOTdhYjNiYyJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTVhZDkzZDU2NTQ2ZjEyZDUzNTZlZmZjYmM2ZWM0Yzg3YmEyNDVkODFlMTY2MmM0YjgzMGY3ZDI5OGU5In19fQ==", 15); + colors.put(15, "white"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDRiMDM3OTRiOWIzZTNiNWQwN2UzYmU2OGI5NmFmODdkZjIxNWMzNzUyZTU0NzM2YzgwZjdkNTBiZDM0MzdhNCJ9fX0=", 16); + colors.put(16, "rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 17); + colors.put(17, "lilac"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 18); + colors.put(18, "dark-red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM4NmY5YjBiMWQ5ODc5YzNkYTMzYzdhOGNhMjQ0MGMxZTQxMWZlOTNjMjdjOWRiYmZmNTZiZDY5N2JiNzM3NSJ9fX0=", 19); + colors.put(19, "i-rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjdiYmQwYjI5MTFjOTZiNWQ4N2IyZGY3NjY5MWE1MWI4YjEyYzZmZWZkNTIzMTQ2ZDhhYzVlZjFiOGVlIn19fQ==", 20); + colors.put(20, "yellow"); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorProcessorMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorProcessorMatcher.java new file mode 100644 index 00000000..5505fe9c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorProcessorMatcher.java @@ -0,0 +1,49 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.color; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class ColorProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return + right.getBlock(0,1,1).getBlock() == Blocks.stonebrick && + right.getBlock(0,1,2).getBlock() == Blocks.stonebrick && + right.getBlock(0,1,3).getBlock() == Blocks.stonebrick; + } + + @Override + public String getName() { + return "colorMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new ColorLeftProcessor(solver,left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new ColorRightProcessor(solver,right); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorRightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorRightProcessor.java new file mode 100644 index 00000000..5c77abe1 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/color/ColorRightProcessor.java @@ -0,0 +1,175 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.color; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +import java.util.HashMap; +import java.util.Map; + +public class ColorRightProcessor extends GeneralDefuseChamberProcessor { + public ColorRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + center = chamber.getBlockPos(4,4,4); + b1 = chamber.getBlockPos(1,3,3); + b2 = chamber.getBlockPos(1,3,2); + b3 = chamber.getBlockPos(1,3,1); + } + + private final BlockPos center; + + private final BlockPos b1; + private final BlockPos b2; + private final BlockPos b3; + private byte b1b = 0, b2b = 0, b3b = 0, c1b, c2b, c3b; + private int answer = -1; + + @Override + public String getName() { + return "colorRight"; + } + + @Override + public void tick() { + super.tick(); + c1b = match(getChamber().getEntityAt(EntityArmorStand.class,b1.add(0, -1, 0))); + c2b = match(getChamber().getEntityAt(EntityArmorStand.class,b2.add(0, -1, 0))); + c3b = match(getChamber().getEntityAt(EntityArmorStand.class,b3.add(0, -1, 0))); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(answer == -1 ? "Press "+ GameSettings.getKeyDisplayString(FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) +" to request solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) c1b), b1.getX()+ 0.5f, b1.getY()+0.6f, b1.getZ()+ 0.5f,c1b == b1b ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) c2b), b2.getX()+ 0.5f, b2.getY()+0.6f, b2.getZ()+ 0.5f,c2b == b2b ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) c3b), b3.getX()+ 0.5f, b3.getY()+0.6f, b3.getZ()+ 0.5f,c3b == b3b ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + + RenderUtils.drawTextAtWorld( colors.get((int) b1b), b1.getX()+ 0.5f, b1.getY()+0.2f, b1.getZ()+ 0.5f,0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) b2b), b2.getX()+ 0.5f, b2.getY()+0.2f, b2.getZ()+ 0.5f,0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld( colors.get((int) b3b), b3.getX()+ 0.5f, b3.getY()+0.2f, b3.getZ()+ 0.5f,0xFFFFFF00, 0.03F, false, false, partialTicks); + } + + @Override + public void onSendData() { + super.onSendData(); + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 6); + nbt.setByte("f", (byte) Block.getIdFromBlock(getChamber().getBlock(0,3,3).getBlock())); + nbt.setByte("s", (byte) Block.getIdFromBlock(getChamber().getBlock(0,3,2).getBlock())); + nbt.setByte("t", (byte) Block.getIdFromBlock(getChamber().getBlock(0,3,1).getBlock())); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (7 == compound.getByte("a")) { + answer = compound.getInteger("b"); + b3b = (byte) (answer / 10000); + b2b = (byte) ((answer % 10000) / 100); + b1b = (byte) (answer % 100); + + } + } + + private byte match(EntityArmorStand armorStand) { + if (armorStand == null) { + return 0; + } + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return (byte) (!integers.containsKey(str) ? 0 : integers.get(str)); + } + + private static final Map<String, Integer> integers = new HashMap<String, Integer>(); + private static final BiMap<Integer, String> colors = HashBiMap.create(); + static { + colors.put(0, "?"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2YzZTQwNjI5MTE3NGQyNGNkZjBmOTUzZjhhMTc0YTgyYmIzNDg5ZGNlOGY2NzlhNDQzZWYxYWFlMDE2OTA2MSJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWE4MWZjYjUxYmUyYTlmODliMWFkYzlkODcyMzliYTQyOWQ2MzVmYmUwMWIzN2VjMzI5MTY0ODg3YmY2NjViIn19fQ==", 1); + colors.put(1, "blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2FiMDI2M2JkZDc2ZjNlNDE4ZGJhNWJmNDgxYjkyMWNlZDM5N2Q4YjhhMzRhNTU2MWZiN2JlYWE0NmVjZTEifX19", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2ZhNGRkYTZkMTlhMWZlMmQ5ODhkNjVkZWM1MzQyOTUwNTMwODE2NmM5MDY3YjY4YTQ3NzBjYTVjNDM2Y2Y5NCJ9fX0=", 2); + colors.put(2, "black"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDg0Njg0MzQ0YWUwOTg1MjlmYzk0MWFhODRlMTk1YmRjYTM3NDhkNjlhY2ZlZTJiYWMxMzMyMTM1ZWRkOThjIn19fQ==", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTM1ODFjMmY5Y2YzNThkN2VkYzc4ZGQ2ZmQ0YjYyNTc1MDFiYzRlNjQ1NWUzM2ZhMGNhYWUyMDdjZjAzMjFhMiJ9fX0=", 3); + colors.put(3, "green"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTllNjkxN2YyZmI0ZWEwOGU3MTMyZGYzMDk2MWQyYjVjNTIzYWJiYTE5Y2U0M2Y4MzVmYzE0YzU2OGY0In19fQ==", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMjFmNTMyMTIyNTY2YWY4OTNkYTI3ODgwYTFiNjA5NWMzNTcxMmYyOWEzNzhjZmVjYzdmZTJiMTMyOGFiNCJ9fX0=", 4); + colors.put(4, "gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODhlZmFkNzRiMjU0ZTU3Yzc5OTc2M2RjZWVlNDUxMWZhMmY4NWFlOWZhNTU2ZWFhOTdkNDViZjY3ZTBiNmIzIn19fQ==", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWZhZGY3NDFhYjc2Y2QzNjIwYWQxNjEzMDAyMDJkN2I1OWEzMzA1MWU1OTY3ZTRiNjE5NGJhYzQwYmIyODBmZiJ9fX0=", 5); + colors.put(5, "cyan"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzJlMzZmNmE2NTRkZTc0NTgzZDgwMzAxNzdhZDZlM2FjNjc1NWQ3NDM1ZDkxMjNlOGViZGZmNzRiMmQ5MGNiIn19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjJjYmQ5ZjQzNjE5YWI1Y2IxYjExZjkxY2IwM2U5NTVjNmZjNmM0NThhYmY4OWFiNjEwMzEzNDZhMDkwNjEyZSJ9fX0=", 6); + colors.put(6, "brown"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjFhZjQ2ZmViZDQ1YzBmNGQ4MWU4ZmExYjY2YjI3NWQ4OWUyNzJiMmFkNTVjOTc4NTUzYTk5YzczM2UxZmYifX19", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTYzZTY2NDZmMWMwZDQxZmQzYmY1NTg0YTFjZTA0NGY1YzQ2ZDU5ODI1OGRiNDYyMTYxMTc4NTlmNTdhZjE5NyJ9fX0=", 7); + colors.put(7, "light-blue"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDY3NDcwYTBjMThmNjg1MWU5MTQzNTM3MTllNzk1ODc3ZDI5YjMyNTJmN2U2YmQ0YTFiODY1NzY1YmQ3NGZlYiJ9fX0=", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzc0NzJkNjA4ODIxZjQ1YTg4MDUzNzZlYzBjNmZmY2I3ODExNzgyOWVhNWY5NjAwNDFjMmEwOWQxMGUwNGNiNCJ9fX0=", 8); + colors.put(8, "lime"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWJiNDM4NmJjZGE4NGUzNTNjMzFkNzc4ZDNiMTFiY2QyNmZlYTQ5NGRkNjM0OTZiOGE4MmM3Yzc4YTRhZCJ9fX0=", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjk3MDEyZWQ2YTkyYjA1ZWEwZjE5NDk1MDc0ODU0NGUwNzViYWEyODc4MWNhMzczZDFiMjdlMjhjMjY5NTNjIn19fQ==", 9); + colors.put(9, "magenta"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvY2JmNzc5N2EyNGE2YWY4NzVmNWM4MjcxYzViOGM0MjVlMTlmMzcyYTQxNWUwNTUyZmMyNDc3NjNmMjg1OWQxIn19fQ==", 10); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWRmMmViMjA1YTIzYzExOTZiM2VjZjIxZTY4YzA3NmI2OTZlNzYxNjNhYzhmYzRmYjlmNTMxOGMyYTVlNWIxYSJ9fX0=", 10); + colors.put(10, "orange"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmJlY2ZiMzg3OTkzNmI4OTllNDIwYmZjZDNhNzRmOGExYmY5ZGQ1NGM1OGVjN2ZiOWY4MWQ5YTVkOTg4ZSJ9fX0=", 11); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ODM2NTBlYTkyOWRiMGVhYmRmNWJjNzU1OTlkOGVmMDBkNzAzNDBjZDFjZTVlMDRhZDk1ZWY4ZWQ4M2I3MyJ9fX0=", 11); + colors.put(11, "pink"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYmE5NGNiMjVkZTYyOGNhMzU5YjJmNmVhNWE4ODY4Y2JlMjY1OTVlZWRiMmJmZmI3NTA5NjdhZDFlZTE4NTAifX19", 12); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODllYzVhMzAyMjJkMDY1OWIwZGJlZTg0NGI4ZjUzZWFlNjJmZTk1YjRhMzQ0OGE5ZWY3OTBhN2FlZGIyOTZkOSJ9fX0=", 12); + colors.put(12, "purple"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvODZkMzVhOTYzZDU5ODc4OTRiNmJjMjE0ZTMyOGIzOWNkMjM4MjQyNmZmOWM4ZTA4MmIwYjZhNmUwNDRkM2EzIn19fQ==", 13); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjk1M2IxMmEwOTQ2YjYyOWI0YzA4ODlkNDFmZDI2ZWQyNmZiNzI5ZDRkNTE0YjU5NzI3MTI0YzM3YmI3MGQ4ZCJ9fX0=", 13); + colors.put(13, "red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvOTk4YmEyYjM3NGNmYzg5NDU0YzFiOGMzMmRiNDU4YTI3MDY3NTQzOWE0OTU0OTZjOTY3NzFjOTg5MTE2MTYyIn19fQ==", 14); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTUyODhkZGM5MTFhNzVmNzdjM2E1ZDMzNjM2NWE4ZjhiMTM5ZmE1MzkzMGI0YjZlZTEzOTg3NWM4MGNlMzY2YyJ9fX0=", 14); + colors.put(14, "light-gray"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvM2ZhZjRjMjlmMWU3NDA1ZjQ2ODBjNWMyYjAzZWY5Mzg0ZjFhZWNmZTI5ODZhZDUwMTM4YzYwNWZlZmZmMmYxNSJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDA4ZGY2MGM1MTA3NGVlZjI1NDRmZjM4Y2VhZDllMTY2NzVhZTQyNTE5MTYxMDUxODBlMWY4Y2UxOTdhYjNiYyJ9fX0=", 15); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMTVhZDkzZDU2NTQ2ZjEyZDUzNTZlZmZjYmM2ZWM0Yzg3YmEyNDVkODFlMTY2MmM0YjgzMGY3ZDI5OGU5In19fQ==", 15); + colors.put(15, "white"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNDRiMDM3OTRiOWIzZTNiNWQwN2UzYmU2OGI5NmFmODdkZjIxNWMzNzUyZTU0NzM2YzgwZjdkNTBiZDM0MzdhNCJ9fX0=", 16); + colors.put(16, "rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 17); + colors.put(17, "lilac"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTkxMjdjYjdiZDNhOTg5ZDcyYzJlNWM0MjZlMWNjMTQ0NmI1ZTZkZTc0MTRkNDI3ODNmMmZlNmJhZGIxNzdkNCJ9fX0=", 18); + colors.put(18, "dark-red"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM4NmY5YjBiMWQ5ODc5YzNkYTMzYzdhOGNhMjQ0MGMxZTQxMWZlOTNjMjdjOWRiYmZmNTZiZDY5N2JiNzM3NSJ9fX0=", 19); + colors.put(19, "i-rainbow"); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMjdiYmQwYjI5MTFjOTZiNWQ4N2IyZGY3NjY5MWE1MWI4YjEyYzZmZWZkNTIzMTQ2ZDhhYzVlZjFiOGVlIn19fQ==", 20); + colors.put(20, "yellow"); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperLeftProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperLeftProcessor.java new file mode 100644 index 00000000..f651a780 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperLeftProcessor.java @@ -0,0 +1,95 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.creeper; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.init.Blocks; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; + +import java.awt.*; + +public class CreeperLeftProcessor extends GeneralDefuseChamberProcessor { + public CreeperLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + poses = new BlockPos[9]; + for (int i = 0; i < 9; i++) { + poses[i] = chamber.getBlockPos(3+(i%3), 1, 1+(i/3)); + } + } + + @Override + public String getName() { + return "creeperLeft"; + } + + + private int answer = -1; + private final BlockPos[] poses; + @Override + public void tick() { + super.tick(); + if (answer != -1) return; + answer = 0; + for (int i = 0; i < poses.length; i++) { + BlockPos pos = poses[i]; + if (getChamber().getRoom().getContext().getWorld().getBlockState(pos).getBlock() == Blocks.air) { + answer |= (1 << i); + } + } + } + + @Override + public void drawScreen(float partialTicks) { + if (answer == -1) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + for (int i = 0; i < 9; i++) { + if (((answer >> i) & 0x01) != 0) { + RenderUtils.highlightBlock(poses[i], new Color(255,0,0,100), partialTicks, false); + } else { + RenderUtils.highlightBlock(poses[i], new Color(0,255,0,100), partialTicks, false); + } + } + } + + @Override + public void onSendData() { + if (answer == -1) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 2); + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (2 == compound.getByte("a")) { + answer = compound.getInteger("b"); + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperProcessorMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperProcessorMatcher.java new file mode 100644 index 00000000..f2ad23b6 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperProcessorMatcher.java @@ -0,0 +1,52 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.creeper; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class CreeperProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + int airs = 0; + for (int x = 0; x < 3; x ++) { + for (int y = 0; y < 3; y++) { + if (right.getBlock(3 + x, 1, y + 1).getBlock() != Blocks.stone) return false; + } + } + return true; + } + + @Override + public String getName() { + return "creeperMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new CreeperLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new CreeperRightProcessor(solver, right); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperRightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperRightProcessor.java new file mode 100644 index 00000000..258c0e8f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/creeper/CreeperRightProcessor.java @@ -0,0 +1,73 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.creeper; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; + +import java.awt.*; + +public class CreeperRightProcessor extends GeneralDefuseChamberProcessor { + public CreeperRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + poses = new BlockPos[9]; + for (int i = 0; i < 9; i++) { + poses[i] = chamber.getBlockPos(3+(i%3), 1, 1+(i/3)); + } + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "creeperRight"; + } + + + private int answer = -1; + private final BlockPos[] poses; + private final BlockPos center; + @Override + public void tick() { + super.tick(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(answer == -1 ? "Answer not received yet. Visit left room to obtain solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + if (answer != -1) { + for (int i = 0; i < 9; i++) { + if (((answer >> i) & 0x01) == 0) { + RenderUtils.highlightBlock(poses[i], new Color(0,255,0, 50), partialTicks, false); + } + } + } + } + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (2 == compound.getByte("a")) { + answer = compound.getInteger("b"); + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathLeftProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathLeftProcessor.java new file mode 100644 index 00000000..6a531aed --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathLeftProcessor.java @@ -0,0 +1,141 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.goldenpath; + +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.IChatComponent; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class GoldenPathLeftProcessor extends GeneralDefuseChamberProcessor { + public GoldenPathLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + } + + @Override + public String getName() { + return "goldenPathLeft"; + } + + + // 1 up 2 right 3 down 4 left + private static final Point[] vectors = new Point[] { + new Point(0,1), + new Point(-1,0), + new Point(0, -1), + new Point(1, 0) + }; + + private final LinkedList<BlockPos> blocksolution = new LinkedList<BlockPos>(); + private String goldenPathsolution; + @Override + public void tick() { + super.tick(); + if (goldenPathsolution != null) return; + + List<Integer> solution = new ArrayList<Integer>(); + Set<BlockPos> visited = new HashSet<BlockPos>(); + BlockPos lastLoc = new BlockPos(4,0,0); + visited.add(lastLoc); + blocksolution.add(getChamber().getBlockPos(4,1,0)); + BlockPos target = new BlockPos(4,0,5); + while (!lastLoc.equals(target)) { + boolean solution2 = false; + for (int i =0; i<vectors.length; i++) { + BlockPos target2 = lastLoc.add(vectors[i].x, 0, vectors[i].y); + if (visited.contains(target2)) continue; + if (target2.getX() < 0 || target2.getZ() < 0 || target2.getX() > 8 || target2.getZ() > 5) continue; + + visited.add(target2); + if (getChamber().getBlock(target2.getX(), 0, target2.getZ()).getBlock() == Blocks.hardened_clay + || getChamber().getBlock(target2.getX(), 0, target2.getZ()).getBlock() == Blocks.stained_hardened_clay) { + lastLoc = target2; + + blocksolution.add(getChamber().getBlockPos(lastLoc.getX(), 1, lastLoc.getZ())); + solution.add(i); + solution2 = true; + break; + } + } + if (!solution2){ + return; + } + } + + goldenPathsolution = ""; + for (Integer i:solution) + goldenPathsolution += i; + } + + @Override + public void drawScreen(float partialTicks) { + if (goldenPathsolution == null) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawLines(blocksolution, new AColor(0,0,255,0), 1,partialTicks, false); + } + + @Override + public void onSendData() { + if (goldenPathsolution == null) return; + Minecraft.getMinecraft().thePlayer.sendChatMessage("/pc $DG-BDGP "+goldenPathsolution); + + ChatComponentText text = new ChatComponentText("$DG-BDGP "+goldenPathsolution); + for (RoomProcessorBombDefuseSolver.ChamberSet ch: getSolver().getChambers()) { + if (ch.getLeft() != null && ch.getLeft().getProcessor() != null) + ch.getLeft().getProcessor().chatReceived(text); + if (ch.getRight() != null && ch.getRight().getProcessor() != null) + ch.getRight().getProcessor().chatReceived(text); + } + } + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (chat.getFormattedText().contains("$DG-BDGP ")) { + String data = chat.getFormattedText().substring(chat.getFormattedText().indexOf("$DG-BDGP ")); + String actual = TextUtils.stripColor(data).trim().split(" ")[1].trim(); + + blocksolution.clear(); + BlockPos lastLoc = new BlockPos(4,0,0); + blocksolution.addFirst(getChamber().getBlockPos(4,1,0)); + for (Character c:actual.toCharArray()) { + int dir = Integer.parseInt(c+"") % 4; + lastLoc = lastLoc.add(vectors[dir].x, 0, vectors[dir].y); + blocksolution.add(getChamber().getBlockPos(lastLoc.getX(), 1, lastLoc.getZ())); + } + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathProcessorMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathProcessorMatcher.java new file mode 100644 index 00000000..5f5ac89b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathProcessorMatcher.java @@ -0,0 +1,47 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.goldenpath; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class GoldenPathProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(4,0,0).getBlock() == Blocks.hardened_clay + || left.getBlock(4,0,0).getBlock() == Blocks.stained_hardened_clay; + } + + @Override + public String getName() { + return "goldPath"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new GoldenPathLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new GoldenPathRightProcessor(solver, right); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathRightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathRightProcessor.java new file mode 100644 index 00000000..d432da80 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/goldenpath/GoldenPathRightProcessor.java @@ -0,0 +1,97 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.goldenpath; + +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.*; + +public class GoldenPathRightProcessor extends GeneralDefuseChamberProcessor { + public GoldenPathRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "goldenPathRight"; + } + + + private final BlockPos center; + // 1 up 2 right 3 down 4 left + private static final Point[] vectors = new Point[] { + new Point(0,1), + new Point(-1,0), + new Point(0, -1), + new Point(1, 0) + }; + + private final LinkedList<BlockPos> blocksolution = new LinkedList<BlockPos>(); + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(blocksolution.size() == 0 ? "Answer not received yet. Visit left room to obtain solution" : "" , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + RenderUtils.drawLines(blocksolution, new AColor(0,0,255,0),1, partialTicks, false); + + } + + @Override + public void chatReceived(IChatComponent chat) { + super.chatReceived(chat); + if (chat.getFormattedText().contains("$DG-BDGP ")) { + String data = chat.getFormattedText().substring(chat.getFormattedText().indexOf("$DG-BDGP")); + String actual = TextUtils.stripColor(data).trim().split(" ")[1].trim(); + + blocksolution.clear(); + BlockPos lastLoc = new BlockPos(4,0,0); + blocksolution.addFirst(getChamber().getBlockPos(4,1,0)); + for (Character c:actual.toCharArray()) { + int dir = Integer.parseInt(c+"") % 4; + lastLoc = lastLoc.add(vectors[dir].x, 0, vectors[dir].y); + blocksolution.add(getChamber().getBlockPos(lastLoc.getX(), 1, lastLoc.getZ())); + } + + World w = getChamber().getRoom().getContext().getWorld(); + for (int x = 0; x <9; x++) { + for (int z =0; z < 6; z++) { + BlockPos pos = getChamber().getBlockPos(x,1,z); + if (blocksolution.contains(pos)) { + w.setBlockState(pos, Blocks.light_weighted_pressure_plate.getDefaultState()); + } else { + w.setBlockState(pos, Blocks.wooden_pressure_plate.getDefaultState()); + } + } + } + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeLeftProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeLeftProcessor.java new file mode 100644 index 00000000..d2b9927c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeLeftProcessor.java @@ -0,0 +1,80 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.maze; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.ScaledResolution; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.settings.GameSettings; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; +import net.minecraft.util.MovingObjectPosition; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +public class MazeLeftProcessor extends GeneralDefuseChamberProcessor { + public MazeLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + } + + @Override + public String getName() { + return "mazeLeft"; + } + + + @Override + public void drawScreen(float partialTicks) { + if (Minecraft.getMinecraft().objectMouseOver == null ) return; + MovingObjectPosition pos = Minecraft.getMinecraft().objectMouseOver; + if (pos.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) return; + + Block b = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(pos.getBlockPos()).getBlock(); + + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + ScaledResolution sr = new ScaledResolution(Minecraft.getMinecraft()); + String str = "Press "+ GameSettings.getKeyDisplayString(FeatureRegistry.SOLVER_BOMBDEFUSE.<Integer>getParameter("key").getValue()) + " to request open "+b.getLocalizedName(); + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString(str, (sr.getScaledWidth() - fr.getStringWidth(str)) / 2, (sr.getScaledHeight() - fr.FONT_HEIGHT) / 2, 0xFFFFFFFF); + } + + @Override + public void onSendData() { + if (Minecraft.getMinecraft().objectMouseOver == null ) return; + MovingObjectPosition pos = Minecraft.getMinecraft().objectMouseOver; + if (pos.typeOfHit != MovingObjectPosition.MovingObjectType.BLOCK) return; + + BlockPos block = pos.getBlockPos(); + Block b = getChamber().getRoom().getContext().getWorld().getBlockState(block).getBlock(); + + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 5); + nbt.setInteger("b", Block.getIdFromBlock(b)); + getSolver().communicate(nbt); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeProcessorMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeProcessorMatcher.java new file mode 100644 index 00000000..1429d302 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeProcessorMatcher.java @@ -0,0 +1,47 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.maze; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class MazeProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return right.getBlock(1,0,1).getBlock() != Blocks.double_stone_slab && + left.getBlock(1,1,1).getBlock() != Blocks.barrier; + } + + @Override + public String getName() { + return "mazeMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new MazeLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new MazeRightProcessor(solver, right); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeRightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeRightProcessor.java new file mode 100644 index 00000000..df9f8f93 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/maze/MazeRightProcessor.java @@ -0,0 +1,73 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.maze; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.HashMap; +import java.util.Map; + +public class MazeRightProcessor extends GeneralDefuseChamberProcessor { + public MazeRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + center = chamber.getBlockPos(4,4,4); + + for (int x = 0; x < 9; x++) { + for (int y =0; y< 6; y++) { + Block b = chamber.getBlock(x,0,y).getBlock(); + BlockPos pos = chamber.getBlockPos(x,0,y); + blockToBlockPosMap.put(b, pos); + } + } + } + + private final BlockPos center; + private final Map<Block, BlockPos> blockToBlockPosMap = new HashMap<Block, BlockPos>(); + @Override + public String getName() { + return "mazeRight"; + } + + + private Block latestRequest = null; + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(latestRequest == null ? "Request not received yet" : "Requested received "+latestRequest.getLocalizedName() , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + BlockPos pos = blockToBlockPosMap.get(latestRequest); + if (pos == null) return; + RenderUtils.highlightBlock(pos, new Color(0,255,0,100), partialTicks, false); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (5 == compound.getByte("a")) { + int latestRequestid = compound.getInteger("b"); + latestRequest = Block.getBlockById(latestRequestid); + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberLeftProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberLeftProcessor.java new file mode 100644 index 00000000..11c7fefd --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberLeftProcessor.java @@ -0,0 +1,125 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.number; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +public class NumberLeftProcessor extends GeneralDefuseChamberProcessor { + public NumberLeftProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + d1p = chamber.getBlockPos(1,1,4); + d2p = chamber.getBlockPos(2,1,4); + d3p = chamber.getBlockPos(6,1,4); + d4p = chamber.getBlockPos(7,1,4); + } + + @Override + public String getName() { + return "numberLeft"; + } + + + private int answer = -1, d1, d2, d3 ,d4; + private final BlockPos d1p; + private final BlockPos d2p; + private final BlockPos d3p; + private final BlockPos d4p; + @Override + public void tick() { + super.tick(); + if (answer != -1) return; + d1 = match(getChamber().getEntityAt(EntityArmorStand.class,d1p)); + d2 = match(getChamber().getEntityAt(EntityArmorStand.class,d2p)); + d3 = match(getChamber().getEntityAt(EntityArmorStand.class,d3p)); + d4 = match(getChamber().getEntityAt(EntityArmorStand.class,d4p)); + if (d1 == -1 || d2 == -1 || d3 == -1 || d4 == -1) return; + + answer = d1 * 1000 + d2 * 100 + d3 * 10 + d4; + } + + @Override + public void drawScreen(float partialTicks) { + if (answer == -1) return; + drawPressKey(); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(d1+"", d1p.getX()+ 0.5f, d1p.getY()+ 0.5f, d1p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d2+"", d2p.getX()+ 0.5f, d2p.getY()+ 0.5f, d2p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d3+"", d3p.getX()+ 0.5f, d3p.getY()+ 0.5f, d3p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d4+"", d4p.getX()+ 0.5f, d4p.getY()+ 0.5f, d4p.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + + } + + @Override + public void onSendData() { + if (answer == -1) return; + NBTTagCompound nbt = new NBTTagCompound(); + nbt.setByte("a", (byte) 1); + nbt.setInteger("b", answer); + getSolver().communicate(nbt); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (1 == compound.getByte("a")) { + answer = compound.getInteger("b"); + d1 = answer / 1000; + d2 = (answer % 1000) / 100; + d3 = (answer % 100) / 10; + d4 = (answer % 10); + answer = d1 * 1000 + d2 * 100 + d3 * 10 + d4; + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) return -1; + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(10); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzFhOTQ2M2ZkM2M0MzNkNWUxZDlmZWM2ZDVkNGIwOWE4M2E5NzBiMGI3NGRkNTQ2Y2U2N2E3MzM0OGNhYWIifX19", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYWNiNDE5ZDk4NGQ4Nzk2MzczYzk2NDYyMzNjN2EwMjY2NGJkMmNlM2ExZDM0NzZkZDliMWM1NDYzYjE0ZWJlIn19fQ==", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjhlYmFiNTdiNzYxNGJiMjJhMTE3YmU0M2U4NDhiY2QxNGRhZWNiNTBlOGY1ZDA5MjZlNDg2NGRmZjQ3MCJ9fX0=", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNjJiZmNmYjQ4OWRhODY3ZGNlOTZlM2MzYzE3YTNkYjdjNzljYWU4YWMxZjlhNWE4YzhhYzk1ZTRiYTMifX19", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZWY0ZWNmMTEwYjBhY2VlNGFmMWRhMzQzZmIxMzZmMWYyYzIxNjg1N2RmZGE2OTYxZGVmZGJlZTdiOTUyOCJ9fX0=", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZjMzMWE2YTZmY2Q2OTk1YjYyMDg4ZDM1M2JmYjY4ZDliODlhZTI1ODMyNWNhZjNmMjg4NjQ2NGY1NGE3MzI5In19fQ==", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDRiYTZhYzA3ZDQyMjM3N2E4NTU3OTNmMzZkZWEyZWQyNDAyMjNmNTJmZDE2NDgxODE2MTJlY2QxYTBjZmQ1In19fQ==", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYzYxYThhNjQxNDM3YmU5YWVhMjA3MjUzZGQzZjI1NDQwZDk1NGVhMmI1ODY2YzU1MmYzODZiMjlhYzRkMDQ5In19fQ==", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvYTE5MjhlMWJmZDg2YTliNzkzOTdjNGNiNGI2NWVmOTlhZjQ5YjdkNWY3OTU3YWQ2MmMwYzY5OWE2MjJjZmJlIn19fQ==", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTVhMjI0ODA3NjkzOTc4ZWQ4MzQzNTVmOWU1MTQ1ZjljNTZlZjY4Y2Y2ZjJjOWUxNzM0YTQ2ZTI0NmFhZTEifX19", 0); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberProcessorMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberProcessorMatcher.java new file mode 100644 index 00000000..488583ff --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberProcessorMatcher.java @@ -0,0 +1,53 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.number; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BombDefuseChamberGenerator; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.ChamberProcessor; +import net.minecraft.init.Blocks; + +public class NumberProcessorMatcher implements BombDefuseChamberGenerator { + @Override + public boolean match(BDChamber left, BDChamber right) { + return left.getBlock(1,1,4).getBlock() == Blocks.stone && + left.getBlock(2,1,4).getBlock() == Blocks.stone && + left.getBlock(6,1,4).getBlock() == Blocks.stone && + left.getBlock(7,1,4).getBlock() == Blocks.stone && + right.getBlock(1,1,4).getBlock() == Blocks.stone && + right.getBlock(2,1,4).getBlock() == Blocks.stone && + right.getBlock(6,1,4).getBlock() == Blocks.stone && + right.getBlock(7,1,4).getBlock() == Blocks.stone; + } + + @Override + public String getName() { + return "numberMatch"; + } + @Override + public ChamberProcessor createLeft(BDChamber left, RoomProcessorBombDefuseSolver solver) { + return new NumberLeftProcessor(solver, left); + } + + @Override + public ChamberProcessor createRight(BDChamber right, RoomProcessorBombDefuseSolver solver) { + return new NumberRightProcessor(solver, right); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberRightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberRightProcessor.java new file mode 100644 index 00000000..66ba993a --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bombdefuse/chambers/number/NumberRightProcessor.java @@ -0,0 +1,114 @@ +/* + * 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.mod.dungeon.roomprocessor.bombdefuse.chambers.number; + +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.RoomProcessorBombDefuseSolver; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.BDChamber; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.bombdefuse.chambers.GeneralDefuseChamberProcessor; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; +import net.minecraft.nbt.NBTTagList; +import net.minecraft.util.BlockPos; + +public class NumberRightProcessor extends GeneralDefuseChamberProcessor { + public NumberRightProcessor(RoomProcessorBombDefuseSolver solver, BDChamber chamber) { + super(solver, chamber); + + d1p = chamber.getBlockPos(1,1,4); + d2p = chamber.getBlockPos(2,1,4); + d3p = chamber.getBlockPos(6,1,4); + d4p = chamber.getBlockPos(7,1,4); + center = chamber.getBlockPos(4,4,4); + } + + @Override + public String getName() { + return "numberRight"; + } + + + private int answer = -1, d1, d2, d3 ,d4, a1, a2, a3, a4; + private final BlockPos d1p; + private final BlockPos d2p; + private final BlockPos d3p; + private final BlockPos d4p; + private final BlockPos center; + @Override + public void tick() { + super.tick(); + a1 = match(getChamber().getEntityAt(EntityArmorStand.class,d1p)); + a2 = match(getChamber().getEntityAt(EntityArmorStand.class,d2p)); + a3 = match(getChamber().getEntityAt(EntityArmorStand.class,d3p)); + a4 = match(getChamber().getEntityAt(EntityArmorStand.class,d4p)); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + RenderUtils.drawTextAtWorld(a1+"", d1p.getX()+ 0.5f, d1p.getY()+ 0.6f, d1p.getZ()+ 0.5f, a1 == d1 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(a2+"", d2p.getX()+ 0.5f, d2p.getY()+ 0.6f, d2p.getZ()+ 0.5f, a2 == d2 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(a3+"", d3p.getX()+ 0.5f, d3p.getY()+ 0.6f, d3p.getZ()+ 0.5f, a3 == d3 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(a4+"", d4p.getX()+ 0.5f, d4p.getY()+ 0.6f, d4p.getZ()+ 0.5f, a4 == d4 ? 0xFF00FF00 : 0xFFFF0000, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(answer == -1 ? "Answer not received yet. Visit left room to obtain solution" : ("Solution: "+answer) , center.getX()+ 0.5f, center.getY(), center.getZ()+ 0.5f, 0xFFFFFFFF, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d1+"", d1p.getX()+ 0.5f, d1p.getY()+ 0.2f, d1p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d2+"", d2p.getX()+ 0.5f, d2p.getY()+ 0.2f, d2p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d3+"", d3p.getX()+ 0.5f, d3p.getY()+ 0.2f, d3p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + RenderUtils.drawTextAtWorld(d4+"", d4p.getX()+ 0.5f, d4p.getY()+ 0.2f, d4p.getZ()+ 0.5f, 0xFFFFFF00, 0.03F, false, false, partialTicks); + } + + @Override + public void onDataRecieve(NBTTagCompound compound) { + if (1 == compound.getByte("a")) { + answer = compound.getInteger("b"); + d1 = answer / 1000; + d2 = (answer % 1000) / 100; + d3 = (answer % 100) / 10; + d4 = (answer % 10); + answer = d4 * 1000 + d3 * 100 + d2 * 10 + d1; + } + } + + private int match(EntityArmorStand armorStand) { + if (armorStand == null) { + return -1; + } + ItemStack item = armorStand.getInventory()[4]; + NBTTagList list = item.getTagCompound().getCompoundTag("SkullOwner").getCompoundTag("Properties").getTagList("textures", 10); + String str = ((NBTTagCompound)list.get(0)).getString("Value"); + return !integers.containsKey(str) ? -1 : integers.get(str); + } + + private static final BiMap<String, Integer> integers = HashBiMap.create(10); + { + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNzFiYzJiY2ZiMmJkMzc1OWU2YjFlODZmYzdhNzk1ODVlMTEyN2RkMzU3ZmMyMDI4OTNmOWRlMjQxYmM5ZTUzMCJ9fX0=", 1); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNGNkOWVlZWU4ODM0Njg4ODFkODM4NDhhNDZiZjMwMTI0ODVjMjNmNzU3NTNiOGZiZTg0ODczNDE0MTk4NDcifX19", 2); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMWQ0ZWFlMTM5MzM4NjBhNmRmNWU4ZTk1NTY5M2I5NWE4YzNiMTVjMzZiOGI1ODc1MzJhYzA5OTZiYzM3ZTUifX19", 3); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZDJlNzhmYjIyNDI0MjMyZGMyN2I4MWZiY2I0N2ZkMjRjMWFjZjc2MDk4NzUzZjJkOWMyODU5ODI4N2RiNSJ9fX0=", 4); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmQ1N2UzYmM4OGE2NTczMGUzMWExNGUzZjQxZTAzOGE1ZWNmMDg5MWE2YzI0MzY0M2I4ZTU0NzZhZTIifX19", 5); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMzM0YjM2ZGU3ZDY3OWI4YmJjNzI1NDk5YWRhZWYyNGRjNTE4ZjVhZTIzZTcxNjk4MWUxZGNjNmIyNzIwYWIifX19", 6); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNmRiNmViMjVkMWZhYWJlMzBjZjQ0NGRjNjMzYjU4MzI0NzVlMzgwOTZiN2UyNDAyYTNlYzQ3NmRkN2I5In19fQ==", 7); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvNTkxOTQ5NzNhM2YxN2JkYTk5NzhlZDYyNzMzODM5OTcyMjI3NzRiNDU0Mzg2YzgzMTljMDRmMWY0Zjc0YzJiNSJ9fX0=", 8); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZTY3Y2FmNzU5MWIzOGUxMjVhODAxN2Q1OGNmYzY0MzNiZmFmODRjZDQ5OWQ3OTRmNDFkMTBiZmYyZTViODQwIn19fQ==", 9); + integers.put("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvMGViZTdlNTIxNTE2OWE2OTlhY2M2Y2VmYTdiNzNmZGIxMDhkYjg3YmI2ZGFlMjg0OWZiZTI0NzE0YjI3In19fQ==", 0); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessor.java new file mode 100644 index 00000000..12ef6bdf --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessor.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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessor; + +import java.util.List; + +public interface BossfightProcessor extends RoomProcessor { + List<String> getPhases(); + String getCurrentPhase(); + List<String> getNextPhases(); + + List<HealthData> getHealths(); + + String getBossName(); +}
\ No newline at end of file diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorBonzo.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorBonzo.java new file mode 100644 index 00000000..3380a447 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorBonzo.java @@ -0,0 +1,85 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorBonzo extends GeneralBossfightProcessor { + public BossfightProcessorBonzo() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("start") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Gratz for making it this far, but I’m basically unbeatable.§r") + .nextPhase("fight-1").build() + ); + + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: I can summon lots of undead! Check this out.§r") + .nextPhase("first-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Oh I'm dead!§r").signatureMsg("§r§c[BOSS] Bonzo §r§f: Hoho, looks like you killed me!§r") + .nextPhase("fight-2").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Sike§r").signatureMsg("§r§c[BOSS] Bonzo §r§f: I can revive myself and become much stronger!§r") + .nextPhase("final-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] Bonzo §r§f: Alright, maybe I'm just weak after all..§r").build() + ); + } + + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + long health = 0; + if (bonzoStand != null) { + String name = TextUtils.stripColor(bonzoStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Bonzo", (int) health,250000 , this.getCurrentPhase().startsWith("fight-"))); + return healths; + } + + @Override + public String getBossName() { + return "Bonzo"; + } + + private EntityArmorStand bonzoStand; + @Override + // §e﴾ §c§lBonzo§r §e71k§c❤ §e﴿ + // §e﴾ §c§lBonzo§r §a250k§c❤ §e﴿ + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lBonzo§r ") && updateEvent.entityLiving instanceof EntityArmorStand) { + bonzoStand = (EntityArmorStand) updateEvent.entityLiving; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorLivid.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorLivid.java new file mode 100644 index 00000000..f75226b6 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorLivid.java @@ -0,0 +1,90 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import lombok.Getter; +import net.minecraft.client.entity.EntityOtherPlayerMP; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.*; + +@Getter +public class BossfightProcessorLivid extends GeneralBossfightProcessor { + private String realLividName; + private String prefix; + private EntityOtherPlayerMP realLivid; + + private final Set<String> knownLivids = new HashSet<String>(); + + private boolean isMasterMode; + + public BossfightProcessorLivid(boolean isMasterMode) { + addPhase(PhaseData.builder().phase("start").build()); + this.isMasterMode = isMasterMode; + } + private static final Map<String, String> lividColorPrefix = new HashMap<String, String>() {{ + put("Vendetta", "§f"); + put("Crossed", "§d"); + put("Hockey", "§c"); + put("Doctor", "§7"); + put("Frog", "§2"); + put("Smile", "§a"); + put("Scream", "§1"); + put("Purple", "§5"); + put("Arcade", "§e"); + }}; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving.getName().endsWith("Livid") && updateEvent.entityLiving instanceof EntityOtherPlayerMP) { + if (!knownLivids.contains(updateEvent.entityLiving.getName())) { + knownLivids.add(updateEvent.entityLiving.getName()); + realLividName = updateEvent.entityLiving.getName(); + realLivid = (EntityOtherPlayerMP) updateEvent.entityLiving; + prefix = lividColorPrefix.get(realLividName.split(" ")[0]); + } else if (realLividName.equalsIgnoreCase(updateEvent.entityLiving.getName())) { + realLivid = (EntityOtherPlayerMP) updateEvent.entityLiving; + } + } else if (updateEvent.entityLiving.getName().startsWith(prefix+"﴾ ") && updateEvent.entityLiving instanceof EntityArmorStand) { + lividStand = (EntityArmorStand) updateEvent.entityLiving; + } + } + private EntityArmorStand lividStand; + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + long health = 0; + if (lividStand != null) { + try { + String name = TextUtils.stripColor(lividStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } catch (Exception e) {e.printStackTrace();} + } + healths.add(new HealthData(realLividName == null ? "unknown" : realLividName, (int) health,isMasterMode ? 600000000 : 7000000 , true)); + return healths; + } + + @Override + public String getBossName() { + return realLividName == null ? "Livid" : realLividName; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorNecron.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorNecron.java new file mode 100644 index 00000000..49b572fe --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorNecron.java @@ -0,0 +1,77 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import net.minecraft.entity.boss.BossStatus; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorNecron extends GeneralBossfightProcessor { + // \A7 to § + public BossfightProcessorNecron() { + addPhase(PhaseData.builder() + .phase("crystals") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cFinally, I heard so much about you. The Eye likes you very much.§r") + .nextPhase("laser-attack").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("laser-attack") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cYou tricked me!§r") + .nextPhase("fight-1").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cFINE! LET'S MOVE TO SOMEWHERE ELSE!!§r") + .nextPhase("terminals").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("terminals") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cCRAP!! IT BROKE THE FLOOR!§r") + .nextPhase("fight-2").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cTHAT'S IT YOU HAVE DONE IT!§r") + .nextPhase("won").nextPhase("lost").build() + ); + addPhase(PhaseData.builder() + .phase("won") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cAll this, for nothing...§r").build() + ); + addPhase(PhaseData.builder() + .phase("lost") + .signatureMsg("§r§4[BOSS] Necron§r§c: §r§cFINALLY! This took way too long.§r").build() + ); + } + + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + int maxHealth = 1_000_000_000; + healths.add(new HealthData("Necron", (int) (BossStatus.healthScale * maxHealth),maxHealth , this.getCurrentPhase().startsWith("fight-"))); + return healths; + } + + @Override + public String getBossName() { + return "Necron"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorProf.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorProf.java new file mode 100644 index 00000000..169b9773 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorProf.java @@ -0,0 +1,144 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorProf extends GeneralBossfightProcessor { + public BossfightProcessorProf() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("start") + .signatureMsg("§r§c[BOSS] The Professor§r§f: I was burdened with terrible news recently...§r") + .nextPhase("fight-1").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] The Professor§r§f: I'll show you real power!§r") + .nextPhase("first-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] The Professor§r§f: Oh? You found my Guardians one weakness?§r") + .nextPhase("fight-2").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] The Professor§r§f: This time I'll be your opponent!§r") + .nextPhase("second-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("second-defeat") + .signatureMsg("§r§c[BOSS] The Professor§r§f: I see. You have forced me to use my ultimate technique.§r") + .nextPhase("fight-3").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-3") + .signatureMsg("§r§c[BOSS] The Professor§r§f: The process is irreversible, but I'll be stronger than a Wither now!§r") + .nextPhase("final-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] The Professor§r§f: What?! My Guardian power is unbeatable!§r").build() + ); + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + { + long health = 0; + if (profStand != null) { + String name = TextUtils.stripColor(profStand.getName()); + String healthPart = name.split(" ")[3]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("The Professor", (int) health, 3000000, this.getCurrentPhase().startsWith("fight-") && !this.getCurrentPhase().equals("fight-1"))); + } + if (!getCurrentPhase().equals("second-defeat") && !getCurrentPhase().equals("fight-3") && !getCurrentPhase().equals("final-defeat")) { + { + long health = 0; + if (healthyGuard != null) { + String name = TextUtils.stripColor(healthyGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Healthy Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + { + long health = 0; + if (chaosGuard != null) { + String name = TextUtils.stripColor(chaosGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Chaos Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + { + long health = 0; + if (laserGuard != null) { + String name = TextUtils.stripColor(laserGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Laser Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + { + long health = 0; + if (reinforcedGuard != null) { + String name = TextUtils.stripColor(reinforcedGuard.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Reinforced Guardian", (int) health, 1000000, this.getCurrentPhase().equals("fight-1"))); + } + } + return healths; + } + + @Override + public String getBossName() { + return "The Professor"; + } + + private EntityArmorStand profStand; + private EntityArmorStand laserGuard; + private EntityArmorStand chaosGuard; + private EntityArmorStand reinforcedGuard; + private EntityArmorStand healthyGuard; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lThe Professor§r ")) + profStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cHealthy Guardian ")) + healthyGuard = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cChaos Guardian ")) + chaosGuard = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cLaser Guardian ")) + laserGuard = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§cReinforced Guardian ")) + reinforcedGuard = (EntityArmorStand) updateEvent.entityLiving; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorSadan.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorSadan.java new file mode 100644 index 00000000..0de8aa56 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorSadan.java @@ -0,0 +1,144 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorSadan extends GeneralBossfightProcessor { + public BossfightProcessorSadan() { + addPhase(PhaseData.builder() + .phase("start") + .signatureMsg("So you made it all the way §r§fhere...and§r§f you wish to defy me? Sadan?!§r") + .nextPhase("fight-1").build() + ); + addPhase(PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] Sadan §r§f: I am the bridge between this realm and the world below! You shall not pass!§r") + .nextPhase("first-defeat").build() + ); + addPhase(PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] Sadan §r§f: ENOUGH!§r") + .nextPhase("fight-2").build() + ); + addPhase(PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] Sadan §r§f: My giants! Unleashed!§r") + .nextPhase("second-defeat").build() + ); + addPhase(PhaseData.builder() + .phase("second-defeat") + .signatureMsg("§r§c[BOSS] Sadan §r§f: You did it. I understand now, you have earned my respect.§r") + .nextPhase("fight-3").build() + ); + addPhase(PhaseData.builder() + .phase("fight-3") + .signatureMsg("§r§c[BOSS] Sadan §r§f: I'm sorry but I need to concentrate. I wish it didn't have to come to this.§r") + .nextPhase("final-defeat").build() + ); + addPhase(PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] Sadan §r§f: NOOOOOOOOO!!! THIS IS IMPOSSIBLE!!§r").build() + ); + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + { + long health = 0; + if (sadanStand != null) { + String name = TextUtils.stripColor(sadanStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Sadan", (int) health, 40000000, this.getCurrentPhase().equals("fight-3"))); + } + if (getCurrentPhase().equals("fight-2")) { + { + long health = 0; + if (diamondGiant != null) { + String name = TextUtils.stripColor(diamondGiant.getName()); + String healthPart = name.split(" ")[3]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("The Diamond Giant", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (bigfootGiant != null) { + String name = TextUtils.stripColor(bigfootGiant.getName()); + String healthPart = name.split(" ")[1]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Bigfoot", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (laserGiant != null) { + String name = TextUtils.stripColor(laserGiant.getName()); + String healthPart = name.split(" ")[1]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("L.A.S.R.", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (boulderGiant != null) { + String name = TextUtils.stripColor(boulderGiant.getName()); + String healthPart = name.split(" ")[3]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Jolly Pink Giant", (int) health, 25000000, this.getCurrentPhase().startsWith("fight-"))); + } + } + return healths; + } + + @Override + public String getBossName() { + return "Sadan"; + } + + private EntityArmorStand sadanStand; + private EntityArmorStand diamondGiant; + private EntityArmorStand laserGiant; + private EntityArmorStand bigfootGiant; + private EntityArmorStand boulderGiant; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lSadan§r ")) + sadanStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§d§lJolly Pink Giant ")) + boulderGiant = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§4§lL.A.S.R. ")) + laserGiant = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§3§lThe Diamond Giant ")) + diamondGiant = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§c§c§lBigfoot ")) + bigfootGiant = (EntityArmorStand) updateEvent.entityLiving; + } + } +}
\ No newline at end of file diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorScarf.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorScarf.java new file mode 100644 index 00000000..44fdea1b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorScarf.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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.utils.TextUtils; +import net.minecraft.entity.item.EntityArmorStand; +import net.minecraftforge.event.entity.living.LivingEvent; + +import java.util.ArrayList; +import java.util.List; + +public class BossfightProcessorScarf extends GeneralBossfightProcessor { + public BossfightProcessorScarf() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("start") + .signatureMsg("§r§c[BOSS] Scarf §r§f: This is where the journey ends for you, Adventurers.§r") + .nextPhase("fight-1").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-1") + .signatureMsg("§r§c[BOSS] Scarf §r§f: ARISE, MY CREATIONS!§r") + .nextPhase("first-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("first-defeat") + .signatureMsg("§r§c[BOSS] Scarf §r§f: Those toys are not strong enough I see.§r") + .nextPhase("fight-2").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight-2") + .signatureMsg("§r§c[BOSS] Scarf §r§f: Did you forget? I was taught by the best! Let's dance.§r") + .nextPhase("final-defeat").build() + ); + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("final-defeat") + .signatureMsg("§r§c[BOSS] Scarf §r§f: Whatever...§r").build() + ); + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + { + long health = 0; + if (scarfStand != null) { + String name = TextUtils.stripColor(scarfStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Scarf", (int) health, 1000000, this.getCurrentPhase().equals("fight-2"))); + } + if (!getCurrentPhase().equals("start") && !getCurrentPhase().equals("final-defeat")) { + { + long health = 0; + if (priestStand != null) { + String name = TextUtils.stripColor(priestStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Priest", (int) health, 600000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (berserkStand != null) { + String name = TextUtils.stripColor(berserkStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Warrior", (int) health, 500000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (mageStand != null) { + String name = TextUtils.stripColor(mageStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Mage", (int) health, 400000, this.getCurrentPhase().startsWith("fight-"))); + } + { + long health = 0; + if (archerStand != null) { + String name = TextUtils.stripColor(archerStand.getName()); + String healthPart = name.split(" ")[2]; + health = TextUtils.reverseFormat(healthPart.substring(0, healthPart.length() - 1)); + } + healths.add(new HealthData("Undead Archer", (int) health, 400000, this.getCurrentPhase().startsWith("fight-"))); + } + } + return healths; + } + + @Override + public String getBossName() { + return "Scarf"; + } + + private EntityArmorStand scarfStand; + private EntityArmorStand priestStand; + private EntityArmorStand mageStand; + private EntityArmorStand berserkStand; + private EntityArmorStand archerStand; + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + if (updateEvent.entityLiving instanceof EntityArmorStand) { + if (updateEvent.entityLiving.getName().startsWith("§e﴾ §c§lScarf§r ")) + scarfStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Archer ")) + archerStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Mage ")) + mageStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Priest ")) + priestStand = (EntityArmorStand) updateEvent.entityLiving; + else if (updateEvent.entityLiving.getName().startsWith("§6§4§lUndead Warrior ")) + berserkStand = (EntityArmorStand) updateEvent.entityLiving; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorThorn.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorThorn.java new file mode 100644 index 00000000..eb5a71d6 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/BossfightProcessorThorn.java @@ -0,0 +1,103 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.entity.boss.BossStatus; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +import java.awt.*; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class BossfightProcessorThorn extends GeneralBossfightProcessor { + + + public BossfightProcessorThorn() { + addPhase(GeneralBossfightProcessor.PhaseData.builder() + .phase("fight").build() + ); + w= DungeonsGuide.getDungeonsGuide().getDungeonFacade().getContext().getWorld(); + } + private final Set<BlockPos> progressBar = new HashSet<BlockPos>(); + private final World w; + + private int ticksPassed = 0; + + @Override + public void tick() { + ticksPassed ++; + if (ticksPassed == 20) { + progressBar.clear(); + for (int x = -30; x <= 30; x++) { + for (int y = -30; y <= 30; y++) { + BlockPos newPos = new BlockPos(5 + x, 77, 5 + y); + Block b = w.getBlockState(newPos).getBlock(); + if ((b == Blocks.coal_block || b == Blocks.sea_lantern) && w.getBlockState(newPos.add(0, 1, 0)).getBlock() != Blocks.carpet) + progressBar.add(newPos); + } + } + } + } + + @Override + public List<HealthData> getHealths() { + List<HealthData> healths = new ArrayList<HealthData>(); + healths.add(new HealthData("Thorn", Math.round(BossStatus.healthScale * 4),4, true)); + return healths; + } + + @Override + public String getBossName() { + return "Thorn"; + } + + public double calculatePercentage() { + int total = progressBar.size(), lit = 0; + if (total == 0) return 0; + for (BlockPos pos : progressBar) { + if (w.getBlockState(pos).getBlock() == Blocks.sea_lantern ) lit++; + } + + return lit / (double)total; + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.DEBUG.isEnabled()) return; + try { + BlockPos pos = new BlockPos(205,77, 205); + RenderUtils.highlightBlock(pos, new Color(0, 255, 255, 50), partialTicks, false); + for (BlockPos pos2 : progressBar) { + RenderUtils.highlightBlock(pos2, w.getBlockState(pos2).getBlock() == Blocks.sea_lantern ? + new Color(0, 255, 0, 50) : new Color(255,0,0, 50), partialTicks, false); + } + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/GeneralBossfightProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/GeneralBossfightProcessor.java new file mode 100644 index 00000000..50fd9868 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/GeneralBossfightProcessor.java @@ -0,0 +1,155 @@ +/* + * 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.mod.dungeon.roomprocessor.bossfight; + +import kr.syeyoung.dungeonsguide.mod.events.impl.BlockUpdateEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.KeyBindPressedEvent; +import kr.syeyoung.dungeonsguide.mod.events.impl.PlayerInteractEntityEvent; +import lombok.*; +import net.minecraft.util.IChatComponent; +import net.minecraft.world.World; +import net.minecraftforge.client.event.GuiScreenEvent; +import net.minecraftforge.event.entity.living.LivingDeathEvent; +import net.minecraftforge.event.entity.living.LivingEvent; +import net.minecraftforge.event.entity.player.PlayerInteractEvent; + +import java.util.*; + +public abstract class GeneralBossfightProcessor implements BossfightProcessor { + private final Map<String, PhaseData> phases = new HashMap<String, PhaseData>(); + private PhaseData currentPhase = null; + + @Getter + @Setter + private String name; + + private World world; + + public void addPhase(PhaseData phaseData) { + if (phaseData == null) return; + if (currentPhase == null) currentPhase = phaseData; + phases.put(phaseData.getPhase(), phaseData); + } + + @Override + public List<String> getPhases() { + List<String> phases = new ArrayList<String>(); + for (PhaseData pd:this.phases.values()) + phases.add(pd.getPhase()); + return phases; + } + + @Override + public List<String> getNextPhases() { + if (currentPhase == null) return Collections.emptyList(); + List<String> phases = new ArrayList<String>(this.currentPhase.getNextPhases()); + return phases; + } + + + @Override + public String getCurrentPhase() { + return currentPhase == null ? "unknown" : currentPhase.getPhase(); + } + + @Override + public void chatReceived(IChatComponent chat) { + if (currentPhase == null) return; + + for (String nextPhase : currentPhase.getNextPhases()) { + PhaseData phaseData = phases.get(nextPhase); + if (phaseData == null) continue; + if (phaseData.signatureMsgs.contains(chat.getFormattedText().replace(" ", ""))) { + currentPhase = phaseData; + onPhaseChange(); + return; + } + } + } + + @Override + public void actionbarReceived(IChatComponent chat) {} + + @Override + public void tick() {} + + @Override + public void drawScreen(float partialTicks) {} + + @Override + public void drawWorld(float partialTicks) {} + + @Override + public boolean readGlobalChat() {return true;} + + @Override + public void onPostGuiRender(GuiScreenEvent.DrawScreenEvent.Post event) { + + } + + @Override + public void onEntityUpdate(LivingEvent.LivingUpdateEvent updateEvent) { + + } + + @Override + public void onInteract(PlayerInteractEntityEvent event) { + + } + + @Override + public void onKeybindPress(KeyBindPressedEvent keyInputEvent) { + + } + + @Override + public void onInteractBlock(PlayerInteractEvent event) { + + } + @Override + public void onEntityDeath(LivingDeathEvent deathEvent) { + + } + @Override + public void onBlockUpdate(BlockUpdateEvent blockUpdateEvent) { + + } + + public void onPhaseChange() {} + + @Data + @Builder + public static class PhaseData { + private PhaseData(String phase, Set<String> signatureMsgs, Set<String> nextPhase) { + this.phase = phase; + this.nextPhases = new HashSet<>(nextPhase); + this.signatureMsgs = new HashSet<>(); + for (String signatureMsg : signatureMsgs) { + this.signatureMsgs.add(signatureMsg.replace(" ", "")); + } + } + + private String phase; + @Singular + private Set<String> signatureMsgs; + @Singular + private Set<String> nextPhases; + + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/HealthData.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/HealthData.java new file mode 100644 index 00000000..ace9b39b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/bossfight/HealthData.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.mod.dungeon.roomprocessor.bossfight; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class HealthData { + private String name; + private int health; + private int maxHealth; + private boolean attackable; +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/boxpuzzle/BoxPuzzleSolvingThread.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/boxpuzzle/BoxPuzzleSolvingThread.java new file mode 100755 index 00000000..feeb7228 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/boxpuzzle/BoxPuzzleSolvingThread.java @@ -0,0 +1,182 @@ +/* + * 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.mod.dungeon.roomprocessor.boxpuzzle; + +import lombok.Getter; +import lombok.Setter; + +import java.awt.*; +import java.util.*; +import java.util.List; + +@Getter +@Setter +public class BoxPuzzleSolvingThread extends Thread { + private byte[][] data; + private int playerX; + private int playerY; + private Runnable callback; + + + public BoxPuzzleSolvingThread(byte[][] data, int playerX, int playerY, Runnable onDone) { + this.data = data; + this.playerX = playerX; + this.playerY = playerY; + this.callback = onDone; + } + + Route solution = null; + + private boolean solved = false; + + @Override + public void run() { + solved = false; + solution = solve(data,playerX,playerY, 20); + solved = true; + callback.run(); + } + + + public static String stateString(byte[][] array) { + StringBuilder sb = new StringBuilder(); + for (int y = 0; y < array.length; y++) + for(int x = 0; x < array[y].length; x++) + sb.append(array[y][x]); + + return sb.toString(); + } + + + private static final List<Point> directions = Arrays.asList(new Point(-1,0), new Point(1,0), new Point(0,1), new Point(0,-1)); + private static Route solve(byte[][] boardStart, int playerX, int playerY, int maxRecursion) { // result:: playerY == 0 + Queue<Route> routes = new LinkedList<Route>(); + Set<String> globalStatesBeen = new HashSet<String>(); + + Route r = new Route(); + r.currentState = boardStart; + routes.add(r); + + while (!routes.isEmpty()) { + Route route = routes.poll(); + + if (routes.size() > 3000000) return null; + + String stateId = stateString(route.currentState); + if (maxRecursion < route.boxMoves.size()) continue; + if (globalStatesBeen.contains(stateId)) continue; + + Queue<Point> points = new LinkedList<Point>(); + Set<Point> reached= new HashSet<Point>(); + List<BoxMove> possibleBoxMoves = new ArrayList<BoxMove>(); + points.add(new Point(playerX, playerY)); + + while (!points.isEmpty()) { + Point pt = points.poll(); + if (pt.y == 0) { + return route; + } + if (reached.contains(pt)) continue; + reached.add(pt); + for (Point dir:directions) { + int resX= pt.x + dir.x; + int resY = pt.y + dir.y; + if (resX < 0 || resY < 0 || resX >= route.currentState[0].length || resY >= route.currentState.length) { + continue; + } + if (route.currentState[resY][resX] > 0) { + possibleBoxMoves.add(new BoxMove(resX, resY, dir.x, dir.y)); + continue; + } + points.add(new Point(resX, resY)); + } + } + + globalStatesBeen.add(stateId); + for (BoxMove possibleBoxMove : possibleBoxMoves) { + byte[][] copied = new byte[route.currentState.length][]; + for (int y = 0; y < copied.length; y++) + copied[y] = route.currentState[y].clone(); + + if (push(copied, possibleBoxMove.x, possibleBoxMove.y, possibleBoxMove.dx, possibleBoxMove.dy)){ + String stateId2 = stateString(copied); + if (globalStatesBeen.contains(stateId2)) continue; + + Route route2 = new Route(); + route2.boxMoves = new ArrayList<BoxMove>(route.boxMoves); + route2.boxMoves.add(possibleBoxMove); + route2.currentState = copied; + + routes.add(route2); + } + } + } + + + return null; + } + + + public static boolean push(byte[][] board, int x,int y,int dx,int dy) { + if (board[y][x] != 1) return false; + int resultingX= x + dx; + int resultingY = y +dy; + if (resultingX < 0 || resultingY < 0 || resultingX >= board[0].length || resultingY >= board.length) return false; + if (board[resultingY][resultingX] == 1 || resultingY == 6) return false; + + board[resultingY][resultingX] = 1; + board[y][x] = 0; + return true; + } + + public static class BoxMove { + int x; + int y; + int dx; + int dy; + + public BoxMove(int x, int y, int dx, int dy) { + this.x = x; + this.y = y; + this.dx = dx; + this.dy = dy; + } + + public int getX() { + return x; + } + + public int getY() { + return y; + } + + public int getDx() { + return dx; + } + + public int getDy() { + return dy; + } + } + + public static class Route { + List<BoxMove> boxMoves = new LinkedList<BoxMove>(); + byte[][] currentState; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/boxpuzzle/RoomProcessorBoxSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/boxpuzzle/RoomProcessorBoxSolver.java new file mode 100755 index 00000000..f4c80a57 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/boxpuzzle/RoomProcessorBoxSolver.java @@ -0,0 +1,392 @@ +/* + * 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.mod.dungeon.roomprocessor.boxpuzzle; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.mod.config.types.AColor; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.block.Block; +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.init.Blocks; +import net.minecraft.util.*; +import net.minecraft.world.World; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL14; + +import java.awt.*; +import java.util.*; +import java.util.List; + +public class RoomProcessorBoxSolver extends GeneralRoomProcessor { + + + private BlockPos[][] poses = new BlockPos[7][7]; + private boolean bugged= true; + + private BoxPuzzleSolvingThread puzzleSolvingThread; + + public RoomProcessorBoxSolver(DungeonRoom dungeonRoom) { + super(dungeonRoom); + + OffsetPointSet ops = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("board"); + try { + if (ops != null) { + for (int y = 0; y < 7; y++) { + for (int x = 0; x < 7; x++) { + poses[y][x] = ops.getOffsetPointList().get(y * 7 + x).getBlockPos(dungeonRoom); + } + } + bugged = false; + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private byte[][] buildCurrentState() { + World w = getDungeonRoom().getContext().getWorld(); + byte[][] board = new byte[poses.length][poses[0].length]; + for (int y = 0; y < poses.length; y++) { + for (int x = 0; x < poses[0].length; x++) { + if (y == 6) { + board[y][x] = -1; + continue; + } + BlockPos pos = poses[y][x]; + Block b = w.getChunkFromBlockCoords(pos).getBlock(pos); + if (b == Blocks.air) + board[y][x] = 0; + else + board[y][x] = 1; + } + } + return board; + } + + private boolean calcReq = true; + + private boolean calcDone= false; + private boolean calcDone2 = false; + private int step = 0; + private byte[][] lastState; + + @Override + public void tick() { + super.tick(); + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (bugged) return; + byte[][] currboard = buildCurrentState(); + if (puzzleSolvingThread == null) { + calcDone = false; + puzzleSolvingThread = new BoxPuzzleSolvingThread(currboard, 0, 6, new Runnable() { + @Override + public void run() { + calcDone = true; + calcDone2 = true; + } + }); + puzzleSolvingThread.start(); + } + if (calcReq) { + OffsetPointSet ops = (OffsetPointSet) getDungeonRoom().getDungeonRoomInfo().getProperties().get("board"); + if (ops != null) { + poses = new BlockPos[7][7]; + for (int y = 0; y < 7; y++) { + for (int x = 0; x < 7; x++) { + poses[y][x] = ops.getOffsetPointList().get(y * 7 + x).getBlockPos(getDungeonRoom()); + } + } + bugged = false; + } + + calcDone = false; + if (puzzleSolvingThread != null) + puzzleSolvingThread.stop(); + puzzleSolvingThread = new BoxPuzzleSolvingThread(currboard, 0, 6, new Runnable() { + @Override + public void run() { + calcDone = true; + calcDone2 = true; + } + }); + puzzleSolvingThread.start(); + calcReq = false; + } + + boolean pathFindReq = false; + if (calcDone2) { + BoxPuzzleSolvingThread.Route semi_solution = puzzleSolvingThread.solution; + if (semi_solution == null) { + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §eBox Solver §7:: §cCouldn't find solution involving less than 20 box moves within 3m concurrent possibility")); + step = 0; + calcDone2 = false; + pathFindReq = true; + totalPath = new LinkedList<BlockPos>(); + totalPushedBlocks = new LinkedList<BlockPos>(); + solution = new LinkedList<BoxPuzzleSolvingThread.BoxMove>(); + return; + } else{ + solution = semi_solution.boxMoves; + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide §7:: §eBox Solver §7:: Solution Found!")); + } + step = 0; + lastState = currboard; + calcDone2 = false; + pathFindReq = true; + + calcTotalPath(); + } + + if (lastState == null) return; + boolean moved = false; + label: + for (int y = 0 ; y < currboard.length; y++) { + for (int x = 0; x < currboard[y].length; x++) { + if (lastState[y][x] != currboard[y][x]) { + moved = true; + lastState = currboard; + break label; + } + } + } + + if (moved) { + step++; + } + + Point player = getPlayerPos(currboard); + boolean currYState = Minecraft.getMinecraft().thePlayer.getPosition().getY() < 68; + if (((currYState && !player.equals(lastPlayer)) || (currYState != yState) || (moved) || pathFindReq) && solution != null) { + Point target = null; + if (step < solution.size()) { + BoxPuzzleSolvingThread.BoxMove boxMove = solution.get(step); + target = new Point(boxMove.x - boxMove.dx, boxMove.y - boxMove.dy); + } + List<Point> semi_pathFound = pathfind(currboard, player, target); + pathFound = new LinkedList<BlockPos>(); + for (Point point : semi_pathFound) { + pathFound.add(poses[point.y][point.x].add(0,-1,0)); + } + + lastPlayer = player; + yState = currYState; + } + + } + + public void calcTotalPath() { + Point player = new Point(0,6); + totalPath = new LinkedList<BlockPos>(); + totalPushedBlocks = new LinkedList<BlockPos>(); + byte[][] currboard = buildCurrentState(); + for (int i = 0; i <= solution.size(); i++) { + Point target = null; + BoxPuzzleSolvingThread.BoxMove boxMove = null; + if (i < solution.size()) { + boxMove = solution.get(i); + target = new Point(boxMove.x - boxMove.dx, boxMove.y - boxMove.dy); + } + List<Point> semi_pathFound = pathfind(currboard, player, target); + for (int i1 = semi_pathFound.size() - 1; i1 >= 0; i1--) { + Point point = semi_pathFound.get(i1); + totalPath.add(poses[point.y][point.x].add(0, -1, 0)); + } + + player = target; + if (boxMove != null) { + BoxPuzzleSolvingThread.push(currboard, boxMove.x, boxMove.y, boxMove.dx, boxMove.dy); + int fromX = boxMove.x - boxMove.dx; + int fromY = boxMove.y - boxMove.dy; + + BlockPos pos = poses[fromY][fromX]; + BlockPos pos2 = poses[boxMove.y][boxMove.x]; + BlockPos dir = pos.subtract(pos2); + dir = new BlockPos(MathHelper.clamp_int(dir.getX(), -1,1), 0, MathHelper.clamp_double(dir.getZ(), -1, 1)); + + BlockPos highlight = pos2.add(dir); + totalPushedBlocks.add(highlight); + } + } + } + + private boolean yState = true; + public Point getPlayerPos(byte[][] map) { + BlockPos playerPos = Minecraft.getMinecraft().thePlayer.getPosition(); + int minDir = Integer.MAX_VALUE; + Point pt = null; + for (int y = 0; y < poses.length; y++) { + for (int x = 0; x < poses[0].length; x++) { + if (map[y][x] == 1) continue; + int dir = (int) poses[y][x].distanceSq(playerPos); + if (dir < minDir) { + minDir = dir; + pt = new Point(x,y); + } + } + } + return pt; + } + + private List<BoxPuzzleSolvingThread.BoxMove> solution; + private List<BlockPos> pathFound; + private List<BlockPos> totalPath; + private List<BlockPos> totalPushedBlocks; + private Point lastPlayer; + + private static final java.util.List<Point> directions = Arrays.asList(new Point(-1,0), new Point(1,0), new Point(0,1), new Point(0,-1)); + public List<Point> pathfind(byte[][] map, Point start, Point target2) { + int[][] distances = new int[map.length][map[0].length]; + + Queue<Point> evalulate = new LinkedList<Point>(); + evalulate.add(start); + Point target = null; + while (!evalulate.isEmpty()) { + Point p = evalulate.poll(); + if (p.equals(target2) || (target2 == null &&p.y == 0)) { + target = p; + break; + } + int max = 0; + for (Point dir:directions) { + int resX= p.x + dir.x; + int resY = p.y + dir.y; + if (resX < 0 || resY < 0 || resX >= distances[0].length || resY >= distances.length) { + continue; + } + + if (max < distances[resY][resX]) { + max = distances[resY][resX]; + } + if (distances[resY][resX] == 0 && (map[resY][resX] == 0 ||map[resY][resX] == -1)) { + evalulate.add(new Point(resX, resY)); + } + } + distances[p.y][p.x] = max + 1; + } + if (target == null) return Collections.emptyList(); + + List<Point> route = new LinkedList<Point>(); + while(!target.equals(start)) { + route.add(target); + int min = Integer.MAX_VALUE; + Point minPoint = null; + for (Point dir:directions) { + int resX= target.x + dir.x; + int resY = target.y + dir.y; + if (resX < 0 || resY < 0 || resX >= distances[0].length || resY >= distances.length) { + continue; + } + + if (min > distances[resY][resX] && distances[resY][resX] != 0) { + min = distances[resY][resX]; + minPoint = new Point(resX, resY); + } + } + target = minPoint; + } + route.add(start); + return route; + } + + @Override + public void chatReceived(IChatComponent chat) { + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (chat.getFormattedText().toLowerCase().contains("recalc")) { + if (calcDone) { + calcReq = true; + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide :::: Recalculating Route...")); + } else { + calcReq = true; + ChatTransmitter.addToQueue(new ChatComponentText("§eDungeons Guide :::: Currently Calculating Route...")); + } + } + } + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (FeatureRegistry.SOLVER_BOX.disableText()) return; + FontRenderer fr = Minecraft.getMinecraft().fontRendererObj; + GlStateManager.enableBlend(); + GL14.glBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + GlStateManager.tryBlendFuncSeparate(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA, GL11.GL_ONE, GL11.GL_ONE_MINUS_SRC_ALPHA); + fr.drawString("Type \"recalc\" in chat to recalculate the solution", 0, 0, 0xFFFFFFFF); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_BOX.isEnabled()) return; + if (bugged) return; + if (!calcDone) return; + if (solution == null) return; + if (Minecraft.getMinecraft().thePlayer.getPosition().getY() < 68) { + if (step < solution.size()) { + BoxPuzzleSolvingThread.BoxMove boxMove = solution.get(step); + int fromX = boxMove.x - boxMove.dx; + int fromY = boxMove.y - boxMove.dy; + + BlockPos pos = poses[fromY][fromX]; + BlockPos pos2 = poses[boxMove.y][boxMove.x]; + BlockPos dir = pos.subtract(pos2); + dir = new BlockPos(MathHelper.clamp_int(dir.getX(), -1, 1), 0, MathHelper.clamp_double(dir.getZ(), -1, 1)); + + BlockPos highlight = pos2.add(dir); + AColor color = FeatureRegistry.SOLVER_BOX.getTargetColor().multiplyAlpha(MathHelper.clamp_double(Minecraft.getMinecraft().thePlayer.getPosition().distanceSq(highlight), 100, 255) / 255); + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(highlight.getX(), highlight.getY(), highlight.getZ(), highlight.getX()+1, highlight.getY() + 1, highlight.getZ() + 1), color, partialTicks, false); + } + + if (pathFound != null) { + RenderUtils.drawLines(pathFound, FeatureRegistry.SOLVER_BOX.getLineColor(),FeatureRegistry.SOLVER_BOX.getLineWidth(), partialTicks, true); + } + } else { + if (totalPath != null) { + RenderUtils.drawLines(totalPath, FeatureRegistry.SOLVER_BOX.getLineColor(),FeatureRegistry.SOLVER_BOX.getLineWidth(), partialTicks, false); + } + if (totalPushedBlocks != null) { + for (int i = 0; i < totalPushedBlocks.size(); i++) { + BlockPos pos = totalPushedBlocks.get(i); + RenderUtils.highlightBoxAColor(AxisAlignedBB.fromBounds(pos.getX(), pos.getY(), pos.getZ(), pos.getX()+1, pos.getY() + 1, pos.getZ() + 1), FeatureRegistry.SOLVER_BOX.getTargetColor(), partialTicks, false); + RenderUtils.drawTextAtWorld("#"+i, pos.getX()+0.5f, pos.getY() +0.5f, pos.getZ() + 0.5f, i != step ? + RenderUtils.getColorAt(pos.getX(), pos.getY(), pos.getZ(), FeatureRegistry.SOLVER_BOX.getTextColor2()) : RenderUtils.getColorAt(pos.getX(), pos.getY(), pos.getZ(), FeatureRegistry.SOLVER_BOX.getTextColor()), 0.1f, false, false, partialTicks); + } + } + } + + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorBoxSolver> { + @Override + public RoomProcessorBoxSolver createNew(DungeonRoom dungeonRoom) { + RoomProcessorBoxSolver defaultRoomProcessor = new RoomProcessorBoxSolver(dungeonRoom); + return defaultRoomProcessor; + } + } + + + +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/icefill/RoomProcessorIcePath2.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/icefill/RoomProcessorIcePath2.java new file mode 100755 index 00000000..94732dc9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/icefill/RoomProcessorIcePath2.java @@ -0,0 +1,151 @@ +/* + * 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.mod.dungeon.roomprocessor.icefill; + +import kr.syeyoung.dungeonsguide.mod.chat.ChatTransmitter; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; + +public class RoomProcessorIcePath2 extends GeneralRoomProcessor { + private final List<List<BlockPos>> solution = new CopyOnWriteArrayList<List<BlockPos>>(); + + + public RoomProcessorIcePath2(DungeonRoom dungeonRoom) { + + super(dungeonRoom); + + String levels = (String) dungeonRoom.getDungeonRoomInfo().getProperties().get("levels"); + if (levels == null) { + return; + } + + for (final String s : levels.split(",")) { + try { + OffsetPointSet level = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get(s + "-board"); + String data = (String) dungeonRoom.getDungeonRoomInfo().getProperties().get(s + "-level"); + final int width = Integer.parseInt(data.split(":")[0]); + final int height = Integer.parseInt(data.split(":")[1]); + final int startX = Integer.parseInt(data.split(":")[2]); + final int startY = Integer.parseInt(data.split(":")[3]); + final int endX = Integer.parseInt(data.split(":")[4]); + final int endY = Integer.parseInt(data.split(":")[5]); + + final int[][] map = new int[height][width]; + final BlockPos[][] map2 = new BlockPos[height][width]; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + map2[y][x] = level.getOffsetPointList().get(y * width + x).getBlockPos(dungeonRoom); + map[y][x] = level.getOffsetPointList().get(y * width + x).getBlock(dungeonRoom) == Blocks.air ? 0 : 1; + } + } + + new Thread() { + public void run() { + List<Point> hamiltonianPath = findFirstHamiltonianPath(map, startX, startY, endX, endY); + if (hamiltonianPath == null) { + ChatTransmitter.addToQueue("§eDungeons Guide §7:: §eIcePath §7:: §cCouldn't find solution for floor "+s); + return; + } + hamiltonianPath.add(0,new Point(startX, startY)); + List<BlockPos> poses = new LinkedList<BlockPos>(); + for (int i = 0; i < hamiltonianPath.size(); i++) { + Point p = hamiltonianPath.get(i); + poses.add(map2[p.y][p.x]); + } + solution.add(poses); + } + }.start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void tick() { + super.tick(); + if (!FeatureRegistry.SOLVER_ICEPATH.isEnabled()) return; + } + + @Override + public void drawWorld(float partialTicks) { + if (!FeatureRegistry.SOLVER_ICEPATH.isEnabled()) return; + for (List<BlockPos> solution:this.solution) + RenderUtils.drawLines(solution, FeatureRegistry.SOLVER_ICEPATH.getLineColor(),FeatureRegistry.SOLVER_ICEPATH.getLineWidth(), partialTicks, true); + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorIcePath2> { + @Override + public RoomProcessorIcePath2 createNew(DungeonRoom dungeonRoom) { + RoomProcessorIcePath2 defaultRoomProcessor = new RoomProcessorIcePath2(dungeonRoom); + return defaultRoomProcessor; + } + } + + private static List<Point> findFirstHamiltonianPath(int[][] map, int startX, int startY, int endX, int endY) { + int emptySpace =0; + for (int y = 0; y < map.length; y++) + for (int x = 0; x < map[y].length; x++) + if (map[y][x] == 0) emptySpace++; + + map[startY][startX] = 2; + + return findHamiltonianPath(map, startX, startY, endX, endY, 0, emptySpace-1); + } + + + private static final List<Point> directions = Arrays.asList(new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1)); + private static LinkedList<Point> findHamiltonianPath(int[][] map, int startX, int startY, int endX, int endY, int depth, int reqDepth) { + if (endX == startX && endY == startY) { + if (depth != reqDepth) return null; + LinkedList<Point> path = new LinkedList<Point>(); + path.add(new Point(startX, startY)); + return path; + } + + for (Point p : directions) { + int y = p.y +startY,x=p.x + startX; + if (y <0 || y >= map.length || x <0 || x >= map[0].length || map[y][x] != 0) continue; + + int[][] copiedMap = new int[map.length][map[0].length]; + for (int y2 = 0; y2 < copiedMap.length; y2++) + copiedMap[y2] = map[y2].clone(); + copiedMap[y][x] = 2; + + LinkedList<Point> potentialRoute = findHamiltonianPath(copiedMap, x,y,endX,endY, depth +1, reqDepth); + if (potentialRoute != null) { + potentialRoute.addFirst(new Point(x,y)); + return potentialRoute; + } + } + return null; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverState.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverState.java new file mode 100755 index 00000000..e86fdd5c --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverState.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.mod.dungeon.roomprocessor.waterpuzzle; + +import lombok.AllArgsConstructor; +import lombok.Data; + +@Data +@AllArgsConstructor +public class LeverState { + private String blockId; + private boolean requiredState; + + public LeverState invert() { + return new LeverState(blockId, !requiredState); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverStateContradict.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverStateContradict.java new file mode 100755 index 00000000..a574d6bf --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverStateContradict.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.mod.dungeon.roomprocessor.waterpuzzle; + +public class LeverStateContradict extends LeverState { + public LeverStateContradict() { + super("contradict", true); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java new file mode 100755 index 00000000..d4b05bc9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.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.mod.dungeon.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomfinder.DungeonRoom; +import kr.syeyoung.dungeonsguide.mod.features.FeatureRegistry; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.GeneralRoomProcessor; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.RoomProcessorGenerator; +import kr.syeyoung.dungeonsguide.mod.utils.RenderUtils; +import net.minecraft.util.BlockPos; + +import java.awt.*; +import java.util.List; + +public class RoomProcessorWaterPuzzle extends GeneralRoomProcessor { + + private boolean argumentsFulfilled = false; + + private WaterBoard waterBoard; + private final OffsetPointSet doorsClosed; + private final OffsetPointSet levers; + private final OffsetPointSet frontBoard; + private final OffsetPointSet backBoard; + private final OffsetPoint water_lever; + + public RoomProcessorWaterPuzzle(DungeonRoom dungeonRoom) { + super(dungeonRoom); + frontBoard = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("front"); + backBoard = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("back"); + levers = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("levers"); + doorsClosed = (OffsetPointSet) dungeonRoom.getDungeonRoomInfo().getProperties().get("doors"); + water_lever = (OffsetPoint) dungeonRoom.getDungeonRoomInfo().getProperties().get("water-lever"); + + if (frontBoard == null || backBoard == null || levers == null || doorsClosed == null ||water_lever == null) { + argumentsFulfilled = false; + } else { + argumentsFulfilled = true; + + try { + waterBoard = new WaterBoard(this, frontBoard, backBoard, levers, doorsClosed, water_lever); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + @Override + public void tick() { + super.tick(); + if (!FeatureRegistry.SOLVER_WATERPUZZLE.isEnabled()) return; + if (!argumentsFulfilled) return; + try { + waterBoard.tick(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public void drawScreen(float partialTicks) { + super.drawScreen(partialTicks); + } + + @Override + public void drawWorld(float partialTicks) { + super.drawWorld(partialTicks); + if (!FeatureRegistry.SOLVER_WATERPUZZLE.isEnabled()) return; + if (!argumentsFulfilled) return; + if (waterBoard == null) return; + + Route route = waterBoard.getCurrentRoute(); + if (route != null) { + int j = 1; + for (int i = 0; i < route.getConditionList().size(); i++) { + LeverState condition = route.getConditionList().get(i); + if (condition == null) continue; + SwitchData switchData = waterBoard.getValidSwitches().get(condition.getBlockId()); + if (switchData.getCurrentState(getDungeonRoom().getContext().getWorld()) != condition.isRequiredState()) { + + RenderUtils.highlightBlock(switchData.getSwitchLoc(), new Color(0,255,0,50), partialTicks, true); + RenderUtils.drawTextAtWorld("#"+j,switchData.getSwitchLoc().getX(), switchData.getSwitchLoc().getY()+1, switchData.getSwitchLoc().getZ(), 0xFF000000,0.1f, false, false, partialTicks); + RenderUtils.drawTextAtWorld(condition.isRequiredState() ? "on":"off",switchData.getSwitchLoc().getX(), switchData.getSwitchLoc().getY(), switchData.getSwitchLoc().getZ(), 0xFF000000,0.1f, false, false, partialTicks); + j++; + } + } + for (WaterNode node : route.getNodes()) { + RenderUtils.highlightBlock(node.getBlockPos(), new Color(0,255,255,50), partialTicks, true); + } + } + List<BlockPos> targets = waterBoard.getTarget(); + if (targets != null) { + for (BlockPos target : targets) { + RenderUtils.highlightBlock(target, new Color(0,255,255,100), partialTicks, true); + } + RenderUtils.highlightBlock(waterBoard.getToggleableMap().get("mainStream").getBlockPos(), new Color(0,255,0,255), partialTicks, true); + } + } + + public static class Generator implements RoomProcessorGenerator<RoomProcessorWaterPuzzle> { + @Override + public RoomProcessorWaterPuzzle createNew(DungeonRoom dungeonRoom) { + RoomProcessorWaterPuzzle defaultRoomProcessor = new RoomProcessorWaterPuzzle(dungeonRoom); + return defaultRoomProcessor; + } + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Route.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Route.java new file mode 100755 index 00000000..a122d83f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Route.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.mod.dungeon.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.nodes.WaterNodeEnd; +import lombok.Data; +import org.jetbrains.annotations.NotNull; + +import java.util.*; + +@Data +public class Route implements Cloneable, Comparable { + private Set<WaterNode> nodes = new LinkedHashSet<WaterNode>(); + private List<LeverState> conditionList = new ArrayList<LeverState>(); + private Set<WaterNodeEnd> endingNodes = new HashSet<WaterNodeEnd>(); + + + private int matches = 0; + private int stateFlops = 0; + private int notMatches = 0; + + public double calculateCost() { + return (1.0/matches) * 50 + stateFlops * 20 + notMatches * 10000; + } + + @Override + protected Route clone() { + Route r = new Route(); + r.getNodes().addAll(nodes); + r.getConditionList().addAll(conditionList); + r.getEndingNodes().addAll(endingNodes); + return r; + } + + @Override + public int compareTo(@NotNull Object o) { + if (o instanceof Route) { + double var0 = calculateCost(); + double var1 = ((Route)o).calculateCost(); + return Double.compare(var0, var1); + } + return 0; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/SwitchData.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/SwitchData.java new file mode 100755 index 00000000..1b43448f --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/SwitchData.java @@ -0,0 +1,46 @@ +/* + * 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.mod.dungeon.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.nodes.WaterNodeStart; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.nodes.WaterNodeToggleable; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class SwitchData { + private WaterBoard waterBoard; + + private BlockPos switchLoc; + private BlockPos blockLoc; + + private String blockId; + + public boolean getCurrentState(World w) { + WaterNode waterNode = waterBoard.getToggleableMap().get(blockId); + if (waterNode instanceof WaterNodeStart) + return ((WaterNodeStart) waterNode).isTriggered(w); + else if (waterNode instanceof WaterNodeToggleable) + return ((WaterNodeToggleable) waterNode).isTriggered(w); + return false; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterBoard.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterBoard.java new file mode 100755 index 00000000..56b372e4 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterBoard.java @@ -0,0 +1,424 @@ +/* + * 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.mod.dungeon.roomprocessor.waterpuzzle; + +import kr.syeyoung.dungeonsguide.mod.DungeonsGuide; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint; +import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.nodes.*; +import lombok.Getter; +import net.minecraft.block.Block; +import net.minecraft.block.BlockLever; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.Tuple; +import net.minecraft.world.World; + +import java.util.*; +import java.util.List; + +public class WaterBoard { + @Getter + WaterNode[][] board; + RoomProcessorWaterPuzzle waterPuzzle; + + private final OffsetPointSet frontPlate; + private final OffsetPointSet backPlate; + private final OffsetPointSet levers; + private final OffsetPointSet doors; + private final OffsetPoint lever; + + @Getter + private final List<SwitchData> switchData = new ArrayList<SwitchData>(); + @Getter + private final Map<String, SwitchData> validSwitches = new HashMap<String, SwitchData>(); + + private WaterNodeStart waterNodeStart; + private final Map<String, WaterNodeEnd> waterNodeEndMap = new HashMap<String, WaterNodeEnd>(); + + @Getter + private final Map<String, WaterNode> toggleableMap = new HashMap<String, WaterNode>(); + + @Getter + private Set<String> reqOpen = new HashSet<String>(); + @Getter + private Route currentRoute; + @Getter + private List<BlockPos> target; + @Getter + private List<String> target2; + + public WaterBoard(RoomProcessorWaterPuzzle roomProcessorWaterPuzzle, OffsetPointSet frontPlate, OffsetPointSet backPlate, OffsetPointSet levers, OffsetPointSet doors, OffsetPoint leverMain) { + this.waterPuzzle = roomProcessorWaterPuzzle; + this.frontPlate = frontPlate; + this.backPlate = backPlate; + this.levers = levers; + this.doors = doors; + this.lever = leverMain; + + buildLeverStates(); + buildNodes(); + } + + private void buildLeverStates(){ + for (OffsetPoint offsetPoint : levers.getOffsetPointList()) { + if (offsetPoint.getBlock(waterPuzzle.getDungeonRoom()) == Blocks.lever){ + BlockPos pos = offsetPoint.getBlockPos(waterPuzzle.getDungeonRoom()); + World w= waterPuzzle.getDungeonRoom().getContext().getWorld(); + BlockLever.EnumOrientation enumOrientation = w.getBlockState(pos).getValue(BlockLever.FACING); + EnumFacing enumFacing = enumOrientation.getFacing(); + BlockPos newPos = pos.add(-enumFacing.getDirectionVec().getX(),0,-enumFacing.getDirectionVec().getZ()); + + int id = Block.getIdFromBlock(w.getChunkFromBlockCoords(newPos).getBlock(newPos)); + int data = w.getChunkFromBlockCoords(newPos).getBlockMetadata(newPos); + + SwitchData sw; + switchData.add(sw = new SwitchData(this, pos,newPos,id+":"+data)); + validSwitches.put(id+":"+data, sw); + } + } + SwitchData sw; + switchData.add(sw = new SwitchData(this, lever.getBlockPos(waterPuzzle.getDungeonRoom()),lever.getBlockPos(waterPuzzle.getDungeonRoom()).add(0,-1,0),"mainStream")); + validSwitches.put("mainStream", sw); + } + + public void tick() { + Set<String> doorsToOpen = new HashSet<String>(); + for (OffsetPoint offsetPoint : doors.getOffsetPointList()) { + Block b =offsetPoint.getBlock(waterPuzzle.getDungeonRoom()); + if (b != Blocks.air) { + doorsToOpen.add(Block.getIdFromBlock(b)+":"+offsetPoint.getData(waterPuzzle.getDungeonRoom())); + } + } +// if (!(reqOpen.containsAll(doorsToOpen) && doorsToOpen.containsAll(reqOpen))) { + reqOpen = doorsToOpen; + if (doorsToOpen.size() != 0) { + Set<WaterNodeEnd> ends = new HashSet<WaterNodeEnd>(); + for (String s : doorsToOpen) { + ends.add(waterNodeEndMap.get(s)); + } + currentRoute = getBestRoute(ends); +// { +// +// Set<LeverState> currentState = new HashSet<LeverState>(); +// World w = waterPuzzle.getDungeonRoom().getContext().getWorld(); +// for (SwitchData switchDatum : this.switchData) { +// currentState.add(new LeverState(switchDatum.getBlockId(), switchDatum.getCurrentState(w))); +// } +// currentRoute = simulate(currentState); +// } + + target = new ArrayList<BlockPos>(); + target2 = new ArrayList<String>(); + if (currentRoute != null) { + for (WaterNodeEnd endingNode : currentRoute.getEndingNodes()) { + target.add(endingNode.getBlockPos()); + target2.add(endingNode.getResultId()); + } + } + } +// } + } + + public Route getBestRoute(Set<WaterNodeEnd> potentialEnds) { + int totalStates = (int) Math.pow(2, validSwitches.size() - 1); + List<SwitchData> switchData = new ArrayList<SwitchData>(); + Set<LeverState> currentState = new HashSet<LeverState>(); + World w = waterPuzzle.getDungeonRoom().getContext().getWorld(); + for (SwitchData switchDatum : this.switchData) { + if (!switchDatum.getBlockId().equals("mainStream")) { + switchData.add(switchDatum); + } + currentState.add(new LeverState(switchDatum.getBlockId(), switchDatum.getCurrentState(w))); + } + PriorityQueue<Route> routes = new PriorityQueue<Route>(); + + for (int i = 0; i < totalStates; i++) { + Set<LeverState> states = new HashSet<LeverState>(); + for (int i1 = 0; i1 < switchData.size(); i1++) { + states.add(new LeverState(switchData.get(i1).getBlockId(), ((i >> i1) & 0x1) > 0)); + } + states.add(new LeverState("mainStream", true)); + + Route r = simulate(states); + + for (LeverState leverState : currentState) { + if (!states.contains(leverState)) + r.setStateFlops(r.getStateFlops() + 1); + } + for (WaterNodeEnd potentialEnd : r.getEndingNodes()) { + if (potentialEnds.contains(potentialEnd)) { + r.setMatches(r.getMatches() + 1); + } else { + r.setNotMatches(r.getNotMatches() + 1); + } + } + if (r.getMatches() > 0) + routes.add(r); + } + + + return routes.peek(); + } + + public Route simulate(Set<LeverState> leverStates) { + leverStates.add(null); + Route r = new Route(); + final Queue<WaterNode> toGoDownTo = new LinkedList<WaterNode>(); + Set<WaterNode> searched = new HashSet<WaterNode>(); + Set<LeverState> waterBlockingStates = new HashSet<LeverState>(); + World w = waterPuzzle.getDungeonRoom().getContext().getWorld(); +// toGoDownTo.add(getNodeAt(waterNodeStart.getX(), waterNodeStart.getY() + 1)); + { + Queue<Tuple<WaterNode, Boolean>> toGo = new LinkedList<>(); + toGo.add(new Tuple<>(waterNodeStart, true)); + toGoDownTo.add(getNodeAt(waterNodeStart.getX(), waterNodeStart.getY() + 1)); + Set<WaterNode> visited = new HashSet<>(); + while (!toGo.isEmpty()) { + Tuple<WaterNode, Boolean> waterNode = toGo.poll(); + if (waterNode.getFirst() == null) continue; + if (visited.contains(waterNode.getFirst())) continue; + if (!waterNode.getFirst().canWaterGoThrough()) continue; + if (waterNode.getFirst() instanceof WaterNodeEnd) continue; + visited.add(waterNode.getFirst()); + + boolean water = waterNode.getFirst().isWaterFilled(w); + if (water && !waterNode.getSecond()) { + toGoDownTo.add(getNodeAt(waterNode.getFirst().getX(), waterNode.getFirst().getY())); + } + + int x = waterNode.getFirst().getX(), y = waterNode.getFirst().getY(); + toGo.add(new Tuple<>(getNodeAt(x+1, y), water)); + toGo.add(new Tuple<>(getNodeAt(x-1, y), water)); + toGo.add(new Tuple<>(getNodeAt(x, y+1), water)); + } + } + while (!toGoDownTo.isEmpty()) { + WaterNode asd = toGoDownTo.poll(); + if (asd == null) continue; + if (searched.contains(asd)) continue; + searched.add(asd); + + if (asd instanceof WaterNodeEnd) { + if (!asd.isWaterFilled(w)) + r.getEndingNodes().add((WaterNodeEnd) asd); + continue; + } + + r.getNodes().add(asd); + + if (asd.isWaterFilled(w) && ( + (getNodeAt(asd.getX() + 1, asd.getY()) != null && getNodeAt(asd.getX() + 1, asd.getY()).isWaterFilled(w)) + || (getNodeAt(asd.getX() - 1, asd.getY()) != null && getNodeAt(asd.getX() - 1, asd.getY()).isWaterFilled(w)))) { + boolean followWater = getNodeAt(asd.getX() - 1, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() - 1, asd.getY()).getCondition()) + && getNodeAt(asd.getX() - 2, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() - 2, asd.getY()).getCondition()); + for (int i = asd.getX(); i < asd.getX() + 8; i++) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (followWater && !nodehere.isWaterFilled(w)) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (i != asd.getX()) + followWater = nodehere.isWaterFilled(w) && (down == null || (down.canWaterGoThrough() && leverStates.contains(down.getCondition()))); + r.getNodes().add(nodehere); + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + if (!followWater) break; + } + } + followWater = getNodeAt(asd.getX() +1, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() + 1, asd.getY()).getCondition()) + && getNodeAt(asd.getX() +2, asd.getY()) != null && leverStates.contains(getNodeAt(asd.getX() + 2, asd.getY()).getCondition()); + for (int i = asd.getX(); i > asd.getX() - 8; i--) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (followWater && !nodehere.isWaterFilled(w)) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (i != asd.getX()) + followWater = nodehere.isWaterFilled(w) && (down == null || (down.canWaterGoThrough() && leverStates.contains(down.getCondition()))); + r.getNodes().add(nodehere); + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + if (!followWater) break; + } + } + } else { + int minDistToDropRight = 9999; + for (int i = asd.getX(); i < asd.getX() + 8; i++) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())))) { + int dist = i - asd.getX(); + if (dist < minDistToDropRight) + minDistToDropRight = dist; + break; + } + } + int minDistToDropLeft = 9999; + for (int i = asd.getX(); i > asd.getX() - 8; i--) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere == null) break; + if (!nodehere.canWaterGoThrough()) break; + if (!leverStates.contains(nodehere.getCondition()) && !nodehere.isWaterFilled(w)) break; + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())))) { + int dist = asd.getX() - i; + if (dist < minDistToDropLeft) + minDistToDropLeft = dist; + break; + } + } + + int min = Math.min(minDistToDropRight, minDistToDropLeft); + if (min == 9999) continue; + if (minDistToDropRight == min) { + for (int i = asd.getX(); i <= asd.getX() + minDistToDropRight; i++) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + r.getNodes().add(nodehere); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + } + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + } + } + if (minDistToDropLeft == min) { + for (int i = asd.getX(); i >= asd.getX() - minDistToDropLeft; i--) { + WaterNode nodehere = getNodeAt(i, asd.getY()); + if (nodehere.getCondition() != null && leverStates.contains(nodehere.getCondition().invert()) && nodehere.isWaterFilled(w)) waterBlockingStates.add(nodehere.getCondition().invert()); + r.getNodes().add(nodehere); + WaterNode down = getNodeAt(i, asd.getY() + 1); + if (down != null && ((down.canWaterGoThrough() && leverStates.contains(down.getCondition())) || down.isWaterFilled(w))) { + toGoDownTo.add(down); + } + if (down != null && down.canWaterGoThrough() && down.getCondition() != null && leverStates.contains(down.getCondition().invert())) { + waterBlockingStates.add(down.getCondition().invert()); + } + } + } + } + } + ArrayList<LeverState> state = new ArrayList<LeverState>(waterBlockingStates); + state.remove(null); + Collections.sort(state, new Comparator<LeverState>() { + @Override + public int compare(LeverState leverState, LeverState t1) { + int var0 = toggleableMap.get(leverState.getBlockId()).getY(); + int var1 = toggleableMap.get(t1.getBlockId()).getY(); + return var0 < var1 ? -1 : (var0 == var1 ? 0 : 1); + } + }); + LinkedList<LeverState> states = new LinkedList<LeverState>(state); + for (LeverState ls : leverStates) { + if (!states.contains(ls)) { + states.add(ls); + } + } + states.remove(null); + + + r.setConditionList(states); + return r; + } + + + public WaterNode getNodeAt(int x, int y) { + if (x < 0 || y < 0) return null; + if (x >= board[0].length || y >= board.length) return null; + return board[y][x]; + } + + private void buildNodes() { + List<OffsetPoint> frontPoints = frontPlate.getOffsetPointList(); + List<OffsetPoint> backPoints = backPlate.getOffsetPointList(); + + board = new WaterNode[25][19]; + for (int x = 0; x < 19; x++) { + for (int y = 0; y < 25; y++) { + OffsetPoint front = frontPoints.get(x *25 +y); + OffsetPoint back = backPoints.get(x * 25 +y); + int frontId = Block.getIdFromBlock(front.getBlock(waterPuzzle.getDungeonRoom())); + int backId = Block.getIdFromBlock(back.getBlock(waterPuzzle.getDungeonRoom())); + int frontData = front.getData(waterPuzzle.getDungeonRoom()); + int backData = back.getData(waterPuzzle.getDungeonRoom()); + WaterNode node; + if (validSwitches.containsKey(backId +":"+backData)) { + String resId = backId + ":"+backData; + node = new WaterNodeToggleable(resId, isSwitchActive(validSwitches.get(resId)), front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + + toggleableMap.put(resId, node); + } else if (validSwitches.containsKey(frontId +":"+frontData)) { + String resId = frontId +":"+frontData; + node = new WaterNodeToggleable(resId, !isSwitchActive(validSwitches.get(resId)), front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + + toggleableMap.put(resId, node); + } else if (frontId == 0 || frontId == 8 || frontId == 9) { + if (y == 24) { + OffsetPoint pos; + if (x != 0) { + pos = frontPoints.get((x-1)*25+y); + } else { + pos = frontPoints.get((x+1) * 25 +y); + } + + int id = Block.getIdFromBlock(pos.getBlock(waterPuzzle.getDungeonRoom())); + int data= pos.getData(waterPuzzle.getDungeonRoom()); + node = new WaterNodeEnd(id+":"+data, front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + waterNodeEndMap.put(id+":"+data, (WaterNodeEnd) node); + } else if (y == 2 && x == 9) { + waterNodeStart = (WaterNodeStart) (node = new WaterNodeStart(front.getBlockPos(waterPuzzle.getDungeonRoom()), + frontId != 0 ^ isSwitchActive(validSwitches.get("mainStream")),x,y)); + } else { + node = new WaterNodeAir(front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + } + } else { + node = new WaterNodeWall(front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y); + } + board[y][x] =node; + } + } + toggleableMap.put("mainStream", waterNodeStart); + } + + private boolean isSwitchActive(SwitchData switchData) { + BlockPos switch2 = switchData.getSwitchLoc(); + World w= waterPuzzle.getDungeonRoom().getContext().getWorld(); + boolean bool = DungeonsGuide.getDungeonsGuide().getBlockCache().getBlockState(switch2).getValue(BlockLever.POWERED); + return bool; + } + + +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterNode.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterNode.java new file mode 100755 index 00000000..cbcb1cb0 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterNode.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.mod.dungeon.roomprocessor.waterpuzzle; + +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +public interface WaterNode { + boolean canWaterGoThrough(); + + // condition for water go + LeverState getCondition(); + + boolean isWaterFilled(World w); + + BlockPos getBlockPos(); + + int getX(); + int getY(); +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java new file mode 100755 index 00000000..274a232b --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java @@ -0,0 +1,59 @@ +/* + * 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.mod.dungeon.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeAir implements WaterNode { + BlockPos blockPos; + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return null; + } + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + public BlockPos getBlockPos() { + return blockPos; + } + + private int x,y; + + public String toString() { + return "A"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java new file mode 100755 index 00000000..3ca59934 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.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.mod.dungeon.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeEnd implements WaterNode { + private String resultId; + BlockPos blockPos; + + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return null; + } + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + public BlockPos getBlockPos() { + return blockPos; + } + private int x,y; + + public String toString() { + return "E"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java new file mode 100755 index 00000000..09ec7070 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java @@ -0,0 +1,66 @@ +/* + * 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.mod.dungeon.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeStart implements WaterNode { + + private BlockPos blockPos; + private boolean isReversed; + + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return new LeverState("mainStream", !isReversed); + } + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + public boolean isTriggered(World w) { + return isWaterFilled(w); + } + + + public BlockPos getBlockPos() { + return blockPos; + } + private int x,y; + + public String toString() { + return "S"; + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java new file mode 100755 index 00000000..039c1cf9 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.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.mod.dungeon.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeToggleable implements WaterNode { + private String blockId; + private boolean invert; + + BlockPos blockPos; + + @Override + public boolean canWaterGoThrough() { + return true; + } + + @Override + public LeverState getCondition() { + return new LeverState(blockId, invert); + } + + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + private int x,y; + + public boolean isTriggered(World w) { + Block b= w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + + return !(b == Blocks.air || b == Blocks.water || b == Blocks.flowing_water) ^ invert; + } + + + public BlockPos getBlockPos() { + return blockPos; + } + + + public String toString() { + return "T:"+blockId+(invert ? ":Y":":N"); + } +} diff --git a/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java new file mode 100755 index 00000000..b09750f2 --- /dev/null +++ b/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java @@ -0,0 +1,62 @@ +/* + * 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.mod.dungeon.roomprocessor.waterpuzzle.nodes; + +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.LeverState; +import kr.syeyoung.dungeonsguide.mod.dungeon.roomprocessor.waterpuzzle.WaterNode; +import lombok.AllArgsConstructor; +import lombok.Data; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.util.BlockPos; +import net.minecraft.world.World; + +@Data +@AllArgsConstructor +public class WaterNodeWall implements WaterNode { + + BlockPos blockPos; + @Override + public boolean canWaterGoThrough() { + return false; + } + + @Override + public LeverState getCondition() { + return null; + } + + + @Override + public boolean isWaterFilled(World w) { + Block b = w.getChunkFromBlockCoords(blockPos).getBlock(blockPos); + return b == Blocks.water || b == Blocks.flowing_water; + } + + private int x,y; + + public BlockPos getBlockPos() { + return blockPos; + } + + + public String toString() { + return "W"; + } +} |