forked from SteamWar/SteamWar
Make TechHider access checks player-scoped
AccessPrivilegeProvider#forPlayer returns a PlayerAccess that resolves the player's hidden region once. TechHider creates it once per outer packet (shared across bundle sub-packets) and passes it to every processor, so all decisions within a packet are consistent and the region/referee lookup no longer runs per block on the netty thread.
This commit is contained in:
@@ -34,9 +34,11 @@ import org.bukkit.util.Vector;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.logging.Level;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Config {
|
||||
|
||||
@@ -80,7 +82,7 @@ public class Config {
|
||||
|
||||
//event parameter
|
||||
public static final EventFight EventKampf;
|
||||
private static final Set<Integer> Referees;
|
||||
private static final Set<UUID> Referees;
|
||||
public static final int EventTeamBlueID;
|
||||
public static final int EventTeamRedID;
|
||||
public static final boolean BothTeamsPublic;
|
||||
@@ -237,7 +239,11 @@ public class Config {
|
||||
BothTeamsPublic = EventTeamRedID == 0 && EventTeamBlueID == 0;
|
||||
SpectatePort = EventKampf.getSpectatePort() == null ? 0 : EventKampf.getSpectatePort();
|
||||
LiveReplay = SpectatePort != 0;
|
||||
Referees = Referee.get(Config.EventKampf.getEventID());
|
||||
Referees = Referee.get(Config.EventKampf.getEventID()).stream()
|
||||
.map(SteamwarUser::byId)
|
||||
.filter(Objects::nonNull)
|
||||
.map(SteamwarUser::getUUID)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
|
||||
Event event = Event.byId(EventKampf.getEventID());
|
||||
if (BothTeamsPublic) {
|
||||
@@ -305,6 +311,6 @@ public class Config {
|
||||
}
|
||||
|
||||
public static boolean isReferee(Player player) {
|
||||
return Referees.contains(SteamwarUser.get(player.getUniqueId()).getId());
|
||||
return Referees.contains(player.getUniqueId());
|
||||
}
|
||||
}
|
||||
|
||||
+65
-31
@@ -31,6 +31,7 @@ import de.steamwar.fightsystem.states.FightState;
|
||||
import de.steamwar.fightsystem.states.StateDependent;
|
||||
import de.steamwar.fightsystem.states.StateDependentListener;
|
||||
import de.steamwar.techhider.AccessPrivilegeProvider;
|
||||
import de.steamwar.techhider.AccessPrivilegeProvider.ForPlayer;
|
||||
import de.steamwar.techhider.TechHider;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.core.Holder;
|
||||
@@ -91,49 +92,82 @@ public class TechHiderWrapper extends StateDependent implements Listener {
|
||||
.map(Holder.Reference::value)
|
||||
.collect(Collectors.toUnmodifiableSet());
|
||||
|
||||
new TechHider(CraftMagicNumbers.getBlock(Config.GameModeConfig.Techhider.ObfuscateWith), new AccessPrivilegeProvider() {
|
||||
new TechHider(CraftMagicNumbers.getBlock(Config.GameModeConfig.Techhider.ObfuscateWith), newProvider(blockStatesToObfuscate, blocksToObfuscate, blockEntityTypeToObfuscate));
|
||||
}
|
||||
|
||||
private AccessPrivilegeProvider newProvider(Set<BlockState> blockStatesToObfuscate, Set<Block> blocksToObfuscate, Set<BlockEntityType<?>> blockEntityTypeToObfuscate) {
|
||||
return new AccessPrivilegeProvider() {
|
||||
@Override
|
||||
public boolean isEveryonePrivilegedToAccessAllDataWithinChunk(int chunkX, int chunkZ) {
|
||||
return Fight.teams().stream().map(FightTeam::getExtendRegion).allMatch(region -> region.chunkOutside(chunkX, chunkZ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerPrivilegedToAccessPosition(Player p, int blockX, int blockY, int blockZ) {
|
||||
return !hullHider.isBlockHidden(p, blockX, blockY, blockZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block) {
|
||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerPrivilegedToAccessBlockState(Player p, int blockX, int blockY, int blockZ, BlockState blockState) {
|
||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blockStatesToObfuscate.contains(blockState);
|
||||
}
|
||||
|
||||
// TODO will require entity tracking on the netty thread to prevent future race conditions
|
||||
@Override
|
||||
public boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId) {
|
||||
net.minecraft.world.entity.Entity nmsEntity = ((CraftWorld) p.getWorld()).getHandle().moonrise$getEntityLookup().get(entityId);
|
||||
|
||||
if (nmsEntity != null) {
|
||||
return !hullHider.isBlockHidden(p, nmsEntity.getBlockX(), nmsEntity.getBlockY(), nmsEntity.getBlockZ());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType<?> type) {
|
||||
return !getHiddenRegion(p).inRegion(blockX, blockY, blockZ) || !blockEntityTypeToObfuscate.contains(type);
|
||||
public ForPlayer forPlayer(Player p) {
|
||||
return new FightPlayerAccess(p, getHiddenRegion(p), blockStatesToObfuscate, blocksToObfuscate, blockEntityTypeToObfuscate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPlayerPrivilegedToPerformAction(Player p) {
|
||||
return p.getGameMode() != GameMode.SPECTATOR;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Snapshot of what one player may access, taken once per outgoing packet on the netty thread.
|
||||
*/
|
||||
private class FightPlayerAccess implements ForPlayer {
|
||||
private final Player player;
|
||||
private final Region hiddenRegion;
|
||||
private final Set<BlockState> blockStatesToObfuscate;
|
||||
private final Set<Block> blocksToObfuscate;
|
||||
private final Set<BlockEntityType<?>> blockEntityTypeToObfuscate;
|
||||
|
||||
private FightPlayerAccess(Player player, Region hiddenRegion, Set<BlockState> blockStatesToObfuscate, Set<Block> blocksToObfuscate, Set<BlockEntityType<?>> blockEntityTypeToObfuscate) {
|
||||
this.player = player;
|
||||
this.hiddenRegion = hiddenRegion;
|
||||
this.blockStatesToObfuscate = blockStatesToObfuscate;
|
||||
this.blocksToObfuscate = blocksToObfuscate;
|
||||
this.blockEntityTypeToObfuscate = blockEntityTypeToObfuscate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Player getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccessPosition(int blockX, int blockY, int blockZ) {
|
||||
return !hullHider.isBlockHidden(player, blockX, blockY, blockZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccessBlock(int blockX, int blockY, int blockZ, Block block) {
|
||||
return !hiddenRegion.inRegion(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccessBlockState(int blockX, int blockY, int blockZ, BlockState blockState) {
|
||||
return !hiddenRegion.inRegion(blockX, blockY, blockZ) || !blockStatesToObfuscate.contains(blockState);
|
||||
}
|
||||
|
||||
// TODO will require entity tracking on the netty thread to prevent future race conditions
|
||||
@Override
|
||||
public boolean canAccessEntity(int entityId) {
|
||||
net.minecraft.world.entity.Entity nmsEntity = ((CraftWorld) player.getWorld()).getHandle().moonrise$getEntityLookup().get(entityId);
|
||||
|
||||
if (nmsEntity != null) {
|
||||
return !hullHider.isBlockHidden(player, nmsEntity.getBlockX(), nmsEntity.getBlockY(), nmsEntity.getBlockZ());
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canAccessBlockEntity(int blockX, int blockY, int blockZ, BlockEntityType<?> type) {
|
||||
return !hiddenRegion.inRegion(blockX, blockY, blockZ) || !blockEntityTypeToObfuscate.contains(type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user