Calculate hull visibility on block faces

Instead of a block occluding as a whole, the hull stores which of its six
faces are full, using the occlusion shapes the client culls faces with. A ray
inside a block can only leave it through an open face and enter the next
block through its open opposite face; if only that face is full, the ray
reaches its surface, so the block is visible, but stops there. Slabs, stairs
and stacked slabs now hide what is behind them; double slabs need no special
case anymore. Faces only open up on block updates, after which the rays that
could not get into, out of or past the block are continued.

Hidden blocks occlude by the same decision as the techhider, so waterlogged
blocks count as well when water is hidden. The hull therefore takes the
ObfuscationConfig, which the fight shares with its TechHiderWrapper.
This commit is contained in:
2026-10-31 21:18:24 +01:00
parent e1ff37bea2
commit baa4cf34e5
4 changed files with 147 additions and 80 deletions
@@ -33,6 +33,8 @@ import de.steamwar.fightsystem.states.StateDependentTask;
import de.steamwar.hullhider.Hull;
import de.steamwar.hullhider.HullHider;
import de.steamwar.hullhider.Viewers;
import de.steamwar.techhider.ObfuscationConfig;
import lombok.Getter;
import org.bukkit.block.Block;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.Player;
@@ -51,13 +53,16 @@ import java.util.function.BiConsumer;
public class FightHullHider {
private final HullHider<FightTeam> hullHider = new HullHider<>(true);
// Shared with the TechHiderWrapper
@Getter
private final ObfuscationConfig obfuscation = ObfuscationConfig.of(Config.GameModeConfig.Techhider);
public FightHullHider() {
if (!TechHiderWrapper.ENABLED) return;
Fight.teams().forEach(team -> {
Region region = team.getSchemRegion();
hullHider.addHull(team, new Hull(FightSystem.getPlugin(), Config.world, region.toHullRegion(), region.getMinY() != Config.PlayerRegion.getMinY(), Config.GameModeConfig.Techhider.HiddenBlocks, new Viewers.HiddenByDefault()));
hullHider.addHull(team, new Hull(FightSystem.getPlugin(), Config.world, region.toHullRegion(), region.getMinY() != Config.PlayerRegion.getMinY(), obfuscation, new Viewers.HiddenByDefault()));
});
new StateDependentListener(TechHiderWrapper.ENABLED, FightState.All, new MembershipListener());
@@ -69,8 +69,7 @@ public class TechHiderWrapper extends StateDependent implements Listener {
@Override
public void enable() {
ObfuscationConfig obfuscation = ObfuscationConfig.of(Config.GameModeConfig.Techhider);
new TechHider(newProvider(obfuscation));
new TechHider(newProvider(hullHider.getObfuscation()));
}
private AccessPrivilegeProvider newProvider(ObfuscationConfig obfuscation) {