forked from SteamWar/SteamWar
TechHider refactoring, simple Blocktagging
This commit is contained in:
+6
-15
@@ -27,9 +27,7 @@ import net.minecraft.core.SectionPosition;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutBlockChange;
|
||||
import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
@@ -38,20 +36,13 @@ public class HullHiderWrapper18 implements HullHiderWrapper {
|
||||
private static final Reflection.MethodInvoker getState = Reflection.getTypedMethod(Reflection.getClass("{obc}.block.data.CraftBlockData"), "getState", IBlockData.class);
|
||||
@Override
|
||||
public Object generateBlockChangePacket(List<Hull.IntVector> changes) {
|
||||
List<Object> blockdata = new ArrayList<>(changes.size());
|
||||
Object[] blockdata = new Object[changes.size()];
|
||||
for(int i = 0; i < blockdata.length; i++) {
|
||||
Hull.IntVector change = changes.get(i);
|
||||
blockdata[i] = getState.invoke(Config.world.getBlockData(change.getX(), change.getY(), change.getZ()));
|
||||
}
|
||||
|
||||
changes.removeIf(change -> {
|
||||
BlockData data = Config.world.getBlockData(change.getX(), change.getY(), change.getZ());
|
||||
boolean unchanged = data.getMaterial() == Config.ObfuscateWith || Config.HiddenBlocks.contains(data.getMaterial());
|
||||
if(!unchanged)
|
||||
blockdata.add(getState.invoke(data));
|
||||
return unchanged;
|
||||
});
|
||||
|
||||
if(changes.isEmpty())
|
||||
return null;
|
||||
|
||||
return generateBlockChangePacket(changes, blockdata.toArray());
|
||||
return generateBlockChangePacket(changes, blockdata);
|
||||
}
|
||||
|
||||
private Object generateBlockChangePacket(List<Hull.IntVector> changes, Object[] blockdata) {
|
||||
|
||||
@@ -21,7 +21,6 @@ package de.steamwar.fightsystem.utils;
|
||||
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import de.steamwar.fightsystem.Config;
|
||||
import org.bukkit.Material;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -31,14 +30,6 @@ public class HullHiderWrapper8 implements HullHiderWrapper {
|
||||
private static final Reflection.MethodInvoker getHandle = Reflection.getMethod("{obc}.CraftChunk", "getHandle");
|
||||
@Override
|
||||
public Object generateBlockChangePacket(List<Hull.IntVector> changes) {
|
||||
changes.removeIf(change -> {
|
||||
Material material = Config.world.getBlockAt(change.getX(), change.getY(), change.getZ()).getType();
|
||||
return material == Config.ObfuscateWith || Config.HiddenBlocks.contains(material);
|
||||
});
|
||||
|
||||
if(changes.isEmpty())
|
||||
return null;
|
||||
|
||||
Hull.IntVector chunk = changes.get(0);
|
||||
chunk = new Hull.IntVector(chunk.getX() >> 4, chunk.getY() >> 4, chunk.getZ() >> 4);
|
||||
int xOffset = 16*chunk.getX();
|
||||
|
||||
@@ -187,9 +187,6 @@ public class Hull {
|
||||
|
||||
for (Map.Entry<IntVector, List<IntVector>> entry : sectionWise.entrySet()) {
|
||||
Object packet = HullHiderWrapper.impl.generateBlockChangePacket(entry.getValue());
|
||||
if(packet == null)
|
||||
continue;
|
||||
|
||||
players.forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -112,7 +112,9 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati
|
||||
public TechHider.State check(Player player, int x, int y, int z) {
|
||||
if(hiddenRegion.computeIfAbsent(player, this::getHiddenRegion).inRegion(x, y, z)) {
|
||||
if(FightSystem.getHullHider().isBlockHidden(player, x, y, z)) {
|
||||
return TechHider.State.HIDE;
|
||||
long pattern = player.getUniqueId().getLeastSignificantBits();
|
||||
int id = ((y&3) << 4) + ((z&3) << 2) + (x&3);
|
||||
return (pattern & (1L << id)) == 0 ? TechHider.State.HIDE : TechHider.State.HIDE_AIR;
|
||||
} else {
|
||||
return TechHider.State.CHECK;
|
||||
}
|
||||
|
||||
@@ -19,24 +19,26 @@
|
||||
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
public class ChunkHider14 extends ChunkHider9 {
|
||||
|
||||
@Override
|
||||
protected void dataHider(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, boolean skip, boolean blockPrecise) {
|
||||
out.writeShort(in.readShort()); // Block count
|
||||
byte bitsPerBlock = in.readByte();
|
||||
out.writeByte(bitsPerBlock);
|
||||
protected void dataHider(SectionHider section) {
|
||||
section.copyBlockCount();
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
if(bitsPerBlock < 9) {
|
||||
obfuscationTarget = ChunkHider.processPalette(obfuscationTarget, obfuscate, in, out);
|
||||
obfuscate = Collections.emptySet();
|
||||
boolean hasPalette = section.getBitsPerBlock() < 9;
|
||||
if(hasPalette)
|
||||
section.processPalette();
|
||||
|
||||
if(section.isSkipSection()) {
|
||||
section.skipDataArray();
|
||||
} else {
|
||||
if(hasPalette && !section.blockPrecise()) {
|
||||
section.skipDataArray();
|
||||
return;
|
||||
}
|
||||
|
||||
processDataArray(section);
|
||||
}
|
||||
|
||||
processDataArray(locationEvaluator, obfuscationTarget, obfuscate, in, out, bitsPerBlock, skip || (!blockPrecise && bitsPerBlock < 9));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,31 +20,34 @@
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
public class ProtocolWrapper14 extends ProtocolWrapper8 {
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
UnaryOperator<Object> blockBreakCloner = ProtocolUtils.shallowCloneGenerator(blockBreakPacket);
|
||||
Reflection.FieldAccessor<?> blockBreakPosition = Reflection.getField(blockBreakPacket, TechHider.blockPosition, 0);
|
||||
Reflection.FieldAccessor<?> blockBreakBlockData = Reflection.getField(blockBreakPacket, TechHider.iBlockData, 0);
|
||||
|
||||
return (p, packet) -> {
|
||||
switch (locationEvaluator.checkBlockPos(p, blockBreakPosition.get(packet))) {
|
||||
switch (techHider.getLocationEvaluator().checkBlockPos(p, blockBreakPosition.get(packet))) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(!TechHider.iBlockDataHidden(obfuscate, blockBreakBlockData.get(packet)))
|
||||
if(!techHider.iBlockDataHidden(blockBreakBlockData.get(packet)))
|
||||
return packet;
|
||||
case HIDE:
|
||||
packet = blockBreakCloner.apply(packet);
|
||||
blockBreakBlockData.set(packet, techHider.getObfuscationTarget());
|
||||
return packet;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
packet = blockBreakCloner.apply(packet);
|
||||
blockBreakBlockData.set(packet, obfuscationTarget);
|
||||
blockBreakBlockData.set(packet, TechHider.AIR);
|
||||
return packet;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -31,7 +31,6 @@ import net.minecraft.util.SimpleBitStorage;
|
||||
import net.minecraft.world.level.block.entity.TileEntityTypes;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -55,26 +54,27 @@ public class ChunkHider18 implements ChunkHider {
|
||||
private static final Reflection.FieldAccessor<List> tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities) {
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = chunkXField.get(packet);
|
||||
int chunkZ = chunkZField.get(packet);
|
||||
if (locationEvaluator.skipChunk(p, chunkX, chunkZ))
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = chunkPacketCloner.apply(packet);
|
||||
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
|
||||
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
tileEntities.set(dataWrapper, ((List<?>)tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
|
||||
|
||||
ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
int xOffset = 16*chunkX;
|
||||
int zOffset = 16*chunkZ;
|
||||
for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
||||
int finalYOffset = yOffset;
|
||||
int chunkY = yOffset/16;
|
||||
dataHider((x, y, z) -> locationEvaluator.check(p, x+xOffset, y+finalYOffset, z+zOffset), obfuscationTarget, obfuscate, in, out, locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ), locationEvaluator.blockPrecise(p, chunkX, chunkY, chunkZ));
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ);
|
||||
|
||||
section.copyBlockCount();
|
||||
blocks(section);
|
||||
biomes(section);
|
||||
}
|
||||
out.writeBytes(in); // MC appends a 0 byte at the end if there is a full chunk, idk why
|
||||
|
||||
@@ -96,70 +96,57 @@ public class ChunkHider18 implements ChunkHider {
|
||||
return !hiddenBlockEntities.contains((String) getName.invoke(getKey.invoke(tileEntityTypes, entityType.get(tile))));
|
||||
}
|
||||
|
||||
private void dataHider(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, boolean skip, boolean blockPrecise) {
|
||||
out.writeShort(in.readShort()); // Block count
|
||||
private void blocks(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
|
||||
containerWalker(in, out, 15, obfuscationTarget, skip ? Collections.emptySet() : obfuscate, (paletteTarget, dataArrayLength, bitsPerBlock) -> {
|
||||
Set<Integer> palettedObfuscate;
|
||||
if(bitsPerBlock < 15) {
|
||||
palettedObfuscate = Collections.emptySet();
|
||||
} else {
|
||||
paletteTarget = obfuscationTarget;
|
||||
palettedObfuscate = obfuscate;
|
||||
}
|
||||
boolean singletonPalette = section.getBitsPerBlock() == 0;
|
||||
if(singletonPalette) {
|
||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
||||
}else if(section.getBitsPerBlock() < 15) {
|
||||
section.processPalette();
|
||||
}
|
||||
|
||||
if(skip || dataArrayLength == 0 || (!blockPrecise && bitsPerBlock < 15)) {
|
||||
out.writeBytes(in, dataArrayLength*8);
|
||||
return;
|
||||
}
|
||||
if(section.isSkipSection() || singletonPalette || (!section.blockPrecise() && section.isPaletted())) {
|
||||
section.skipDataArray();
|
||||
return;
|
||||
}
|
||||
|
||||
long[] array = new long[dataArrayLength];
|
||||
for(int i = 0; i < dataArrayLength; i++)
|
||||
array[i] = in.readLong();
|
||||
SimpleBitStorage values = new SimpleBitStorage(bitsPerBlock, 4096, array);
|
||||
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readDataArray());
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
switch (locationEvaluator.test(x, y, z)) {
|
||||
case SKIP:
|
||||
switch (section.test(x, y, z)) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if(!section.getObfuscate().contains(values.a(pos)))
|
||||
break;
|
||||
case CHECK:
|
||||
if(!palettedObfuscate.contains(values.a(pos)))
|
||||
break;
|
||||
default:
|
||||
values.b(pos, paletteTarget);
|
||||
}
|
||||
case HIDE:
|
||||
values.b(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.b(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (long l : values.a())
|
||||
out.writeLong(l);
|
||||
});
|
||||
containerWalker(in, out, 6, 0, Collections.emptySet(), (paletteTarget, dataArrayLength, bitsPerBlock) -> out.writeBytes(in, dataArrayLength * 8)); // Biomes
|
||||
}
|
||||
|
||||
private void containerWalker(ByteBuf in, ByteBuf out, int globalPalette, int obfuscationTarget, Set<Integer> obfuscate, TriConsumer<Integer, Integer, Byte> dataArray) {
|
||||
byte bitsPerBlock = in.readByte();
|
||||
out.writeByte(bitsPerBlock);
|
||||
|
||||
//blockId -> obfuscate.contains(blockId) ? obfuscationTarget : blockId
|
||||
if(bitsPerBlock == 0) {
|
||||
int value = ProtocolUtils.readVarInt(in);
|
||||
ProtocolUtils.writeVarInt(out, obfuscate.contains(value) ? obfuscationTarget : value);
|
||||
}else if(bitsPerBlock < globalPalette) {
|
||||
obfuscationTarget = ChunkHider.processPalette(obfuscationTarget, obfuscate, in, out);
|
||||
}
|
||||
|
||||
int dataArrayLength = ProtocolUtils.readVarInt(in);
|
||||
ProtocolUtils.writeVarInt(out, dataArrayLength);
|
||||
dataArray.accept(obfuscationTarget, dataArrayLength, bitsPerBlock);
|
||||
section.writeDataArray(values.a());
|
||||
}
|
||||
|
||||
private interface TriConsumer<X, Y, Z> {
|
||||
void accept(X x, Y y, Z z);
|
||||
private void biomes(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
boolean singletonPalette = section.getBitsPerBlock() == 0;
|
||||
if(singletonPalette)
|
||||
section.copyVarInt();
|
||||
else if(section.getBitsPerBlock() < 6)
|
||||
section.skipPalette();
|
||||
|
||||
section.skipDataArray();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,9 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak;
|
||||
import net.minecraft.world.level.block.entity.TileEntitySign;
|
||||
import net.minecraft.world.level.block.entity.TileEntityTypes;
|
||||
import net.minecraft.world.level.block.state.IBlockData;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ProtocolWrapper18 implements ProtocolWrapper {
|
||||
@@ -38,8 +36,9 @@ public class ProtocolWrapper18 implements ProtocolWrapper {
|
||||
private static final Reflection.FieldAccessor<short[]> multiBlockChangePos = Reflection.getField(TechHider.multiBlockChangePacket, short[].class, 0);
|
||||
private static final Reflection.FieldAccessor<IBlockData[]> multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, IBlockData[].class, 0);
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
|
||||
Object chunkCoords = multiBlockChangeChunk.get(packet);
|
||||
int chunkX = TechHider.blockPositionX.get(chunkCoords);
|
||||
int chunkY = TechHider.blockPositionY.get(chunkCoords);
|
||||
@@ -62,7 +61,7 @@ public class ProtocolWrapper18 implements ProtocolWrapper {
|
||||
break;
|
||||
case CHECK:
|
||||
poss.add(pos);
|
||||
blocks.add(TechHider.iBlockDataHidden(obfuscate, block) ? (IBlockData) obfuscationTarget : block);
|
||||
blocks.add(techHider.iBlockDataHidden(block) ? (IBlockData) techHider.getObfuscationTarget() : block);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -90,17 +89,20 @@ public class ProtocolWrapper18 implements ProtocolWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
PacketPlayOutBlockBreak breakPacket = (PacketPlayOutBlockBreak) packet;
|
||||
switch (locationEvaluator.checkBlockPos(p, breakPacket.b())) {
|
||||
switch (techHider.getLocationEvaluator().checkBlockPos(p, breakPacket.b())) {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(!TechHider.iBlockDataHidden(obfuscate, breakPacket.c()))
|
||||
if(!techHider.iBlockDataHidden(breakPacket.c()))
|
||||
return packet;
|
||||
case HIDE:
|
||||
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) techHider.getObfuscationTarget(), breakPacket.d(), breakPacket.a());
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) obfuscationTarget, breakPacket.d(), breakPacket.a());
|
||||
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) TechHider.AIR, breakPacket.d(), breakPacket.a());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,16 +19,14 @@
|
||||
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ProtocolWrapper19 extends ProtocolWrapper18 {
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ package de.steamwar.techhider;
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ChunkHider8 implements ChunkHider {
|
||||
@@ -34,7 +33,7 @@ public class ChunkHider8 implements ChunkHider {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities) {
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (player, packet) -> packet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public class ProtocolWrapper8 implements ProtocolWrapper {
|
||||
@@ -40,8 +38,9 @@ public class ProtocolWrapper8 implements ProtocolWrapper {
|
||||
private static final Class<?> multiBlockChangeInfoArray = Reflection.getClass("[L{nms}.PacketPlayOutMultiBlockChange$MultiBlockChangeInfo;");
|
||||
private static final Reflection.FieldAccessor<?> multiBlockChangeInfos = Reflection.getField(TechHider.multiBlockChangePacket, multiBlockChangeInfoArray, 0);
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
|
||||
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
|
||||
Object chunkCoords = multiBlockChangeChunk.get(packet);
|
||||
int chunkX = chunkCoordinateX.get(chunkCoords);
|
||||
int chunkZ = chunkCoordinateZ.get(chunkCoords);
|
||||
@@ -58,7 +57,7 @@ public class ProtocolWrapper8 implements ProtocolWrapper {
|
||||
blockChangeInfos.add(mbci);
|
||||
break;
|
||||
case CHECK:
|
||||
blockChangeInfos.add(TechHider.iBlockDataHidden(obfuscate, multiBlockChangeInfoBlock.get(mbci)) ? multiBlockChangeInfoConstructor.invoke(packet, pos, obfuscationTarget) : mbci);
|
||||
blockChangeInfos.add(techHider.iBlockDataHidden(multiBlockChangeInfoBlock.get(mbci)) ? multiBlockChangeInfoConstructor.invoke(packet, pos, techHider.getObfuscationTarget()) : mbci);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -80,7 +79,7 @@ public class ProtocolWrapper8 implements ProtocolWrapper {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator bypass) {
|
||||
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -45,20 +44,19 @@ public class ChunkHider9 extends ChunkHider8 {
|
||||
private static final Reflection.MethodInvoker nbtTagGetString = Reflection.getTypedMethod(nbtTagCompound, null, String.class, String.class);
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities) {
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = mapChunkX.get(packet);
|
||||
int chunkZ = mapChunkZ.get(packet);
|
||||
if (locationEvaluator.skipChunk(p, chunkX, chunkZ))
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = mapChunkCloner.apply(packet);
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
mapChunkBlockEntities.set(packet, ((List<?>)mapChunkBlockEntities.get(packet)).stream().filter(
|
||||
nbttag -> !hiddenBlockEntities.contains((String) nbtTagGetString.invoke(nbttag, "id"))
|
||||
).collect(Collectors.toList()));
|
||||
|
||||
int xOffset = 16*chunkX;
|
||||
int zOffset = 16*chunkZ;
|
||||
int primaryBitMask = mapChunkBitMask.get(packet);
|
||||
ByteBuf in = Unpooled.wrappedBuffer(mapChunkData.get(packet));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
@@ -66,8 +64,8 @@ public class ChunkHider9 extends ChunkHider8 {
|
||||
if(((1 << chunkY) & primaryBitMask) == 0)
|
||||
continue;
|
||||
|
||||
int yOffset = 16*chunkY;
|
||||
dataHider((x, y, z) -> locationEvaluator.check(p, x+xOffset, y+yOffset, z+zOffset), obfuscationTarget, obfuscate, in, out, locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ), locationEvaluator.blockPrecise(p, chunkX, chunkY, chunkZ));
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, chunkY, chunkZ);
|
||||
dataHider(section);
|
||||
}
|
||||
byte[] data = new byte[out.readableBytes()];
|
||||
out.readBytes(data);
|
||||
@@ -77,51 +75,45 @@ public class ChunkHider9 extends ChunkHider8 {
|
||||
};
|
||||
}
|
||||
|
||||
protected void dataHider(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, boolean skip, boolean blockPrecise) {
|
||||
byte bitsPerBlock = in.readByte();
|
||||
out.writeByte(bitsPerBlock);
|
||||
protected void dataHider(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
section.processPalette();
|
||||
|
||||
int paletteTarget = ChunkHider.processPalette(obfuscationTarget, skip ? Collections.emptySet() : obfuscate, in, out);
|
||||
if(bitsPerBlock < 13) {
|
||||
obfuscationTarget = paletteTarget;
|
||||
obfuscate = Collections.emptySet();
|
||||
if(section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) { //section.getBitsPerBlock() < 9
|
||||
section.skipDataArray();
|
||||
} else {
|
||||
processDataArray(section);
|
||||
}
|
||||
|
||||
processDataArray(locationEvaluator, obfuscationTarget, obfuscate, in, out, bitsPerBlock, skip || (!blockPrecise && bitsPerBlock < 9));
|
||||
|
||||
out.writeBytes(in, 4096); //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
|
||||
section.getOut().writeBytes(section.getIn(), 4096); //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
|
||||
}
|
||||
|
||||
protected void processDataArray(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, int bitsPerBlock, boolean skip) {
|
||||
int dataArrayLength = ProtocolUtils.readVarInt(in);
|
||||
ProtocolUtils.writeVarInt(out, dataArrayLength);
|
||||
protected void processDataArray(SectionHider section) {
|
||||
VariableValueArray values = new VariableValueArray(section.getBitsPerBlock(), section.readDataArray());
|
||||
|
||||
if(skip) {
|
||||
out.writeBytes(in, dataArrayLength*8);
|
||||
return;
|
||||
}
|
||||
|
||||
VariableValueArray values = new VariableValueArray(bitsPerBlock, dataArrayLength, in);
|
||||
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;
|
||||
|
||||
switch (locationEvaluator.test(x, y, z)) {
|
||||
switch (section.test(x, y, z)) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if(!obfuscate.contains(values.get(pos)))
|
||||
if(!section.getObfuscate().contains(values.get(pos)))
|
||||
break;
|
||||
case HIDE:
|
||||
values.set(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.set(pos, obfuscationTarget);
|
||||
values.set(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for(long l : values.backing)
|
||||
out.writeLong(l);
|
||||
section.writeDataArray(values.backing);
|
||||
}
|
||||
|
||||
private static class VariableValueArray {
|
||||
@@ -129,13 +121,10 @@ public class ChunkHider9 extends ChunkHider8 {
|
||||
private final int bitsPerValue;
|
||||
private final long valueMask;
|
||||
|
||||
public VariableValueArray(int bitsPerEntry, int dataArrayLength, ByteBuf in) {
|
||||
public VariableValueArray(int bitsPerEntry, long[] dataArray) {
|
||||
this.bitsPerValue = bitsPerEntry;
|
||||
this.valueMask = (1L << this.bitsPerValue) - 1;
|
||||
|
||||
this.backing = new long[dataArrayLength];
|
||||
for(int i = 0; i < dataArrayLength; i++)
|
||||
backing[i] = in.readLong();
|
||||
this.backing = dataArray;
|
||||
}
|
||||
|
||||
public int get(int index) {
|
||||
|
||||
@@ -22,8 +22,10 @@ package de.steamwar.techhider;
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@@ -31,29 +33,124 @@ public interface ChunkHider {
|
||||
ChunkHider impl = VersionDependent.getVersionImpl(Core.getInstance());
|
||||
|
||||
Class<?> mapChunkPacket();
|
||||
BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities);
|
||||
BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider);
|
||||
|
||||
static int processPalette(int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out) {
|
||||
int paletteLength = ProtocolUtils.readVarInt(in);
|
||||
ProtocolUtils.writeVarInt(out, paletteLength);
|
||||
@Getter
|
||||
class SectionHider {
|
||||
private final Player player;
|
||||
private final TechHider techHider;
|
||||
private final ByteBuf in;
|
||||
private final ByteBuf out;
|
||||
|
||||
int paletteTarget = 0;
|
||||
private final int chunkX;
|
||||
private final int chunkY;
|
||||
private final int chunkZ;
|
||||
private final int offsetX;
|
||||
private final int offsetY;
|
||||
private final int offsetZ;
|
||||
|
||||
for(int i = 0; i < paletteLength; i++) {
|
||||
int entry = ProtocolUtils.readVarInt(in);
|
||||
if(obfuscate.contains(entry))
|
||||
entry = obfuscationTarget;
|
||||
private final boolean skipSection;
|
||||
|
||||
if(entry == obfuscationTarget)
|
||||
paletteTarget = i;
|
||||
private boolean paletted;
|
||||
private int bitsPerBlock;
|
||||
private int air;
|
||||
private int target;
|
||||
private Set<Integer> obfuscate;
|
||||
|
||||
ProtocolUtils.writeVarInt(out, entry);
|
||||
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();
|
||||
}
|
||||
|
||||
return paletteTarget;
|
||||
}
|
||||
public boolean blockPrecise() {
|
||||
return techHider.getLocationEvaluator().blockPrecise(player, chunkX, chunkY, chunkZ);
|
||||
}
|
||||
|
||||
interface PosEvaluator {
|
||||
TechHider.State test(int x, int y, int z);
|
||||
public TechHider.State test(int x, int y, int z) {
|
||||
return techHider.getLocationEvaluator().check(player, offsetX+x, offsetY+y, offsetZ+z);
|
||||
}
|
||||
|
||||
public void copyBlockCount() {
|
||||
out.writeShort(in.readShort());
|
||||
}
|
||||
|
||||
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 long[] readDataArray() {
|
||||
long[] array = new long[copyVarInt()];
|
||||
for(int i = 0; i < array.length; i++)
|
||||
array[i] = in.readLong();
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
public void writeDataArray(long[] array) {
|
||||
for(long l : array)
|
||||
out.writeLong(l);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,10 +20,8 @@
|
||||
package de.steamwar.techhider;
|
||||
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import com.google.common.primitives.Bytes;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.lang.reflect.Field;
|
||||
@@ -37,10 +35,6 @@ import java.util.function.UnaryOperator;
|
||||
public class ProtocolUtils {
|
||||
private ProtocolUtils() {}
|
||||
|
||||
public static void broadcastPacket(Object packet) {
|
||||
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static BiFunction<Object, UnaryOperator<Object>, Object> arrayCloneGenerator(Class<?> elementClass) {
|
||||
return (array, worker) -> {
|
||||
|
||||
@@ -21,10 +21,8 @@ package de.steamwar.techhider;
|
||||
|
||||
import de.steamwar.core.Core;
|
||||
import de.steamwar.core.VersionDependent;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
public interface ProtocolWrapper {
|
||||
@@ -33,7 +31,7 @@ public interface ProtocolWrapper {
|
||||
|
||||
boolean unfilteredTileEntityDataAction(Object packet);
|
||||
|
||||
BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator);
|
||||
BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider);
|
||||
|
||||
BiFunction<Player, Object, Object> multiBlockChangeGenerator(Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator);
|
||||
BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ package de.steamwar.techhider;
|
||||
import com.comphenix.tinyprotocol.Reflection;
|
||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||
import de.steamwar.core.Core;
|
||||
import lombok.Getter;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.entity.Player;
|
||||
@@ -49,34 +50,44 @@ public class TechHider {
|
||||
|
||||
private static final Reflection.MethodInvoker getBlockByBlockData = Reflection.getTypedMethod(iBlockData, null, block);
|
||||
private static final Reflection.MethodInvoker getMaterialByBlock = Reflection.getTypedMethod(craftMagicNumbers, "getMaterial", Material.class, block);
|
||||
public static boolean iBlockDataHidden(Set<Material> obfuscate, Object iBlockData) {
|
||||
public boolean iBlockDataHidden(Object iBlockData) {
|
||||
return obfuscate.contains((Material) getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(iBlockData)));
|
||||
}
|
||||
|
||||
private final Map<Class<?>, BiFunction<Player, Object, Object>> techhiders = new HashMap<>();
|
||||
private final LocationEvaluator locationEvaluator;
|
||||
private final Object obfuscationTarget;
|
||||
private final Set<Material> obfuscate;
|
||||
public static final Object AIR = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, Material.AIR));
|
||||
public static final int AIR_ID = BlockIds.impl.materialToId(Material.AIR);
|
||||
|
||||
@Deprecated
|
||||
public TechHider(BypassEvaluator bypass, Material obfuscationTarget, Set<Material> obfuscate, Set<String> hiddenBlockEntities) {
|
||||
this((LocationEvaluator) (player, x, z) -> bypass.bypass(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z)), obfuscationTarget, obfuscate, hiddenBlockEntities);
|
||||
}
|
||||
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<Material> obfuscate;
|
||||
@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.obfuscate = obfuscate;
|
||||
this.obfuscateIds = obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet());
|
||||
this.hiddenBlockEntities = hiddenBlockEntities;
|
||||
this.obfuscationTarget = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, obfuscationTarget));
|
||||
this.obfuscationTargetId = BlockIds.impl.materialToId(obfuscationTarget);
|
||||
|
||||
techhiders.put(blockActionPacket, this::blockActionHider);
|
||||
techhiders.put(blockChangePacket, this::blockChangeHider);
|
||||
techhiders.put(tileEntityDataPacket, this::tileEntityDataHider);
|
||||
techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this.obfuscationTarget, obfuscate, locationEvaluator));
|
||||
techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(locationEvaluator, BlockIds.impl.materialToId(obfuscationTarget), obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet()), hiddenBlockEntities));
|
||||
techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this));
|
||||
techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(this));
|
||||
|
||||
if(Core.getVersion() > 12 && Core.getVersion() < 19) {
|
||||
Class<?> blockBreakClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutBlockBreak");
|
||||
techhiders.put(blockBreakClass, ProtocolWrapper.impl.blockBreakHiderGenerator(blockBreakClass, this.obfuscationTarget, obfuscate, locationEvaluator));
|
||||
techhiders.put(blockBreakClass, ProtocolWrapper.impl.blockBreakHiderGenerator(blockBreakClass, this));
|
||||
}
|
||||
|
||||
if(Core.getVersion() > 8){
|
||||
@@ -106,12 +117,17 @@ public class TechHider {
|
||||
case SKIP:
|
||||
return packet;
|
||||
case CHECK:
|
||||
if(!iBlockDataHidden(obfuscate, blockChangeBlockData.get(packet)))
|
||||
if(!iBlockDataHidden(blockChangeBlockData.get(packet)))
|
||||
return packet;
|
||||
default:
|
||||
case HIDE:
|
||||
packet = blockChangeCloner.apply(packet);
|
||||
blockChangeBlockData.set(packet, obfuscationTarget);
|
||||
return packet;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
packet = blockChangeCloner.apply(packet);
|
||||
blockChangeBlockData.set(packet, AIR);
|
||||
return packet;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,15 +153,11 @@ public class TechHider {
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public interface BypassEvaluator {
|
||||
boolean bypass(Player p, int chunkX, int chunkZ);
|
||||
}
|
||||
|
||||
public enum State {
|
||||
SKIP,
|
||||
CHECK,
|
||||
HIDE
|
||||
HIDE,
|
||||
HIDE_AIR
|
||||
}
|
||||
|
||||
public interface LocationEvaluator {
|
||||
|
||||
Reference in New Issue
Block a user