aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java5
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java7
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java69
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java85
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java22
-rw-r--r--src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java8
6 files changed, 186 insertions, 10 deletions
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java
index 61b65452..2a2e402c 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/MapProcessor.java
@@ -195,6 +195,7 @@ public class MapProcessor {
List<Point> ayConnected = new ArrayList<Point>();
int minX = Integer.MAX_VALUE, minY = Integer.MAX_VALUE;
+ int maxX = 0, maxY = 0;
while(toCheck.peek() != null) {
Point[] check = toCheck.poll();
if (checked.contains(check[1])) continue;
@@ -204,6 +205,8 @@ public class MapProcessor {
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});
@@ -220,7 +223,7 @@ public class MapProcessor {
Point pt2 = roomPointToMapPoint(ayConnected.get(0));
byte unit1 = MapUtils.getMapColorAt(mapData, pt2.x, pt2.y);
- return new DungeonRoom(ayConnected, shape, unit1, roomPointToWorldPoint(new Point(minX, minY)), context);
+ return new DungeonRoom(ayConnected, shape, unit1, roomPointToWorldPoint(new Point(minX, minY)), roomPointToWorldPoint(new Point(maxX+1, maxY+1)).add(-1, 0, -1), context);
}
private boolean checkIfConnected(byte[] mapData, Point unitPoint1, Point unitPoint2) {
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java
index c3d0a65d..2917bf90 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/data/DungeonRoomInfo.java
@@ -9,6 +9,13 @@ import java.util.UUID;
@Setter
public class DungeonRoomInfo {
+ public DungeonRoomInfo(short shape, byte color) {
+ this.uuid = UUID.randomUUID();
+ this.name = this.uuid.toString();
+ this.shape = shape;
+ this.color = color;
+ }
+
private transient boolean registered;
private short shape;
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java
index 91761c7c..cd174660 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/DungeonRoom.java
@@ -2,17 +2,17 @@ package kr.syeyoung.dungeonsguide.dungeon.roomfinder;
import com.google.common.collect.Sets;
import kr.syeyoung.dungeonsguide.dungeon.DungeonContext;
+import kr.syeyoung.dungeonsguide.dungeon.MapProcessor;
import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo;
import kr.syeyoung.dungeonsguide.dungeon.doorfinder.DungeonDoor;
import lombok.Getter;
+import net.minecraft.block.Block;
import net.minecraft.util.BlockPos;
import javax.vecmath.Vector2d;
import java.awt.*;
-import java.util.ArrayList;
-import java.util.HashSet;
+import java.util.*;
import java.util.List;
-import java.util.Set;
@Getter
public class DungeonRoom {
@@ -21,6 +21,8 @@ public class DungeonRoom {
private final byte color;
private final BlockPos min;
+ private final BlockPos max;
+ private final Point minRoomPt;
private final DungeonContext context;
@@ -28,14 +30,26 @@ public class DungeonRoom {
private DungeonRoomInfo dungeonRoomInfo;
- public DungeonRoom(List<Point> points, short shape, byte color, BlockPos min, DungeonContext context) {
+ private final int unitWidth; // X
+ private final int unitHeight; // Z
+
+ public DungeonRoom(List<Point> points, short shape, byte color, BlockPos min, BlockPos max, DungeonContext context) {
this.unitPoints = points;
this.shape = shape;
this.color = color;
this.min = min;
+ this.max = max;
this.context = context;
buildDoors();
buildRoom();
+
+ 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);
}
private static final Set<Vector2d> directions = Sets.newHashSet(new Vector2d(0,16), new Vector2d(0, -16), new Vector2d(16, 0), new Vector2d(-16 , 0));
@@ -66,4 +80,51 @@ public class DungeonRoom {
this.dungeonRoomInfo = dungeonRoomInfo;
}
+
+ 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 this.context.getWorld().getChunkFromBlockCoords(pos).getBlock(pos);
+ }
+ 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(),0,min.getZ());
+ return this.context.getWorld().getChunkFromBlockCoords(pos).getBlock(pos);
+ }
+ return null;
+ }
+
+ 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(),0,min.getZ());
+ return this.context.getWorld().getChunkFromBlockCoords(pos).getBlockMetadata(pos);
+ }
+ 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)) {
+ return this.context.getWorld().getChunkFromBlockCoords(pos).getBlockMetadata(pos);
+ }
+ 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 (shape >>((z/32) *4 +(x/32)) & 0x1) > 0;
+ }
}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java
index 197348bf..b31193c7 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/dungeon/roomfinder/RoomMatcher.java
@@ -1,18 +1,101 @@
package kr.syeyoung.dungeonsguide.dungeon.roomfinder;
import kr.syeyoung.dungeonsguide.dungeon.data.DungeonRoomInfo;
+import kr.syeyoung.dungeonsguide.utils.ArrayUtils;
+import kr.syeyoung.dungeonsguide.utils.ShortUtils;
+import lombok.Getter;
+import net.minecraft.block.Block;
+
+import java.util.List;
public class RoomMatcher {
private DungeonRoom dungeonRoom;
+
+ @Getter
+ private DungeonRoomInfo match;
+ @Getter
+ private int rotation;
+ private boolean triedMatch = false;
+
public RoomMatcher(DungeonRoom dungeonRoom) {
this.dungeonRoom = dungeonRoom;
}
public DungeonRoomInfo match() {
+ if (triedMatch) return match;
+ triedMatch = true;
+ 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) {
+ if (tryMatching(roomInfo, rotation)) {
+ match = roomInfo;
+ this.rotation = rotation;
+ return match;
+ }
+ }
+ }
return null;
}
+ private boolean tryMatching(DungeonRoomInfo dungeonRoomInfo, int rotation) {
+ if (dungeonRoomInfo.getColor() != dungeonRoom.getColor()) return false;
+
+ int[][] res = dungeonRoomInfo.getBlocks();
+ for (int i = 0; i < rotation; i++)
+ res = ArrayUtils.rotateCounterClockwise(res);
+
+ int y = dungeonRoom.getMin().getY();
+ for (int z = 0; z < res.length; z ++) {
+ for (int x = 0; x < res[0].length; x++) {
+ int data = res[y][x];
+ if (data == -1) continue;
+ Block b = dungeonRoom.getRelativeBlockAt(x,y,z);
+ if (b == null) return false;
+ if (Block.getIdFromBlock(b) != data) return false;
+ }
+ }
+ return true;
+ }
+
+ private static final int offset = 3;
public DungeonRoomInfo createNew() {
- return new DungeonRoomInfo();
+ 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 y = dungeonRoom.getMin().getY();
+ int widthX = maxX - minX;
+ int heightZ = maxZ - minZ;
+ int[][] data = new int[dungeonRoom.getMax().getX() - dungeonRoom.getMin().getX() + 1][dungeonRoom.getMax().getZ() - dungeonRoom.getMin().getZ() +1];
+
+ for (int z = 0; z < data.length; z++) {
+ for (int x = 0; x < data[0].length; x++) {
+ if (!(offset <= x && widthX - offset >= x && offset <= z && heightZ - offset >= z)) {
+ data[z][x] = -1;
+ continue;
+ }
+ if (!(dungeonRoom.canAccessRelative(x + offset, z + offset) && dungeonRoom.canAccessRelative(x - offset, z - offset))) {
+ data[z][x] = -1;
+ continue;
+ }
+
+ Block b = dungeonRoom.getRelativeBlockAt(x,y,z);
+ if (b == null) {
+ data[z][x] = -1;
+ } else {
+ data[z][x] = Block.getIdFromBlock(b);
+ }
+ }
+ }
+
+ roomInfo.setBlocks(data);
+ return roomInfo;
}
}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java b/src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java
new file mode 100644
index 00000000..7b9e8b59
--- /dev/null
+++ b/src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java
@@ -0,0 +1,22 @@
+package kr.syeyoung.dungeonsguide.utils;
+
+public class ArrayUtils {
+ public static int[][] rotateCounterClockwise(int[][] arr) {
+ int[][] res = new int[arr[0].length][arr.length];
+ for(int y=0; y<arr.length; y++) {
+ for (int x = 0; x< arr[0].length; x++) {
+ res[res.length - x - 1][y] = arr[y][x];
+ }
+ }
+ return res;
+ }
+ public static int[][] rotateClockwise(int[][] arr) {
+ int[][] res = new int[arr[0].length][arr.length];
+ for(int y=0; y<arr.length; y++) {
+ for (int x = 0; x< arr[0].length; x++) {
+ res[x][res[0].length - y - 1] = arr[y][x];
+ }
+ }
+ return res;
+ }
+}
diff --git a/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java b/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java
index d7ce60c5..ffe306a4 100644
--- a/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java
+++ b/src/main/java/kr/syeyoung/dungeonsguide/utils/ShortUtils.java
@@ -1,21 +1,21 @@
package kr.syeyoung.dungeonsguide.utils;
public class ShortUtils {
- public static short rotateClockwise(short integer) {
+ public static short rotateCounterClockwise(short integer) {
int res = 0;
for(int i=0; i<16; i++){
int x = i % 4;
int y = i / 4;
- res |= (integer >> i & 0x1) << (x*4 + y);
+ res |= (integer >> i & 0x1) << ((4-x-1)*4 + y);
}
return (short) (res & 0xFFFF);
}
- public static short rotateCounterClockwise(short integer) {
+ public static short rotateClockwise(short integer) {
int res = 0;
for(int i=0; i<16; i++){
int x = i % 4;
int y = i / 4;
- res |= (integer >> i & 0x1) << ((4-x-1) *4 +(4 - y - 1));
+ res |= (integer >> i & 0x1) << (x *4 +(4 - y - 1));
}
return (short) (res & 0xFFFF);
}