Merge branch 'region_manager_thread_safety' into 'master'
Add thread safety to the region manager as well as a kotlin conversion. See merge request 2009scape/2009scape!72
This commit is contained in:
@@ -29,7 +29,7 @@ public final class SilverSicklePlugin extends OptionHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean handle(Player player, Node node, String option) {
|
public boolean handle(Player player, Node node, String option) {
|
||||||
Region region = RegionManager.getRegionCache().get(player.getLocation().getRegionId());
|
Region region = RegionManager.forId(player.getLocation().getRegionId());
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case "operate":
|
case "operate":
|
||||||
case "cast bloom":
|
case "cast bloom":
|
||||||
@@ -48,6 +48,7 @@ public final class SilverSicklePlugin extends OptionHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
RegionManager.getLock().unlock();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -761,7 +761,7 @@ public class Player extends Entity {
|
|||||||
*/
|
*/
|
||||||
public void updateSceneGraph(boolean login) {
|
public void updateSceneGraph(boolean login) {
|
||||||
Region region = getViewport().getRegion();
|
Region region = getViewport().getRegion();
|
||||||
if (region instanceof DynamicRegion || (region == null && (region = RegionManager.getRegionCache().get(location.getRegionId())) instanceof DynamicRegion || region == null)) {
|
if (region instanceof DynamicRegion || region == null && (region = RegionManager.forId(location.getRegionId())) instanceof DynamicRegion) {
|
||||||
PacketRepository.send(BuildDynamicScene.class, new DynamicSceneContext(this, login));
|
PacketRepository.send(BuildDynamicScene.class, new DynamicSceneContext(this, login));
|
||||||
} else {
|
} else {
|
||||||
PacketRepository.send(UpdateSceneGraph.class, new SceneGraphContext(this, login));
|
PacketRepository.send(UpdateSceneGraph.class, new SceneGraphContext(this, login));
|
||||||
|
|||||||
@@ -381,7 +381,7 @@ public final class HouseManager {
|
|||||||
region = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
region = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
||||||
region.setBorders(borders);
|
region.setBorders(borders);
|
||||||
region.setUpdateAllPlanes(true);
|
region.setUpdateAllPlanes(true);
|
||||||
RegionManager.getRegionCache().put(region.getId(), region);
|
RegionManager.addRegion(region.getId(), region);
|
||||||
configureRoofs();
|
configureRoofs();
|
||||||
for (int z = 0; z < 3; z++) {
|
for (int z = 0; z < 3; z++) {
|
||||||
for (int x = 0; x < 8; x++) {
|
for (int x = 0; x < 8; x++) {
|
||||||
@@ -406,7 +406,7 @@ public final class HouseManager {
|
|||||||
dungeon = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
dungeon = new DynamicRegion(-1, borders.getSouthWestX() >> 6, borders.getSouthWestY() >> 6);
|
||||||
dungeon.setBorders(borders);
|
dungeon.setBorders(borders);
|
||||||
dungeon.setUpdateAllPlanes(true);
|
dungeon.setUpdateAllPlanes(true);
|
||||||
RegionManager.getRegionCache().put(dungeon.getId(), dungeon);
|
RegionManager.addRegion(dungeon.getId(), dungeon);
|
||||||
for (int x = 0; x < 8; x++) {
|
for (int x = 0; x < 8; x++) {
|
||||||
for (int y = 0; y < 8; y++) {
|
for (int y = 0; y < 8; y++) {
|
||||||
Room room = rooms[3][x][y];
|
Room room = rooms[3][x][y];
|
||||||
|
|||||||
@@ -1,737 +0,0 @@
|
|||||||
package core.game.world.map;
|
|
||||||
|
|
||||||
import core.game.node.Node;
|
|
||||||
import core.game.node.entity.Entity;
|
|
||||||
import core.game.node.entity.npc.NPC;
|
|
||||||
import core.game.node.entity.player.Player;
|
|
||||||
import core.game.node.object.Scenery;
|
|
||||||
import rs09.game.system.SystemLogger;
|
|
||||||
import core.game.world.map.zone.ZoneBorders;
|
|
||||||
import core.tools.RandomFunction;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Manages the regions.
|
|
||||||
* @author Emperor
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public final class RegionManager {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The region cache mapping.
|
|
||||||
*/
|
|
||||||
private static final Map<Integer, Region> REGION_CACHE = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the region for the given region id.
|
|
||||||
* @param regionId The region id.
|
|
||||||
* @return The region.
|
|
||||||
*/
|
|
||||||
public static Region forId(int regionId) {
|
|
||||||
Region region = REGION_CACHE.get(regionId);
|
|
||||||
if (region == null) {
|
|
||||||
region = new Region(regionId >> 8 & 0xFF, regionId & 0xFF);
|
|
||||||
REGION_CACHE.put(regionId, region);
|
|
||||||
}
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pulses the active regions.
|
|
||||||
*/
|
|
||||||
public static void pulse() {
|
|
||||||
Object[] rCacheArray = new Object[0];
|
|
||||||
try {
|
|
||||||
rCacheArray = REGION_CACHE.values().toArray();
|
|
||||||
} catch (ConcurrentModificationException e){
|
|
||||||
SystemLogger.logErr("Region Cache tried to process too early -- restarting...");
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
int rCacheLength = rCacheArray.length;
|
|
||||||
for (int i = 0; i < rCacheLength; i++) {
|
|
||||||
Region r = (Region) rCacheArray[i];
|
|
||||||
if (r != null && r.isActive()) {
|
|
||||||
RegionPlane[] planes = r.getPlanes();
|
|
||||||
int size = planes.length;
|
|
||||||
for (int j = 0; j < size; j++) {
|
|
||||||
planes[j].pulse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the clipping flag on the given location.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The clipping flag.
|
|
||||||
*/
|
|
||||||
public static int getClippingFlag(Location l) {
|
|
||||||
return getClippingFlag(l.getZ(), l.getX(), l.getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the clipping flag.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The absolute x-coordinate.
|
|
||||||
* @param y The absolute y-coordinate.
|
|
||||||
* @return The clipping flags.
|
|
||||||
*/
|
|
||||||
public static int getClippingFlag(int z, int x, int y) {
|
|
||||||
Region region = forId((x >> 6) << 8 | y >> 6);
|
|
||||||
Region.load(region);
|
|
||||||
if (!region.isHasFlags()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
x -= (x >> 6) << 6;
|
|
||||||
y -= (y >> 6) << 6;
|
|
||||||
return region.getPlanes()[z].getFlags().getClippingFlags()[x][y];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the water variant of a tile's clipping flag
|
|
||||||
* Essentially strips the landscape flag off a tile and keeps other flags, and makes normally walkable tiles unwalkable.
|
|
||||||
* @author Ceikry
|
|
||||||
*/
|
|
||||||
public static int getWaterClipFlag(int z, int x, int y){
|
|
||||||
int flag = getClippingFlag(z,x,y);
|
|
||||||
if(!isClipped(z,x,y)){
|
|
||||||
return flag | 0x100;
|
|
||||||
}
|
|
||||||
return flag & (~0x200000);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the tile is part of the landscape.
|
|
||||||
* @param l The location.
|
|
||||||
* @return {@code True} if so.
|
|
||||||
*/
|
|
||||||
public static boolean isLandscape(Location l) {
|
|
||||||
return isLandscape(l.getZ(), l.getX(), l.getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the tile is part of the landscape.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The absolute x-coordinate.
|
|
||||||
* @param y The absolute y-coordinate.
|
|
||||||
* @return {@code True} if so.
|
|
||||||
*/
|
|
||||||
public static boolean isLandscape(int z, int x, int y) {
|
|
||||||
Region region = forId((x >> 6) << 8 | y >> 6);
|
|
||||||
Region.load(region);
|
|
||||||
if (!region.isHasFlags() || region.getPlanes()[z].getFlags().getLandscape() == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
x -= (x >> 6) << 6;
|
|
||||||
y -= (y >> 6) << 6;
|
|
||||||
return region.getPlanes()[z].getFlags().getLandscape()[x][y];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the clipping flag on the given location.
|
|
||||||
* @param l The location.
|
|
||||||
* @param flag The flag to set.
|
|
||||||
*/
|
|
||||||
public static void setClippingFlag(Location l, int flag) {
|
|
||||||
int x = l.getX();
|
|
||||||
int y = l.getY();
|
|
||||||
int z = l.getZ();
|
|
||||||
Region region = forId((x >> 6) << 8 | y >> 6);
|
|
||||||
Region.load(region);
|
|
||||||
if (!region.isHasFlags()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
x -= (x >> 6) << 6;
|
|
||||||
y -= (y >> 6) << 6;
|
|
||||||
region.getPlanes()[z].getFlags().getClippingFlags()[x][y] = flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a clipping flag.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The absolute x-coordinate.
|
|
||||||
* @param y The absolute y-coordinate.
|
|
||||||
* @param projectile If the flag is being set for projectile pathfinding.
|
|
||||||
* @param flag The clipping flag.
|
|
||||||
*/
|
|
||||||
public static void addClippingFlag(int z, int x, int y, boolean projectile, int flag) {
|
|
||||||
Region region = forId((x >> 6) << 8 | y >> 6);
|
|
||||||
Region.load(region);
|
|
||||||
if (!region.isHasFlags()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
x -= (x >> 6) << 6;
|
|
||||||
y -= (y >> 6) << 6;
|
|
||||||
if (projectile) {
|
|
||||||
region.getPlanes()[z].getProjectileFlags().flag(x, y, flag);
|
|
||||||
} else {
|
|
||||||
region.getPlanes()[z].getFlags().flag(x, y, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a clipping flag.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The absolute x-coordinate.
|
|
||||||
* @param y The absolute y-coordinate.
|
|
||||||
* @param projectile If the flag is being set for projectile pathfinding.
|
|
||||||
* @param flag The clipping flag.
|
|
||||||
*/
|
|
||||||
public static void removeClippingFlag(int z, int x, int y, boolean projectile, int flag) {
|
|
||||||
Region region = forId((x >> 6) << 8 | y >> 6);
|
|
||||||
Region.load(region);
|
|
||||||
if (!region.isHasFlags()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
x -= (x >> 6) << 6;
|
|
||||||
y -= (y >> 6) << 6;
|
|
||||||
if (projectile) {
|
|
||||||
region.getPlanes()[z].getProjectileFlags().unflag(x, y, flag);
|
|
||||||
} else {
|
|
||||||
region.getPlanes()[z].getFlags().unflag(x, y, flag);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the clipping flag.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The absolute x-coordinate.
|
|
||||||
* @param y The absolute y-coordinate.
|
|
||||||
* @return The clipping flags.
|
|
||||||
*/
|
|
||||||
public static int getProjectileFlag(int z, int x, int y) {
|
|
||||||
Region region = forId((x >> 6) << 8 | y >> 6);
|
|
||||||
Region.load(region);
|
|
||||||
if (!region.isHasFlags()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
x -= (x >> 6) << 6;
|
|
||||||
y -= (y >> 6) << 6;
|
|
||||||
return region.getPlanes()[z].getProjectileFlags().getClippingFlags()[x][y];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the clipping flag
|
|
||||||
* @param location the Location
|
|
||||||
* @return the clipping flag
|
|
||||||
*/
|
|
||||||
public static boolean isTeleportPermitted(Location location) {
|
|
||||||
return isTeleportPermitted(location.getZ(), location.getX(), location.getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the clipping flag.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The absolute x-coordinate.
|
|
||||||
* @param y The absolute y-coordinate.
|
|
||||||
* @return The clipping flags.
|
|
||||||
*/
|
|
||||||
public static boolean isTeleportPermitted(int z, int x, int y) {
|
|
||||||
if (!isLandscape(z, x, y)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
int flag = getClippingFlag(z, x, y);
|
|
||||||
return (flag & 0x12c0102) == 0 || (flag & 0x12c0108) == 0 || (flag & 0x12c0120) == 0 || (flag & 0x12c0180) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the location has any clipping flags.
|
|
||||||
* @param location The location.
|
|
||||||
* @return {@code True} if a clipping flag disables access for this location.
|
|
||||||
*/
|
|
||||||
public static boolean isClipped(Location location) {
|
|
||||||
return isClipped(location.getZ(), location.getX(), location.getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks if the location has any clipping flags.
|
|
||||||
* @param z The plane.
|
|
||||||
* @param x The x-coordinate.
|
|
||||||
* @param y The y-coordinate.
|
|
||||||
* @return {@code True} if a clipping flag disables access for this location.
|
|
||||||
*/
|
|
||||||
public static boolean isClipped(int z, int x, int y) {
|
|
||||||
if (!isLandscape(z, x, y)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
int flag = getClippingFlag(z, x, y);
|
|
||||||
return (flag & 0x12c0102) != 0 || (flag & 0x12c0108) != 0 || (flag & 0x12c0120) != 0 || (flag & 0x12c0180) != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the spawn location of a node.
|
|
||||||
* @param owner the owner.
|
|
||||||
* @param node the node.
|
|
||||||
* @return the location.
|
|
||||||
*/
|
|
||||||
public static Location getSpawnLocation(Player owner, Node node) {
|
|
||||||
if (owner == null || node == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
Location destination = null;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
Direction dir = Direction.get(i);
|
|
||||||
Location l = owner.getLocation().transform(dir, dir.toInteger() < 2 ? 1 : node.size());
|
|
||||||
boolean success = true;
|
|
||||||
loop:{
|
|
||||||
for (int x = 0; x < node.size(); x++) {
|
|
||||||
for (int y = 0; y < node.size(); y++) {
|
|
||||||
if (RegionManager.isClipped(l.transform(x, y, 0))) {
|
|
||||||
success = false;
|
|
||||||
break loop;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (success) {
|
|
||||||
destination = l;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the scenery on the current location.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The scenery, or {@code null} if no object was found.
|
|
||||||
*/
|
|
||||||
public static Scenery getObject(Location l) {
|
|
||||||
return getObject(l.getZ(), l.getX(), l.getY());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the scenery on the current absolute coordinates.
|
|
||||||
* @param z The height.
|
|
||||||
* @param x The x-coordinate.
|
|
||||||
* @param y The y-coordinate.
|
|
||||||
* @return The scenery, or {@code null} if no object was found.
|
|
||||||
*/
|
|
||||||
public static Scenery getObject(int z, int x, int y) {
|
|
||||||
return getObject(z, x, y, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the object on the given absolute coordinates.
|
|
||||||
* @param z The height.
|
|
||||||
* @param x The x-coordinate.
|
|
||||||
* @param y The y-coordinate.
|
|
||||||
* @param objectId The object id.
|
|
||||||
* @return The scenery, or {@code null} if no object was found.
|
|
||||||
*/
|
|
||||||
public static Scenery getObject(int z, int x, int y, int objectId) {
|
|
||||||
int regionId = ((x >> 6) << 8) | y >> 6;
|
|
||||||
x -= ((x >> 6) << 6);
|
|
||||||
y -= ((y >> 6) << 6);
|
|
||||||
Region region = forId(regionId);
|
|
||||||
Region.load(region);
|
|
||||||
Scenery object = region.getPlanes()[z].getChunkObject(x, y, objectId);
|
|
||||||
if (object != null && !object.isRenderable()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return object;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the region plane for this location.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The region plane.
|
|
||||||
*/
|
|
||||||
public static RegionPlane getRegionPlane(Location l) {
|
|
||||||
int regionId = ((l.getX() >> 6) << 8) | l.getY() >> 6;
|
|
||||||
return forId(regionId).getPlanes()[l.getZ()];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a region chunk.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The region chunk.
|
|
||||||
*/
|
|
||||||
public static RegionChunk getRegionChunk(Location l) {
|
|
||||||
RegionPlane plane = getRegionPlane(l);
|
|
||||||
return plane.getRegionChunk(l.getLocalX() / RegionChunk.SIZE, l.getLocalY() / RegionChunk.SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Moves the entity from the current region to the new one.
|
|
||||||
* @param entity The entity.
|
|
||||||
*/
|
|
||||||
public static void move(Entity entity) {
|
|
||||||
boolean player = entity instanceof Player;
|
|
||||||
int regionId = (entity.getLocation().getRegionX() >> 3) << 8 | (entity.getLocation().getRegionY() >> 3);
|
|
||||||
Viewport viewport = entity.getViewport();
|
|
||||||
Region current = forId(regionId);
|
|
||||||
int z = entity.getLocation().getZ();
|
|
||||||
RegionPlane plane = current.getPlanes()[z];
|
|
||||||
viewport.updateViewport(entity);
|
|
||||||
if (plane == viewport.getCurrentPlane()) {
|
|
||||||
entity.getZoneMonitor().updateLocation(entity.getWalkingQueue().getFootPrint());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
viewport.remove(entity);
|
|
||||||
if (player) {
|
|
||||||
current.add((Player) entity);
|
|
||||||
} else {
|
|
||||||
current.add((NPC) entity);
|
|
||||||
}
|
|
||||||
viewport.setRegion(current);
|
|
||||||
viewport.setCurrentPlane(plane);
|
|
||||||
List<RegionPlane> view = new LinkedList<>();
|
|
||||||
for (int regionX = (entity.getLocation().getRegionX() >> 3) - 1; regionX <= (entity.getLocation().getRegionX() >> 3) + 1; regionX++) {
|
|
||||||
for (int regionY = (entity.getLocation().getRegionY() >> 3) - 1; regionY <= (entity.getLocation().getRegionY() >> 3) + 1; regionY++) {
|
|
||||||
if (regionX < 0 || regionY < 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Region region = forId(regionX << 8 | regionY);
|
|
||||||
RegionPlane p = region.getPlanes()[z];
|
|
||||||
if (player) {
|
|
||||||
region.incrementViewAmount();
|
|
||||||
region.flagActive();
|
|
||||||
}
|
|
||||||
view.add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
viewport.setViewingPlanes(view);
|
|
||||||
entity.getZoneMonitor().updateLocation(entity.getWalkingQueue().getFootPrint());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of local NPCs with a maximum distance of 16.
|
|
||||||
* @param n The entity.
|
|
||||||
* @return The list of local NPCs.
|
|
||||||
*/
|
|
||||||
public static List<NPC> getLocalNpcs(Entity n) {
|
|
||||||
return getLocalNpcs(n, MapDistance.RENDERING.getDistance());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the location entitys.
|
|
||||||
* @param location the location.
|
|
||||||
* @param distance the distance.
|
|
||||||
* @return the list.
|
|
||||||
*/
|
|
||||||
public static List<Entity> getLocalEntitys(Location location, int distance){
|
|
||||||
List<Entity> entitys = new ArrayList<>(20);
|
|
||||||
entitys.addAll(getLocalNpcs(location, distance));
|
|
||||||
entitys.addAll(getLocalPlayers(location, distance));
|
|
||||||
return entitys;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the location entitys.
|
|
||||||
* @param entity the entity.
|
|
||||||
* @param distance the distance.
|
|
||||||
* @return the list.
|
|
||||||
*/
|
|
||||||
public static List<Entity> getLocalEntitys(Entity entity, int distance) {
|
|
||||||
return getLocalEntitys(entity.getLocation(), distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the local entitys.
|
|
||||||
* @param entity the entity.
|
|
||||||
* @return the entitys.
|
|
||||||
*/
|
|
||||||
public static List<Entity> getLocalEntitys(Entity entity) {
|
|
||||||
return getLocalEntitys(entity.getLocation(), MapDistance.RENDERING.getDistance());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of local NPCs.
|
|
||||||
* @param n The entity.
|
|
||||||
* @param distance The distance to the entity.
|
|
||||||
* @return The list of local NPCs.
|
|
||||||
*/
|
|
||||||
public static List<NPC> getLocalNpcs(Entity n, int distance) {
|
|
||||||
List<NPC> npcs = new LinkedList<>();
|
|
||||||
for (RegionPlane r : n.getViewport().getViewingPlanes()) {
|
|
||||||
for (NPC npc : r.getNpcs()) {
|
|
||||||
if (npc.getLocation().withinDistance(n.getLocation(), distance)) {
|
|
||||||
npcs.add(npc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return npcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of local players with a maximum distance of 15.
|
|
||||||
* @param n The entity.
|
|
||||||
* @return The list of local players.
|
|
||||||
*/
|
|
||||||
public static List<Player> getLocalPlayers(Entity n) {
|
|
||||||
return getLocalPlayers(n, MapDistance.RENDERING.getDistance());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the list of local players.
|
|
||||||
* @param n The entity.
|
|
||||||
* @param distance The distance to the entity.
|
|
||||||
* @return The list of local players.
|
|
||||||
*/
|
|
||||||
public static List<Player> getLocalPlayers(Entity n, int distance) {
|
|
||||||
List<Player> players = new LinkedList<>();
|
|
||||||
for (RegionPlane r : n.getViewport().getViewingPlanes()) {
|
|
||||||
for (Player p : r.getPlayers()) {
|
|
||||||
if (p.getLocation().withinDistance(n.getLocation(), distance)) {
|
|
||||||
players.add(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return players;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the surrounding players.
|
|
||||||
* @param n The node the players should be surrounding.
|
|
||||||
* @param ignore The nodes not to add to the list.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<Player> getSurroundingPlayers(Node n, Node...ignore) {
|
|
||||||
return getSurroundingPlayers(n, 9, ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the surrounding players.
|
|
||||||
* @param n The node the players should be surrounding.
|
|
||||||
* @param ignore The nodes not to add to the list.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<Player> getSurroundingPlayers(Node n, int maximum, Node...ignore) {
|
|
||||||
List<Player> players = getLocalPlayers(n.getLocation(), 1);
|
|
||||||
int count = 0;
|
|
||||||
for (Iterator<Player> it = players.iterator(); it.hasNext();) {
|
|
||||||
Player p = it.next();
|
|
||||||
if (++count >= maximum) {
|
|
||||||
it.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Node node : ignore) {
|
|
||||||
if (p == node) {
|
|
||||||
count--;
|
|
||||||
it.remove();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return players;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the surrounding players.
|
|
||||||
* @param n The node the players should be surrounding.
|
|
||||||
* @param ignore The nodes not to add to the list.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<NPC> getSurroundingNPCs(Node n, Node...ignore) {
|
|
||||||
return getSurroundingNPCs(n, 9, ignore);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the surrounding players.
|
|
||||||
* @param n The node the npcs should be surrounding.
|
|
||||||
* @param ignore The nodes not to add to the list.
|
|
||||||
* @return The list of npcs.
|
|
||||||
*/
|
|
||||||
public static List<NPC> getSurroundingNPCs(Node n, int maximum, Node...ignore) {
|
|
||||||
List<NPC> npcs = getLocalNpcs(n.getLocation(), 1);
|
|
||||||
int count = 0;
|
|
||||||
for (Iterator<NPC> it = npcs.iterator(); it.hasNext();) {
|
|
||||||
NPC p = it.next();
|
|
||||||
if (++count > maximum) {
|
|
||||||
it.remove();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (Node node : ignore) {
|
|
||||||
if (p == node) {
|
|
||||||
count--;
|
|
||||||
it.remove();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return npcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a random teleport location in the radius around the given location.
|
|
||||||
* @param location The centre location.
|
|
||||||
* @param radius The radius.
|
|
||||||
* @return A random teleport location.
|
|
||||||
*/
|
|
||||||
public static Location getTeleportLocation(Location location, int radius) {
|
|
||||||
int mod = radius >> 1;
|
|
||||||
if (mod == 0) {
|
|
||||||
mod++;
|
|
||||||
radius--;
|
|
||||||
}
|
|
||||||
return getTeleportLocation(location.transform(-mod, -mod, 0), mod + radius, mod + radius);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a random teleport location in the radius around the given location.
|
|
||||||
* @param location The centre location.
|
|
||||||
* @return A random teleport location.
|
|
||||||
*/
|
|
||||||
public static Location getTeleportLocation(Location location, int areaX, int areaY) {
|
|
||||||
Location destination = location;
|
|
||||||
int x = RandomFunction.random(1 + areaX);
|
|
||||||
int y = RandomFunction.random(1 + areaY);
|
|
||||||
int count = 0;
|
|
||||||
while (!isTeleportPermitted(destination = location.transform(x, y, 0))) {
|
|
||||||
x = RandomFunction.random(1 + areaX);
|
|
||||||
y = RandomFunction.random(1 + areaY);
|
|
||||||
if (count++ >= areaX * 2) {
|
|
||||||
//This would be able to keep looping for several seconds otherwise (this actually happens).
|
|
||||||
for (x = 0; x < areaX + 1; x++) {
|
|
||||||
for (y = 0; y < areaY + 1; y++) {
|
|
||||||
if (isTeleportPermitted(destination = location.transform(x, y, 0))) {
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return destination;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current viewport for the location.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The viewport.
|
|
||||||
*/
|
|
||||||
public static List<Player> getViewportPlayers(Location l) {
|
|
||||||
List<Player> players = new LinkedList<>();
|
|
||||||
l = l.getChunkBase().transform(-8, -8, 0);
|
|
||||||
ZoneBorders b = new ZoneBorders(l.getX(), l.getY(), l.getX() + 24, l.getY() + 24);
|
|
||||||
for (int regionX = (l.getRegionX() - 6) >> 3; regionX <= (l.getRegionX() + 6) >> 3; regionX++) {
|
|
||||||
for (int regionY = (l.getRegionY() - 6) >> 3; regionY <= (l.getRegionY() + 6) >> 3; regionY++) {
|
|
||||||
for (Player player : forId(regionX << 8 | regionY).getPlanes()[l.getZ()].getPlayers()) {
|
|
||||||
l = player.getLocation();
|
|
||||||
if (b.insideBorder(l.getX(), l.getY())) {
|
|
||||||
players.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return players;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of players in the given region.
|
|
||||||
* @param regionId The region id.
|
|
||||||
* @return The list of players in this region.
|
|
||||||
*/
|
|
||||||
public static List<Player> getRegionPlayers(int regionId) {
|
|
||||||
Region r = forId(regionId);
|
|
||||||
List<Player> players = new ArrayList<>(20);
|
|
||||||
for (RegionPlane plane : r.getPlanes()) {
|
|
||||||
players.addAll(plane.getPlayers());
|
|
||||||
}
|
|
||||||
return players;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of local players within rendering distance of the location.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<Player> getLocalPlayers(Location l) {
|
|
||||||
return getLocalPlayers(l, MapDistance.RENDERING.getDistance());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of local players.
|
|
||||||
* @param l The location.
|
|
||||||
* @param distance The distance to that location.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<Player> getLocalPlayers(Location l, int distance) {
|
|
||||||
List<Player> players = new LinkedList<>();
|
|
||||||
for (int regionX = (l.getRegionX() - 6) >> 3; regionX <= (l.getRegionX() + 6) >> 3; regionX++) {
|
|
||||||
for (int regionY = (l.getRegionY() - 6) >> 3; regionY <= (l.getRegionY() + 6) >> 3; regionY++) {
|
|
||||||
for (Player player : forId(regionX << 8 | regionY).getPlanes()[l.getZ()].getPlayers()) {
|
|
||||||
if (player.getLocation().withinDistance(l, distance)) {
|
|
||||||
players.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return players;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of local players within 16 tile distance of the location.
|
|
||||||
* @param l The location.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<NPC> getLocalNpcs(Location l) {
|
|
||||||
return getLocalNpcs(l, MapDistance.RENDERING.getDistance());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the npc.
|
|
||||||
* @param entity the entity.
|
|
||||||
* @param id the id.
|
|
||||||
*/
|
|
||||||
public static NPC getNpc(final Entity entity, final int id) {
|
|
||||||
return getNpc(entity, id, 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the npc.
|
|
||||||
* @param entity the entity.
|
|
||||||
* @param id the id.
|
|
||||||
* @param distance the distance.
|
|
||||||
* @return the npc.
|
|
||||||
*/
|
|
||||||
public static NPC getNpc(Entity entity, int id, int distance) {
|
|
||||||
return getNpc(entity.getLocation(), id, distance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets an npc near the entity.
|
|
||||||
* @param id the id,
|
|
||||||
* @param distance the dinstance.
|
|
||||||
* @return the npc.
|
|
||||||
*/
|
|
||||||
public static NPC getNpc(final Location location, int id, int distance) {
|
|
||||||
List<NPC> npcs = getLocalNpcs(location, distance);
|
|
||||||
for (NPC n : npcs) {
|
|
||||||
if (n.getId() == id) {
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a list of local players.
|
|
||||||
* @param l The location.
|
|
||||||
* @param distance The distance to that location.
|
|
||||||
* @return The list of players.
|
|
||||||
*/
|
|
||||||
public static List<NPC> getLocalNpcs(Location l, int distance) {
|
|
||||||
List<NPC> npcs = new LinkedList<>();
|
|
||||||
for (int regionX = (l.getRegionX() - 6) >> 3; regionX <= (l.getRegionX() + 6) >> 3; regionX++) {
|
|
||||||
for (int regionY = (l.getRegionY() - 6) >> 3; regionY <= (l.getRegionY() + 6) >> 3; regionY++) {
|
|
||||||
for (NPC n : forId(regionX << 8 | regionY).getPlanes()[l.getZ()].getNpcs()) {
|
|
||||||
if (n.getLocation().withinDistance(l, (n.size() >> 1) + distance)) {
|
|
||||||
npcs.add(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return npcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the regionCache.
|
|
||||||
* @return The regionCache.
|
|
||||||
*/
|
|
||||||
public static Map<Integer, Region> getRegionCache() {
|
|
||||||
return REGION_CACHE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,807 @@
|
|||||||
|
package core.game.world.map
|
||||||
|
|
||||||
|
import core.game.world.map.RegionManager
|
||||||
|
import core.game.world.map.RegionPlane
|
||||||
|
import core.game.node.`object`.Scenery
|
||||||
|
import core.game.node.Node
|
||||||
|
import core.game.node.entity.Entity
|
||||||
|
import core.game.node.entity.npc.NPC
|
||||||
|
import core.game.node.entity.player.Player
|
||||||
|
import core.game.world.map.zone.ZoneBorders
|
||||||
|
import core.tools.RandomFunction
|
||||||
|
import rs09.game.system.SystemLogger
|
||||||
|
import java.util.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manages the regions.
|
||||||
|
* @author Emperor
|
||||||
|
*/
|
||||||
|
object RegionManager {
|
||||||
|
/**
|
||||||
|
* The region cache mapping.
|
||||||
|
*/
|
||||||
|
private val REGION_CACHE: MutableMap<Int, Region> = HashMap()
|
||||||
|
|
||||||
|
public val LOCK = ReentrantLock()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the region for the given region id.
|
||||||
|
* @param regionId The region id.
|
||||||
|
* @return The region.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun forId(regionId: Int): Region {
|
||||||
|
LOCK.tryLock(10000, TimeUnit.MILLISECONDS)
|
||||||
|
var region = REGION_CACHE[regionId]
|
||||||
|
if (region == null) {
|
||||||
|
region = Region((regionId shr 8) and 0xFF, regionId and 0xFF)
|
||||||
|
if(region!!.regionId != regionId){
|
||||||
|
SystemLogger.logErr("IDs do NOT match - ${region!!.regionId} supposed to be $regionId")
|
||||||
|
}
|
||||||
|
REGION_CACHE[regionId] = region
|
||||||
|
}
|
||||||
|
LOCK.unlock()
|
||||||
|
return REGION_CACHE[regionId]!!
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pulses the active regions.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun pulse() {
|
||||||
|
LOCK.tryLock(10000,TimeUnit.MILLISECONDS)
|
||||||
|
for (r in REGION_CACHE.values) {
|
||||||
|
if (r != null && r.isActive) {
|
||||||
|
for (p in r.planes) {
|
||||||
|
p.pulse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOCK.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the clipping flag on the given location.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The clipping flag.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getClippingFlag(l: Location): Int {
|
||||||
|
return getClippingFlag(l.z, l.x, l.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the clipping flag.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The absolute x-coordinate.
|
||||||
|
* @param y The absolute y-coordinate.
|
||||||
|
* @return The clipping flags.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getClippingFlag(z: Int, x: Int, y: Int): Int {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
val region = forId(((x shr 6) shl 8) or (y shr 6))
|
||||||
|
Region.load(region)
|
||||||
|
if (!region.isHasFlags) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
x -= x shr 6 shl 6
|
||||||
|
y -= y shr 6 shl 6
|
||||||
|
return region.planes[z].flags.clippingFlags[x][y]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the water variant of a tile's clipping flag
|
||||||
|
* Essentially strips the landscape flag off a tile and keeps other flags, and makes normally walkable tiles unwalkable.
|
||||||
|
* @author Ceikry
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getWaterClipFlag(z: Int, x: Int, y: Int): Int {
|
||||||
|
val flag = getClippingFlag(z, x, y)
|
||||||
|
return if (!isClipped(z, x, y)) {
|
||||||
|
flag or 0x100
|
||||||
|
} else flag and 0x200000.inv()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the tile is part of the landscape.
|
||||||
|
* @param l The location.
|
||||||
|
* @return `True` if so.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun isLandscape(l: Location): Boolean {
|
||||||
|
return isLandscape(l.z, l.x, l.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the tile is part of the landscape.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The absolute x-coordinate.
|
||||||
|
* @param y The absolute y-coordinate.
|
||||||
|
* @return `True` if so.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun isLandscape(z: Int, x: Int, y: Int): Boolean {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
val region = forId(((x shr 6) shl 8) or (y shr 6))
|
||||||
|
Region.load(region)
|
||||||
|
if (!region.isHasFlags || region.planes[z].flags.landscape == null) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
x -= x shr 6 shl 6
|
||||||
|
y -= y shr 6 shl 6
|
||||||
|
return region.planes[z].flags.landscape[x][y]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the clipping flag on the given location.
|
||||||
|
* @param l The location.
|
||||||
|
* @param flag The flag to set.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun setClippingFlag(l: Location, flag: Int) {
|
||||||
|
var x = l.x
|
||||||
|
var y = l.y
|
||||||
|
val z = l.z
|
||||||
|
val region = forId(((x shr 6) shl 8) or (y shr 6))
|
||||||
|
Region.load(region)
|
||||||
|
if (!region.isHasFlags) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
x -= x shr 6 shl 6
|
||||||
|
y -= y shr 6 shl 6
|
||||||
|
region.planes[z].flags.clippingFlags[x][y] = flag
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a clipping flag.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The absolute x-coordinate.
|
||||||
|
* @param y The absolute y-coordinate.
|
||||||
|
* @param projectile If the flag is being set for projectile pathfinding.
|
||||||
|
* @param flag The clipping flag.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun addClippingFlag(z: Int, x: Int, y: Int, projectile: Boolean, flag: Int) {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
val region = forId(((x shr 6) shl 8) or (y shr 6))
|
||||||
|
Region.load(region)
|
||||||
|
if (!region.isHasFlags) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
x -= x shr 6 shl 6
|
||||||
|
y -= y shr 6 shl 6
|
||||||
|
if (projectile) {
|
||||||
|
region.planes[z].projectileFlags.flag(x, y, flag)
|
||||||
|
} else {
|
||||||
|
region.planes[z].flags.flag(x, y, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a clipping flag.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The absolute x-coordinate.
|
||||||
|
* @param y The absolute y-coordinate.
|
||||||
|
* @param projectile If the flag is being set for projectile pathfinding.
|
||||||
|
* @param flag The clipping flag.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun removeClippingFlag(z: Int, x: Int, y: Int, projectile: Boolean, flag: Int) {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
val region = forId(((x shr 6) shl 8) or (y shr 6))
|
||||||
|
Region.load(region)
|
||||||
|
if (!region.isHasFlags) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
x -= x shr 6 shl 6
|
||||||
|
y -= y shr 6 shl 6
|
||||||
|
if (projectile) {
|
||||||
|
region.planes[z].projectileFlags.unflag(x, y, flag)
|
||||||
|
} else {
|
||||||
|
region.planes[z].flags.unflag(x, y, flag)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the clipping flag.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The absolute x-coordinate.
|
||||||
|
* @param y The absolute y-coordinate.
|
||||||
|
* @return The clipping flags.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getProjectileFlag(z: Int, x: Int, y: Int): Int {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
val region = forId(((x shr 6) shl 8) or (y shr 6))
|
||||||
|
Region.load(region)
|
||||||
|
if (!region.isHasFlags) {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
x -= x shr 6 shl 6
|
||||||
|
y -= y shr 6 shl 6
|
||||||
|
return region.planes[z].projectileFlags.clippingFlags[x][y]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the clipping flag
|
||||||
|
* @param location the Location
|
||||||
|
* @return the clipping flag
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun isTeleportPermitted(location: Location): Boolean {
|
||||||
|
return isTeleportPermitted(location.z, location.x, location.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the clipping flag.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The absolute x-coordinate.
|
||||||
|
* @param y The absolute y-coordinate.
|
||||||
|
* @return The clipping flags.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun isTeleportPermitted(z: Int, x: Int, y: Int): Boolean {
|
||||||
|
if (!isLandscape(z, x, y)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
val flag = getClippingFlag(z, x, y)
|
||||||
|
return flag and 0x12c0102 == 0 || flag and 0x12c0108 == 0 || flag and 0x12c0120 == 0 || flag and 0x12c0180 == 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the location has any clipping flags.
|
||||||
|
* @param location The location.
|
||||||
|
* @return `True` if a clipping flag disables access for this location.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun isClipped(location: Location): Boolean {
|
||||||
|
return isClipped(location.z, location.x, location.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the location has any clipping flags.
|
||||||
|
* @param z The plane.
|
||||||
|
* @param x The x-coordinate.
|
||||||
|
* @param y The y-coordinate.
|
||||||
|
* @return `True` if a clipping flag disables access for this location.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun isClipped(z: Int, x: Int, y: Int): Boolean {
|
||||||
|
if (!isLandscape(z, x, y)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
val flag = getClippingFlag(z, x, y)
|
||||||
|
return flag and 0x12c0102 != 0 || flag and 0x12c0108 != 0 || flag and 0x12c0120 != 0 || flag and 0x12c0180 != 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the spawn location of a node.
|
||||||
|
* @param owner the owner.
|
||||||
|
* @param node the node.
|
||||||
|
* @return the location.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getSpawnLocation(owner: Player?, node: Node?): Location? {
|
||||||
|
if (owner == null || node == null) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
var destination: Location? = null
|
||||||
|
for (i in 0..3) {
|
||||||
|
val dir = Direction.get(i)
|
||||||
|
val l = owner.location.transform(dir, if (dir.toInteger() < 2) 1 else node.size())
|
||||||
|
var success = true
|
||||||
|
for (x in 0 until node.size()) {
|
||||||
|
for (y in 0 until node.size()) {
|
||||||
|
if (isClipped(l.transform(x, y, 0))) {
|
||||||
|
success = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (success) {
|
||||||
|
destination = l
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the scenery on the current location.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The scenery, or `null` if no object was found.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getObject(l: Location): Scenery? {
|
||||||
|
return getObject(l.z, l.x, l.y)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the scenery on the current absolute coordinates.
|
||||||
|
* @param z The height.
|
||||||
|
* @param x The x-coordinate.
|
||||||
|
* @param y The y-coordinate.
|
||||||
|
* @return The scenery, or `null` if no object was found.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getObject(z: Int, x: Int, y: Int): Scenery? {
|
||||||
|
return getObject(z, x, y, -1)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the object on the given absolute coordinates.
|
||||||
|
* @param z The height.
|
||||||
|
* @param x The x-coordinate.
|
||||||
|
* @param y The y-coordinate.
|
||||||
|
* @param objectId The object id.
|
||||||
|
* @return The scenery, or `null` if no object was found.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getObject(z: Int, x: Int, y: Int, objectId: Int): Scenery? {
|
||||||
|
var x = x
|
||||||
|
var y = y
|
||||||
|
val regionId = ((x shr 6) shl 8) or (y shr 6)
|
||||||
|
x -= (x shr 6) shl 6
|
||||||
|
y -= (y shr 6) shl 6
|
||||||
|
val region = forId(regionId)
|
||||||
|
Region.load(region)
|
||||||
|
val `object`: Scenery? = region.planes[z].getChunkObject(x, y, objectId)
|
||||||
|
return if (`object` != null && !`object`.isRenderable()) {
|
||||||
|
null
|
||||||
|
} else `object`
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the region plane for this location.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The region plane.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getRegionPlane(l: Location): RegionPlane {
|
||||||
|
val regionId = ((l.x shr 6) shl 8) or (l.y shr 6)
|
||||||
|
return forId(regionId).planes[l.z]
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a region chunk.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The region chunk.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getRegionChunk(l: Location): RegionChunk {
|
||||||
|
val plane = getRegionPlane(l)
|
||||||
|
return plane.getRegionChunk(l.localX / RegionChunk.SIZE, l.localY / RegionChunk.SIZE)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the entity from the current region to the new one.
|
||||||
|
* @param entity The entity.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun move(entity: Entity) {
|
||||||
|
val player = entity is Player
|
||||||
|
val regionId = ((entity.location.regionX shr 3) shl 8) or (entity.location.regionY shr 3)
|
||||||
|
val viewport = entity.viewport
|
||||||
|
val current = forId(regionId)
|
||||||
|
val z = entity.location.z
|
||||||
|
val plane = current.planes[z]
|
||||||
|
viewport.updateViewport(entity)
|
||||||
|
if (plane == viewport.currentPlane) {
|
||||||
|
entity.zoneMonitor.updateLocation(entity.walkingQueue.footPrint)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
viewport.remove(entity)
|
||||||
|
if (player) {
|
||||||
|
current.add(entity as Player)
|
||||||
|
} else {
|
||||||
|
current.add(entity as NPC)
|
||||||
|
}
|
||||||
|
viewport.region = current
|
||||||
|
viewport.currentPlane = plane
|
||||||
|
val view: MutableList<RegionPlane> = LinkedList()
|
||||||
|
for (regionX in ((entity.location.regionX shr 3) - 1)..((entity.location.regionX shr 3) + 1)) {
|
||||||
|
for (regionY in ((entity.location.regionY shr 3) - 1)..((entity.location.regionY shr 3) + 1)) {
|
||||||
|
if (regionX < 0 || regionY < 0) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
val region = forId((regionX shl 8) or regionY)
|
||||||
|
val p = region.planes[z]
|
||||||
|
if (player) {
|
||||||
|
region.incrementViewAmount()
|
||||||
|
region.flagActive()
|
||||||
|
}
|
||||||
|
view.add(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewport.viewingPlanes = view
|
||||||
|
entity.zoneMonitor.updateLocation(entity.walkingQueue.footPrint)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of local NPCs with a maximum distance of 16.
|
||||||
|
* @param n The entity.
|
||||||
|
* @return The list of local NPCs.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalNpcs(n: Entity): List<NPC> {
|
||||||
|
return getLocalNpcs(n, MapDistance.RENDERING.distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the location entitys.
|
||||||
|
* @param location the location.
|
||||||
|
* @param distance the distance.
|
||||||
|
* @return the list.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalEntitys(location: Location, distance: Int): List<Entity> {
|
||||||
|
val entitys: MutableList<Entity> = ArrayList(20)
|
||||||
|
entitys.addAll(getLocalNpcs(location, distance))
|
||||||
|
entitys.addAll(getLocalPlayers(location, distance))
|
||||||
|
return entitys
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the location entitys.
|
||||||
|
* @param entity the entity.
|
||||||
|
* @param distance the distance.
|
||||||
|
* @return the list.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalEntitys(entity: Entity, distance: Int): List<Entity> {
|
||||||
|
return getLocalEntitys(entity.location, distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the local entitys.
|
||||||
|
* @param entity the entity.
|
||||||
|
* @return the entitys.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalEntitys(entity: Entity): List<Entity> {
|
||||||
|
return getLocalEntitys(entity.location, MapDistance.RENDERING.distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of local NPCs.
|
||||||
|
* @param n The entity.
|
||||||
|
* @param distance The distance to the entity.
|
||||||
|
* @return The list of local NPCs.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalNpcs(n: Entity, distance: Int): List<NPC> {
|
||||||
|
val npcs: MutableList<NPC> = LinkedList()
|
||||||
|
for (r in n.viewport.viewingPlanes) {
|
||||||
|
for (npc in r.npcs) {
|
||||||
|
if (npc.location.withinDistance(n.location, distance)) {
|
||||||
|
npcs.add(npc)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npcs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of local players with a maximum distance of 15.
|
||||||
|
* @param n The entity.
|
||||||
|
* @return The list of local players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalPlayers(n: Entity): List<Player> {
|
||||||
|
return getLocalPlayers(n, MapDistance.RENDERING.distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the list of local players.
|
||||||
|
* @param n The entity.
|
||||||
|
* @param distance The distance to the entity.
|
||||||
|
* @return The list of local players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalPlayers(n: Entity, distance: Int): List<Player> {
|
||||||
|
val players: MutableList<Player> = LinkedList()
|
||||||
|
for (r in n.viewport.viewingPlanes) {
|
||||||
|
for (p in r.players) {
|
||||||
|
if (p.location.withinDistance(n.location, distance)) {
|
||||||
|
players.add(p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the surrounding players.
|
||||||
|
* @param n The node the players should be surrounding.
|
||||||
|
* @param ignore The nodes not to add to the list.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getSurroundingPlayers(n: Node, vararg ignore: Node): List<Player> {
|
||||||
|
return getSurroundingPlayers(n, 9, *ignore)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the surrounding players.
|
||||||
|
* @param n The node the players should be surrounding.
|
||||||
|
* @param ignore The nodes not to add to the list.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getSurroundingPlayers(n: Node, maximum: Int, vararg ignore: Node): List<Player> {
|
||||||
|
val players = getLocalPlayers(n.location, 1)
|
||||||
|
var count = 0
|
||||||
|
val it = players.iterator()
|
||||||
|
while (it.hasNext()) {
|
||||||
|
val p = it.next()
|
||||||
|
if (++count >= maximum) {
|
||||||
|
it.remove()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for (node in ignore) {
|
||||||
|
if (p === node) {
|
||||||
|
count--
|
||||||
|
it.remove()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the surrounding players.
|
||||||
|
* @param n The node the players should be surrounding.
|
||||||
|
* @param ignore The nodes not to add to the list.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getSurroundingNPCs(n: Node, vararg ignore: Node): List<NPC> {
|
||||||
|
return getSurroundingNPCs(n, 9, *ignore)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the surrounding players.
|
||||||
|
* @param n The node the npcs should be surrounding.
|
||||||
|
* @param ignore The nodes not to add to the list.
|
||||||
|
* @return The list of npcs.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getSurroundingNPCs(n: Node, maximum: Int, vararg ignore: Node): List<NPC> {
|
||||||
|
val npcs = getLocalNpcs(n.location, 1)
|
||||||
|
var count = 0
|
||||||
|
val it = npcs.iterator()
|
||||||
|
while (it.hasNext()) {
|
||||||
|
val p = it.next()
|
||||||
|
if (++count > maximum) {
|
||||||
|
it.remove()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for (node in ignore) {
|
||||||
|
if (p === node) {
|
||||||
|
count--
|
||||||
|
it.remove()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npcs
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a random teleport location in the radius around the given location.
|
||||||
|
* @param location The centre location.
|
||||||
|
* @param radius The radius.
|
||||||
|
* @return A random teleport location.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getTeleportLocation(location: Location, radius: Int): Location {
|
||||||
|
var radius = radius
|
||||||
|
var mod = radius shr 1
|
||||||
|
if (mod == 0) {
|
||||||
|
mod++
|
||||||
|
radius--
|
||||||
|
}
|
||||||
|
return getTeleportLocation(location.transform(-mod, -mod, 0), mod + radius, mod + radius)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a random teleport location in the radius around the given location.
|
||||||
|
* @param location The centre location.
|
||||||
|
* @return A random teleport location.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getTeleportLocation(location: Location, areaX: Int, areaY: Int): Location {
|
||||||
|
var destination = location
|
||||||
|
var x: Int = RandomFunction.random(1 + areaX)
|
||||||
|
var y: Int = RandomFunction.random(1 + areaY)
|
||||||
|
var count = 0
|
||||||
|
while (!isTeleportPermitted(location.transform(x, y, 0).also { destination = it })) {
|
||||||
|
x = RandomFunction.random(1 + areaX)
|
||||||
|
y = RandomFunction.random(1 + areaY)
|
||||||
|
if (count++ >= areaX * 2) {
|
||||||
|
//This would be able to keep looping for several seconds otherwise (this actually happens).
|
||||||
|
x = 0
|
||||||
|
while (x < areaX + 1) {
|
||||||
|
y = 0
|
||||||
|
while (y < areaY + 1) {
|
||||||
|
if (isTeleportPermitted(location.transform(x, y, 0).also { destination = it })) {
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
y++
|
||||||
|
}
|
||||||
|
x++
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return destination
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current viewport for the location.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The viewport.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getViewportPlayers(l: Location): List<Player> {
|
||||||
|
var l = l
|
||||||
|
val players: MutableList<Player> = LinkedList()
|
||||||
|
l = l.chunkBase.transform(-8, -8, 0)
|
||||||
|
val b = ZoneBorders(l.x, l.y, l.x + 24, l.y + 24)
|
||||||
|
for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) {
|
||||||
|
for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) {
|
||||||
|
for (player in forId(regionX shl 8 or regionY).planes[l.z].players) {
|
||||||
|
l = player.location
|
||||||
|
if (b.insideBorder(l.x, l.y)) {
|
||||||
|
players.add(player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of players in the given region.
|
||||||
|
* @param regionId The region id.
|
||||||
|
* @return The list of players in this region.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getRegionPlayers(regionId: Int): List<Player> {
|
||||||
|
val r = forId(regionId)
|
||||||
|
val players: MutableList<Player> = ArrayList(20)
|
||||||
|
for (plane in r.planes) {
|
||||||
|
players.addAll(plane.players)
|
||||||
|
}
|
||||||
|
return players
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of local players within rendering distance of the location.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalPlayers(l: Location): List<Player> {
|
||||||
|
return getLocalPlayers(l, MapDistance.RENDERING.distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of local players.
|
||||||
|
* @param l The location.
|
||||||
|
* @param distance The distance to that location.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalPlayers(l: Location, distance: Int): MutableList<Player> {
|
||||||
|
val players: MutableList<Player> = LinkedList()
|
||||||
|
for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) {
|
||||||
|
for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) {
|
||||||
|
for (player in forId((regionX shl 8) or regionY).planes[l.z].players) {
|
||||||
|
if (player.location.withinDistance(l, distance)) {
|
||||||
|
players.add(player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return players
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of local players within 16 tile distance of the location.
|
||||||
|
* @param l The location.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalNpcs(l: Location): List<NPC> {
|
||||||
|
return getLocalNpcs(l, MapDistance.RENDERING.distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the npc.
|
||||||
|
* @param entity the entity.
|
||||||
|
* @param id the id.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getNpc(entity: Entity, id: Int): NPC? {
|
||||||
|
return getNpc(entity, id, 16)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the npc.
|
||||||
|
* @param entity the entity.
|
||||||
|
* @param id the id.
|
||||||
|
* @param distance the distance.
|
||||||
|
* @return the npc.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getNpc(entity: Entity, id: Int, distance: Int): NPC? {
|
||||||
|
return getNpc(entity.location, id, distance)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an npc near the entity.
|
||||||
|
* @param id the id,
|
||||||
|
* @param distance the dinstance.
|
||||||
|
* @return the npc.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getNpc(location: Location, id: Int, distance: Int): NPC? {
|
||||||
|
val npcs: List<NPC> = getLocalNpcs(location, distance)
|
||||||
|
for (n in npcs) {
|
||||||
|
if (n.id == id) {
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of local players.
|
||||||
|
* @param l The location.
|
||||||
|
* @param distance The distance to that location.
|
||||||
|
* @return The list of players.
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun getLocalNpcs(l: Location, distance: Int): MutableList<NPC> {
|
||||||
|
val npcs: MutableList<NPC> = LinkedList()
|
||||||
|
for (regionX in ((l.regionX - 6) shr 3)..((l.regionX + 6) shr 3)) {
|
||||||
|
for (regionY in ((l.regionY - 6) shr 3)..((l.regionY + 6) shr 3)) {
|
||||||
|
for (n in forId(regionX shl 8 or regionY).planes[l.z].npcs) {
|
||||||
|
if (n.location.withinDistance(l, (n.size() shr 1) + distance)) {
|
||||||
|
npcs.add(n)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npcs
|
||||||
|
}
|
||||||
|
|
||||||
|
@JvmStatic
|
||||||
|
fun addRegion(id: Int, region: Region){
|
||||||
|
LOCK.tryLock(10000, TimeUnit.MILLISECONDS)
|
||||||
|
REGION_CACHE[id] = region
|
||||||
|
LOCK.unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the regionCache.
|
||||||
|
* @return The regionCache.
|
||||||
|
*/
|
||||||
|
val regionCache: Map<Int, Region>
|
||||||
|
@JvmStatic get(){
|
||||||
|
return REGION_CACHE
|
||||||
|
}
|
||||||
|
|
||||||
|
val lock: ReentrantLock
|
||||||
|
@JvmStatic get() = LOCK
|
||||||
|
}
|
||||||
@@ -122,14 +122,14 @@ public final class DynamicRegion extends Region {
|
|||||||
Location loc = l.transform((x - baseX) << 6, (y - baseY) << 6, 0);
|
Location loc = l.transform((x - baseX) << 6, (y - baseY) << 6, 0);
|
||||||
DynamicRegion region = copy(regionId, loc);
|
DynamicRegion region = copy(regionId, loc);
|
||||||
region.setBorders(border);
|
region.setBorders(border);
|
||||||
Region r = RegionManager.getRegionCache().get(region.getId());
|
Region r = RegionManager.forId(region.getId());
|
||||||
if (r != null) {
|
if (r != null) {
|
||||||
for (int z = 0; z < 4; z++) {
|
for (int z = 0; z < 4; z++) {
|
||||||
region.getPlanes()[z].getPlayers().addAll(r.getPlanes()[z].getPlayers());
|
region.getPlanes()[z].getPlayers().addAll(r.getPlanes()[z].getPlayers());
|
||||||
region.getPlanes()[z].getNpcs().addAll(r.getPlanes()[z].getNpcs());
|
region.getPlanes()[z].getNpcs().addAll(r.getPlanes()[z].getNpcs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RegionManager.getRegionCache().put(region.getId(), region);
|
RegionManager.addRegion(region.getId(), region);
|
||||||
regions.add(region);
|
regions.add(region);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,7 +247,7 @@ class ScriptAPI(private val bot: Player) {
|
|||||||
* @return an Array of the nearest NPCs with matching name, or null.
|
* @return an Array of the nearest NPCs with matching name, or null.
|
||||||
* @author Ceikry
|
* @author Ceikry
|
||||||
*/
|
*/
|
||||||
private fun findTargets(entity: Entity?, radius: Int, name: String? = null): List<Entity>? {
|
private fun findTargets(entity: Entity, radius: Int, name: String? = null): List<Entity>? {
|
||||||
val targets: MutableList<Entity> = ArrayList()
|
val targets: MutableList<Entity> = ArrayList()
|
||||||
val localNPCs: Array<Any> = RegionManager.getLocalNpcs(entity, radius).toTypedArray()
|
val localNPCs: Array<Any> = RegionManager.getLocalNpcs(entity, radius).toTypedArray()
|
||||||
var length = localNPCs.size
|
var length = localNPCs.size
|
||||||
|
|||||||
@@ -4,29 +4,20 @@ import kotlinx.coroutines.GlobalScope
|
|||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class ConfigParser {
|
class ConfigParser {
|
||||||
fun prePlugin() = GlobalScope.launch{
|
fun prePlugin() {
|
||||||
launch {
|
|
||||||
NPCConfigParser().load()
|
NPCConfigParser().load()
|
||||||
ItemConfigParser().load()
|
ItemConfigParser().load()
|
||||||
}
|
|
||||||
launch {
|
|
||||||
ObjectConfigParser().load()
|
ObjectConfigParser().load()
|
||||||
XteaParser().load()
|
XteaParser().load()
|
||||||
}
|
|
||||||
InterfaceConfigParser().load()
|
InterfaceConfigParser().load()
|
||||||
}
|
}
|
||||||
|
fun postPlugin() {
|
||||||
fun postPlugin() = GlobalScope.launch{
|
|
||||||
launch {
|
|
||||||
ShopParser().load()
|
ShopParser().load()
|
||||||
DropTableParser().load()
|
DropTableParser().load()
|
||||||
NPCSpawner().load()
|
NPCSpawner().load()
|
||||||
}
|
|
||||||
launch {
|
|
||||||
DoorConfigLoader().load()
|
DoorConfigLoader().load()
|
||||||
GroundSpawnLoader().load()
|
GroundSpawnLoader().load()
|
||||||
MusicConfigLoader().load()
|
MusicConfigLoader().load()
|
||||||
}
|
|
||||||
RangedConfigLoader().load()
|
RangedConfigLoader().load()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user