Partial diagonal HullHider uncovering, performance improvement

This commit is contained in:
Lixfel
2024-12-21 10:52:41 +01:00
parent 0e43c2a615
commit 10e016c850
@@ -39,38 +39,35 @@ import java.util.stream.IntStream;
public class Hull { public class Hull {
private static final IntVector[] NO_BRANCHES = new IntVector[0];
private static boolean isOccluding(Material material) { private static boolean isOccluding(Material material) {
return material.isOccluding() || Config.HiddenBlocks.contains(material); return material.isOccluding() || Config.HiddenBlocks.contains(material);
} }
private final Region region; private final Region region;
private final boolean groundVisible; private final boolean groundVisible;
private final IntVector primaryDirection;
private final IntVector[] directions; private final IntVector[] directions;
private final IntVector[] branchDirections;
private final BitSet occluding; private final BitSet occluding;
private final BitSet visibility; private final BitSet visibility;
private final HashMap<IntVector, BitSet> visibilityDirections = new HashMap<>(); // Contains the visible directions of each occluding visible block private final HashMap<IntVector, BitSet> visibilityDirections = new HashMap<>(); // Contains the visible directions of each occluding visible block
private final Set<IntVector> uncoveredSurface = new HashSet<>(); private final HashSet<IntVector> uncoveredSurface = new HashSet<>();
private final HashSet<Player> players = new HashSet<>(); private final HashSet<Player> players = new HashSet<>();
private final Set<Entity> entities = new HashSet<>(); private final HashSet<Entity> entities = new HashSet<>();
private final Set<REntity> rentities = new HashSet<>(); private final HashSet<REntity> rentities = new HashSet<>();
public Hull(FightTeam team) { public Hull(FightTeam team) {
this.region = team.getSchemRegion(); this.region = team.getSchemRegion();
this.groundVisible = region.getMinY() != Config.PlayerRegion.getMinY(); this.groundVisible = region.getMinY() != Config.PlayerRegion.getMinY();
this.primaryDirection = new IntVector(0, 0, team.isBlue() == (Config.BlueToRedZ > 0) ? -1 : 1);
this.occluding = new BitSet(region.volume()); this.occluding = new BitSet(region.volume());
this.visibility = new BitSet(region.volume()); this.visibility = new BitSet(region.volume());
IntVector primaryDirection = new IntVector(0, 0, team.isBlue() == (Config.BlueToRedZ > 0) ? -1 : 1);
directions = IntStream.range(0, 27) directions = IntStream.range(0, 27)
.mapToObj(v -> new IntVector(v%3 -1, (v/3)%3 -1, v/9 -1)) .mapToObj(v -> new IntVector(v%3 -1, (v/3)%3 -1, v/9 -1))
.filter(v -> v.sqLength() == 1 || v.x*primaryDirection.x + v.y*primaryDirection.y + v.z*primaryDirection.z >= 1) // Not pointing away from primary direction .filter(v -> v.sqLength() == 1 || v.x*primaryDirection.x + v.y*primaryDirection.y + v.z*primaryDirection.z == 1) // Not pointing away from primary direction
.toArray(IntVector[]::new);
branchDirections = Arrays.stream(directions)
.filter(v -> v.sqLength() >= 2) // Diagonal
.toArray(IntVector[]::new); .toArray(IntVector[]::new);
for(IntVector direction : directions) for(IntVector direction : directions)
@@ -141,6 +138,7 @@ public class Hull {
public void initialize() { public void initialize() {
visibility.clear(); visibility.clear();
occluding.clear(); occluding.clear();
uncoveredSurface.clear();
for(BitSet directionalVisibility : visibilityDirections.values()) for(BitSet directionalVisibility : visibilityDirections.values())
directionalVisibility.clear(); directionalVisibility.clear();
@@ -150,7 +148,7 @@ public class Hull {
if (isOccluding(Config.world.getBlockAt(x, y, z).getType())) if (isOccluding(Config.world.getBlockAt(x, y, z).getType()))
occluding.set(block.toId(region)); occluding.set(block.toId(region));
}); });
forEachBorder((root, direction) -> updateBlocks(new NullList<>(), root, direction, visibilityDirections.get(direction))); forEachBorder((root, direction) -> uncoverBlocks(new NullList<>(), root, direction));
FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.cardinality()); FightSystem.getPlugin().getLogger().log(Level.INFO, () -> "[HullHider] initialisation finished: " + (System.currentTimeMillis() - start) + " ms, visible blocks: " + visibility.cardinality());
} }
@@ -171,34 +169,11 @@ public class Hull {
for(Map.Entry<IntVector, BitSet> directionalVisibility : visibilityDirections.entrySet()) { for(Map.Entry<IntVector, BitSet> directionalVisibility : visibilityDirections.entrySet()) {
if(directionalVisibility.getValue().get(id)) { if(directionalVisibility.getValue().get(id)) {
directionalVisibility.getValue().clear(id); directionalVisibility.getValue().clear(id);
updateBlocks(uncovered, root, directionalVisibility.getKey(), directionalVisibility.getValue()); uncoverBlocks(uncovered, root, directionalVisibility.getKey());
} }
} }
if(uncovered.isEmpty()) uncoveredSurface.addAll(new HashSet<>(uncovered));
return;
Set<IntVector> uncoveredSet = new HashSet<>(uncovered);
Iterator<Entity> it = entities.iterator();
while(it.hasNext()) {
Entity entity = it.next();
if(uncoveredSet.contains(new IntVector(entity.getLocation()))) {
it.remove();
for(Player player : players)
BlockIdWrapper.impl.trackEntity(player, entity);
}
}
Iterator<REntity> rit = rentities.iterator();
while(rit.hasNext()) {
REntity entity = rit.next();
if(uncoveredSet.contains(new IntVector(new Location(Config.world, entity.getX(), entity.getY(), entity.getZ())))) {
rit.remove();
entity.hide(false);
}
}
uncoveredSurface.addAll(uncoveredSet);
uncoveredSurface.remove(root); uncoveredSurface.remove(root);
} }
@@ -243,7 +218,18 @@ public class Hull {
} }
} }
private void updateBlocks(List<IntVector> uncovered, IntVector block, IntVector direction, BitSet directionalVisibility) { private void uncoverBlocks(List<IntVector> uncovered, IntVector block, IntVector direction) {
uncoverBlocks(
uncovered, block, direction, visibilityDirections.get(direction),
direction.sqLength() == 1
? Arrays.stream(directions)
.filter(v -> v.sqLength() >= 2 && v.x*direction.x + v.y*direction.y + v.z*direction.z == 1)
.toArray(IntVector[]::new)
: NO_BRANCHES
);
}
private void uncoverBlocks(List<IntVector> uncovered, IntVector block, IntVector direction, BitSet directionalVisibility, IntVector[] branchDirections) {
if (block.notInRegion(region)) if (block.notInRegion(region))
return; return;
@@ -260,16 +246,9 @@ public class Hull {
if (occluding.get(id)) if (occluding.get(id))
return; return;
updateBlocks(uncovered, block.add(direction), direction, directionalVisibility); uncoverBlocks(uncovered, block.add(direction), direction, directionalVisibility, branchDirections);
if(!direction.equals(primaryDirection))
return;
for(IntVector branchDirection : branchDirections) for(IntVector branchDirection : branchDirections)
updateBlocks(uncovered, block.add(branchDirection), branchDirection, visibilityDirections.get(branchDirection)); uncoverBlocks(uncovered, block.add(branchDirection), branchDirection, visibilityDirections.get(branchDirection), NO_BRANCHES);
}
private int directionId(IntVector v) {
return 1 << (9*(v.z+1) + 3*(v.y+1) + (v.x+1));
} }