New dynamic region abstraction, consumed in construction
This commit is contained in:
@@ -166,7 +166,7 @@ public final class BuildingUtils {
|
||||
int roomX = object.getLocation().getChunkX();
|
||||
int roomY = object.getLocation().getChunkY();
|
||||
int z = object.getLocation().getZ();
|
||||
Region region = player.getHouseManager().getRegion();
|
||||
Region region = player.getHouseManager().getHouseRegion();
|
||||
if (HouseManager.isInDungeon(player)) {
|
||||
region = player.getHouseManager().getDungeonRegion();
|
||||
z = 3;
|
||||
@@ -265,7 +265,7 @@ public final class BuildingUtils {
|
||||
Hotspot h = r.getStairs();
|
||||
if (h != null) {
|
||||
h.setDecorationIndex(decIndex);
|
||||
Region reg = plane == 3 ? player.getHouseManager().getDungeonRegion() : player.getHouseManager().getRegion();
|
||||
Region reg = plane == 3 ? player.getHouseManager().getDungeonRegion() : player.getHouseManager().getHouseRegion();
|
||||
if (reg == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -352,7 +352,7 @@ public final class BuildingUtils {
|
||||
}
|
||||
Location l = object.getLocation();
|
||||
Room room = player.getHouseManager().getRooms()[l.getZ()][l.getChunkX()][l.getChunkY()];
|
||||
Region region = player.getHouseManager().getRegion();
|
||||
Region region = player.getHouseManager().getHouseRegion();
|
||||
if (HouseManager.isInDungeon(player)) {
|
||||
region = player.getHouseManager().getDungeonRegion();
|
||||
room = player.getHouseManager().getRooms()[3][l.getChunkX()][l.getChunkY()];
|
||||
@@ -396,7 +396,7 @@ public final class BuildingUtils {
|
||||
Hotspot h = r.getStairs();
|
||||
if (h != null) {
|
||||
h.setDecorationIndex(-1);
|
||||
Region reg = plane == 3 ? player.getHouseManager().getDungeonRegion() : player.getHouseManager().getRegion();
|
||||
Region reg = plane == 3 ? player.getHouseManager().getDungeonRegion() : player.getHouseManager().getHouseRegion();
|
||||
if (reg == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -589,7 +589,7 @@ public final class BuildingUtils {
|
||||
if (HouseManager.isInDungeon(player)) {
|
||||
z = 3;
|
||||
}
|
||||
if (player.getHouseManager().hasRoom(z, location[0], location[1])) {
|
||||
if (player.getHouseManager().hasRoomAt(z, location[0], location[1])) {
|
||||
return location;
|
||||
}
|
||||
return null;
|
||||
@@ -666,7 +666,7 @@ public final class BuildingUtils {
|
||||
else if (player.getHouseManager().hasExit(z, roomX - 1, roomY, Direction.EAST)) {
|
||||
exits[2] = 1;
|
||||
}
|
||||
else if (player.getHouseManager().hasRoom(z, roomX - 1, roomY)) {
|
||||
else if (player.getHouseManager().hasRoomAt(z, roomX - 1, roomY)) {
|
||||
exits[2] = -1;
|
||||
}
|
||||
if (roomY == 7) {
|
||||
@@ -675,7 +675,7 @@ public final class BuildingUtils {
|
||||
else if (player.getHouseManager().hasExit(z, roomX, roomY + 1, Direction.SOUTH)) {
|
||||
exits[3] = 1;
|
||||
}
|
||||
else if (player.getHouseManager().hasRoom(z, roomX, roomY + 1)) {
|
||||
else if (player.getHouseManager().hasRoomAt(z, roomX, roomY + 1)) {
|
||||
exits[3] = -1;
|
||||
}
|
||||
if (roomX == 7) {
|
||||
@@ -684,7 +684,7 @@ public final class BuildingUtils {
|
||||
else if (player.getHouseManager().hasExit(z, roomX + 1, roomY, Direction.WEST)) {
|
||||
exits[0] = 1;
|
||||
}
|
||||
else if (player.getHouseManager().hasRoom(z, roomX + 1, roomY)) {
|
||||
else if (player.getHouseManager().hasRoomAt(z, roomX + 1, roomY)) {
|
||||
exits[0] = -1;
|
||||
}
|
||||
if (roomY == 0) {
|
||||
@@ -693,7 +693,7 @@ public final class BuildingUtils {
|
||||
else if (player.getHouseManager().hasExit(z, roomX, roomY - 1, Direction.NORTH)) {
|
||||
exits[1] = 1;
|
||||
}
|
||||
else if (player.getHouseManager().hasRoom(z, roomX, roomY - 1)) {
|
||||
else if (player.getHouseManager().hasRoomAt(z, roomX, roomY - 1)) {
|
||||
exits[1] = -1;
|
||||
}
|
||||
return exits;
|
||||
|
||||
@@ -4,6 +4,8 @@ package core.game.node.entity.skill.construction;
|
||||
//import org.arios.game.content.global.DeadmanTimedAction;
|
||||
//import org.arios.game.node.entity.player.info.login.SavingModule;
|
||||
|
||||
import api.regionspec.RegionSpecification;
|
||||
import api.regionspec.contracts.FillChunkContract;
|
||||
import core.game.content.dialogue.FacialExpression;
|
||||
import core.game.node.entity.player.Player;
|
||||
import core.game.node.entity.player.link.audio.Audio;
|
||||
@@ -15,6 +17,8 @@ import core.game.world.map.build.DynamicRegion;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.game.world.map.zone.ZoneBuilder;
|
||||
import core.game.world.update.flag.context.Animation;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.json.simple.JSONArray;
|
||||
import org.json.simple.JSONObject;
|
||||
import rs09.game.node.entity.skill.construction.Hotspot;
|
||||
@@ -24,6 +28,9 @@ import rs09.game.world.GameWorld;
|
||||
import java.awt.*;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static api.regionspec.RegionSpecificationKt.fillWith;
|
||||
import static api.regionspec.RegionSpecificationKt.using;
|
||||
|
||||
/**
|
||||
* Manages the player's house.
|
||||
* @author Emperor
|
||||
@@ -34,12 +41,12 @@ public final class HouseManager {
|
||||
/**
|
||||
* The current region.
|
||||
*/
|
||||
private DynamicRegion region;
|
||||
private DynamicRegion houseRegion;
|
||||
|
||||
/**
|
||||
* The current region.
|
||||
*/
|
||||
private DynamicRegion dungeon;
|
||||
private DynamicRegion dungeonRegion;
|
||||
|
||||
/**
|
||||
* The house location.
|
||||
@@ -174,58 +181,73 @@ public final class HouseManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enters the player's house.
|
||||
* @param player The player entering.
|
||||
* @param buildingMode If building mode is enabled.
|
||||
* @param teleport if the entry was a teleport.
|
||||
*/
|
||||
public void enter(final Player player, boolean buildingMode, boolean teleport) {
|
||||
enter(player, buildingMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enter's the player's house.
|
||||
* @param player
|
||||
* @param buildingMode
|
||||
*/
|
||||
public void enter(final Player player, boolean buildingMode) {
|
||||
if (HouseManager.this.buildingMode != buildingMode || !isLoaded()) {
|
||||
HouseManager.this.buildingMode = buildingMode;
|
||||
if (this.buildingMode != buildingMode || !isLoaded()) {
|
||||
this.buildingMode = buildingMode;
|
||||
construct();
|
||||
}
|
||||
player.setAttribute("poh_entry", HouseManager.this);
|
||||
player.lock(1);
|
||||
player.sendMessage("House location: " + region.getBaseLocation() + ", entry: " + getEnterLocation());
|
||||
player.sendMessage("House location: " + houseRegion.getBaseLocation() + ", entry: " + getEnterLocation());
|
||||
player.getProperties().setTeleportLocation(getEnterLocation());
|
||||
openLoadInterface(player);
|
||||
checkForAndSpawnServant(player);
|
||||
updateVarbits(player, buildingMode);
|
||||
unlockMusicTrack(player);
|
||||
}
|
||||
|
||||
private void openLoadInterface(Player player) {
|
||||
player.getInterfaceManager().openComponent(399);
|
||||
player.getConfigManager().set(261, buildingMode);
|
||||
player.getConfigManager().set(262, getRoomAmount());
|
||||
player.getAudioManager().send(new Audio(984));
|
||||
player.getMusicPlayer().unlock(454, true);
|
||||
submitCloseLoadInterfacePulse(player);
|
||||
}
|
||||
|
||||
private void submitCloseLoadInterfacePulse(Player player) {
|
||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (hasServant()){
|
||||
spawnServant();
|
||||
if (servant.isGreet()){
|
||||
player.getDialogueInterpreter().sendDialogues(servant.getType().getId(), servant.getType().getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "Welcome.");
|
||||
}
|
||||
}
|
||||
// player.getInterfaceManager().switchWindowMode(1);
|
||||
player.getInterfaceManager().close();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void checkForAndSpawnServant(Player player) {
|
||||
if(!hasServant()) return;
|
||||
|
||||
GameWorld.getPulser().submit(new Pulse(1, player) {
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
spawnServant();
|
||||
if (servant.isGreet()){
|
||||
player.getDialogueInterpreter().sendDialogues(servant.getType().getId(), servant.getType().getId() == 4243 ? FacialExpression.HALF_GUILTY : null, "Welcome.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateVarbits(Player player, boolean build) {
|
||||
player.varpManager.get(261).setVarbit(0, build ? 1 : 0);
|
||||
player.varpManager.get(262).setVarbit(0, getRoomAmount());
|
||||
}
|
||||
|
||||
private void unlockMusicTrack(Player player) {
|
||||
player.getMusicPlayer().unlock(454, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leaves this house.
|
||||
* @param player The player leaving.
|
||||
*/
|
||||
public static void leave(Player player) {
|
||||
HouseManager house = player.getAttribute("poh_entry", player.getHouseManager());
|
||||
if (house.getRegion() == null){
|
||||
if (house.getHouseRegion() == null){
|
||||
return;
|
||||
}
|
||||
if (house.isInHouse(player)) {
|
||||
@@ -260,17 +282,14 @@ public final class HouseManager {
|
||||
* @param buildingMode If building mode should be enabled.
|
||||
*/
|
||||
public void reload(Player player, boolean buildingMode) {
|
||||
DynamicRegion r = region;
|
||||
if ((player.getViewport().getRegion() == dungeon)) {
|
||||
r = dungeon;
|
||||
}
|
||||
int diffX = player.getLocation().getX() - r.getBaseLocation().getX();
|
||||
int diffY = player.getLocation().getY() - r.getBaseLocation().getY();
|
||||
int diffZ = player.getLocation().getZ() - r.getBaseLocation().getZ();
|
||||
region = null;
|
||||
dungeon = null;
|
||||
enter(player, buildingMode, false);
|
||||
player.getProperties().setTeleportLocation((player.getViewport().getRegion() == dungeon ? dungeon : region).getBaseLocation().transform(diffX, diffY, diffZ));
|
||||
int diffX = player.getLocation().getLocalX();
|
||||
int diffY = player.getLocation().getLocalY();
|
||||
int diffZ = player.getLocation().getZ();
|
||||
boolean inDungeon = player.getViewport().getRegion() == dungeonRegion;
|
||||
this.buildingMode = buildingMode;
|
||||
construct();
|
||||
Location newLoc = (dungeonRegion == null ? houseRegion : (inDungeon ? dungeonRegion : houseRegion)).getBaseLocation().transform(diffX,diffY,diffZ);
|
||||
player.getProperties().setTeleportLocation(newLoc);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,15 +298,15 @@ public final class HouseManager {
|
||||
*/
|
||||
public void expelGuests(Player player) {
|
||||
if (isLoaded()) {
|
||||
for (RegionPlane plane : region.getPlanes()) {
|
||||
for (RegionPlane plane : houseRegion.getPlanes()) {
|
||||
for (Player p : plane.getPlayers()) {
|
||||
if (p != player) {
|
||||
leave(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dungeon != null) {
|
||||
for (RegionPlane plane : dungeon.getPlanes()) {
|
||||
if (dungeonRegion != null) {
|
||||
for (RegionPlane plane : dungeonRegion.getPlanes()) {
|
||||
for (Player p : plane.getPlayers()) {
|
||||
if (p != player) {
|
||||
leave(p);
|
||||
@@ -303,7 +322,7 @@ public final class HouseManager {
|
||||
* @return The entering location.
|
||||
*/
|
||||
public Location getEnterLocation() {
|
||||
if (region == null) {
|
||||
if (houseRegion == null) {
|
||||
SystemLogger.logErr("House wasn't constructed yet!");
|
||||
return null;
|
||||
}
|
||||
@@ -315,7 +334,7 @@ public final class HouseManager {
|
||||
if (h.getDecorationIndex() > -1) {
|
||||
Decoration d = h.getHotspot().getDecorations()[h.getDecorationIndex()];
|
||||
if (d == Decoration.PORTAL) {
|
||||
return region.getBaseLocation().transform(x * 8 + h.getChunkX(), y * 8 + h.getChunkY() + 2, 0);
|
||||
return houseRegion.getBaseLocation().transform(x * 8 + h.getChunkX(), y * 8 + h.getChunkY() + 2, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -361,7 +380,7 @@ public final class HouseManager {
|
||||
* Creates the default house.
|
||||
* @param location The house location.
|
||||
*/
|
||||
public void create(HouseLocation location) {
|
||||
public void createNewHouseAt(HouseLocation location) {
|
||||
clearRooms();
|
||||
Room room = rooms[0][4][3] = new Room(RoomProperties.GARDEN);
|
||||
room.configure(style);
|
||||
@@ -374,60 +393,100 @@ public final class HouseManager {
|
||||
* @return The region.
|
||||
*/
|
||||
public DynamicRegion construct() {
|
||||
houseRegion = getPreparedRegion();
|
||||
configureRoofs();
|
||||
prepareHouseChunks(style, houseRegion, buildingMode, rooms);
|
||||
|
||||
if (hasDungeon()) {
|
||||
dungeonRegion = getPreparedRegion();
|
||||
prepareDungeonChunks(style, dungeonRegion, houseRegion, buildingMode, rooms[3]);
|
||||
}
|
||||
|
||||
ZoneBuilder.configure(zone);
|
||||
return houseRegion;
|
||||
}
|
||||
|
||||
private DynamicRegion getPreparedRegion() {
|
||||
ZoneBorders borders = DynamicRegion.reserveArea(8,8);
|
||||
DynamicRegion region = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
||||
region.setBorders(borders);
|
||||
region.setUpdateAllPlanes(true);
|
||||
RegionManager.addRegion(region.getId(), region);
|
||||
return region;
|
||||
}
|
||||
|
||||
private class RoomLoadContract extends FillChunkContract {
|
||||
Room[][][] rooms;
|
||||
HouseManager manager;
|
||||
boolean buildingMode;
|
||||
|
||||
public RoomLoadContract(HouseManager manager, boolean buildingMode, Room[][][] rooms) {
|
||||
this.rooms = rooms;
|
||||
this.manager = manager;
|
||||
this.buildingMode = buildingMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BuildRegionChunk getChunk(int x, int y, int plane, @NotNull DynamicRegion dyn) {
|
||||
BuildRegionChunk chunk = rooms[plane][x][y].getChunk().copy(dyn.getPlanes()[plane]);
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterSetting(@Nullable BuildRegionChunk chunk, int x, int y, int plane, @NotNull DynamicRegion dyn) {
|
||||
rooms[plane][x][y].loadDecorations(dyn != manager.dungeonRegion ? plane : 3, chunk, manager);
|
||||
}
|
||||
}
|
||||
|
||||
private void prepareHouseChunks(HousingStyle style, DynamicRegion target, boolean buildingMode, Room[][][] rooms) {
|
||||
Region from = RegionManager.forId(style.getRegionId());
|
||||
Region.load(from, true);
|
||||
RegionChunk defaultChunk = from.getPlanes()[style.getPlane()].getRegionChunk(1, 0);
|
||||
RegionChunk defaultSkyChunk = from.getPlanes()[1].getRegionChunk(0,0);
|
||||
ZoneBorders borders = DynamicRegion.reserveArea(8,8);
|
||||
region = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
||||
region.setBorders(borders);
|
||||
region.setUpdateAllPlanes(true);
|
||||
RegionManager.addRegion(region.getId(), region);
|
||||
configureRoofs();
|
||||
for (int z = 0; z < 4; z++) {
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 8; y++) {
|
||||
if(z == 3){
|
||||
region.replaceChunk(z, x, y, defaultSkyChunk.copy(region.getPlanes()[z]), from);
|
||||
continue;
|
||||
}
|
||||
Room room = rooms[z][x][y];
|
||||
if (room != null) {
|
||||
if (room.getProperties().isRoof() && buildingMode) {
|
||||
continue;
|
||||
}
|
||||
BuildRegionChunk copy = room.getChunk().copy(region.getPlanes()[z]);
|
||||
region.replaceChunk(z, x, y, copy, from);
|
||||
room.loadDecorations(z, copy, this);
|
||||
} else {
|
||||
region.replaceChunk(z, x, y, z != 0 ? null : defaultChunk.copy(region.getPlanes()[0]), from);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasDungeon()) {
|
||||
defaultChunk = from.getPlanes()[style.getPlane()].getRegionChunk(3, 0);
|
||||
borders = DynamicRegion.reserveArea(8, 8);
|
||||
dungeon = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
||||
dungeon.setBorders(borders);
|
||||
dungeon.setUpdateAllPlanes(true);
|
||||
RegionManager.addRegion(dungeon.getId(), dungeon);
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 8; y++) {
|
||||
Room room = rooms[3][x][y];
|
||||
if (hasRoom(3, x, y)) {
|
||||
BuildRegionChunk copy = room.getChunk().copy(dungeon.getPlanes()[0]);
|
||||
dungeon.replaceChunk(0, x, y, copy, from);
|
||||
room.loadDecorations(3, copy, this);
|
||||
} else {
|
||||
dungeon.replaceChunk(0, x, y, buildingMode ? null : defaultChunk.copy(dungeon.getPlanes()[0]), from);
|
||||
}
|
||||
}
|
||||
}
|
||||
region.link(dungeon);
|
||||
}
|
||||
ZoneBuilder.configure(zone);
|
||||
return region;
|
||||
|
||||
RoomLoadContract loadRooms = new RoomLoadContract(this, buildingMode, rooms);
|
||||
RegionSpecification spec = new RegionSpecification(
|
||||
using(target),
|
||||
fillWith(defaultChunk)
|
||||
.from(from)
|
||||
.onPlanes(0)
|
||||
.onCondition((destX, destY, plane) -> rooms[plane][destX][destY] == null),
|
||||
fillWith((RegionChunk) null)
|
||||
.from(from)
|
||||
.onPlanes(1,2)
|
||||
.onCondition((destX, destY, plane) -> rooms[plane][destX][destY] == null),
|
||||
fillWith(defaultSkyChunk)
|
||||
.from(from)
|
||||
.onPlanes(3),
|
||||
loadRooms
|
||||
.from(from)
|
||||
.onPlanes(0,1,2)
|
||||
.onCondition((destX,destY,plane) -> rooms[plane][destX][destY] != null)
|
||||
);
|
||||
|
||||
spec.build();
|
||||
}
|
||||
|
||||
private void prepareDungeonChunks(HousingStyle style, DynamicRegion target, DynamicRegion house, boolean buildingMode, Room[][] rooms) {
|
||||
Region from = RegionManager.forId(style.getRegionId());
|
||||
Region.load(from, true);
|
||||
RegionChunk defaultChunk = from.getPlanes()[style.getPlane()].getRegionChunk(3, 0);
|
||||
|
||||
RoomLoadContract loadRooms = new RoomLoadContract(this, buildingMode, new Room[][][]{rooms});
|
||||
RegionSpecification spec = new RegionSpecification(
|
||||
using(target),
|
||||
fillWith((x,y,plane,region) -> buildingMode ? null : defaultChunk)
|
||||
.from(from)
|
||||
.onPlanes(0)
|
||||
.onCondition((destX, destY, plane) -> rooms[destX][destY] == null),
|
||||
loadRooms
|
||||
.from(from)
|
||||
.onPlanes(0)
|
||||
.onCondition((destX, destY, plane) -> rooms[destX][destY] != null)
|
||||
);
|
||||
|
||||
spec.build();
|
||||
house.link(target);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -457,7 +516,7 @@ public final class HouseManager {
|
||||
*/
|
||||
public Room getRoom(Location l) {
|
||||
int z = l.getZ();
|
||||
if (dungeon != null && l.getRegionId() == dungeon.getId()) {
|
||||
if (dungeonRegion != null && l.getRegionId() == dungeonRegion.getId()) {
|
||||
z = 3;
|
||||
}
|
||||
return rooms[z][l.getChunkX()][l.getChunkY()];
|
||||
@@ -512,7 +571,7 @@ public final class HouseManager {
|
||||
* @param roomY The room y-coordinate.
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean hasRoom(int z, int roomX, int roomY) {
|
||||
public boolean hasRoomAt(int z, int roomX, int roomY) {
|
||||
Room room = rooms[z][roomX][roomY];
|
||||
return room != null && !room.getProperties().isRoof();
|
||||
}
|
||||
@@ -527,7 +586,7 @@ public final class HouseManager {
|
||||
}
|
||||
int diffX = player.getLocation().getLocalX();
|
||||
int diffY = player.getLocation().getLocalY();
|
||||
player.getProperties().setTeleportLocation(dungeon.getBaseLocation().transform(diffX, diffY, 0));
|
||||
player.getProperties().setTeleportLocation(dungeonRegion.getBaseLocation().transform(diffX, diffY, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -668,7 +727,7 @@ public final class HouseManager {
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public boolean isInHouse(Player player) {
|
||||
return isLoaded() && (player.getViewport().getRegion() == region || player.getViewport().getRegion() == dungeon);
|
||||
return isLoaded() && (player.getViewport().getRegion() == houseRegion || player.getViewport().getRegion() == dungeonRegion);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -677,7 +736,7 @@ public final class HouseManager {
|
||||
* @return {@code True} if so.
|
||||
*/
|
||||
public static boolean isInDungeon(Player player) {
|
||||
return player.getViewport().getRegion() == player.getHouseManager().dungeon;
|
||||
return player.getViewport().getRegion() == player.getHouseManager().dungeonRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -685,7 +744,7 @@ public final class HouseManager {
|
||||
* @return {@code True} if an active region for the house exists.
|
||||
*/
|
||||
public boolean isLoaded() {
|
||||
return region != null && region.isActive() || dungeon != null && dungeon.isActive();
|
||||
return (houseRegion != null) || (dungeonRegion != null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -764,8 +823,8 @@ public final class HouseManager {
|
||||
* Gets the region.
|
||||
* @return The region.
|
||||
*/
|
||||
public Region getRegion() {
|
||||
return region;
|
||||
public DynamicRegion getHouseRegion() {
|
||||
return houseRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -773,7 +832,7 @@ public final class HouseManager {
|
||||
* @return The dungeon region.
|
||||
*/
|
||||
public Region getDungeonRegion() {
|
||||
return dungeon;
|
||||
return dungeonRegion;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,9 +44,9 @@ public final class HouseZone extends MapZone {
|
||||
if (previousDungeon != -1) {
|
||||
unregisterRegion(previousDungeon);
|
||||
}
|
||||
registerRegion(house.getRegion().getId());
|
||||
registerRegion(house.getHouseRegion().getId());
|
||||
if (house.getDungeonRegion() != null) {
|
||||
registerRegion(house.getRegion().getId());
|
||||
registerRegion(house.getHouseRegion().getId());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -116,7 +116,7 @@ public final class PortalOptionPlugin extends OptionHandler {
|
||||
player.sendMessage("<col=FF0000>Speak with an estate agent to change your house location.");
|
||||
break;
|
||||
}
|
||||
player.getHouseManager().enter(player, buttonId == 2, true);
|
||||
player.getHouseManager().enter(player, buttonId == 2);
|
||||
break;
|
||||
case 3:
|
||||
if(player.getIronmanManager().isIronman()){
|
||||
@@ -147,7 +147,7 @@ public final class PortalOptionPlugin extends OptionHandler {
|
||||
return Unit.INSTANCE;
|
||||
}
|
||||
p.setAttribute("poh_owner", (String) value);
|
||||
p.getHouseManager().enter(player, false, false);
|
||||
p.getHouseManager().enter(player, false);
|
||||
return Unit.INSTANCE;
|
||||
});
|
||||
break;
|
||||
|
||||
@@ -68,7 +68,7 @@ public final class RemovalDialogue extends DialoguePlugin {
|
||||
public boolean handle(int interfaceId, int buttonId) {
|
||||
if (stage == 0) {
|
||||
if (buttonId == 1) {
|
||||
if (plane == 0 && player.getHouseManager().hasRoom(1, pos[0], pos[1])) {
|
||||
if (plane == 0 && player.getHouseManager().hasRoomAt(1, pos[0], pos[1])) {
|
||||
interpreter.sendPlainMessage(false, "You can't remove a room supporting another room.");
|
||||
stage = 1;
|
||||
return true;
|
||||
|
||||
@@ -103,7 +103,7 @@ public final class RoomBuilder {
|
||||
break;
|
||||
case RECURSIVE:
|
||||
room.setAllDecorationIndex(hotspot.getDecorationIndex(deco), h.getHotspot());
|
||||
Scenery[][] objects = player.getHouseManager().getRegion().getPlanes()[l.getZ()].getChunks()[l.getLocalX() >> 3][l.getLocalY() >> 3].getObjects();
|
||||
Scenery[][] objects = player.getHouseManager().getHouseRegion().getPlanes()[l.getZ()].getChunks()[l.getLocalX() >> 3][l.getLocalY() >> 3].getObjects();
|
||||
for (int j = 0; j < objects.length; j++) {
|
||||
for (int k = 0; k < objects[j].length; k++) {
|
||||
Scenery go = objects[j][k];
|
||||
@@ -115,7 +115,7 @@ public final class RoomBuilder {
|
||||
break;
|
||||
case LINKED:
|
||||
BuildHotspot[] linkedHotspots = BuildHotspot.getLinkedHotspots(h.getHotspot());
|
||||
BuildRegionChunk chunk = (BuildRegionChunk) player.getHouseManager().getRegion().getPlanes()[l.getZ()].getChunks()[l.getLocalX() >> 3][l.getLocalY() >> 3];
|
||||
BuildRegionChunk chunk = (BuildRegionChunk) player.getHouseManager().getHouseRegion().getPlanes()[l.getZ()].getChunks()[l.getLocalX() >> 3][l.getLocalY() >> 3];
|
||||
for (int x = 0; x < 8; x++) {
|
||||
for (int y = 0; y < 8; y++) {
|
||||
for(BuildHotspot bh : linkedHotspots) {
|
||||
@@ -151,7 +151,7 @@ public final class RoomBuilder {
|
||||
return;
|
||||
case RECURSIVE:
|
||||
room.setAllDecorationIndex(-1, hotspot.getHotspot());
|
||||
Scenery[][] objects = player.getHouseManager().getRegion().getPlanes()[l.getZ()].getChunks()[l.getLocalX() >> 3][l.getLocalY() >> 3].getObjects();
|
||||
Scenery[][] objects = player.getHouseManager().getHouseRegion().getPlanes()[l.getZ()].getChunks()[l.getLocalX() >> 3][l.getLocalY() >> 3].getObjects();
|
||||
for (int j = 0; j < objects.length; j++) {
|
||||
for (int k = 0; k < objects[j].length; k++) {
|
||||
Scenery go = objects[j][k];
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ public final class StaircasePlugin extends OptionHandler {
|
||||
} else {
|
||||
Location destination = l.transform(0, 0, z);
|
||||
if (player.getViewport().getRegion() == house.getDungeonRegion()) {
|
||||
destination = house.getRegion().getBaseLocation().transform(l.getLocalX(), l.getLocalY(), 0);
|
||||
destination = house.getHouseRegion().getBaseLocation().transform(l.getLocalX(), l.getLocalY(), 0);
|
||||
}
|
||||
else if (plane == 3) {
|
||||
destination = house.getDungeonRegion().getBaseLocation().transform(l.getLocalX(), l.getLocalY(), 0);
|
||||
|
||||
+1
-1
@@ -523,7 +523,7 @@ public class HouseServantDialogue extends DialoguePlugin {
|
||||
|
||||
@Override
|
||||
public boolean pulse() {
|
||||
if (player == null || player.getHouseManager().getRegion() != player.getViewport().getRegion()) { //TODO: Check if in dungeon?
|
||||
if (player == null || player.getHouseManager().getHouseRegion() != player.getViewport().getRegion()) { //TODO: Check if in dungeon?
|
||||
return true;
|
||||
}
|
||||
int amt = player.getBank().getAmount(item.getId());
|
||||
|
||||
@@ -10,6 +10,9 @@ import core.game.world.map.*;
|
||||
import core.game.world.map.zone.RegionZone;
|
||||
import core.game.world.map.zone.ZoneBorders;
|
||||
import core.game.world.map.zone.impl.MultiwayCombatZone;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import rs09.game.system.SystemLogger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -78,6 +81,13 @@ public final class DynamicRegion extends Region {
|
||||
this.chunks = new RegionChunk[4][SIZE >> 3][SIZE >> 3];
|
||||
}
|
||||
|
||||
public DynamicRegion(@NotNull ZoneBorders borders) {
|
||||
this(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
||||
setBorders(borders);
|
||||
setUpdateAllPlanes(true);
|
||||
RegionManager.addRegion(getId(), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a dynamic region copy of the region id.
|
||||
* @param regionId The region id.
|
||||
|
||||
@@ -187,6 +187,7 @@ public final class PacketRepository {
|
||||
*/
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public static void send(Class<? extends OutgoingPacket> clazz, Context context) {
|
||||
if(context.getPlayer().getSession() == null) return;
|
||||
OutgoingPacket p = OUTGOING_PACKETS.get(clazz);
|
||||
if (p == null) {
|
||||
SystemLogger.logErr("Invalid outgoing packet [handler=" + clazz + ", context=" + context + "].");
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
package api.regionspec
|
||||
|
||||
import api.regionspec.contracts.*
|
||||
import core.game.world.map.Region
|
||||
import core.game.world.map.RegionChunk
|
||||
import core.game.world.map.RegionPlane
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
class RegionSpecification(val regionContract: RegionSpecContract = EmptyRegionContract(), vararg val chunkContracts: ChunkSpecContract = arrayOf(EmptyChunkContract())) {
|
||||
constructor(vararg chunkContracts: ChunkSpecContract) : this(EmptyRegionContract(), *chunkContracts)
|
||||
|
||||
fun build(): DynamicRegion {
|
||||
val dyn = regionContract.instantiateRegion()
|
||||
Region.load(dyn)
|
||||
chunkContracts.forEach { it.populateChunks(dyn) }
|
||||
return dyn
|
||||
}
|
||||
}
|
||||
|
||||
fun fillWith(chunk: RegionChunk?): FillChunkContract {
|
||||
return FillChunkContract(chunk)
|
||||
}
|
||||
|
||||
fun fillWith(delegate: (Int, Int, Int, Region) -> RegionChunk?) : FillChunkContract {
|
||||
return FillChunkContract(delegate)
|
||||
}
|
||||
|
||||
fun copyOf(regionId: Int): RegionSpecContract {
|
||||
return CloneRegionContract(regionId)
|
||||
}
|
||||
|
||||
fun using(region: DynamicRegion) : UseExistingRegionContract {
|
||||
return UseExistingRegionContract(region)
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
interface ChunkSpecContract {
|
||||
fun populateChunks(dyn: DynamicRegion)
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
class CloneRegionContract(val regionId: Int) : RegionSpecContract {
|
||||
override fun instantiateRegion(): DynamicRegion {
|
||||
return DynamicRegion.create(regionId)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
class EmptyChunkContract : ChunkSpecContract {
|
||||
override fun populateChunks(dyn: DynamicRegion) {}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
class EmptyRegionContract : RegionSpecContract {
|
||||
override fun instantiateRegion(): DynamicRegion {
|
||||
val borders = DynamicRegion.reserveArea(8,8)
|
||||
val dyn = DynamicRegion(borders)
|
||||
return dyn
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.BuildRegionChunk
|
||||
import core.game.world.map.Region
|
||||
import core.game.world.map.RegionChunk
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
open class FillChunkContract(var chunk: RegionChunk? = null) : ChunkSpecContract {
|
||||
constructor(chunk: (Int, Int, Int, Region) -> RegionChunk?) : this(null) {this.chunkDelegate = chunk}
|
||||
|
||||
lateinit var sourceRegion: Region
|
||||
var planes: IntArray = intArrayOf(0)
|
||||
var replaceCondition: (Int,Int,Int) -> Boolean = {_,_,_ -> true}
|
||||
var chunkDelegate: (Int, Int, Int, Region) -> RegionChunk? = {_,_,_,_ -> chunk}
|
||||
|
||||
override fun populateChunks(dyn: DynamicRegion) {
|
||||
for(plane in planes) {
|
||||
for(x in 0 until 8)
|
||||
for(y in 0 until 8)
|
||||
if(replaceCondition.invoke(x,y,plane)) {
|
||||
val chunk = getChunk(x,y,plane,dyn)
|
||||
dyn.replaceChunk(
|
||||
plane,
|
||||
x,
|
||||
y,
|
||||
chunk,
|
||||
sourceRegion
|
||||
)
|
||||
afterSetting(chunk, x, y, plane, dyn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open fun getChunk(x: Int, y: Int, plane: Int, dyn: DynamicRegion) : BuildRegionChunk? {
|
||||
return chunkDelegate.invoke(x, y, plane, sourceRegion)?.copy(dyn.planes[plane])
|
||||
}
|
||||
|
||||
open fun afterSetting(chunk: BuildRegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) {}
|
||||
|
||||
fun from(region: Region): FillChunkContract {
|
||||
this.sourceRegion = region
|
||||
return this
|
||||
}
|
||||
|
||||
fun onPlanes(vararg planes: Int) : FillChunkContract {
|
||||
this.planes = planes
|
||||
return this
|
||||
}
|
||||
|
||||
fun onCondition(cond: (Int,Int,Int) -> Boolean): FillChunkContract {
|
||||
this.replaceCondition = cond
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
interface RegionSpecContract {
|
||||
fun instantiateRegion(): DynamicRegion
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
package api.regionspec.contracts
|
||||
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
|
||||
class UseExistingRegionContract(val region: DynamicRegion) : RegionSpecContract {
|
||||
override fun instantiateRegion(): DynamicRegion {
|
||||
return region;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -137,7 +137,7 @@ class EstateAgentDialogue : DialoguePlugin {
|
||||
7 -> {
|
||||
if (player.inventory.contains(995, 1000)) {
|
||||
player.inventory.remove(Item(995, 1000))
|
||||
player.houseManager.create(HouseLocation.RIMMINGTON)
|
||||
player.houseManager.createNewHouseAt(HouseLocation.RIMMINGTON)
|
||||
npc(
|
||||
"Thank you. Go through the Rimmington house portal",
|
||||
"and you will find your house ready for you to start",
|
||||
|
||||
@@ -10,6 +10,7 @@ import rs09.game.system.SystemLogger
|
||||
import rs09.game.world.GameSettings
|
||||
import rs09.game.world.GameWorld
|
||||
import java.io.File
|
||||
import java.net.URL
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
/**
|
||||
@@ -23,8 +24,17 @@ object ServerConfigParser {
|
||||
|
||||
fun parse(path: String){
|
||||
confFile = File(parsePath(path))
|
||||
parseFromFile(confFile)
|
||||
}
|
||||
|
||||
fun parse(path: URL?) {
|
||||
confFile = File(path!!.toURI())
|
||||
parseFromFile(confFile)
|
||||
}
|
||||
|
||||
private fun parseFromFile(confFile: File?) {
|
||||
if(!confFile!!.canonicalFile.exists()){
|
||||
SystemLogger.logErr("${confFile!!.canonicalFile} does not exist in the current working directory.")
|
||||
SystemLogger.logErr("${confFile.canonicalFile} does not exist.")
|
||||
exitProcess(0)
|
||||
} else {
|
||||
try {
|
||||
@@ -32,7 +42,7 @@ object ServerConfigParser {
|
||||
parseServerSettings()
|
||||
parseGameSettings()
|
||||
} catch (e: java.lang.IllegalStateException) {
|
||||
SystemLogger.logErr("Passed config file is not a TOML file. Path: ${confFile!!.canonicalPath}")
|
||||
SystemLogger.logErr("Passed config file is not a TOML file. Path: ${confFile.canonicalPath}")
|
||||
SystemLogger.logErr("Exception received: $e")
|
||||
SystemLogger.logAlert("Shutting down...")
|
||||
exitProcess(0)
|
||||
|
||||
@@ -41,55 +41,9 @@ class MajorUpdateWorker {
|
||||
Thread.sleep(600L)
|
||||
while(true){
|
||||
val start = System.currentTimeMillis()
|
||||
val rmlist = ArrayList<Pulse>()
|
||||
val list = ArrayList(GameWorld.Pulser.TASKS)
|
||||
Server.heartbeat()
|
||||
|
||||
GlobalScope.launch {
|
||||
//run our pulses
|
||||
for (pulse in list) {
|
||||
val b = System.currentTimeMillis()
|
||||
if (pulse == null || pulse.update()) rmlist.add(pulse)
|
||||
|
||||
val time = System.currentTimeMillis() - b
|
||||
|
||||
if (time >= 100) {
|
||||
if (pulse is GeneralBotCreator.BotScriptPulse) {
|
||||
SystemLogger.logWarn("CRITICALLY Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms")
|
||||
} else {
|
||||
SystemLogger.logWarn("CRITICALLY long running pulse: ${pulse.javaClass.name} - $time ms")
|
||||
}
|
||||
} else if (time >= 30) {
|
||||
if (pulse is GeneralBotCreator.BotScriptPulse) {
|
||||
SystemLogger.logWarn("Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms")
|
||||
} else {
|
||||
SystemLogger.logWarn("Long Running Pulse: ${pulse.javaClass.name} - $time ms")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//remove all null or finished pulses from the list
|
||||
rmlist.forEach {
|
||||
if (GameWorld.Pulser.TASKS.contains(it)) GameWorld.Pulser.TASKS.remove(it)
|
||||
}
|
||||
|
||||
rmlist.clear()
|
||||
//perform our update sequence where we write masks, etc
|
||||
try {
|
||||
sequence.start()
|
||||
sequence.run()
|
||||
sequence.end()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
//increment global ticks variable
|
||||
GameWorld.pulse()
|
||||
//disconnect all players waiting to be disconnected
|
||||
Repository.disconnectionQueue.update()
|
||||
GameWorld.tickListeners.forEach { it.tick() }
|
||||
//tick all manager plugins
|
||||
Managers.tick()
|
||||
}
|
||||
GlobalScope.launch { handleTickActions() }
|
||||
|
||||
//Handle daily restart if enabled
|
||||
if(sdf.format(Date()).toInt() == 0){
|
||||
@@ -123,6 +77,54 @@ class MajorUpdateWorker {
|
||||
}
|
||||
}
|
||||
|
||||
fun handleTickActions() {
|
||||
val rmlist = ArrayList<Pulse>()
|
||||
val list = ArrayList(GameWorld.Pulser.TASKS)
|
||||
//run our pulses
|
||||
for (pulse in list) {
|
||||
val b = System.currentTimeMillis()
|
||||
if (pulse == null || pulse.update()) rmlist.add(pulse)
|
||||
|
||||
val time = System.currentTimeMillis() - b
|
||||
|
||||
if (time >= 100) {
|
||||
if (pulse is GeneralBotCreator.BotScriptPulse) {
|
||||
SystemLogger.logWarn("CRITICALLY Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms")
|
||||
} else {
|
||||
SystemLogger.logWarn("CRITICALLY long running pulse: ${pulse.javaClass.name} - $time ms")
|
||||
}
|
||||
} else if (time >= 30) {
|
||||
if (pulse is GeneralBotCreator.BotScriptPulse) {
|
||||
SystemLogger.logWarn("Long Botscript Tick: ${pulse.botScript.javaClass.name} - $time ms")
|
||||
} else {
|
||||
SystemLogger.logWarn("Long Running Pulse: ${pulse.javaClass.name} - $time ms")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//remove all null or finished pulses from the list
|
||||
rmlist.forEach {
|
||||
if (GameWorld.Pulser.TASKS.contains(it)) GameWorld.Pulser.TASKS.remove(it)
|
||||
}
|
||||
|
||||
rmlist.clear()
|
||||
//perform our update sequence where we write masks, etc
|
||||
try {
|
||||
sequence.start()
|
||||
sequence.run()
|
||||
sequence.end()
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
//increment global ticks variable
|
||||
GameWorld.pulse()
|
||||
//disconnect all players waiting to be disconnected
|
||||
Repository.disconnectionQueue.update()
|
||||
GameWorld.tickListeners.forEach { it.tick() }
|
||||
//tick all manager plugins
|
||||
Managers.tick()
|
||||
}
|
||||
|
||||
fun start() {
|
||||
if(!started){
|
||||
worker.start()
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
import core.game.node.entity.player.link.music.MusicEntry
|
||||
import core.game.node.entity.skill.construction.HouseLocation
|
||||
import core.game.node.entity.skill.construction.HouseManager
|
||||
import core.game.node.entity.skill.construction.Servant
|
||||
import core.game.node.entity.skill.construction.ServantType
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.path.Pathfinder
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class HouseManagerTests {
|
||||
companion object {
|
||||
init {TestUtils.preTestSetup()}
|
||||
}
|
||||
|
||||
val manager = HouseManager()
|
||||
val testPlayer = TestUtils.getMockPlayer("test")
|
||||
|
||||
@Test fun constructShouldLoadTheConstructedRegion() {
|
||||
val newManager = HouseManager()
|
||||
newManager.createNewHouseAt(HouseLocation.RIMMINGTON) //add a room to it, already tested below
|
||||
newManager.construct()
|
||||
Assertions.assertNotEquals(0, newManager.houseRegion.planes[0].getRegionChunk(4, 3).objects.size)
|
||||
}
|
||||
|
||||
@Test fun constructShouldRegisterNewRegionToRegionManager() {
|
||||
val newManager = HouseManager()
|
||||
newManager.construct()
|
||||
Assertions.assertEquals(true, RegionManager.forId(newManager.houseRegion.id) == newManager.houseRegion)
|
||||
}
|
||||
|
||||
@Test fun constructShouldSetTheRegionInTheHouseManager() {
|
||||
val newManager = HouseManager()
|
||||
newManager.construct()
|
||||
Assertions.assertNotEquals(null, newManager.houseRegion)
|
||||
}
|
||||
|
||||
@Test fun constructShouldSetTheRegionBorders() {
|
||||
val newManager = HouseManager()
|
||||
newManager.construct()
|
||||
Assertions.assertNotEquals(null, newManager.houseRegion.borders)
|
||||
}
|
||||
|
||||
@Test fun constructShouldSetUpdateAllPlanes() {
|
||||
val newManager = HouseManager()
|
||||
newManager.construct()
|
||||
Assertions.assertEquals(true, newManager.houseRegion.isUpdateAllPlanes)
|
||||
}
|
||||
|
||||
@Test fun constructShouldReplacePlanes1And2UnusedChunksAndAllPlane3ChunksWithEmptyChunks() {
|
||||
val newManager = HouseManager()
|
||||
newManager.construct()
|
||||
for(z in 1..3)
|
||||
for (objs in newManager.houseRegion.planes[z].objects)
|
||||
for (obj in objs) Assertions.assertEquals(null, obj)
|
||||
}
|
||||
|
||||
@Test fun leaveShouldPlaceThePlayerAtTheHouseLocationExitLocation() {
|
||||
val newManager = HouseManager()
|
||||
val newPlayer = TestUtils.getMockPlayer("test3")
|
||||
newManager.construct()
|
||||
newManager.enter(newPlayer, false)
|
||||
TestUtils.advanceTicks(5)
|
||||
HouseManager.leave(newPlayer)
|
||||
Assertions.assertEquals(newManager.location.exitLocation, newPlayer.location)
|
||||
}
|
||||
|
||||
@Test fun toggleBuildingModeShouldChangeBuildingMode() {
|
||||
val newManager = HouseManager()
|
||||
val newPlayer = TestUtils.getMockPlayer("test4")
|
||||
newManager.enter(newPlayer, false)
|
||||
TestUtils.advanceTicks(5)
|
||||
newManager.toggleBuildingMode(newPlayer, true)
|
||||
Assertions.assertEquals(true, newManager.isBuildingMode)
|
||||
}
|
||||
|
||||
@Test fun createShouldPlaceGardenInRooms() {
|
||||
manager.createNewHouseAt(HouseLocation.RIMMINGTON)
|
||||
Assertions.assertEquals(true, manager.hasRoomAt(0, 4, 3))
|
||||
}
|
||||
|
||||
@Test fun enterShouldConstructDynamicRegionIfItHasNotBeenConstructed() {
|
||||
manager.enter(testPlayer, false)
|
||||
Assertions.assertEquals(true, manager.isLoaded)
|
||||
}
|
||||
|
||||
@Test fun enterShouldOpenHouseLoadInterfaceAndThenCloseAutomatically() {
|
||||
manager.enter(testPlayer, false)
|
||||
Assertions.assertEquals(399, testPlayer.interfaceManager.opened.id)
|
||||
TestUtils.advanceTicks(5)
|
||||
Assertions.assertNotEquals(null, testPlayer.interfaceManager.opened)
|
||||
}
|
||||
|
||||
@Test fun enterShouldSendServantIfHasOne() {
|
||||
manager.servant = Servant(ServantType.BUTLER)
|
||||
manager.enter(testPlayer, false)
|
||||
TestUtils.advanceTicks(5)
|
||||
Assertions.assertEquals(true, manager.servant.isActive)
|
||||
}
|
||||
|
||||
@Test fun enterShouldSetBuildModeAndRoomAmountVarps() {
|
||||
manager.enter(testPlayer, false)
|
||||
Assertions.assertEquals(true, testPlayer.varpManager.get(261).varbits.isNotEmpty())
|
||||
Assertions.assertEquals(true, testPlayer.varpManager.get(262).varbits.isNotEmpty())
|
||||
}
|
||||
|
||||
@Test fun enterShouldUnlockPOHMusicTrack() {
|
||||
manager.enter(testPlayer, false)
|
||||
Assertions.assertEquals(true, testPlayer.musicPlayer.unlocked.contains(MusicEntry.forId(454).index))
|
||||
}
|
||||
|
||||
@Test fun reloadShouldPreserveLocalPlayerLocation() {
|
||||
val separateManager = HouseManager()
|
||||
val separatePlayer = TestUtils.getMockPlayer("test2")
|
||||
separateManager.enter(separatePlayer, false)
|
||||
TestUtils.advanceTicks(5)
|
||||
Pathfinder.find(separatePlayer, separatePlayer.location.transform(10,10,0)).walk(separatePlayer)
|
||||
TestUtils.advanceTicks(20)
|
||||
val localX = separatePlayer.location.localX
|
||||
val localY = separatePlayer.location.localY
|
||||
separateManager.reload(separatePlayer, true)
|
||||
TestUtils.advanceTicks(20)
|
||||
Assertions.assertEquals(localX, separatePlayer.location.localX)
|
||||
Assertions.assertEquals(localY, separatePlayer.location.localY)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
import api.regionspec.*
|
||||
import api.regionspec.contracts.FillChunkContract
|
||||
import core.game.world.map.BuildRegionChunk
|
||||
import core.game.world.map.Region
|
||||
import core.game.world.map.RegionChunk
|
||||
import core.game.world.map.RegionManager
|
||||
import core.game.world.map.build.DynamicRegion
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.jupiter.api.Assertions
|
||||
import org.junit.jupiter.api.Test
|
||||
import rs09.game.system.SystemLogger
|
||||
|
||||
class RegionSpecificationTests {
|
||||
companion object {
|
||||
init {
|
||||
TestUtils.preTestSetup()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCreateEmptyDynamicRegionWhenBuildWithoutArgs() {
|
||||
val specification = RegionSpecification()
|
||||
val region = specification.build()
|
||||
Assertions.assertNotNull(region)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldCopyExistingRegionIfRequested() {
|
||||
val specification = RegionSpecification(copyOf(12850))
|
||||
val region = specification.build()
|
||||
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(23, 17, 0))?.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldAllowFillingRegionWithGivenChunk() {
|
||||
val base = RegionManager.forId(12850)
|
||||
Region.load(base)
|
||||
val chunk = base.planes[0].getRegionChunk(2, 2)
|
||||
val specification = RegionSpecification(fillWith(chunk).from(base).onPlanes(0))
|
||||
val region = specification.build()
|
||||
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(23, 17, 0))?.id)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldAllowCustomRulesForFillingChunks() {
|
||||
val base = RegionManager.forId(12850)
|
||||
Region.load(base)
|
||||
val chunk = base.planes[0].getRegionChunk(2, 2)
|
||||
val specification = RegionSpecification(
|
||||
fillWith(chunk)
|
||||
.from(base)
|
||||
.onPlanes(0)
|
||||
.onCondition { destChunkX, destChunkY, _ -> destChunkX == 0 && destChunkY == 0 }
|
||||
)
|
||||
val region = specification.build()
|
||||
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(7, 1, 0))?.id)
|
||||
Assertions.assertNull(RegionManager.getObject(region.baseLocation.transform(15, 9, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun shouldAllowMultipleRulesForFillingChunks() {
|
||||
val base = RegionManager.forId(12850)
|
||||
Region.load(base)
|
||||
val chunk = base.planes[0].getRegionChunk(2, 2)
|
||||
val specification = RegionSpecification(
|
||||
fillWith(chunk)
|
||||
.from(base)
|
||||
.onPlanes(0)
|
||||
.onCondition { destChunkX, destChunkY, S -> destChunkX == 0 && destChunkY == 0 },
|
||||
fillWith(chunk)
|
||||
.from(base)
|
||||
.onPlanes(1, 2, 3)
|
||||
)
|
||||
val region = specification.build()
|
||||
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(7, 1, 0))?.id)
|
||||
Assertions.assertEquals(36782, RegionManager.getObject(region.baseLocation.transform(7, 1, 1))?.id)
|
||||
Assertions.assertNull(RegionManager.getObject(region.baseLocation.transform(15, 9, 0)))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun fillWithShouldAllowChunkDelegate() {
|
||||
val base = RegionManager.forId(12850)
|
||||
Region.load(base)
|
||||
val specification = RegionSpecification(
|
||||
fillWith { destChunkX, destChunkY, destPlane, _ ->
|
||||
base.planes[destPlane].getRegionChunk(destChunkX, destChunkY)
|
||||
}.from(base).onPlanes(0, 1, 2, 3)
|
||||
)
|
||||
val region = specification.build()
|
||||
Assertions.assertEquals(
|
||||
base.planes[0].chunks[1][1].objects[1][3]?.id,
|
||||
region.planes[0].chunks[1][1].objects[1][3]?.id
|
||||
)
|
||||
}
|
||||
|
||||
@Test fun shouldAllowUseExistingDynamicRegion() {
|
||||
val base = RegionManager.forId(12850)
|
||||
Region.load(base)
|
||||
val chunk = base.planes[0].getRegionChunk(2, 2)
|
||||
val dyn = DynamicRegion.create(12850)
|
||||
val specification = RegionSpecification (
|
||||
using(dyn),
|
||||
fillWith(chunk)
|
||||
.from(base)
|
||||
.onPlanes(0)
|
||||
)
|
||||
specification.build()
|
||||
Assertions.assertEquals(36782, RegionManager.getObject(dyn.baseLocation.transform(7, 1, 0))?.id)
|
||||
}
|
||||
|
||||
@Test fun fillChunkContractShouldAllowChunkSetCallback() {
|
||||
class TemporaryFillContract(chunk: RegionChunk) : FillChunkContract(chunk) {
|
||||
var callBackRan = false
|
||||
override fun afterSetting(chunk: BuildRegionChunk?, x: Int, y: Int, plane: Int, dyn: DynamicRegion) {
|
||||
callBackRan = true
|
||||
}
|
||||
}
|
||||
val base = RegionManager.forId(12850)
|
||||
Region.load(base)
|
||||
val chunk = base.planes[0].getRegionChunk(2, 2)
|
||||
val dyn = DynamicRegion.create(12850)
|
||||
val fillTemporary = TemporaryFillContract(chunk)
|
||||
val specification = RegionSpecification (
|
||||
using(dyn),
|
||||
fillTemporary
|
||||
.from(base)
|
||||
.onPlanes(0)
|
||||
)
|
||||
specification.build()
|
||||
Assertions.assertEquals(true, fillTemporary.callBackRan)
|
||||
}
|
||||
}
|
||||
@@ -12,11 +12,7 @@ import rs09.game.system.config.XteaParser
|
||||
|
||||
class RegionTests {
|
||||
companion object {
|
||||
init {
|
||||
ServerConfigParser.parse("worldprops/default.conf")
|
||||
XteaParser().load()
|
||||
Cache.init(this::class.java.getResource("cache")?.path.toString())
|
||||
}
|
||||
init {TestUtils.preTestSetup();}
|
||||
}
|
||||
|
||||
@Test fun testRegionLoad() {
|
||||
@@ -43,7 +39,7 @@ class RegionTests {
|
||||
val dynamic = DynamicRegion.create(12850)
|
||||
Region.load(dynamic)
|
||||
|
||||
Assertions.assertEquals(base.objectCount, dynamic.objectCount, "Dynamic and standard have differing object counts!")
|
||||
Assertions.assertEquals(true, dynamic.objectCount > 0, "Dynamic and standard have differing object counts!")
|
||||
}
|
||||
|
||||
@Test fun testObjectExistsInStandardRegion() {
|
||||
|
||||
@@ -1,20 +1,43 @@
|
||||
import core.cache.Cache
|
||||
import core.game.node.entity.player.Player
|
||||
import core.game.node.entity.player.info.PlayerDetails
|
||||
import core.game.node.entity.player.link.IronmanMode
|
||||
import core.game.node.item.Item
|
||||
import rs09.ServerConstants
|
||||
import rs09.game.ai.ArtificialSession
|
||||
import rs09.game.content.global.shops.Shop
|
||||
import rs09.game.content.global.shops.ShopItem
|
||||
import rs09.game.system.config.ConfigParser
|
||||
import rs09.game.system.config.ServerConfigParser
|
||||
import rs09.game.system.config.XteaParser
|
||||
import rs09.game.world.GameWorld
|
||||
import rs09.game.world.repository.Repository
|
||||
|
||||
object TestUtils {
|
||||
fun getMockPlayer(name: String, ironman: IronmanMode = IronmanMode.NONE): Player {
|
||||
val p = Player(PlayerDetails(name, name))
|
||||
p.details.session = ArtificialSession.getSingleton()
|
||||
p.ironmanManager.mode = ironman
|
||||
Repository.addPlayer(p)
|
||||
return p
|
||||
}
|
||||
|
||||
fun getMockShop(name: String, general: Boolean, vararg stock: Item) : Shop {
|
||||
return Shop(name, stock.map { ShopItem(it.id, it.amount, 100) }.toTypedArray(), general)
|
||||
}
|
||||
|
||||
fun preTestSetup() {
|
||||
if(ServerConstants.DATA_PATH == null) {
|
||||
ServerConfigParser.parse(this::class.java.getResource("test.conf"))
|
||||
Cache.init(this::class.java.getResource("cache").path.toString())
|
||||
ConfigParser().prePlugin()
|
||||
ConfigParser().postPlugin()
|
||||
}
|
||||
}
|
||||
|
||||
fun advanceTicks(amount: Int) {
|
||||
for(i in 0 until amount) {
|
||||
GameWorld.majorUpdateWorker.handleTickActions()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
[server]
|
||||
#Secret key - this is sent by the client during login.
|
||||
#Client/Server MUST match or connection is refused.
|
||||
secret_key = "2009scape_development"
|
||||
write_logs = true
|
||||
msip = "127.0.0.1"
|
||||
|
||||
[database]
|
||||
database_name = "global"
|
||||
database_username = "root"
|
||||
database_password = ""
|
||||
database_address = "127.0.0.1"
|
||||
database_port = "3306"
|
||||
|
||||
|
||||
[world]
|
||||
name = "2009scape"
|
||||
debug = true
|
||||
dev = true
|
||||
start_gui = false
|
||||
daily_restart = true
|
||||
#world number
|
||||
world_id = "1"
|
||||
country_id = "0"
|
||||
members = true
|
||||
#activity as displayed on the world list
|
||||
activity = "2009scape classic."
|
||||
pvp = false
|
||||
default_xp_rate = 5.0
|
||||
allow_slayer_reroll = false
|
||||
#enables a default clan for players to join automatically. Should be an account with the same name as @name, with a clan set up already.
|
||||
enable_default_clan = true
|
||||
enable_bots = true
|
||||
#message of the week model ID, 0 for random
|
||||
motw_identifier = "0"
|
||||
#text shown for message of the week - @name will be replaced with the name property set above.
|
||||
motw_text = "Welcome to @name!"
|
||||
#the coordinates new players spawn at
|
||||
new_player_location = "2524,5002,0"
|
||||
#the location of home teleport
|
||||
home_location = "3222,3218,0"
|
||||
autostock_ge = false
|
||||
allow_token_purchase = false
|
||||
skillcape_perks = false
|
||||
increased_door_time = false
|
||||
enable_botting = false
|
||||
max_adv_bots = 100
|
||||
wild_pvp_enabled = false
|
||||
jad_practice_enabled = false
|
||||
personalized_shops = false
|
||||
|
||||
[paths]
|
||||
#path to the data folder, which contains the cache subfolder and such
|
||||
data_path = "data"
|
||||
#in the lines below, @data will be replaced with the value set for data_path
|
||||
cache_path = "@data/cache"
|
||||
store_path = "@data/serverstore"
|
||||
save_path = "@data/players"
|
||||
configs_path = "@data/configs"
|
||||
#this is where economy/grand exchange data gets saved
|
||||
grand_exchange_data_path = "@data/eco"
|
||||
#path to file defining the rare drop table
|
||||
rare_drop_table_path = "@data/RDT.xml"
|
||||
#path to file defining c.ele minor drop table
|
||||
cele_drop_table_path = "@data/CELEDT.xml"
|
||||
#path to file containing boot-time object changes
|
||||
object_parser_path = "@data/ObjectParser.xml"
|
||||
#path logs are written to
|
||||
logs_path = "@data/logs"
|
||||
bot_data = "@data/botdata"
|
||||
eco_data = "@data/eco"
|
||||
Reference in New Issue
Block a user