/*
* Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod
* Copyright (C) 2021 cyoung06
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package kr.syeyoung.dungeonsguide.roomprocessor.icefill;
import kr.syeyoung.dungeonsguide.config.Config;
import kr.syeyoung.dungeonsguide.config.types.AColor;
import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
import kr.syeyoung.dungeonsguide.features.FeatureRegistry;
import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor;
import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator;
import kr.syeyoung.dungeonsguide.utils.RenderUtils;
import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
import net.minecraft.util.BlockPos;
import net.minecraft.util.ChatComponentText;
import java.awt.*;
import java.util.Queue;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.CopyOnWriteArrayList;
public class RoomProcessorIcePath2 extends GeneralRoomProcessor {
private final List> solution = new CopyOnWriteArrayList>();
private final Queue messageQueue = new ConcurrentLinkedQueue();
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 hamiltonianPath = findFirstHamiltonianPath(map, startX, startY, endX, endY);
if (hamiltonianPath == null) {
messageQueue.add("§eDungeons Guide §7:: §eIcePath §7:: §cCouldn't find solution for floor "+s);
return;
}
hamiltonianPath.add(0,new Point(startX, startY));
List poses = new LinkedList();
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;
while (!messageQueue.isEmpty()){
Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(messageQueue.poll()));
}
}
@Override
public void drawWorld(float partialTicks) {
if (!FeatureRegistry.SOLVER_ICEPATH.isEnabled()) return;
for (List solution:this.solution)
RenderUtils.drawLines(solution, FeatureRegistry.SOLVER_ICEPATH.getLineColor(),FeatureRegistry.SOLVER_ICEPATH.getLineWidth(), partialTicks, true);
}
public static class Generator implements RoomProcessorGenerator {
@Override
public RoomProcessorIcePath2 createNew(DungeonRoom dungeonRoom) {
RoomProcessorIcePath2 defaultRoomProcessor = new RoomProcessorIcePath2(dungeonRoom);
return defaultRoomProcessor;
}
}
private static List 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 directions = Arrays.asList(new Point(0,-1), new Point(-1,0), new Point(1,0), new Point(0,1));
private static LinkedList 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 path = new LinkedList();
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 potentialRoute = findHamiltonianPath(copiedMap, x,y,endX,endY, depth +1, reqDepth);
if (potentialRoute != null) {
potentialRoute.addFirst(new Point(x,y));
return potentialRoute;
}
}
return null;
}
}