package content.global.skill.construction; import core.game.node.entity.player.Player; import core.game.node.scenery.Scenery; import core.game.node.scenery.SceneryBuilder; import core.game.world.map.*; /** * Represents a room. * @author Emperor * */ public final class Room { /** * The default room type. */ public static final int CHAMBER = 0x0; /** * The rooftop room type. */ public static final int ROOF = 0x1; /** * The dungeon room type. */ public static final int DUNGEON = 0x2; /** * The dungeon room type. */ public static final int LAND = 0x4; /** * The room properties. */ private RoomProperties properties; /** * The region chunk. */ private RegionChunk chunk; /** * The hotspots. */ private Hotspot[] hotspots; /** * The current rotation of the room. */ private Direction rotation = Direction.NORTH; /** * Constructs a new {@code Room} {@code Object}. * @param properties The room properties. */ public Room(RoomProperties properties) { this.properties = properties; } /** * Creates a new room. * @param player The player. * @param properties The room properties. * @return The room. */ public static Room create(Player player, RoomProperties properties) { Room room = new Room(properties); room.configure(player.getHouseManager().getStyle()); return room; } /** * Configures the room. */ public void configure(HousingStyle style) { this.hotspots = new Hotspot[properties.getHotspots().length]; for (int i = 0; i < hotspots.length; i++) { hotspots[i] = properties.getHotspots()[i].copy(); } decorate(style); } /** * Redecorates the room. * @param style The house style. */ public void decorate(HousingStyle style) { Region region = RegionManager.forId(style.getRegionId()); Region.load(region, true); chunk = region.getPlanes()[style.getPlane()].getRegionChunk(properties.getChunkX(), properties.getChunkY()); } /** * Gets the hotspot object for the given hotspot type. * @param hotspot The hotspot type. * @return The hotspot. */ public Hotspot getHotspot(BuildHotspot hotspot) { for (Hotspot h : hotspots) { if (h.getHotspot() == hotspot) { return h; } } return null; } /** * Checks if the building hotspot has been built. * @param hotspot The building hotspot. * @return {@code True} if so. */ public boolean isBuilt(BuildHotspot hotspot) { Hotspot h = getHotspot(hotspot); return h != null && h.getDecorationIndex() > -1; } /** * Loads all the decorations. * @param housePlane The plane. * @param chunk The chunk used in the dynamic region. */ public void loadDecorations(int housePlane, BuildRegionChunk chunk, HouseManager house) { for (int i = 0; i < hotspots.length; i++) { Hotspot spot = hotspots[i]; int x = spot.getChunkX(); int y = spot.getChunkY(); if (spot.getHotspot() == null) { continue; } int index = chunk.getIndex(x, y, spot.getHotspot().getObjectId(house.getStyle())); Scenery[][] objects = chunk.getObjects(index); Scenery object = objects[x][y]; if (object != null && object.getId() == spot.getHotspot().getObjectId(house.getStyle())) { if (spot.getDecorationIndex() > -1 && spot.getDecorationIndex() < spot.getHotspot().getDecorations().length) { int id = spot.getHotspot().getDecorations()[spot.getDecorationIndex()].getObjectId(house.getStyle()); if (spot.getHotspot().getType() == BuildHotspotType.CREST) { id += house.getCrest().ordinal(); } SceneryBuilder.replace(object, object.transform(id, object.getRotation(), chunk.getCurrentBase().transform(x, y, 0))); } else if (object.getId() == BuildHotspot.WINDOW.getObjectId(house.getStyle()) || (!house.isBuildingMode() && object.getId() == BuildHotspot.CHAPEL_WINDOW.getObjectId(house.getStyle()))) { chunk.add(object.transform(house.getStyle().getWindowStyle().getObjectId(house.getStyle()), object.getRotation(), object.getType())); } int[] pos = RegionChunk.getRotatedPosition(x, y, object.getSizeX(), object.getSizeY(), 0, rotation.toInteger()); spot.setCurrentX(pos[0]); spot.setCurrentY(pos[1]); } } if (rotation != Direction.NORTH && chunk.getRotation() == 0) { chunk.rotate(rotation); } if (!house.isBuildingMode()) { removeHotspots(housePlane, house, chunk); } } /** * Removes the building hotspots from the room. * @param housePlane The room's plane in house. * @param house The house manager. * @param chunk The region chunk used. */ private void removeHotspots(int housePlane, HouseManager house, BuildRegionChunk chunk) { for (int i = 0; i < BuildRegionChunk.ARRAY_SIZE; i++) { for (int x = 0; x < 8; x++) { for (int y = 0; y < 8; y++) { Scenery object = chunk.get(x, y, i); if (object != null && object.getDefinition().hasAction("Build")) { if (properties.isChamber() && BuildingUtils.isDoorHotspot(object)) { if (!placeDoors(house, chunk, object, housePlane, x, y, rotation)) { chunk.remove(object); } } else { chunk.remove(object); } } } } } } /** * Places the doors when needed. * @param chunk The chunk. * @param object The object. * @param x The x-coordinate of the object. * @param y The y-coordinate of the object. */ private boolean placeDoors(HouseManager house, BuildRegionChunk chunk, Scenery object, int z, int x, int y, Direction rotation) { int doorX; int doorY; switch (rotation) { case EAST: doorX = y; doorY = 7 - x; break; case SOUTH: doorX = 7 - x; doorY = 7 - y; break; case WEST: doorX = 7 - y; doorY = x; break; default: doorX = x; doorY = y; break; } int chunkX = chunk.getCurrentBase().getChunkX(); int chunkY = chunk.getCurrentBase().getChunkY(); boolean houseExit = true; Room r; if (doorX == 0 && chunkX > 0 && (r = house.getRooms()[z][chunkX - 1][chunkY]) != null && r.getProperties().isChamber()) { houseExit = false; } else if (doorX == 7 && chunkX < 7 && (r = house.getRooms()[z][chunkX + 1][chunkY]) != null && r.getProperties().isChamber()) { houseExit = false; } else if (doorY == 0 && chunkY > 0 && (r = house.getRooms()[z][chunkX][chunkY - 1]) != null && r.getProperties().isChamber()) { houseExit = false; } else if (doorY == 7 && chunkY < 7 && (r = house.getRooms()[z][chunkX][chunkY + 1]) != null && r.getProperties().isChamber()) { houseExit = false; } int replaceId = object.getId() % 2 != 0 ? house.getStyle().getDoorId() : house.getStyle().getSecondDoorId(); houseExit = false; if (z != 0 && houseExit) { r = house.getRooms()[z][chunkX][chunkY]; if (r.getProperties().isDungeon()) { replaceId = 13065; } else { replaceId = house.getStyle().getWallId(); } } else if (!houseExit) { return false; } return SceneryBuilder.replace(object, object.transform(replaceId, object.getRotation(), chunk.getCurrentBase().transform(x, y, 0)), true, true); } /** * Sets the decoration index for a group of object ids * @param index The index. * @param hs The building hotspot. */ public void setAllDecorationIndex(int index, BuildHotspot hs) { for (int i = 0; i < hotspots.length; i++) { Hotspot h = hotspots[i]; if (h.getHotspot() == hs) { h.setDecorationIndex(index); } } } /** * Gets the stairs hotspot for this room (or null if no stairs are available). * @return The stairs. */ public Hotspot getStairs() { for (Hotspot h : hotspots) { if (h.getHotspot().getType() == BuildHotspotType.STAIRCASE || h.getHotspot() == BuildHotspot.LADDER || h.getHotspot() == BuildHotspot.TRAPDOOR || (h.getHotspot() == BuildHotspot.CENTREPIECE_1 && h.getDecorationIndex() == 4) || (h.getHotspot() == BuildHotspot.CENTREPIECE_2 && h.getDecorationIndex() == 2)) { return h; } } return null; } /** * Gets the exit directions * @return The exits information. */ public boolean[] getExits() { return getExits(rotation); } /** * Gets the exit directions. * @return The directions at which you can exit the room (0=east, 1=south, 2=west, 3=north). */ public boolean[] getExits(Direction rotation) { boolean[] exits = properties.getExits(); if (chunk.getRotation() != rotation.toInteger()) { boolean[] exit = new boolean[exits.length]; int offset = rotation.toInteger() - chunk.getRotation(); for (int i = 0; i < 4; i++) { exit[(i + offset) % 4] = exits[i]; } return exit; } return exits; } /** * Gets the hotspot for the given coordinates. * @param build The build hotspot. * @param x The x-coordinate. * @param y The y-coordinate. * @return The hotspot. */ public Hotspot getHotspot(BuildHotspot build, int x, int y) { for (int i = 0; i < getHotspots().length; i++) { Hotspot h = getHotspots()[i]; if (h.getCurrentX() == x && h.getCurrentY() == y && h.getHotspot() == build) { return h; } } return null; } /** * Sets the properties. * @param properties The properties. */ public void updateProperties(Player player, RoomProperties properties) { this.properties = properties; decorate(player.getHouseManager().getStyle()); if (hotspots.length != properties.getHotspots().length) { return; } for (int i = 0; i < hotspots.length; i++) { Hotspot h = hotspots[i]; Hotspot hs = hotspots[i] = properties.getHotspots()[i].copy(); hs.setCurrentX(h.getCurrentX()); hs.setCurrentY(h.getCurrentY()); hs.setDecorationIndex(h.getDecorationIndex()); } } /** * Gets the chunk. * @return The chunk. */ public RegionChunk getChunk() { return chunk; } /** * Sets the chunk. * @param chunk The chunk to set. */ public void setChunk(RegionChunk chunk) { this.chunk = chunk; } /** * Gets the hotspots. * @return The hotspots. */ public Hotspot[] getHotspots() { return hotspots; } /** * Sets the hotspots. * @param hotspots The hotspots to set. */ public void setHotspots(Hotspot[] hotspots) { this.hotspots = hotspots; } /** * Gets the properties. * @return The properties. */ public RoomProperties getProperties() { return properties; } /** * Sets the room rotation. * @param rotation The rotation. */ public void setRotation(Direction rotation) { this.rotation = rotation; } /** * Gets the rotation. * @return The rotation. */ public Direction getRotation() { return rotation; } }