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