forked from SteamWar/SteamWar
Migrate BauSystem to the new TechHider and remove the legacy TechHider
The new TechHider registers a permanent global filter, so BauSystem now uses a single BauTechHider that combines the hiding rules of the spectator techhider, /techhider and /xray per player. To support the different obfuscation blocks of these rules, ForPlayer now provides the obfuscation block per position. The ChunkHider now also checks single valued chunk sections, which were sent unfiltered before, and recalculates their block count if they change. Unhandled packet types are logged once; statistics, debug samples and ping responses are passed through. The legacy TechHider and its access widener entries are removed.
This commit is contained in:
@@ -1,301 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.techhider.legacy;
|
||||
|
||||
import de.steamwar.core.ProtocolUtils;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||
import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Deprecated
|
||||
public class ChunkHider {
|
||||
public static final ChunkHider impl = new ChunkHider();
|
||||
|
||||
private static final UnaryOperator<ClientboundLevelChunkWithLightPacket> chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new);
|
||||
private static final UnaryOperator<ClientboundLevelChunkPacketData> chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class, ClientboundLevelChunkPacketData::new);
|
||||
|
||||
public BiFunction<Player, ClientboundLevelChunkWithLightPacket, ClientboundLevelChunkWithLightPacket> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = packet.getX();
|
||||
int chunkZ = packet.getZ();
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ)) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet = chunkPacketCloner.apply(packet);
|
||||
ClientboundLevelChunkPacketData dataWrapper = chunkDataCloner.apply(packet.getChunkData());
|
||||
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
dataWrapper.blockEntitiesData = dataWrapper.blockEntitiesData.stream()
|
||||
.filter(te -> tileEntityVisible(hiddenBlockEntities, te))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ByteBuf in = Unpooled.wrappedBuffer(dataWrapper.buffer);
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
for (int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset / 16, chunkZ);
|
||||
section.copyBlockCount();
|
||||
|
||||
blocks(section);
|
||||
biomes(section);
|
||||
}
|
||||
|
||||
if (in.readableBytes() != 0) {
|
||||
throw new IllegalStateException("ChunkHider21: Incomplete chunk data, " + in.readableBytes() + " bytes left");
|
||||
}
|
||||
|
||||
byte[] data = new byte[out.readableBytes()];
|
||||
out.readBytes(data);
|
||||
dataWrapper.buffer = data;
|
||||
|
||||
packet.chunkData = dataWrapper;
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
protected boolean tileEntityVisible(Set<String> hiddenBlockEntities, ClientboundLevelChunkPacketData.BlockEntityInfo tile) {
|
||||
BlockEntityType<?> type = tile.type;
|
||||
String path = BuiltInRegistries.BLOCK_ENTITY_TYPE.getKey(type).getPath();
|
||||
return !hiddenBlockEntities.contains(path);
|
||||
}
|
||||
|
||||
private void blocks(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
boolean singleValued = section.getBitsPerBlock() == 0;
|
||||
if (singleValued) {
|
||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
||||
return;
|
||||
} else if (section.getBitsPerBlock() < 9) {
|
||||
// Indirect (paletted) storage – only present when bitsPerBlock < 9 in 1.21+
|
||||
section.processPalette();
|
||||
}
|
||||
|
||||
if (section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) {
|
||||
section.skipNewDataArray(4096);
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readNewDataArray(4096));
|
||||
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int pos = (((y * 16) + z) * 16) + x;
|
||||
|
||||
TechHider.State test = section.test(x, y, z);
|
||||
|
||||
switch (test) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if (!section.getObfuscate().contains(values.get(pos))) {
|
||||
break;
|
||||
}
|
||||
case HIDE:
|
||||
values.set(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.set(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.writeDataArray(values.getRaw());
|
||||
}
|
||||
|
||||
private void biomes(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
if (section.getBitsPerBlock() == 0) {
|
||||
section.copyVarInt();
|
||||
} else if (section.getBitsPerBlock() < 6) {
|
||||
section.skipPalette();
|
||||
section.skipNewDataArray(64);
|
||||
} else {
|
||||
// Direct (global) biome IDs – no palette present
|
||||
section.skipNewDataArray(64);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
class SectionHider {
|
||||
private final Player player;
|
||||
private final TechHider techHider;
|
||||
private final ByteBuf in;
|
||||
private final ByteBuf out;
|
||||
|
||||
private final int chunkX;
|
||||
private final int chunkY;
|
||||
private final int chunkZ;
|
||||
private final int offsetX;
|
||||
private final int offsetY;
|
||||
private final int offsetZ;
|
||||
|
||||
private final boolean skipSection;
|
||||
|
||||
private boolean paletted;
|
||||
private int bitsPerBlock;
|
||||
private int blockCount;
|
||||
private int air;
|
||||
private int target;
|
||||
private Set<Integer> obfuscate;
|
||||
|
||||
public SectionHider(Player player, TechHider techHider, ByteBuf in, ByteBuf out, int chunkX, int chunkY, int chunkZ) {
|
||||
this.player = player;
|
||||
this.techHider = techHider;
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.chunkX = chunkX;
|
||||
this.chunkY = chunkY;
|
||||
this.chunkZ = chunkZ;
|
||||
this.offsetX = 16 * chunkX;
|
||||
this.offsetY = 16 * chunkY;
|
||||
this.offsetZ = 16 * chunkZ;
|
||||
this.skipSection = techHider.getLocationEvaluator().skipChunkSection(player, chunkX, chunkY, chunkZ);
|
||||
|
||||
this.paletted = false;
|
||||
this.bitsPerBlock = 0;
|
||||
this.air = TechHider.AIR_ID;
|
||||
this.target = techHider.getObfuscationTargetId();
|
||||
this.obfuscate = techHider.getObfuscateIds();
|
||||
}
|
||||
|
||||
public boolean blockPrecise() {
|
||||
return techHider.getLocationEvaluator().blockPrecise(player, chunkX, chunkY, chunkZ);
|
||||
}
|
||||
|
||||
public TechHider.State test(int x, int y, int z) {
|
||||
return techHider.getLocationEvaluator().check(player, offsetX + x, offsetY + y, offsetZ + z);
|
||||
}
|
||||
|
||||
public void copyBlockCount() {
|
||||
this.blockCount = in.readShort();
|
||||
out.writeShort(blockCount);
|
||||
}
|
||||
|
||||
public void copyBitsPerBlock() {
|
||||
bitsPerBlock = in.readByte();
|
||||
out.writeByte(bitsPerBlock);
|
||||
}
|
||||
|
||||
public int copyVarInt() {
|
||||
int value = ProtocolUtils.readVarInt(in);
|
||||
ProtocolUtils.writeVarInt(out, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
public void skipPalette() {
|
||||
int paletteLength = copyVarInt();
|
||||
for (int i = 0; i < paletteLength; i++) {
|
||||
copyVarInt();
|
||||
}
|
||||
}
|
||||
|
||||
public void processPalette() {
|
||||
if (skipSection) {
|
||||
skipPalette();
|
||||
return;
|
||||
}
|
||||
|
||||
int paletteLength = copyVarInt();
|
||||
if (paletteLength == 0) return;
|
||||
|
||||
paletted = true;
|
||||
air = 0;
|
||||
target = 0;
|
||||
|
||||
for (int i = 0; i < paletteLength; i++) {
|
||||
int entry = ProtocolUtils.readVarInt(in);
|
||||
if (obfuscate.contains(entry)) {
|
||||
entry = techHider.getObfuscationTargetId();
|
||||
}
|
||||
|
||||
if (entry == TechHider.AIR_ID) {
|
||||
air = i;
|
||||
} else if (entry == techHider.getObfuscationTargetId()) {
|
||||
target = i;
|
||||
}
|
||||
|
||||
ProtocolUtils.writeVarInt(out, entry);
|
||||
}
|
||||
obfuscate = Collections.emptySet();
|
||||
}
|
||||
|
||||
public void skipDataArray() {
|
||||
int dataArrayLength = copyVarInt();
|
||||
out.writeBytes(in, dataArrayLength * 8);
|
||||
}
|
||||
|
||||
public void skipNewDataArray(int entries) {
|
||||
if (bitsPerBlock == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
char valuesPerLong = (char) (64 / bitsPerBlock);
|
||||
int i1 = (entries + valuesPerLong - 1) / valuesPerLong;
|
||||
out.writeBytes(in, i1 * Long.BYTES);
|
||||
}
|
||||
|
||||
public long[] readDataArray() {
|
||||
long[] array = new long[copyVarInt()];
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
array[i] = in.readLong();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public long[] readNewDataArray(int entries) {
|
||||
if (bitsPerBlock == 0) {
|
||||
return new long[entries];
|
||||
}
|
||||
|
||||
char valuesPerLong = (char) (64 / bitsPerBlock);
|
||||
int i1 = (entries + valuesPerLong - 1) / valuesPerLong;
|
||||
long[] array = new long[i1];
|
||||
for (int i = 0; i < i1; i++) {
|
||||
array[i] = in.readLong();
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public void writeDataArray(long[] array) {
|
||||
for (long l : array) {
|
||||
out.writeLong(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.techhider.legacy;
|
||||
|
||||
import net.minecraft.core.SectionPos;
|
||||
import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Deprecated
|
||||
public class ProtocolWrapper {
|
||||
public static final ProtocolWrapper impl = new ProtocolWrapper();
|
||||
|
||||
public BiFunction<Player, ClientboundSectionBlocksUpdatePacket, ClientboundSectionBlocksUpdatePacket> multiBlockChangeGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
|
||||
SectionPos chunkCoords = packet.sectionPos;
|
||||
int chunkX = chunkCoords.getX();
|
||||
int chunkY = chunkCoords.getY();
|
||||
int chunkZ = chunkCoords.getZ();
|
||||
if (locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ)) {
|
||||
return packet;
|
||||
}
|
||||
|
||||
packet = TechHider.multiBlockChangeCloner.apply(packet);
|
||||
final short[] oldPos = packet.positions;
|
||||
final BlockState[] oldBlocks = packet.states;
|
||||
ArrayList<Short> poss = new ArrayList<>(oldPos.length);
|
||||
ArrayList<BlockState> blocks = new ArrayList<>(oldPos.length);
|
||||
for (int i = 0; i < oldPos.length; i++) {
|
||||
short pos = oldPos[i];
|
||||
BlockState block = oldBlocks[i];
|
||||
switch (locationEvaluator.check(p, 16 * chunkX + (pos >> 8 & 0xF), 16 * chunkY + (pos & 0xF), 16 * chunkZ + (pos >> 4 & 0xF))) {
|
||||
case SKIP:
|
||||
poss.add(pos);
|
||||
blocks.add(block);
|
||||
break;
|
||||
case CHECK:
|
||||
poss.add(pos);
|
||||
blocks.add(techHider.iBlockDataHidden(block) ? (BlockState) techHider.getObfuscationTarget() : block);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (blocks.isEmpty()) return null;
|
||||
|
||||
short[] newPos = new short[poss.size()];
|
||||
for (int i = 0; i < newPos.length; i++) {
|
||||
newPos[i] = poss.get(i);
|
||||
}
|
||||
|
||||
packet.positions = newPos;
|
||||
packet.states = blocks.toArray(BlockState[]::new);
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
/*
|
||||
* This file is a part of the SteamWar software.
|
||||
*
|
||||
* Copyright (C) 2025 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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package de.steamwar.techhider.legacy;
|
||||
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.core.BlockIds;
|
||||
import de.steamwar.core.ProtocolUtils;
|
||||
import lombok.Getter;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.network.protocol.game.*;
|
||||
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.Material;
|
||||
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Deprecated
|
||||
public class TechHider {
|
||||
|
||||
public static final Class<?> blockPosition = BlockPos.class;
|
||||
|
||||
public static final Class<?> iBlockData = BlockState.class;
|
||||
public static final Class<?> block = Block.class;
|
||||
|
||||
public boolean iBlockDataHidden(BlockState iBlockData) {
|
||||
return obfuscateIds.contains(BlockIds.impl.getCombinedId(iBlockData));
|
||||
}
|
||||
|
||||
public static final Object AIR = CraftMagicNumbers.getBlock(Material.AIR).defaultBlockState();
|
||||
public static final int AIR_ID = BlockIds.impl.materialToId(Material.AIR);
|
||||
|
||||
private final Map<Class<?>, BiFunction<Player, Object, Object>> techhiders = new HashMap<>();
|
||||
@Getter
|
||||
private final LocationEvaluator locationEvaluator;
|
||||
@Getter
|
||||
private final Object obfuscationTarget;
|
||||
@Getter
|
||||
private final int obfuscationTargetId;
|
||||
@Getter
|
||||
private final Set<Integer> obfuscateIds;
|
||||
@Getter
|
||||
private final Set<String> hiddenBlockEntities;
|
||||
|
||||
public TechHider(LocationEvaluator locationEvaluator, Material obfuscationTarget, Set<Material> obfuscate, Set<String> hiddenBlockEntities) {
|
||||
this.locationEvaluator = locationEvaluator;
|
||||
this.obfuscateIds = obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet());
|
||||
this.hiddenBlockEntities = hiddenBlockEntities;
|
||||
this.obfuscationTarget = CraftMagicNumbers.getBlock(obfuscationTarget).defaultBlockState();
|
||||
this.obfuscationTargetId = BlockIds.impl.materialToId(obfuscationTarget);
|
||||
|
||||
techhiders.put(ClientboundBlockEventPacket.class, (player, o) -> this.blockActionHider(player, (ClientboundBlockEventPacket) o));
|
||||
techhiders.put(ClientboundBlockUpdatePacket.class, (player, o) -> this.blockChangeHider(player, (ClientboundBlockUpdatePacket) o));
|
||||
techhiders.put(ClientboundBlockEntityDataPacket.class, (player, o) -> this.tileEntityDataHider(player, (ClientboundBlockEntityDataPacket) o));
|
||||
techhiders.put(ClientboundSectionBlocksUpdatePacket.class, (BiFunction) ProtocolWrapper.impl.multiBlockChangeGenerator(this));
|
||||
techhiders.put(ClientboundLevelChunkWithLightPacket.class, (BiFunction) ChunkHider.impl.chunkHiderGenerator(this));
|
||||
techhiders.put(ServerboundUseItemOnPacket.class, (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet);
|
||||
techhiders.put(ServerboundInteractPacket.class, (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet);
|
||||
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
techhiders.forEach((type, playerObjectBiFunction) -> TinyProtocol.instance.addFilter((Class) type, playerObjectBiFunction));
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
techhiders.forEach(TinyProtocol.instance::removeFilter);
|
||||
}
|
||||
|
||||
public static final UnaryOperator<ClientboundSectionBlocksUpdatePacket> multiBlockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new);
|
||||
|
||||
private static final UnaryOperator<ClientboundBlockUpdatePacket> blockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new);
|
||||
|
||||
private ClientboundBlockUpdatePacket blockChangeHider(Player p, ClientboundBlockUpdatePacket packet) {
|
||||
switch (locationEvaluator.checkBlockPos(p, packet.getPos())) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if (!iBlockDataHidden(packet.blockState)) {
|
||||
return packet;
|
||||
}
|
||||
case HIDE:
|
||||
packet = blockChangeCloner.apply(packet);
|
||||
packet.blockState = (BlockState) obfuscationTarget;
|
||||
return packet;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
packet = blockChangeCloner.apply(packet);
|
||||
packet.blockState = (BlockState) AIR;
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
private Object blockActionHider(Player p, ClientboundBlockEventPacket packet) {
|
||||
if (locationEvaluator.checkBlockPos(p, packet.getPos()) == State.SKIP) {
|
||||
return packet;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private ClientboundBlockEntityDataPacket tileEntityDataHider(Player p, ClientboundBlockEntityDataPacket packet) {
|
||||
switch (locationEvaluator.checkBlockPos(p, packet.getPos())) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if (packet.getType() != BlockEntityType.SIGN) {
|
||||
return packet;
|
||||
}
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public enum State {
|
||||
SKIP,
|
||||
CHECK,
|
||||
HIDE,
|
||||
HIDE_AIR
|
||||
}
|
||||
|
||||
public interface LocationEvaluator {
|
||||
default boolean suppressInteractions(Player player) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean skipChunk(Player player, int x, int z);
|
||||
|
||||
default boolean skipChunkSection(Player player, int x, int y, int z) {
|
||||
return skipChunk(player, x, z);
|
||||
}
|
||||
|
||||
default State check(Player player, int x, int y, int z) {
|
||||
return skipChunkSection(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(y), ProtocolUtils.posToChunk(z)) ? State.SKIP : State.CHECK;
|
||||
}
|
||||
|
||||
default State checkBlockPos(Player player, Vec3i pos) {
|
||||
return check(player, pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
default boolean blockPrecise(Player player, int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,34 +35,3 @@ accessible field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket yHeadRot B
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket entityId I
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket entityId I
|
||||
|
||||
# For legacy/ChunkHider
|
||||
## transitive-extendable means that a public no args constructor is added without any super initialization
|
||||
transitive-extendable class net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket chunkData Lnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData;
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket chunkData Lnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData;
|
||||
|
||||
## transitive-extendable means that a public no args constructor is added without any super initialization
|
||||
transitive-extendable class net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData buffer [B
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData buffer [B
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData blockEntitiesData Ljava/util/List;
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData blockEntitiesData Ljava/util/List;
|
||||
|
||||
accessible class net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo type Lnet/minecraft/world/level/block/entity/BlockEntityType;
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo packedXZ I
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData$BlockEntityInfo y I
|
||||
|
||||
# For legacy/TechHider
|
||||
## transitive-extendable means that a public no args constructor is added without any super initialization
|
||||
transitive-extendable class net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket sectionPos Lnet/minecraft/core/SectionPos;
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket positions [S
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket positions [S
|
||||
accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket states [Lnet/minecraft/world/level/block/state/BlockState;
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket states [Lnet/minecraft/world/level/block/state/BlockState;
|
||||
|
||||
## transitive-extendable means that a public no args constructor is added without any super initialization
|
||||
transitive-extendable class net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket
|
||||
mutable field net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket blockState Lnet/minecraft/world/level/block/state/BlockState;
|
||||
Reference in New Issue
Block a user