From fdc4638c4bbd84e1429812387d0f3a2626b95ae6 Mon Sep 17 00:00:00 2001 From: syeyoung <42869671+cyoung06@users.noreply.github.com> Date: Mon, 23 Nov 2020 14:17:59 +0900 Subject: room building --- .../dungeonsguide/dungeon/MapProcessor.java | 5 +- .../dungeon/data/DungeonRoomInfo.java | 7 ++ .../dungeon/roomfinder/DungeonRoom.java | 69 +++++++++++++++++- .../dungeon/roomfinder/RoomMatcher.java | 85 +++++++++++++++++++++- .../syeyoung/dungeonsguide/utils/ArrayUtils.java | 22 ++++++ .../syeyoung/dungeonsguide/utils/ShortUtils.java | 8 +- 6 files changed, 186 insertions(+), 10 deletions(-) create mode 100644 src/main/java/kr/syeyoung/dungeonsguide/utils/ArrayUtils.java (limited to 'src/main/java/kr') 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 ayConnected = new ArrayList(); 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 points, short shape, byte color, BlockPos min, DungeonContext context) { + private final int unitWidth; // X + private final int unitHeight; // Z + + public DungeonRoom(List 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 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 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> 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); } -- cgit