diff options
| author | syeyoung <42869671+cyoung06@users.noreply.github.com> | 2023-10-29 01:19:24 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-10-29 01:19:24 +0900 |
| commit | 9e3e93a3337989d7f669678a495866b38fdf3f89 (patch) | |
| tree | 2194ffde48827fc9ab38659a0d566c2c796dd3c6 | |
| parent | ee521c8a3811d46a816cada7256bb006738b1a21 (diff) | |
| download | Skyblock-Dungeons-Guide-9e3e93a3337989d7f669678a495866b38fdf3f89.tar.gz Skyblock-Dungeons-Guide-9e3e93a3337989d7f669678a495866b38fdf3f89.tar.bz2 Skyblock-Dungeons-Guide-9e3e93a3337989d7f669678a495866b38fdf3f89.zip | |
Waterboard simulation fix and one-flow support (#433)
* - New waterboard simulator
Signed-off-by: syeyoung <cyoung06@naver.com>
* - New waterboard simulator
Signed-off-by: syeyoung <cyoung06@naver.com>
* - Hyper accurate waterboard prediction
Signed-off-by: syeyoung <cyoung06@naver.com>
* - Better waterboard solver, with 1 flow support and timings
Signed-off-by: syeyoung <cyoung06@naver.com>
* - a bit mroe strict stableness detection
Signed-off-by: syeyoung <cyoung06@naver.com>
---------
Signed-off-by: syeyoung <cyoung06@naver.com>
14 files changed, 645 insertions, 972 deletions
diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverState.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverState.java deleted file mode 100755 index e86fdd5c..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverState.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a 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/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverStateContradict.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverStateContradict.java deleted file mode 100755 index a574d6bf..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/LeverStateContradict.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a 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/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java index 98ac9cc9..fccfcaa1 100755 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/RoomProcessorWaterPuzzle.java @@ -25,21 +25,43 @@ 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.block.Block; +import net.minecraft.block.BlockLever; +import net.minecraft.block.BlockLiquid; +import net.minecraft.init.Blocks; import net.minecraft.util.BlockPos; +import net.minecraft.util.EnumFacing; +import net.minecraft.world.World; import java.awt.*; +import java.util.*; import java.util.List; +import java.util.stream.Collectors; 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; + + + + private Simulator.Node nodes[][]; + private Simulator.Pt waterNodeStart; + private Map<String, Simulator.Pt> waterNodeEnds = new HashMap<>(); + private Map<String, List<Simulator.Pt>> switchFlips = new HashMap<>(); + private Map<String, BlockPos> switchLoc = new HashMap<>(); + private List<String> targetDoors = new ArrayList<>(); + + private Map<Simulator.Pt, BlockPos> ptMapping = new HashMap<>(); + + private Thread t; + private List<WaterPathfinder.NodeNode> solutionList = new ArrayList<>(); + private long lastStable; + private long lastUnstable; public RoomProcessorWaterPuzzle(DungeonRoom dungeonRoom) { super(dungeonRoom); @@ -47,28 +69,162 @@ public class RoomProcessorWaterPuzzle extends GeneralRoomProcessor { 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"); + OffsetPoint 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(); + buildLeverStates(); + buildNodes(true); + targetDoors(); + + } + + + + } + + + private void buildLeverStates(){ + for (OffsetPoint offsetPoint : levers.getOffsetPointList()) { + if (offsetPoint.getBlock(getDungeonRoom()) == Blocks.lever){ + BlockPos pos = offsetPoint.getBlockPos(getDungeonRoom()); + World w= 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); + + switchFlips.put(id+":"+data, new ArrayList<>()); + switchLoc.put(id+":"+data, pos); } } + switchLoc.put("mainStream", ((OffsetPoint) getDungeonRoom().getDungeonRoomInfo().getProperties().get("water-lever")).getBlockPos(getDungeonRoom())); + switchFlips.put("mainStream", new ArrayList<>()); } + private void buildNodes(boolean switchfips) { + List<OffsetPoint> frontPoints = frontBoard.getOffsetPointList(); + List<OffsetPoint> backPoints = backBoard.getOffsetPointList(); + + nodes = new Simulator.Node[25][19]; + waterNodeStart = new Simulator.Pt(9, 0); + 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); + + ptMapping.put(new Simulator.Pt(x,y), front.getBlockPos(getDungeonRoom())); + int frontId = Block.getIdFromBlock(front.getBlock(getDungeonRoom())); + int backId = Block.getIdFromBlock(back.getBlock(getDungeonRoom())); + int frontData = front.getData(getDungeonRoom()); + int backData = back.getData(getDungeonRoom()); + + if (switchfips) { + String switchD; + + if (switchFlips.containsKey(switchD = (backId + ":" + backData)) || switchFlips.containsKey(switchD = (frontId + ":" + frontData))) { + switchFlips.get(switchD).add(new Simulator.Pt(x, y)); + } + } + + if (frontId == 0 || frontId == 8 /*flowing*/|| 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(getDungeonRoom())); + int data= pos.getData(getDungeonRoom()); + waterNodeEnds.put(id+":"+data, new Simulator.Pt(x,y)); + } + + nodes[y][x] = new Simulator.Node(frontId != 0 ? frontData >= 8 ? 8 : 8-frontData : 0, + frontId == 0 ? Simulator.NodeType.AIR : + y == 0 ? Simulator.NodeType.SOURCE : + Simulator.NodeType.WATER, false); + } else { + nodes[y][x] = new Simulator.Node(0, Simulator.NodeType.BLOCK, false); + } + } + } + if (switchfips) { + switchFlips.get("mainStream").add(waterNodeStart); + } + } + private void targetDoors() { + targetDoors.clear(); + for (OffsetPoint offsetPoint : doorsClosed.getOffsetPointList()) { + if (offsetPoint.getBlock(getDungeonRoom()) != Blocks.air) { + targetDoors.add(Block.getIdFromBlock(offsetPoint.getBlock(getDungeonRoom()))+":"+offsetPoint.getData(getDungeonRoom())); + } + } + } + + Simulator.Node[][] lastCopy = null; + + private int idx = 0; @Override public void tick() { super.tick(); if (!FeatureRegistry.SOLVER_WATERPUZZLE.isEnabled()) return; if (!argumentsFulfilled) return; try { - waterBoard.tick(); + buildNodes(false); + targetDoors(); + + Simulator.Node[][] copy = Simulator.clone(nodes); + boolean changed = !Arrays.deepEquals(lastCopy, copy); + lastCopy = copy; + if (!changed) { + if ((System.currentTimeMillis() - lastUnstable) > 1000) + lastStable = System.currentTimeMillis(); + } else { + lastUnstable = System.currentTimeMillis(); + } + Simulator.simulateTicks(nodes); + if ((System.currentTimeMillis() - lastUnstable) > 1000) { + if (t == null || !t.isAlive()) { + t = new Thread(() -> { + try { + List<Simulator.Pt> targets = targetDoors.stream().map(waterNodeEnds::get).collect(Collectors.toList()); + List<Simulator.Pt> nonTargets = waterNodeEnds.values().stream().filter(a -> !targets.contains(a)).collect(Collectors.toList()); + + WaterPathfinder waterPathfinder = new WaterPathfinder(copy, targets, nonTargets, switchFlips); + WaterPathfinder.NodeNode nodeNode = waterPathfinder.pathfind(); + LinkedList<WaterPathfinder.NodeNode> solution = new LinkedList<>(); + if (nodeNode.getParentToMeAction() != null) + solution.addFirst(nodeNode); + while (nodeNode.getParent() != null) { + nodeNode = nodeNode.getParent(); + if (nodeNode.getParentToMeAction() != null) + solution.addFirst(nodeNode); + } + this.solutionList = solution; + idx = 0; + lastStable = System.currentTimeMillis(); + } catch (Exception e) { + lastCopy = null; + } + }); + t.start(); + } + } + + + + if (solutionList != null && solutionList.size() > 0) { + while (System.currentTimeMillis() - lastStable > (long) (idx) * 2500 + 250) { // water flows 5 ticks/s + idx ++; + } + } } catch (Exception e) { e.printStackTrace(); } @@ -84,33 +240,30 @@ public class RoomProcessorWaterPuzzle extends GeneralRoomProcessor { 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 (int y = 0; y < nodes.length; y++) { + for (int x = 0; x < nodes[y].length; x++) { + Simulator.Node n = nodes[y][x]; + if (n.getNodeType().isWater()) { + RenderUtils.highlightBlock(ptMapping.get(new Simulator.Pt(x,y)), new Color(0, 255, 0, 50), partialTicks, true); } } - 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); + + if (solutionList.size() > 0) { + for (int i = idx; i < solutionList.size(); i++) { + + String key = solutionList.get(i).getParentToMeAction().getKey(); + if (!key.equals("nothing")) { + BlockPos pos = switchLoc.get(key); + // target: + long target = lastStable + 2500L * i; + + double time = (target-System.currentTimeMillis()) / 1000.0 + 0.051; + RenderUtils.drawTextAtWorld(String.format("%.1f", time)+"s", pos.getX()+0.5f, pos.getY()+(i-idx)*0.5f - 0.5f, pos.getZ()+0.5f, + time < 0.5 ? 0xFF00FF00 : 0xFFFF5500, 0.05f, false, false, partialTicks); + } } - RenderUtils.highlightBlock(waterBoard.getToggleableMap().get("mainStream").getBlockPos(), new Color(0,255,0,255), partialTicks, true); + } } diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Route.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Route.java deleted file mode 100755 index a9f73ae2..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Route.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a 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/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Simulator.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Simulator.java new file mode 100644 index 00000000..085abf1c --- /dev/null +++ b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/Simulator.java @@ -0,0 +1,257 @@ +/* + * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod + * Copyright (C) 2023 cyoung06 (syeyoung) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published + * by the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a 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; +import lombok.Getter; + +import java.util.List; +import java.util.Scanner; + +public class Simulator { + + @AllArgsConstructor @Getter + public enum NodeType { + BLOCK(false), AIR(false), WATER(true), SOURCE(true); + + private boolean water; + } + + @Data @AllArgsConstructor + public static class Node { + private int waterLevel; + private NodeType nodeType; + private boolean update; + } + @Getter @AllArgsConstructor @Data + public static class Pt { + private final int x, y; + + public Pt up() {return new Pt(x, y-1);} + public Pt down() {return new Pt(x, y+1);} + public Pt left() {return new Pt(x-1, y);} + public Pt right() {return new Pt(x+1, y);} + + public boolean check(int w, int h) { + return x < 0 || y < 0 || x >= w || y >= h; + } + + public Node get(Node[][] nodes) { + if (check(nodes[0].length, nodes.length)) { + return new Node(0, NodeType.BLOCK, false); + } + return nodes[y][x]; + } + + public void set(Node[][] nodes, NodeType nodeType) { + get(nodes).nodeType = nodeType; + get(nodes).waterLevel = 0; + get(nodes).update = true; + } + + public int getFlowDirection(Node[][] nodes) { + int right = 0; + Pt rightPt = this.right(); + while (true) { + right++; + if (right == 8) { + right = 999; break; + } + if (rightPt.get(nodes).nodeType == NodeType.BLOCK) { + right = 999; break; + } + if (rightPt.down().get(nodes).nodeType != NodeType.BLOCK) { + break; + } + + rightPt = rightPt.right(); + } + int left = 0; + + Pt leftPt = this.left(); + while (true) { + left++; + if (left == 8) { + left = 999; break; + } + if (leftPt.get(nodes).nodeType == NodeType.BLOCK) { + left = 999; break; + } + if (leftPt.down().get(nodes).nodeType != NodeType.BLOCK) { + break; + } + + leftPt = leftPt.left(); + } + + if (left == right) return 0; + if (left > right) return 1; + return -1; + } + + public boolean shouldUpdate(Node[][] nodes) { + return get(nodes).update || right().get(nodes).update + || left().get(nodes).update + || up().get(nodes).update + || down().get(nodes).update; + } + } + // if there is waterLevel bigger coming nearby, make water + // if there is waterLevel bigger coming nearby, delete water + // + public static void simulateTicks(Node[][] nodes) { + while(simulateSingleTick(nodes)); + } + + public static Node[][] clone(Node[][] nodes) { + Node[][] newNodes = new Node[nodes.length][nodes[0].length]; + + for (int y = 0; y < nodes.length; y++) { + for (int x = 0; x < nodes[y].length; x++) { + newNodes[y][x] = new Node(nodes[y][x].waterLevel, nodes[y][x].nodeType, nodes[y][x].update); + } + } + return newNodes; + } + + public static boolean doTick(Node[][] nodes, Node[][] nodesNew, Pt pt) { + int y = pt.y, x = pt.x; + Node prev = pt.get(nodes); + int maxWaterLv = Math.max(0, prev.nodeType == NodeType.SOURCE ? 8 : prev.waterLevel - 1); + if (prev.nodeType == NodeType.AIR || prev.nodeType == NodeType.WATER) { + if (pt.up().get(nodes).nodeType.isWater()) { + maxWaterLv = 8; + } + if (pt.left().get(nodes).nodeType.isWater()) { + boolean isSource = pt.left().get(nodes).nodeType == NodeType.SOURCE; + NodeType bottomLeft = pt.left().down().get(nodes).nodeType; + if (prev.nodeType == NodeType.WATER // if was water + || (pt.left().shouldUpdate(nodes) && (bottomLeft == NodeType.BLOCK || (isSource && bottomLeft != NodeType.AIR)) && pt.left().getFlowDirection(nodes) >= 0)) { + maxWaterLv = Math.max(maxWaterLv, pt.left().get(nodes).waterLevel - 1); + } + } + if (pt.right().get(nodes).nodeType.isWater()) { + boolean isSource = pt.right().get(nodes).nodeType == NodeType.SOURCE; + NodeType bottomRight = pt.right().down().get(nodes).nodeType; + if (prev.nodeType == NodeType.WATER + || (pt.right().shouldUpdate(nodes) && (bottomRight == NodeType.BLOCK || (isSource && bottomRight != NodeType.AIR)) && pt.right().getFlowDirection(nodes) <= 0)) + maxWaterLv = Math.max(maxWaterLv, pt.right().get(nodes).waterLevel - 1); + } + } + + nodesNew[y][x] = new Node(prev.waterLevel, prev.nodeType, false); + nodesNew[y][x].setWaterLevel(maxWaterLv); + if (maxWaterLv == 0 && nodesNew[y][x].nodeType == NodeType.WATER) + nodesNew[y][x].setNodeType(NodeType.AIR); + else if (maxWaterLv > 0 && nodesNew[y][x].nodeType == NodeType.AIR) + nodesNew[y][x].setNodeType(NodeType.WATER); + + if (prev.nodeType != nodesNew[y][x].nodeType || prev.waterLevel != nodesNew[y][x].waterLevel) { + nodesNew[y][x].update = true; + } + return nodesNew[y][x].update; + } + public static boolean simulateSingleTick(Node[][] nodes) { + Node[][] nodesNew = new Node[nodes.length][nodes[0].length]; + boolean update = false; + for (int y = 0; y < nodes.length; y++) { + for (int x = 0; x < nodes[y].length; x++) { + Pt pt = new Pt(x,y); + + + if (doTick(nodes, nodesNew, pt)) update =true; + + if ( pt.get(nodesNew).waterLevel - pt.get(nodes).waterLevel > 0 && pt.get(nodes).nodeType == NodeType.WATER && pt.get(nodesNew).nodeType == NodeType.WATER) { + Node prev = pt.get(nodes); + + nodes[y][x] = nodesNew[y][x]; + + if (!pt.left().check(nodes[0].length, nodes.length)) + doTick(nodes, nodesNew, pt.left()); + if (!pt.right().check(nodes[0].length, nodes.length)) + doTick(nodes, nodesNew, pt.right()); + + nodes[y][x] = prev; + } + } + } + + for (int y = 0; y < nodesNew.length; y++) { + for (int x = 0; x < nodesNew[y].length; x++) { + nodes[y][x] = nodesNew[y][x]; + } + } + return update; + } + + public static void print(Node[][] nodes) { + for (int y = 0; y < nodes.length; y++) { + for (int x = 0; x < nodes[y].length; x++) { + NodeType type = nodes[y][x].nodeType; + int cnt = nodes[y][x].waterLevel; + if (type == NodeType.BLOCK) { + System.out.print("X"); + } else if (type == NodeType.AIR) { + System.out.print(" "); + } else if (type == NodeType.WATER) { + System.out.print(cnt); + } else { + System.out.print("W"); + } + } + System.out.println(); + } + System.out.println("-----------------"); + } + + // New waterboard simulator pog + public static void main(String[] args) { + NodeType[][] nodeTypes = { + {NodeType.BLOCK, NodeType.BLOCK, NodeType.BLOCK, NodeType.BLOCK, NodeType.BLOCK, NodeType.BLOCK, NodeType.AIR, NodeType.SOURCE, NodeType.BLOCK}, + {NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR , NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR }, + {NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR , NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR }, + {NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR , NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR }, + {NodeType.BLOCK, NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR , NodeType.AIR, NodeType.AIR, NodeType.AIR, NodeType.AIR } + }; + + Node[][] nodes = new Node[nodeTypes.length][nodeTypes[0].length]; + for (int y = 0; y < nodes.length; y++) { + for (int x = 0; x < nodes[y].length; x++) { + nodes[y][x] = new Node(0, nodeTypes[y][x], false); + if (nodeTypes[y][x] == NodeType.SOURCE) { + nodes[y][x].update = true; + nodes[y][x].waterLevel = 8; + } + } + } + Scanner scanner = new Scanner(System.in); + while(true) { + print(nodes); + while(simulateSingleTick(nodes)) + print(nodes); + + int x = scanner.nextInt(); + int y= scanner.nextInt(); + nodes[y][x] = new Node(0, + nodes[y][x].nodeType == NodeType.BLOCK ? + NodeType.AIR : NodeType.BLOCK, true); + } + } +} diff --git a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/SwitchData.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/SwitchData.java deleted file mode 100755 index 881716d8..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/SwitchData.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a 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/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterBoard.java b/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterBoard.java deleted file mode 100755 index eece3057..00000000 --- a/mod/src/main/java/kr/syeyoung/dungeonsguide/mod/dungeon/roomprocessor/waterpuzzle/WaterBoard.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Dungeons Guide - The most intelligent Hypixel Skyblock Dungeons Mod - * Copyright (C) 2021 cyoung06 - * - * This program is free software: you can |
