diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java index c00d976d..ff3cbcea 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/tracer/rendering/TraceEntity.java @@ -24,13 +24,16 @@ import de.steamwar.bausystem.configplayer.Config; import de.steamwar.bausystem.features.tracer.TNTPoint; import de.steamwar.bausystem.features.tracer.Trace; import de.steamwar.bausystem.features.tracer.TraceManager; +import de.steamwar.entity.RBlockDisplay; import de.steamwar.entity.REntityServer; -import de.steamwar.entity.RFallingBlockEntity; import lombok.Getter; import net.md_5.bungee.api.chat.ClickEvent; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.entity.Player; +import org.bukkit.util.Transformation; +import org.joml.Quaternionf; +import org.joml.Vector3f; import yapion.hierarchy.types.YAPIONValue; import java.util.List; @@ -41,7 +44,16 @@ import static de.steamwar.bausystem.features.util.TNTClickListener.TNT_CLICK_DET /** * Wrapper for the rendering of a record bundle */ -public class TraceEntity extends RFallingBlockEntity { +public class TraceEntity extends RBlockDisplay { + + private static final float TNT_VISUAL_SCALE = 0.98F; + private static final float TNT_VISUAL_OFFSET = -TNT_VISUAL_SCALE / 2.0F; + private static final Transformation TNT_VISUAL_TRANSFORM = new Transformation( + new Vector3f(TNT_VISUAL_OFFSET, 0.0F, TNT_VISUAL_OFFSET), + new Quaternionf(0, 0, 0, 1), + new Vector3f(TNT_VISUAL_SCALE, TNT_VISUAL_SCALE, TNT_VISUAL_SCALE), + new Quaternionf(0, 0, 0, 1) + ); /** * The records represented by this REntity @@ -57,11 +69,13 @@ public class TraceEntity extends RFallingBlockEntity { private final Trace trace; public TraceEntity(REntityServer server, Location location, boolean isExplosion, List records, Trace trace) { - super(server, location, isExplosion ? Material.RED_STAINED_GLASS : Material.TNT); + super(server, location); + Material material = isExplosion ? Material.RED_STAINED_GLASS : Material.TNT; this.records = records; this.trace = trace; uniqueTntIdsString = records.stream().map(TNTPoint::getTntId).distinct().map(Object::toString).collect(Collectors.joining(" ")); - setNoGravity(true); + setTransform(TNT_VISUAL_TRANSFORM); + setBlock(material.createBlockData()); } /** 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 091d5717..3fc4a364 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -38,7 +38,11 @@ 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; @@ -46,10 +50,12 @@ import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; +import java.util.Collection; import java.util.Optional; 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 { @@ -57,9 +63,21 @@ public class TechHiderWrapper extends StateDependent implements Listener { @Getter private final ConcurrentHashMap hiddenRegion = new ConcurrentHashMap<>(); + private final HullHider hullHider; public TechHiderWrapper(HullHider hullHider) { super(ENABLED, FightState.All); + + this.hullHider = hullHider; + + new StateDependentListener(ENABLED, FightState.All, this); + register(); + } + + @Override + public void enable() { + Set blockStatesToObfuscate = getBlockStatesToHideFromMaterials(Config.GameModeConfig.Techhider.HiddenBlocks); + Set blocksToObfuscate = Config.GameModeConfig.Techhider.HiddenBlocks.stream() .map(CraftMagicNumbers::getBlock) .collect(Collectors.toUnmodifiableSet()); @@ -94,6 +112,11 @@ public class TechHiderWrapper extends StateDependent implements Listener { 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) { @@ -116,13 +139,6 @@ public class TechHiderWrapper extends StateDependent implements Listener { return p.getGameMode() != GameMode.SPECTATOR; } }); - - new StateDependentListener(ENABLED, FightState.All, this); - register(); - } - - @Override - public void enable() { } @Override @@ -175,4 +191,27 @@ public class TechHiderWrapper extends StateDependent implements Listener { return Fight.getOpposite(team).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/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/AccessPrivilegeProvider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/AccessPrivilegeProvider.java index 16df8ab0..b04748c6 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/AccessPrivilegeProvider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/AccessPrivilegeProvider.java @@ -21,6 +21,7 @@ package de.steamwar.techhider; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.entity.BlockEntityType; +import net.minecraft.world.level.block.state.BlockState; import org.bukkit.entity.Player; public interface AccessPrivilegeProvider { @@ -30,6 +31,8 @@ public interface AccessPrivilegeProvider { boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block); + boolean isPlayerPrivilegedToAccessBlockState(Player p, int blockX, int blockY, int blockZ, BlockState blockState); + boolean isPlayerPrivilegedToAccessEntity(Player p, int entityId); boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType type); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java index 0a280bee..3d7fa97c 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java @@ -179,7 +179,7 @@ public class ChunkHider { out.readBytes(data); List blockEntities = chunkBlockEntitiesDataField.get(chunkData); - List filteredBlockEntities = filterBlockEntities(player, blockEntities); + List filteredBlockEntities = filterBlockEntities(player, blockEntities, chunkX, chunkZ); return buildNewChunkPacket(packet, data, filteredBlockEntities); @@ -201,7 +201,7 @@ public class ChunkHider { Block block = blockState.getBlock(); - if (accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlock(player, worldX, worldY, worldZ, block)) { + if (accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlock(player, worldX, worldY, worldZ, block) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockState(player, worldX, worldY, worldZ, blockState)) { obfuscatedData[blockDataIndex] = blockId; } else { obfuscatedData[blockDataIndex] = blockIdUsedForHiding; @@ -256,18 +256,24 @@ public class ChunkHider { private static final Reflection.Field packedXZField = Reflection.getField(blockEntitiyInfoClass, int.class, 0); private static final Reflection.Field yField = Reflection.getField(blockEntitiyInfoClass, int.class, 1); - private List filterBlockEntities(Player player, List blockEntities) { + private List filterBlockEntities(Player player, List blockEntities, int chunkX, int chunkZ) { + int fourBitBitmask = 0b0000_1111; + return blockEntities.stream() .filter((blockEntityInfo) -> { BlockEntityType type = blockEntityInfoTypeField.get(blockEntityInfo); int packedXZ = packedXZField.get(blockEntityInfo); - int y = yField.get(blockEntityInfo); - int x = SectionPos.sectionRelativeX((short) packedXZ); - int z = SectionPos.sectionRelativeZ((short) packedXZ); + int localX = (packedXZ >> 4) & fourBitBitmask; + int localZ = packedXZ & fourBitBitmask; - return accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, x, y, z) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockEntity(player, x, y, z, type); + int worldX = (chunkX * SECTION_SPAN_SIZE) + localX; + int worldZ = (chunkZ * SECTION_SPAN_SIZE) + localZ; + + int worldY = yField.get(blockEntityInfo); + + return accessPrivilegeProvider.isPlayerPrivilegedToAccessPosition(player, worldX, worldY, worldZ) && accessPrivilegeProvider.isPlayerPrivilegedToAccessBlockEntity(player, worldX, worldY, worldZ, type); }).toList(); } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java index ed18f556..f9764bfa 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java @@ -423,12 +423,13 @@ public class TechHider { private Packet processBlockUpdatePacket(Player player, ClientboundBlockUpdatePacket packet) { BlockPos blockPos = packet.getPos(); - Block block = packet.getBlockState().getBlock(); + BlockState blockState = packet.getBlockState(); + Block block = blockState.getBlock(); int blockX = blockPos.getX(); int blockY = blockPos.getY(); int blockZ = blockPos.getZ(); - if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(player, blockX, blockY, blockZ, block)) { + if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(player, blockX, blockY, blockZ, block) && privilegeProvider.isPlayerPrivilegedToAccessBlockState(player, blockX, blockY, blockZ, blockState)) { return packet; } else if (privilegeProvider.isPlayerPrivilegedToAccessPosition(player, blockX, blockY, blockZ)) { return new ClientboundBlockUpdatePacket(blockPos, blockStateUsedForObfuscation); @@ -471,7 +472,6 @@ public class TechHider { short[] oldPos = oldPosField.get(packet); BlockState[] oldStates = oldStatesField.get(packet); - boolean modified = false; List filteredPos = new ArrayList<>(oldPos.length); List filteredStates = new ArrayList<>(oldStates.length); @@ -484,12 +484,10 @@ public class TechHider { int worldY = sectionPos.relativeToBlockY(posShort); int worldZ = sectionPos.relativeToBlockZ(posShort); - if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(p, worldX, worldY, worldZ, block)) { - // TODO statefull !!! + if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ) && privilegeProvider.isPlayerPrivilegedToAccessBlock(p, worldX, worldY, worldZ, block) && privilegeProvider.isPlayerPrivilegedToAccessBlockState(p, worldX, worldY, worldZ, state)) { filteredPos.add(posShort); filteredStates.add(state); } else if (privilegeProvider.isPlayerPrivilegedToAccessPosition(p, worldX, worldY, worldZ)) { - modified = true; filteredPos.add(posShort); filteredStates.add(blockStateUsedForObfuscation); } @@ -498,9 +496,6 @@ public class TechHider { if (filteredStates.isEmpty()) { return null; } - if (!modified) { - return packet; - } short[] newPos = new short[filteredPos.size()]; for (int i = 0; i < newPos.length; i++) { diff --git a/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt b/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt index d8317219..4e95c38f 100644 --- a/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt +++ b/TNTLeague/src/de/steamwar/tntleague/command/InviteCommand.kt @@ -28,6 +28,9 @@ import net.md_5.bungee.api.chat.ClickEvent import org.bukkit.entity.Player object InviteCommand : SWCommand("invite") { + init { + message = de.steamwar.tntleague.message + } @Register fun invitePlayer(@Validator("isLeader") sender: Player, target: Player) { diff --git a/VelocityCore/src/de/steamwar/velocitycore/commands/ReplayCommand.java b/VelocityCore/src/de/steamwar/velocitycore/commands/ReplayCommand.java index 26b55da0..b6bdd7ec 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/commands/ReplayCommand.java +++ b/VelocityCore/src/de/steamwar/velocitycore/commands/ReplayCommand.java @@ -42,6 +42,13 @@ public class ReplayCommand extends SWCommand { super("replay"); } + @Register + public void genericCommand(PlayerChatter sender) { + sender.system("REPLAY_UNAVAILABLE"); + return; + } + + /* @Register public void genericCommand(PlayerChatter sender, int replayId, @StaticValue(value = {"", "-a"}, allowISE = true) @OptionalValue("") boolean isAdmin, @OptionalValue("") String optionalMap) { Fight fight = Fight.getById(replayId); @@ -109,4 +116,5 @@ public class ReplayCommand extends SWCommand { private Message parseLeader(SteamwarUser leader, int players, boolean winner) { return new Message("REPLAY_" + (players > 1 ? "" : "SOLO_") + (winner ? "WINNER" : "LOSER"), leader.getUserName(), players - 1); } + */ }