aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java3
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java3
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DoorFinderRegistry.java2
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java8
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/DefaultRoomProcessor.java29
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java39
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java4
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java1
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java16
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java96
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/Route.java25
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java25
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java263
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterCondition.java15
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterConditionContradict.java7
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java18
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java37
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java38
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java39
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java42
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java39
21 files changed, 711 insertions, 38 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java
index ecb3b268..b6497872 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPoint.java
@@ -8,10 +8,11 @@ import net.minecraft.block.Block;
import net.minecraft.util.BlockPos;
import javax.vecmath.Vector2d;
+import java.io.Serializable;
@Data
@AllArgsConstructor
-public class OffsetPoint implements Cloneable {
+public class OffsetPoint implements Cloneable, Serializable {
private int x;
private int y;
private int z;
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java
index c33f7af8..9aea7610 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/OffsetPointSet.java
@@ -2,11 +2,12 @@ package kr.syeyoung.dungeonsguide.dungeon.data;
import lombok.Data;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
@Data
-public class OffsetPointSet implements Cloneable{
+public class OffsetPointSet implements Cloneable, Serializable {
private List<OffsetPoint> offsetPointList = new ArrayList<OffsetPoint>();
@Override
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DoorFinderRegistry.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DoorFinderRegistry.java
index 306b1993..0fb3c89a 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DoorFinderRegistry.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/doorfinder/DoorFinderRegistry.java
@@ -8,7 +8,7 @@ public class DoorFinderRegistry {
private static final Map<Pattern, StartDoorFinder> doorFinders = new HashMap<Pattern, StartDoorFinder>();
static {
- doorFinders.put(Pattern.compile("The Catacombs F[0-9]"), new CatacombDoorFinder());
+ doorFinders.put(Pattern.compile("The Catacombs (?:F[0-9]|E)"), new CatacombDoorFinder());
}
public static StartDoorFinder getDoorFinder(String dungeonName) {
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java b/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java
index 38d57eef..be517e81 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomedit/panes/RoomDataDisplayPane.java
@@ -76,6 +76,14 @@ public class RoomDataDisplayPane extends MPanel {
this.setBounds(new Rectangle(5,5,parentWidth-10,parentHeight-10));
}
+ @Override
+ public void keyTyped(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
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/DefaultRoomProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/DefaultRoomProcessor.java
deleted file mode 100644
index 596ebb74..00000000
--- a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/DefaultRoomProcessor.java
+++ /dev/null
@@ -1,29 +0,0 @@
-package kr.syeyoung.dungeonsguide.roomprocessor;
-
-import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
-
-public class DefaultRoomProcessor implements RoomProcessor {
-
- public DefaultRoomProcessor(DungeonRoom dungeonRoom) {
-
- }
-
- @Override
- public void tick() {
-
- }
-
- @Override
- public void drawScreen(float partialTicks) {
-
- }
-
- public static class Generator implements RoomProcessorGenerator<DefaultRoomProcessor> {
- @Override
- public DefaultRoomProcessor createNew(DungeonRoom dungeonRoom) {
-
- DefaultRoomProcessor defaultRoomProcessor = new DefaultRoomProcessor(dungeonRoom);
- return defaultRoomProcessor;
- }
- }
-}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java
new file mode 100644
index 00000000..f9472791
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/GeneralRoomProcessor.java
@@ -0,0 +1,39 @@
+package kr.syeyoung.dungeonsguide.roomprocessor;
+
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.RoomProcessorWaterPuzzle;
+import lombok.Getter;
+import lombok.Setter;
+
+public class GeneralRoomProcessor implements RoomProcessor {
+
+ @Getter
+ @Setter
+ private DungeonRoom dungeonRoom;
+ public GeneralRoomProcessor(DungeonRoom dungeonRoom) {
+ this.dungeonRoom = dungeonRoom;
+ }
+
+ @Override
+ public void tick() {
+
+ }
+
+ @Override
+ public void drawScreen(float partialTicks) {
+
+ }
+
+ @Override
+ public void drawWorld(float partialTicks) {
+
+ }
+
+ 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/roomprocessor/ProcessorFactory.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java
index 3f65c642..23976fbd 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/ProcessorFactory.java
@@ -1,6 +1,7 @@
package kr.syeyoung.dungeonsguide.roomprocessor;
import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.RoomProcessorWaterPuzzle;
import java.util.HashMap;
import java.util.Map;
@@ -22,7 +23,8 @@ public class ProcessorFactory {
}
static {
- registerRoomProcessor("default", new DefaultRoomProcessor.Generator());
+ registerRoomProcessor("default", new GeneralRoomProcessor.Generator());
registerRoomProcessor("puzzle_blaze_solver", new RoomProcessorBlazeSolver.Generator());
+ registerRoomProcessor("puzzle_water_solver", new RoomProcessorWaterPuzzle.Generator());
}
}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java
index ed8a89f7..4498811a 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessor.java
@@ -5,4 +5,5 @@ import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
public interface RoomProcessor {
void tick();
void drawScreen(float partialTicks);
+ void drawWorld(float partialTicks);
} \ No newline at end of file
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java
index ec1ed164..54f09010 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/RoomProcessorBlazeSolver.java
@@ -15,20 +15,20 @@ import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
+import java.awt.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
-public class RoomProcessorBlazeSolver implements RoomProcessor {
+public class RoomProcessorBlazeSolver extends GeneralRoomProcessor {
- private DungeonRoom dungeonRoom;
private boolean highToLow = false;
private List<EntityArmorStand> entityList = new ArrayList<EntityArmorStand>();
private EntityArmorStand next;
public RoomProcessorBlazeSolver(DungeonRoom dungeonRoom) {
- this.dungeonRoom = dungeonRoom;
+ super(dungeonRoom);
Object highToLow = dungeonRoom.getDungeonRoomInfo().getProperties().get("order");
if (highToLow == null) this.highToLow = false;
else this.highToLow = (Boolean) highToLow;
@@ -36,6 +36,9 @@ public class RoomProcessorBlazeSolver implements RoomProcessor {
@Override
public void tick() {
+ super.tick();
+
+ DungeonRoom dungeonRoom = getDungeonRoom();
World w = dungeonRoom.getContext().getWorld();
final BlockPos low = dungeonRoom.getMin();
final BlockPos high = dungeonRoom.getMax();
@@ -53,7 +56,7 @@ public class RoomProcessorBlazeSolver implements RoomProcessor {
for (EntityArmorStand ea : entityList) {
String name = ea.getName();
String colorGone = TextUtils.stripColor(name);
- String health2 = colorGone.split("/")[1];
+ String health2 = TextUtils.keepIntegerCharactersOnly(colorGone.split("/")[1]);
try {
int heal = Integer.parseInt(health2);
if (highToLow && heal > health) {
@@ -70,11 +73,14 @@ public class RoomProcessorBlazeSolver implements RoomProcessor {
next = semi_target;
}
+
@Override
- public void drawScreen(float partialTicks) {
+ public void drawWorld(float partialTicks) {
+ super.drawWorld(partialTicks);
if (next == null) return;
Vec3 pos = next.getPositionEyes(partialTicks);
RenderUtils.drawTextAtWorld("NEXT", (float)pos.xCoord, (float)pos.yCoord, (float)pos.zCoord, 0xFFFF0000, 3, true, false, partialTicks);
+ RenderUtils.highlightBlock(next.getPosition(), new Color(0,255,0,50), partialTicks);
}
public static class Generator implements RoomProcessorGenerator<RoomProcessorBlazeSolver> {
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java
new file mode 100644
index 00000000..5cb5502a
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java
@@ -0,0 +1,96 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import kr.syeyoung.dungeonsguide.roomprocessor.GeneralRoomProcessor;
+import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessor;
+import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorBlazeSolver;
+import kr.syeyoung.dungeonsguide.roomprocessor.RoomProcessorGenerator;
+import kr.syeyoung.dungeonsguide.utils.RenderUtils;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.FontRenderer;
+import net.minecraft.util.BlockPos;
+
+import java.awt.*;
+
+public class RoomProcessorWaterPuzzle extends GeneralRoomProcessor {
+
+ private boolean argumentsFulfilled = false;
+
+ private WaterBoard waterBoard;
+ private OffsetPointSet doorsClosed;
+ private OffsetPointSet levers;
+ private OffsetPointSet frontBoard;
+ private OffsetPointSet backBoard;
+ private 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 (!argumentsFulfilled) return;
+ try {
+ waterBoard.tick();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public void drawScreen(float partialTicks) {
+ super.drawScreen(partialTicks);
+ if (!argumentsFulfilled) return;
+ FontRenderer fr = Minecraft.getMinecraft().fontRendererObj;
+ fr.drawString("To Open: "+waterBoard.getReqOpen(),0,200, 0xFFFFFF);
+ fr.drawString("Target: "+waterBoard.getTarget2(),0,200, 0xFFFFFF);
+ }
+
+ @Override
+ public void drawWorld(float partialTicks) {
+ super.drawWorld(partialTicks);
+ if (!argumentsFulfilled) return;
+ BlockPos target = waterBoard.getTarget();
+ if (target != null) {
+ RenderUtils.highlightBlock(target, new Color(0,255,255,255), partialTicks);
+ }
+ Route route = waterBoard.getCurrentRoute();
+ if (route != null) {
+ for (WaterCondition condition : route.getConditionList()) {
+ SwitchData switchData = waterBoard.getValidSwitches().get(condition.getBlockId());
+ if (switchData.getCurrentState() != condition.isRequiredState()) {
+ RenderUtils.highlightBlock(switchData.getSwitchLoc(), new Color(0,255,0,50), partialTicks);
+ RenderUtils.drawTextAtWorld(condition.isRequiredState() ? "on":"off",switchData.getSwitchLoc().getX(), switchData.getSwitchLoc().getY(), switchData.getSwitchLoc().getZ(), 0xFF000000,1.0f, false, false, partialTicks);
+ }
+ }
+ }
+ }
+
+ 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/roomprocessor/waterpuzzle/Route.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/Route.java
new file mode 100644
index 00000000..cdff0477
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/Route.java
@@ -0,0 +1,25 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+import lombok.Data;
+
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+@Data
+public class Route implements Cloneable {
+ private Set<WaterNode> nodes = new LinkedHashSet<WaterNode>();
+ private Set<WaterCondition> conditionList = new HashSet<WaterCondition>();
+ private int x, y;
+
+
+ @Override
+ protected Route clone() {
+ Route r = new Route();
+ r.getNodes().addAll(nodes);
+ r.getConditionList().addAll(conditionList);
+ r.x = x;
+ r.y = y;
+ return r;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java
new file mode 100644
index 00000000..79d0060b
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/SwitchData.java
@@ -0,0 +1,25 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+import kr.syeyoung.dungeonsguide.DungeonsGuide;
+import kr.syeyoung.dungeonsguide.SkyblockStatus;
+import kr.syeyoung.dungeonsguide.dungeon.roomfinder.DungeonRoom;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import net.minecraft.block.BlockLever;
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+
+@Data
+@AllArgsConstructor
+public class SwitchData {
+ private BlockPos switchLoc;
+ private BlockPos blockLoc;
+
+ private String blockId;
+
+ public boolean getCurrentState() {
+ BlockPos switch2 = getSwitchLoc();
+ World w= DungeonsGuide.getDungeonsGuide().getSkyblockStatus().getContext().getWorld();
+ return w.getBlockState(switch2).getValue(BlockLever.POWERED);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java
new file mode 100644
index 00000000..f0f30f0a
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterBoard.java
@@ -0,0 +1,263 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+import com.google.common.collect.Sets;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPoint;
+import kr.syeyoung.dungeonsguide.dungeon.data.OffsetPointSet;
+import kr.syeyoung.dungeonsguide.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.world.World;
+
+import javax.vecmath.Vector2d;
+import java.awt.*;
+import java.util.*;
+import java.util.List;
+
+public class WaterBoard {
+ WaterNode[][] board;
+ RoomProcessorWaterPuzzle waterPuzzle;
+
+ private OffsetPointSet frontPlate;
+ private OffsetPointSet backPlate;
+ private OffsetPointSet levers;
+ private OffsetPointSet doors;
+ private OffsetPoint lever;
+
+ @Getter
+ private List<SwitchData> switchData = new ArrayList<SwitchData>();
+ @Getter
+ private Map<String, SwitchData> validSwitches = new HashMap<String, SwitchData>();
+
+ private WaterNodeStart waterNodeStart;
+ private Map<String, WaterNodeEnd> waterNodeEndMap = new HashMap<String, WaterNodeEnd>();
+
+ @Getter
+ private Set<String> reqOpen = new HashSet<String>();
+
+ @Getter
+ private Route currentRoute;
+ @Getter
+ private BlockPos target;
+ @Getter
+ private 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());
+
+ int id = Block.getIdFromBlock(w.getChunkFromBlockCoords(newPos).getBlock(newPos));
+ int data = w.getChunkFromBlockCoords(newPos).getBlockMetadata(newPos);
+
+ SwitchData sw;
+ switchData.add(sw = new SwitchData(pos,newPos,id+":"+data));
+ validSwitches.put(id+":"+data, sw);
+ }
+ }
+ SwitchData sw;
+ switchData.add(sw = new SwitchData(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) {
+ WaterNodeEnd end = waterNodeEndMap.get(doorsToOpen.iterator().next());
+ target = end.getBlockPos();
+ target2 = end.getResultId();
+ currentRoute = pathFind(end);
+ }
+ }
+ }
+
+ private final Set<Point> possibleDir = Sets.newHashSet(new Point(0,-1), new Point(1,0), new Point(-1, 0));
+ public Route pathFind(WaterNodeEnd endNode) {
+ Route start = new Route();
+ start.setX(endNode.getX());
+ start.setY(endNode.getY());
+ start.getNodes().add(endNode);
+ Queue<Route> routes = new LinkedList<Route>();
+ routes.add(start);
+ List<Route> reachedStart = new ArrayList<Route>();
+ while (!routes.isEmpty()) {
+ Route r2 = routes.poll();
+ int x = r2.getX();
+ int y = r2.getY();
+ int size = 0;
+ for (Point vec:possibleDir) {
+ WaterNode node = getNodeAt(x + vec.x, y + vec.y);
+ if (node == null) continue;
+ if (r2.getNodes().contains(node)) continue;;
+ if (!node.canWaterGoThrough()) continue;
+ size ++;
+ Route r = r2.clone();
+ r.getNodes().add(node);
+ r.getConditionList().add(node.getCondition());
+ r.setX(node.getX());
+ r.setY(node.getY());
+
+ WaterNode void2 = getNodeAt(r.getX(), r.getY() + 1);
+ if ((void2 == null || void2.getCondition() == null) && !r.getNodes().contains(void2)) {
+ continue;
+ }
+
+ if (checkContradiction(r.getConditionList())) {
+ continue;
+ }
+
+ if (node instanceof WaterNodeStart) {
+ reachedStart.add(r);
+ } else {
+ routes.add(r);
+ }
+ }
+ }
+ Iterator<Route> routeIter = reachedStart.iterator();
+ while (routeIter.hasNext()) {
+ Route route = routeIter.next();
+
+ addRouteConditions(route);
+ if (checkContradiction(route.getConditionList()))
+ routeIter.remove();
+ }
+
+ return reachedStart.get(0);
+ }
+
+ public void addRouteConditions(Route r) {
+ int prevY = 0;
+ int startX = -1;
+ for (WaterNode node : r.getNodes()) {
+ int currY = node.getY();
+ if (currY != prevY) {
+ if (startX != -1) {
+ int offset = node.getX() - startX;
+ if (offset != 0) {
+ int start = startX + (offset > 0 ? 1 : -1);
+ int end = node.getX() + offset;
+ int y = node.getY() + 2;
+ int y2 = node.getY() + 1;
+
+ for (int x = start; (start < end) ? (x <= end) : (x >= end); x += (start < end) ?1:-1){
+ WaterNode node2 = getNodeAt(x, y2);
+ if (node2 == null || !node2.canWaterGoThrough()) break;
+ node2 = getNodeAt(x, y);
+ if (node2 == null || node2.getCondition() == null) {
+ r.getConditionList().add(new WaterConditionContradict());
+ return;
+ } else {
+ r.getConditionList().add(node2.getCondition().invert());
+ }
+ }
+ }
+ }
+ startX = node.getX();
+ }
+ }
+ }
+
+ 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[19][25];
+ 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) && frontId == 0) {
+ String resId = backId + ":"+backData;
+ node = new WaterNodeToggleable(resId, isSwitchActive(validSwitches.get(resId)), front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y);
+ } else if (validSwitches.containsKey(frontId +":"+frontData)) {
+ String resId = frontId +":"+frontData;
+ node = new WaterNodeToggleable(resId, !isSwitchActive(validSwitches.get(resId)), front.getBlockPos(waterPuzzle.getDungeonRoom()),x,y);
+ } else if (frontId == 0) {
+ 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 == 0) {
+ waterNodeStart = (WaterNodeStart) (node = new WaterNodeStart(front.getBlockPos(waterPuzzle.getDungeonRoom()),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;
+ }
+ }
+ }
+
+ // true if contradiction
+ private boolean checkContradiction(Set<WaterCondition> conditions) {
+ Map<String, Boolean> conditionMap = new HashMap<String, Boolean>();
+ for (WaterCondition condition : conditions) {
+ if (condition instanceof WaterConditionContradict) return true;
+ if (conditionMap.containsKey(condition.getBlockId())) {
+ if (conditionMap.get(condition.getBlockId()) != condition.isRequiredState())
+ return true;
+ } else {
+ conditionMap.put(condition.getBlockId(), condition.isRequiredState());
+ }
+ }
+ return false;
+ }
+
+ private boolean isSwitchActive(SwitchData switchData) {
+ BlockPos switch2 = switchData.getSwitchLoc();
+ World w= waterPuzzle.getDungeonRoom().getContext().getWorld();
+ boolean bool = w.getBlockState(switch2).getValue(BlockLever.POWERED);
+ return bool;
+ }
+
+
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterCondition.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterCondition.java
new file mode 100644
index 00000000..26678af3
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterCondition.java
@@ -0,0 +1,15 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+
+@Data
+@AllArgsConstructor
+public class WaterCondition {
+ private String blockId;
+ private boolean requiredState;
+
+ public WaterCondition invert() {
+ return new WaterCondition(blockId, !requiredState);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterConditionContradict.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterConditionContradict.java
new file mode 100644
index 00000000..64339655
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterConditionContradict.java
@@ -0,0 +1,7 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+public class WaterConditionContradict extends WaterCondition {
+ public WaterConditionContradict() {
+ super("contradict", true);
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java
new file mode 100644
index 00000000..efd872bc
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/WaterNode.java
@@ -0,0 +1,18 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle;
+
+import net.minecraft.util.BlockPos;
+import net.minecraft.world.World;
+
+public interface WaterNode {
+ boolean canWaterGoThrough();
+
+ // condition for water go
+ WaterCondition getCondition();
+
+ boolean isWaterFilled(World w);
+
+ BlockPos getBlockPos();
+
+ int getX();
+ int getY();
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java
new file mode 100644
index 00000000..d22fde2e
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeAir.java
@@ -0,0 +1,37 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes;
+
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterCondition;
+import kr.syeyoung.dungeonsguide.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 WaterCondition 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;
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java
new file mode 100644
index 00000000..1cc079e2
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeEnd.java
@@ -0,0 +1,38 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes;
+
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterCondition;
+import kr.syeyoung.dungeonsguide.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 WaterCondition 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;
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java
new file mode 100644
index 00000000..11661fcc
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeStart.java
@@ -0,0 +1,39 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes;
+
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterCondition;
+import kr.syeyoung.dungeonsguide.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 {
+
+ BlockPos blockPos;
+
+ @Override
+ public boolean canWaterGoThrough() {
+ return true;
+ }
+
+ @Override
+ public WaterCondition getCondition() {
+ return new WaterCondition("mainStream", true);
+ }
+
+ @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;
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java
new file mode 100644
index 00000000..cc714129
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeToggleable.java
@@ -0,0 +1,42 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes;
+
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterCondition;
+import kr.syeyoung.dungeonsguide.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 WaterCondition getCondition() {
+ return new WaterCondition(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 BlockPos getBlockPos() {
+ return blockPos;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java
new file mode 100644
index 00000000..18260adf
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/roomprocessor/waterpuzzle/nodes/WaterNodeWall.java
@@ -0,0 +1,39 @@
+package kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.nodes;
+
+import kr.syeyoung.dungeonsguide.roomprocessor.waterpuzzle.WaterCondition;
+import kr.syeyoung.dungeonsguide.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 WaterCondition 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;
+ }
+}