forked from SteamWar/SteamWar
Improve DynamicRegionSystem.getNeighbours
This commit is contained in:
+73
-34
@@ -23,8 +23,9 @@ import de.steamwar.bausystem.BauSystem;
|
||||
import de.steamwar.bausystem.features.region.WireframeCommand;
|
||||
import de.steamwar.bausystem.region.dynamic.*;
|
||||
import de.steamwar.bausystem.region.dynamic.global.GlobalRegion;
|
||||
import de.steamwar.bausystem.shared.Pair;
|
||||
import lombok.NonNull;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -117,21 +118,18 @@ public class DynamicRegionSystem implements RegionSystem {
|
||||
}
|
||||
|
||||
public @NonNull Region get(@Nullable Tile tile) {
|
||||
if (tile == null) return getGlobalRegion();
|
||||
return get(tile.getCenterLocation().getBlockX(), tile.getCenterLocation().getBlockZ(), true, regionMap.values());
|
||||
return get(tile, true, regionMap.values());
|
||||
}
|
||||
|
||||
private Region get(int x, int z, boolean fastCache, Collection<Region> regions) {
|
||||
Tile tile = Tile.fromXZ(x, z).orElse(null);
|
||||
if (tile == null) {
|
||||
return getGlobalRegion();
|
||||
}
|
||||
private Region get(@Nullable Tile tile, boolean fastCache, Collection<Region> regions) {
|
||||
if (tile == null) return getGlobalRegion();
|
||||
if (regionCache.containsKey(tile.getId())) {
|
||||
Region region = regionCache.get(tile.getId());
|
||||
if (fastCache || regions.contains(region)) return region;
|
||||
}
|
||||
Location location = tile.getCenterLocation();
|
||||
Region region = regions.stream()
|
||||
.filter(rg -> rg.getArea().inRegion(x, z, false))
|
||||
.filter(rg -> rg.getArea().inRegion(location, false))
|
||||
.findFirst()
|
||||
.orElseGet(this::getGlobalRegion);
|
||||
if (fastCache || regions.contains(region)) {
|
||||
@@ -140,9 +138,14 @@ public class DynamicRegionSystem implements RegionSystem {
|
||||
return region;
|
||||
}
|
||||
|
||||
private Region get(int x, int z, boolean fastCache, Collection<Region> regions) {
|
||||
Tile tile = Tile.fromXZ(x, z).orElse(null);
|
||||
return get(tile, fastCache, regions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNull Region get(@NonNull Location location) {
|
||||
return get(location.getBlockX(), location.getBlockZ(), true, regionMap.values());
|
||||
return get(Tile.fromLocation(location).orElse(null), true, regionMap.values());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,40 +162,76 @@ public class DynamicRegionSystem implements RegionSystem {
|
||||
return regionTypeMap.getOrDefault(type, Collections.emptySet()).stream();
|
||||
}
|
||||
|
||||
private Stream<Pair<Region, NeighbourDirection>> getNeighbours(Region region, boolean noCorners, boolean fastCache, Collection<Region> regions) {
|
||||
Point minPoint = region.getArea().getMinPoint(false).subtract(TILE_SIZE_ADJUSTED, 0, TILE_SIZE_ADJUSTED);
|
||||
Point maxPoint = region.getArea().getMaxPoint(false).add(Tile.tileSize, 0, Tile.tileSize);
|
||||
Set<Pair<Region, NeighbourDirection>> neighbours = new HashSet<>();
|
||||
@RequiredArgsConstructor
|
||||
@ToString
|
||||
public static class Neighbour<T extends Region> {
|
||||
public final T region;
|
||||
public final Tile tile;
|
||||
public final NeighbourDirection direction;
|
||||
|
||||
public <O extends Region> Neighbour<O> as(Class<O> clazz) {
|
||||
if (!clazz.isInstance(region)) {
|
||||
return null;
|
||||
} else {
|
||||
return (Neighbour<O>) this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (!(o instanceof Neighbour<?> neighbour)) return false;
|
||||
return Objects.equals(tile, neighbour.tile) && direction == neighbour.direction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(tile, direction);
|
||||
}
|
||||
}
|
||||
|
||||
private Stream<Neighbour<Region>> getNeighbours(Region region, boolean noCorners, boolean fastCache, Collection<Region> regions) {
|
||||
Tile minTile = Tile.fromPoint(region.getArea().getMinPoint(false)).orElse(null);
|
||||
Tile maxTile = Tile.fromPoint(region.getArea().getMaxPoint(false)).orElse(null);
|
||||
if (minTile == null || maxTile == null) return Stream.empty();
|
||||
|
||||
Set<Neighbour<Region>> neighbours = new HashSet<>();
|
||||
|
||||
for (int x = minPoint.getX() + (noCorners ? TILE_SIZE_ADJUSTED : 0); x <= maxPoint.getX() - (noCorners ? Tile.tileSize : 0); x += Tile.tileSize) {
|
||||
NeighbourDirection minZ = NeighbourDirection.North;
|
||||
if (!noCorners) {
|
||||
if (x == minPoint.getX()) minZ = NeighbourDirection.NorthWest;
|
||||
if (x > maxPoint.getX() - TILE_SIZE_ADJUSTED) minZ = NeighbourDirection.NorthEast;
|
||||
}
|
||||
neighbours.add(new Pair<>(get(x, minPoint.getZ(), fastCache, regions), minZ));
|
||||
neighbours.add(new Neighbour<>(get(minTile.add(-1, -1).orElseThrow(), fastCache, regions), minTile, NeighbourDirection.NorthWest));
|
||||
|
||||
NeighbourDirection maxZ = NeighbourDirection.South;
|
||||
if (!noCorners) {
|
||||
if (x == minPoint.getX()) maxZ = NeighbourDirection.SouthWest;
|
||||
if (x > maxPoint.getX() - TILE_SIZE_ADJUSTED) maxZ = NeighbourDirection.SouthEast;
|
||||
}
|
||||
neighbours.add(new Pair<>(get(x, maxPoint.getZ(), fastCache, regions), maxZ));
|
||||
Tile cornerMinMaxSelf = Tile.fromTile(minTile.getTileX(), maxTile.getTileZ()).orElseThrow();
|
||||
neighbours.add(new Neighbour<>(get(cornerMinMaxSelf.add(-1, 1).orElseThrow(), fastCache, regions), cornerMinMaxSelf, NeighbourDirection.SouthWest));
|
||||
|
||||
Tile cornerMaxMinSelf = Tile.fromTile(maxTile.getTileX(), minTile.getTileZ()).orElseThrow();
|
||||
neighbours.add(new Neighbour<>(get(cornerMaxMinSelf.add(1, -1).orElseThrow(), fastCache, regions), cornerMaxMinSelf, NeighbourDirection.NorthEast));
|
||||
|
||||
neighbours.add(new Neighbour<>(get(maxTile.add(1, 1).orElseThrow(), fastCache, regions), maxTile, NeighbourDirection.SouthEast));
|
||||
}
|
||||
|
||||
for (int z = minPoint.getZ() + TILE_SIZE_ADJUSTED; z <= maxPoint.getZ() - Tile.tileSize; z += Tile.tileSize) {
|
||||
neighbours.add(new Pair<>(get(minPoint.getX(), z, fastCache, regions), NeighbourDirection.West));
|
||||
neighbours.add(new Pair<>(get(maxPoint.getX(), z, fastCache, regions), NeighbourDirection.East));
|
||||
for (int x = minTile.getTileX(); x <= maxTile.getTileX(); x++) {
|
||||
Tile tileMinZSelf = Tile.fromTile(x, minTile.getTileZ()).orElseThrow();
|
||||
neighbours.add(new Neighbour<>(get(tileMinZSelf.add(0, -1).orElseThrow(), fastCache, regions), tileMinZSelf, NeighbourDirection.North));
|
||||
|
||||
Tile tileMaxZSelf = Tile.fromTile(x, maxTile.getTileZ()).orElseThrow();
|
||||
neighbours.add(new Neighbour<>(get(tileMaxZSelf.add(0, 1).orElseThrow(), fastCache, regions), tileMaxZSelf, NeighbourDirection.South));
|
||||
}
|
||||
|
||||
neighbours.removeIf(data -> data.getKey().getType().isGlobal());
|
||||
for (int z = minTile.getTileZ(); z <= maxTile.getTileZ(); z++) {
|
||||
Tile tileMinXSelf = Tile.fromTile(minTile.getTileX(), z).orElseThrow();
|
||||
neighbours.add(new Neighbour<>(get(tileMinXSelf.add(-1, 0).orElseThrow(), fastCache, regions), tileMinXSelf, NeighbourDirection.West));
|
||||
|
||||
Tile tileMaxXSelf = Tile.fromTile(maxTile.getTileX(), z).orElseThrow();
|
||||
neighbours.add(new Neighbour<>(get(tileMaxXSelf.add(1, 0).orElseThrow(), fastCache, regions), tileMaxXSelf, NeighbourDirection.East));
|
||||
}
|
||||
|
||||
neighbours.removeIf(neighbour -> neighbour.region.getType().isGlobal());
|
||||
return neighbours.stream();
|
||||
}
|
||||
|
||||
public Stream<Pair<DynamicRegion, NeighbourDirection>> getNeighbours(Region region) {
|
||||
public Stream<Neighbour<DynamicRegion>> getNeighbours(Region region) {
|
||||
return getNeighbours(region, false, true, regionMap.values())
|
||||
.filter(data -> data.getKey() instanceof DynamicRegion)
|
||||
.map(data -> (Pair<DynamicRegion, NeighbourDirection>) (Pair) data);
|
||||
.map(neighbour -> neighbour.as(DynamicRegion.class))
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -208,7 +247,7 @@ public class DynamicRegionSystem implements RegionSystem {
|
||||
Region r = current.removeFirst();
|
||||
if (!connected.add(r)) continue;
|
||||
getNeighbours(r, true, false, regions)
|
||||
.map(Pair::getKey)
|
||||
.map(neighbour -> neighbour.region)
|
||||
.forEach(current::add);
|
||||
}
|
||||
|
||||
|
||||
+15
-19
@@ -26,15 +26,11 @@ import de.steamwar.bausystem.region.Point;
|
||||
import de.steamwar.bausystem.region.Region;
|
||||
import de.steamwar.bausystem.region.RegionData;
|
||||
import de.steamwar.bausystem.region.dynamic.path.PathRegion;
|
||||
import de.steamwar.bausystem.shared.Pair;
|
||||
import lombok.Getter;
|
||||
import lombok.NonNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.*;
|
||||
|
||||
public abstract class DynamicRegion implements Region {
|
||||
|
||||
@@ -80,25 +76,25 @@ public abstract class DynamicRegion implements Region {
|
||||
public abstract void writeTileData(JsonWriter writer) throws IOException;
|
||||
|
||||
public final void updateNeighbours() {
|
||||
List<Pair<PathRegion, NeighbourDirection>> list = DynamicRegionSystem.INSTANCE.getNeighbours(this)
|
||||
.filter(data -> data.getKey() instanceof PathRegion)
|
||||
.map(data -> (Pair<PathRegion, NeighbourDirection>) (Pair) data)
|
||||
List<DynamicRegionSystem.Neighbour<PathRegion>> list = DynamicRegionSystem.INSTANCE.getNeighbours(this)
|
||||
.map(neighbour -> neighbour.as(PathRegion.class))
|
||||
.filter(Objects::nonNull)
|
||||
.toList();
|
||||
// Calculate Garden State for all neighbouring PathRegions
|
||||
Set<UUID> needsFullReset = new HashSet<>();
|
||||
list.forEach(data -> {
|
||||
boolean previousGardenState = data.getKey().isGarden();
|
||||
data.getKey().calculateGardenState();
|
||||
if (data.getKey().isGarden() != previousGardenState) {
|
||||
needsFullReset.add(data.getKey().getID());
|
||||
boolean previousGardenState = data.region.isGarden();
|
||||
data.region.calculateGardenState();
|
||||
if (data.region.isGarden() != previousGardenState) {
|
||||
needsFullReset.add(data.region.getID());
|
||||
}
|
||||
});
|
||||
// Updating world state for all neighbouring PathRegions
|
||||
list.forEach(data -> {
|
||||
if (needsFullReset.contains(data.getKey().getID())) {
|
||||
data.getKey().getArea().reset(null, false); // TODO: Implement!
|
||||
if (needsFullReset.contains(data.region.getID())) {
|
||||
data.region.getArea().reset(null, false); // TODO: Implement!
|
||||
} else {
|
||||
data.getKey().update(this, data.getValue().opposite());
|
||||
data.region.update(this, data.direction.opposite());
|
||||
}
|
||||
});
|
||||
// All full reset regions need to update their neighbours!
|
||||
@@ -106,11 +102,11 @@ public abstract class DynamicRegion implements Region {
|
||||
Region region = DynamicRegionSystem.INSTANCE.getRegion(uuid).orElse(null);
|
||||
if (!(region instanceof DynamicRegion dynamicRegion)) return;
|
||||
DynamicRegionSystem.INSTANCE.getNeighbours(dynamicRegion)
|
||||
.filter(data -> data.getKey() instanceof PathRegion)
|
||||
.map(data -> (Pair<PathRegion, NeighbourDirection>) (Pair) data)
|
||||
.map(neighbour -> neighbour.as(PathRegion.class))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(data -> {
|
||||
if (data.getKey().isGarden()) return;
|
||||
data.getKey().update(dynamicRegion, data.getValue().opposite());
|
||||
if (data.region.isGarden()) return;
|
||||
data.region.update(dynamicRegion, data.direction.opposite());
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user