diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index 469159c3..1ccaad8e 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -32,32 +32,21 @@ 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.ObfuscationConfig; import de.steamwar.techhider.TechHider; import lombok.Getter; -import net.minecraft.core.Holder; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.material.FluidState; -import net.minecraft.world.level.material.Fluids; import org.bukkit.GameMode; -import org.bukkit.Material; import org.bukkit.craftbukkit.CraftWorld; -import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; import java.util.Arrays; -import java.util.Collection; -import java.util.Objects; -import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; public class TechHiderWrapper extends StateDependent implements Listener { @@ -80,29 +69,15 @@ public class TechHiderWrapper extends StateDependent implements Listener { @Override public void enable() { - Set blockStatesToObfuscate = getBlockStatesToHideFromMaterials(Config.GameModeConfig.Techhider.HiddenBlocks); - - Set blocksToObfuscate = Config.GameModeConfig.Techhider.HiddenBlocks.stream() - .map(CraftMagicNumbers::getBlock) - .collect(Collectors.toUnmodifiableSet()); - - Set> blockEntityTypeToObfuscate = Config.GameModeConfig.Techhider.HiddenBlockEntities.stream() - .map(id -> { - ResourceLocation loc = ResourceLocation.parse(id); - return BuiltInRegistries.BLOCK_ENTITY_TYPE.get(loc).orElse(null); - }) - .filter(Objects::nonNull) - .map(Holder.Reference::value) - .collect(Collectors.toUnmodifiableSet()); - - new TechHider(CraftMagicNumbers.getBlock(Config.GameModeConfig.Techhider.ObfuscateWith), newProvider(blockStatesToObfuscate, blocksToObfuscate, blockEntityTypeToObfuscate)); + ObfuscationConfig obfuscation = ObfuscationConfig.of(Config.GameModeConfig.Techhider); + new TechHider(obfuscation.getObfuscateWith(), newProvider(obfuscation)); } - private AccessPrivilegeProvider newProvider(Set blockStatesToObfuscate, Set blocksToObfuscate, Set> blockEntityTypeToObfuscate) { + private AccessPrivilegeProvider newProvider(ObfuscationConfig obfuscation) { return new AccessPrivilegeProvider() { @Override public ForPlayer forPlayer(Player p) { - return new FightPlayerAccess(p, getHiddenRegions(p), blockStatesToObfuscate, blocksToObfuscate, blockEntityTypeToObfuscate); + return new FightPlayerAccess(p, getHiddenRegions(p), obfuscation); } @Override @@ -118,16 +93,12 @@ public class TechHiderWrapper extends StateDependent implements Listener { private class FightPlayerAccess implements ForPlayer { private final Player player; private final Region[] hiddenRegions; - private final Set blockStatesToObfuscate; - private final Set blocksToObfuscate; - private final Set> blockEntityTypeToObfuscate; + private final ObfuscationConfig obfuscation; - private FightPlayerAccess(Player player, Region[] hiddenRegions, Set blockStatesToObfuscate, Set blocksToObfuscate, Set> blockEntityTypeToObfuscate) { + private FightPlayerAccess(Player player, Region[] hiddenRegions, ObfuscationConfig obfuscation) { this.player = player; this.hiddenRegions = hiddenRegions; - this.blockStatesToObfuscate = blockStatesToObfuscate; - this.blocksToObfuscate = blocksToObfuscate; - this.blockEntityTypeToObfuscate = blockEntityTypeToObfuscate; + this.obfuscation = obfuscation; } private boolean isHidden(int blockX, int blockY, int blockZ) { @@ -155,12 +126,12 @@ public class TechHiderWrapper extends StateDependent implements Listener { @Override public boolean canAccessBlock(int blockX, int blockY, int blockZ, Block block) { - return !isHidden(blockX, blockY, blockZ) || !blocksToObfuscate.contains(block); + return !isHidden(blockX, blockY, blockZ) || !obfuscation.hidesBlock(block); } @Override public boolean canAccessBlockState(int blockX, int blockY, int blockZ, BlockState blockState) { - return !isHidden(blockX, blockY, blockZ) || !blockStatesToObfuscate.contains(blockState); + return !isHidden(blockX, blockY, blockZ) || !obfuscation.hidesBlockState(blockState); } // TODO will require entity tracking on the netty thread to prevent future race conditions @@ -177,7 +148,7 @@ public class TechHiderWrapper extends StateDependent implements Listener { @Override public boolean canAccessBlockEntity(int blockX, int blockY, int blockZ, BlockEntityType type) { - return !isHidden(blockX, blockY, blockZ) || !blockEntityTypeToObfuscate.contains(type); + return !isHidden(blockX, blockY, blockZ) || !obfuscation.hidesBlockEntity(type); } } @@ -235,27 +206,4 @@ public class TechHiderWrapper extends StateDependent implements Listener { return new Region[]{Fight.getOpposite(fightPlayer.getTeam()).getExtendRegion()}; } - - private Stream getWaterloggedBlockStates() { - FluidState waterFluidState = Fluids.WATER.getSource(false); - - return BuiltInRegistries.BLOCK.stream() - .map((block) -> block.getStateDefinition().getPossibleStates()) - .flatMap(Collection::stream) - .filter((blockState -> blockState.getFluidState() == waterFluidState)); - } - - private Set getBlockStatesToHideFromMaterials(Set materials) { - Stream allStatesFromMaterials = materials.stream() - .map(CraftMagicNumbers::getBlock) - .map((block) -> block.getStateDefinition().getPossibleStates()) - .flatMap(Collection::stream); - - if(materials.contains(Material.WATER)) { - return Stream.concat(allStatesFromMaterials, getWaterloggedBlockStates()).collect(Collectors.toUnmodifiableSet()); - } - else { - return allStatesFromMaterials.collect(Collectors.toUnmodifiableSet()); - } - } } diff --git a/HiderCore/build.gradle.kts b/HiderCore/build.gradle.kts index 283cd19e..a0b27617 100644 --- a/HiderCore/build.gradle.kts +++ b/HiderCore/build.gradle.kts @@ -35,6 +35,7 @@ dependencies { compileOnly(libs.netty) compileOnly(libs.fastutil) compileOnly(libs.authlib) + compileOnly(libs.datafixer) } widener { diff --git a/HiderCore/src/de/steamwar/techhider/ObfuscationConfig.java b/HiderCore/src/de/steamwar/techhider/ObfuscationConfig.java new file mode 100644 index 00000000..cc8310a5 --- /dev/null +++ b/HiderCore/src/de/steamwar/techhider/ObfuscationConfig.java @@ -0,0 +1,113 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2026 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.techhider; + +import de.steamwar.sql.GameModeConfig; +import lombok.Getter; +import net.minecraft.core.Holder; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.material.FluidState; +import net.minecraft.world.level.material.Fluids; +import org.bukkit.Material; +import org.bukkit.craftbukkit.util.CraftMagicNumbers; + +import java.util.Collection; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Which blocks, block states and block entities to hide, and the block to replace them with. + */ +@Getter +public final class ObfuscationConfig { + + public static ObfuscationConfig of(GameModeConfig.TechhiderConfig config) { + return new ObfuscationConfig(config.ObfuscateWith, config.HiddenBlocks, config.HiddenBlockEntities); + } + + private final Block obfuscateWith; + private final Set blocks; + private final Set blockStates; + private final Set> blockEntityTypes; + + /** + * @param hiddenBlocks "water" also hides all waterlogged block states + * @param hiddenBlockEntities block entity type ids, e.g. "minecraft:sign" + */ + public ObfuscationConfig(Material obfuscateWith, Set hiddenBlocks, Set hiddenBlockEntities) { + this.obfuscateWith = CraftMagicNumbers.getBlock(obfuscateWith); + + this.blocks = hiddenBlocks.stream() + .map(CraftMagicNumbers::getBlock) + .collect(Collectors.toUnmodifiableSet()); + + this.blockStates = getBlockStatesToHideFromMaterials(hiddenBlocks); + + this.blockEntityTypes = hiddenBlockEntities.stream() + .map(id -> { + ResourceLocation loc = ResourceLocation.parse(id); + return BuiltInRegistries.BLOCK_ENTITY_TYPE.get(loc).orElse(null); + }) + .filter(Objects::nonNull) + .map(Holder.Reference::value) + .collect(Collectors.toUnmodifiableSet()); + } + + public boolean hidesBlock(Block block) { + return blocks.contains(block); + } + + public boolean hidesBlockState(BlockState blockState) { + return blockStates.contains(blockState); + } + + public boolean hidesBlockEntity(BlockEntityType type) { + return blockEntityTypes.contains(type); + } + + private static Stream getWaterloggedBlockStates() { + FluidState waterFluidState = Fluids.WATER.getSource(false); + + return BuiltInRegistries.BLOCK.stream() + .map((block) -> block.getStateDefinition().getPossibleStates()) + .flatMap(Collection::stream) + .filter((blockState -> blockState.getFluidState() == waterFluidState)); + } + + private static Set getBlockStatesToHideFromMaterials(Set materials) { + Stream allStatesFromMaterials = materials.stream() + .map(CraftMagicNumbers::getBlock) + .map((block) -> block.getStateDefinition().getPossibleStates()) + .flatMap(Collection::stream); + + if(materials.contains(Material.WATER)) { + return Stream.concat(allStatesFromMaterials, getWaterloggedBlockStates()).collect(Collectors.toUnmodifiableSet()); + } + else { + return allStatesFromMaterials.collect(Collectors.toUnmodifiableSet()); + } + } +}