TinyProtocol TechHider
Signed-off-by: Lixfel <agga-games@gmx.de>
Dieser Commit ist enthalten in:
Ursprung
05d121fe63
Commit
a4148c8e6d
@ -19,76 +19,27 @@
|
|||||||
|
|
||||||
package de.steamwar.fightsystem.utils;
|
package de.steamwar.fightsystem.utils;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
|
||||||
import de.steamwar.fightsystem.Config;
|
|
||||||
import de.steamwar.fightsystem.FightSystem;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.LongBuffer;
|
import java.nio.LongBuffer;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
|
||||||
import static de.steamwar.fightsystem.utils.TechHider.bypass;
|
public class TechHider14 implements BiFunction<byte[], Integer, byte[]> {
|
||||||
|
|
||||||
public class TechHider14 extends PacketAdapter {
|
|
||||||
|
|
||||||
private final Set<Integer> hiddenBlockIds = BlockIdWrapper.impl.getHiddenBlockIds();
|
private final Set<Integer> hiddenBlockIds = BlockIdWrapper.impl.getHiddenBlockIds();
|
||||||
private final int obfuscateWith = BlockIdWrapper.impl.getObfuscateWith();
|
private final int obfuscateWith = BlockIdWrapper.impl.getObfuscateWith();
|
||||||
|
|
||||||
public TechHider14(){
|
|
||||||
super(FightSystem.getPlugin(), PacketType.Play.Server.MAP_CHUNK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketSending(PacketEvent e) {
|
public byte[] apply(byte[] data, Integer primaryBitMask) {
|
||||||
PacketContainer packet = e.getPacket();
|
|
||||||
StructureModifier<Integer> ints = packet.getIntegers();
|
|
||||||
|
|
||||||
int chunkX = ints.read(0);
|
|
||||||
int chunkZ = ints.read(1);
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if(bypass(p, chunkX, chunkZ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
packet = packet.shallowClone();
|
|
||||||
e.setPacket(packet);
|
|
||||||
StructureModifier<List<NbtBase<?>>> list = packet.getListNbtModifier();
|
|
||||||
List<NbtBase<?>> nmsTags = list.read(0);
|
|
||||||
boolean changed = false;
|
|
||||||
for(int i = nmsTags.size() - 1; i >= 0; i--){
|
|
||||||
NbtBase<?> nbtBase = nmsTags.get(i);
|
|
||||||
assert nbtBase instanceof NbtCompound;
|
|
||||||
NbtCompound nbt = (NbtCompound) nbtBase;
|
|
||||||
if(Config.HiddenBlockEntities.contains(nbt.getString("id"))){
|
|
||||||
nmsTags.remove(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(changed){
|
|
||||||
list.write(0, nmsTags);
|
|
||||||
}
|
|
||||||
|
|
||||||
changed = false;
|
|
||||||
StructureModifier<byte[]> byteArray = packet.getByteArrays();
|
|
||||||
int primaryBitMask = ints.read(2);
|
|
||||||
byte[] data = byteArray.read(0);
|
|
||||||
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100);
|
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
//int chunkY = 0;
|
|
||||||
while(primaryBitMask != 0){
|
while(primaryBitMask != 0){
|
||||||
while((primaryBitMask & 1) == 0){
|
while((primaryBitMask & 1) == 0){
|
||||||
primaryBitMask >>= 1;
|
primaryBitMask >>= 1;
|
||||||
//chunkY++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer.writeBytes(data, i, 2); // Block count
|
buffer.writeBytes(data, i, 2); // Block count
|
||||||
@ -107,7 +58,6 @@ public class TechHider14 extends PacketAdapter {
|
|||||||
|
|
||||||
if(hiddenBlockIds.contains(blockId)){
|
if(hiddenBlockIds.contains(blockId)){
|
||||||
buffer.writeBytes(TechHider.writeVarInt(obfuscateWith));
|
buffer.writeBytes(TechHider.writeVarInt(obfuscateWith));
|
||||||
changed = true;
|
|
||||||
}else{
|
}else{
|
||||||
buffer.writeBytes(data, i, actPaletteLength);
|
buffer.writeBytes(data, i, actPaletteLength);
|
||||||
}
|
}
|
||||||
@ -132,7 +82,6 @@ public class TechHider14 extends PacketAdapter {
|
|||||||
|
|
||||||
for(int pos = 0; pos < 4096; pos++){
|
for(int pos = 0; pos < 4096; pos++){
|
||||||
if(hiddenBlockIds.contains(values.get(pos))){
|
if(hiddenBlockIds.contains(values.get(pos))){
|
||||||
changed = true;
|
|
||||||
values.set(pos, obfuscateWith);
|
values.set(pos, obfuscateWith);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -144,15 +93,12 @@ public class TechHider14 extends PacketAdapter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
primaryBitMask >>= 1;
|
primaryBitMask >>= 1;
|
||||||
//chunkY++;
|
|
||||||
}
|
}
|
||||||
buffer.writeBytes(data, i, data.length - i); // MC appends a 0 byte at the end if there is a full chunk, idk why
|
buffer.writeBytes(data, i, data.length - i); // MC appends a 0 byte at the end if there is a full chunk, idk why
|
||||||
|
|
||||||
if(changed){
|
|
||||||
data = new byte[buffer.readableBytes()];
|
data = new byte[buffer.readableBytes()];
|
||||||
buffer.readBytes(data);
|
buffer.readBytes(data);
|
||||||
byteArray.write(0, data);
|
return data;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class VariableValueArray {
|
private static final class VariableValueArray {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
This file is a part of the SteamWar software.
|
This file is a part of the SteamWar software.
|
||||||
|
|
||||||
Copyright (C) 2020 SteamWar.de-Serverteam
|
Copyright (C) 2021 SteamWar.de-Serverteam
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
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
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
@ -19,64 +19,21 @@
|
|||||||
|
|
||||||
package de.steamwar.fightsystem.utils;
|
package de.steamwar.fightsystem.utils;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
|
||||||
import de.steamwar.fightsystem.Config;
|
|
||||||
import de.steamwar.fightsystem.FightSystem;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import static de.steamwar.fightsystem.utils.TechHider.bypass;
|
public class TechHider9 implements BiFunction<byte[], Integer, byte[]> {
|
||||||
|
|
||||||
public class TechHider12 extends PacketAdapter {
|
|
||||||
|
|
||||||
private final Set<Integer> hiddenBlockIds = BlockIdWrapper.impl.getHiddenBlockIds();
|
private final Set<Integer> hiddenBlockIds = BlockIdWrapper.impl.getHiddenBlockIds();
|
||||||
private final int obfuscateWith = BlockIdWrapper.impl.getObfuscateWith();
|
private final int obfuscateWith = BlockIdWrapper.impl.getObfuscateWith();
|
||||||
|
|
||||||
public TechHider12() {
|
|
||||||
super(FightSystem.getPlugin(), PacketType.Play.Server.MAP_CHUNK);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPacketSending(PacketEvent e) {
|
public byte[] apply(byte[] data, Integer primaryBitMask) {
|
||||||
PacketContainer packet = e.getPacket();
|
|
||||||
StructureModifier<Integer> ints = packet.getIntegers();
|
|
||||||
|
|
||||||
int chunkX = ints.read(0);
|
|
||||||
int chunkZ = ints.read(1);
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if(bypass(p, chunkX, chunkZ))
|
|
||||||
return;
|
|
||||||
|
|
||||||
packet = packet.shallowClone();
|
|
||||||
e.setPacket(packet);
|
|
||||||
StructureModifier<List<NbtBase<?>>> list = packet.getListNbtModifier();
|
|
||||||
List<NbtBase<?>> nmsTags = list.read(0);
|
|
||||||
boolean changed = false;
|
|
||||||
for(int i = nmsTags.size() - 1; i >= 0; i--){
|
|
||||||
NbtCompound nbt = (NbtCompound)nmsTags.get(i);
|
|
||||||
if(Config.HiddenBlockEntities.contains(nbt.getString("id"))){
|
|
||||||
nmsTags.remove(i);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(changed)
|
|
||||||
list.write(0, nmsTags);
|
|
||||||
|
|
||||||
changed = false;
|
|
||||||
StructureModifier<byte[]> byteArray = packet.getByteArrays();
|
|
||||||
byte [] data = byteArray.read(0);
|
|
||||||
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100);
|
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
@ -96,7 +53,6 @@ public class TechHider12 extends PacketAdapter {
|
|||||||
|
|
||||||
if(hiddenBlockIds.contains(entry)){
|
if(hiddenBlockIds.contains(entry)){
|
||||||
entry = obfuscateWith;
|
entry = obfuscateWith;
|
||||||
changed = true;
|
|
||||||
}
|
}
|
||||||
buffer.writeBytes(TechHider.writeVarInt(entry));
|
buffer.writeBytes(TechHider.writeVarInt(entry));
|
||||||
}
|
}
|
||||||
@ -115,10 +71,8 @@ public class TechHider12 extends PacketAdapter {
|
|||||||
i += 4096; //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
|
i += 4096; //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
|
||||||
}
|
}
|
||||||
|
|
||||||
if(changed){
|
|
||||||
data = new byte[buffer.readableBytes()];
|
data = new byte[buffer.readableBytes()];
|
||||||
buffer.readBytes(data);
|
buffer.readBytes(data);
|
||||||
byteArray.write(0, data);
|
return data;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
134
FightSystem_Core/src/de/steamwar/fightsystem/utils/ProtocolAPI.java
Normale Datei
134
FightSystem_Core/src/de/steamwar/fightsystem/utils/ProtocolAPI.java
Normale Datei
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
This file is a part of the SteamWar software.
|
||||||
|
|
||||||
|
Copyright (C) 2021 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.fightsystem.utils;
|
||||||
|
|
||||||
|
import com.comphenix.tinyprotocol.TinyProtocol;
|
||||||
|
import de.steamwar.fightsystem.FightSystem;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
|
import java.lang.reflect.Array;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
|
||||||
|
public class ProtocolAPI {
|
||||||
|
private ProtocolAPI() {}
|
||||||
|
|
||||||
|
private static final Map<Class<?>, BiFunction<Player, Object, Object>> outgoingHandler = new HashMap<>();
|
||||||
|
private static final Map<Class<?>, BiFunction<Player, Object, Object>> incomingHandler = new HashMap<>();
|
||||||
|
|
||||||
|
public static final TinyProtocol tinyProtocol = new TinyProtocol(FightSystem.getPlugin()) {
|
||||||
|
@Override
|
||||||
|
public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) {
|
||||||
|
BiFunction<Player, Object, Object> handler = outgoingHandler.get(packet.getClass());
|
||||||
|
if(handler == null)
|
||||||
|
return packet;
|
||||||
|
return handler.apply(receiver, packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object onPacketInAsync(Player sender, Channel channel, Object packet) {
|
||||||
|
BiFunction<Player, Object, Object> handler = incomingHandler.get(packet.getClass());
|
||||||
|
if(handler == null)
|
||||||
|
return packet;
|
||||||
|
return handler.apply(sender, packet);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
public static void setOutgoingHandler(Class<?> packetClass, BiFunction<Player, Object, Object> handler) {
|
||||||
|
outgoingHandler.put(packetClass, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeOutgoingHandler(Class<?> packetClass) {
|
||||||
|
outgoingHandler.remove(packetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIncomingHandler(Class<?> packetClass, BiFunction<Player, Object, Object> handler) {
|
||||||
|
incomingHandler.put(packetClass, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void removeIncomingHandler(Class<?> packetClass) {
|
||||||
|
incomingHandler.remove(packetClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static BiFunction<Object, UnaryOperator<Object>, Object> arrayCloneGenerator(Class<?> elementClass) {
|
||||||
|
return (array, worker) -> {
|
||||||
|
int length = Array.getLength(array);
|
||||||
|
Object result = Array.newInstance(elementClass, length);
|
||||||
|
|
||||||
|
for(int i = 0; i < length; i++)
|
||||||
|
Array.set(result, i, worker.apply(Array.get(array, i)));
|
||||||
|
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static UnaryOperator<Object> shallowCloneGenerator(Class<?> clazz) {
|
||||||
|
BiConsumer<Object, Object> filler = shallowFill(clazz);
|
||||||
|
|
||||||
|
return source -> {
|
||||||
|
Object clone;
|
||||||
|
try {
|
||||||
|
clone = clazz.newInstance();
|
||||||
|
} catch (InstantiationException | IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException("Could not clone " + clazz.getName(), e);
|
||||||
|
}
|
||||||
|
filler.accept(source, clone);
|
||||||
|
return clone;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private static BiConsumer<Object, Object> shallowFill(Class<?> clazz) {
|
||||||
|
if(clazz == null)
|
||||||
|
return (source, clone) -> {};
|
||||||
|
|
||||||
|
BiConsumer<Object, Object> superFiller = shallowFill(clazz.getSuperclass());
|
||||||
|
|
||||||
|
Field[] fds = clazz.getDeclaredFields();
|
||||||
|
List<Field> fields = new ArrayList<>();
|
||||||
|
for(Field field : fds) {
|
||||||
|
if (Modifier.isStatic(field.getModifiers()))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
field.setAccessible(true);
|
||||||
|
fields.add(field);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (source, clone) -> {
|
||||||
|
superFiller.accept(source, clone);
|
||||||
|
try {
|
||||||
|
for(Field field : fields) {
|
||||||
|
field.set(clone, field.get(source));
|
||||||
|
}
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new IllegalStateException("Could not set field", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
@ -19,21 +19,10 @@
|
|||||||
|
|
||||||
package de.steamwar.fightsystem.utils;
|
package de.steamwar.fightsystem.utils;
|
||||||
|
|
||||||
import com.comphenix.protocol.PacketType;
|
import com.comphenix.tinyprotocol.Reflection;
|
||||||
import com.comphenix.protocol.ProtocolLibrary;
|
|
||||||
import com.comphenix.protocol.ProtocolManager;
|
|
||||||
import com.comphenix.protocol.events.PacketAdapter;
|
|
||||||
import com.comphenix.protocol.events.PacketContainer;
|
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
|
||||||
import com.comphenix.protocol.wrappers.BlockPosition;
|
|
||||||
import com.comphenix.protocol.wrappers.ChunkCoordIntPair;
|
|
||||||
import com.comphenix.protocol.wrappers.MultiBlockChangeInfo;
|
|
||||||
import com.comphenix.protocol.wrappers.WrappedBlockData;
|
|
||||||
import com.google.common.primitives.Bytes;
|
import com.google.common.primitives.Bytes;
|
||||||
import de.steamwar.core.Core;
|
import de.steamwar.core.Core;
|
||||||
import de.steamwar.core.events.ChunkListener;
|
import de.steamwar.core.events.ChunkListener;
|
||||||
import de.steamwar.fightsystem.ArenaMode;
|
|
||||||
import de.steamwar.fightsystem.Config;
|
import de.steamwar.fightsystem.Config;
|
||||||
import de.steamwar.fightsystem.FightSystem;
|
import de.steamwar.fightsystem.FightSystem;
|
||||||
import de.steamwar.fightsystem.VersionDependent;
|
import de.steamwar.fightsystem.VersionDependent;
|
||||||
@ -41,212 +30,198 @@ import de.steamwar.fightsystem.fight.Fight;
|
|||||||
import de.steamwar.fightsystem.fight.FightTeam;
|
import de.steamwar.fightsystem.fight.FightTeam;
|
||||||
import de.steamwar.fightsystem.states.FightState;
|
import de.steamwar.fightsystem.states.FightState;
|
||||||
import de.steamwar.fightsystem.states.StateDependent;
|
import de.steamwar.fightsystem.states.StateDependent;
|
||||||
|
import io.netty.buffer.ByteBuf;
|
||||||
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
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;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.function.BiFunction;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.UnaryOperator;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class TechHider extends StateDependent {
|
public class TechHider extends StateDependent {
|
||||||
|
|
||||||
|
private static final Class<?> blockPosition = Reflection.getClass("{nms}.BlockPosition");
|
||||||
|
private static final Class<?> baseBlockPosition = Reflection.getClass("{nms}.BaseBlockPosition");
|
||||||
|
private static final Reflection.FieldAccessor<Integer> blockPositionX = Reflection.getField(baseBlockPosition, int.class, 0);
|
||||||
|
private static final Reflection.FieldAccessor<Integer> blockPositionZ = Reflection.getField(baseBlockPosition, int.class, 2);
|
||||||
|
|
||||||
|
private static final Class<?> iBlockData = Reflection.getClass("{nms}.IBlockData");
|
||||||
|
private static final Class<?> block = Reflection.getClass("{nms}.Block");
|
||||||
|
private static final Reflection.MethodInvoker getBlockByBlockData = Reflection.getTypedMethod(iBlockData, "getBlock", block);
|
||||||
|
private static final Reflection.MethodInvoker getBlockDataByBlock = Reflection.getTypedMethod(block, "getBlockData", iBlockData);
|
||||||
|
|
||||||
|
private static final Class<?> craftMagicNumbers = Reflection.getClass("{obc}.util.CraftMagicNumbers");
|
||||||
|
private static final Reflection.MethodInvoker getMaterialByBlock = Reflection.getTypedMethod(craftMagicNumbers, "getMaterial", Material.class, block);
|
||||||
|
private static final Reflection.MethodInvoker getBlockByMaterial = Reflection.getTypedMethod(craftMagicNumbers, "getBlock", block, Material.class);
|
||||||
|
|
||||||
public static final boolean ENABLED = !Config.OnlyPublicSchematics && !Config.test() && Config.TechhiderActive;
|
public static final boolean ENABLED = !Config.OnlyPublicSchematics && !Config.test() && Config.TechhiderActive;
|
||||||
|
|
||||||
private final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager();
|
private final Object obfuscateIBlockData = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, Material.getMaterial(Config.ObfuscateWith.toUpperCase())));
|
||||||
private final Map<PacketContainer, PacketContainer> packetCache = new HashMap<>();
|
private final Map<Class<?>, BiFunction<Player, Object, Object>> techhiders = new HashMap<>();
|
||||||
private final Material obfuscateMaterial;
|
private final BiFunction<byte[], Integer, byte[]> chunkDataHider;
|
||||||
private final PacketAdapter chunkHider;
|
|
||||||
private final int threadMultiplier;
|
|
||||||
|
|
||||||
public TechHider(){
|
public TechHider(){
|
||||||
super(ENABLED, FightState.Schem);
|
super(ENABLED, FightState.Schem);
|
||||||
|
|
||||||
obfuscateMaterial = Material.getMaterial(Config.ObfuscateWith.toUpperCase());
|
chunkDataHider = VersionDependent.getVersionImpl(TechHider.class.getName());
|
||||||
chunkHider = VersionDependent.getVersionImpl(TechHider.class.getName());
|
|
||||||
|
|
||||||
if(Config.mode == ArenaMode.EVENT)
|
techhiders.put(blockActionPacket, this::blockActionHider);
|
||||||
threadMultiplier = 4;
|
techhiders.put(blockChangePacket, this::blockChangeHider);
|
||||||
else
|
techhiders.put(tileEntityDataPacket, this::tileEntityDataHider);
|
||||||
threadMultiplier = 1;
|
techhiders.put(multiBlockChangePacket, this::multiBlockChangeHider);
|
||||||
|
if(Core.getVersion() > 8) {
|
||||||
Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), packetCache::clear, 1, 1);
|
techhiders.put(mapChunkPacket, this::mapChunkHider);
|
||||||
|
}
|
||||||
|
if(Core.getVersion() > 12) {
|
||||||
|
Class<?> blockBreakClass = Reflection.getClass("{nms}.PacketPlayOutBlockBreak");
|
||||||
|
techhiders.put(blockBreakClass, blockBreakHiderGenerator(blockBreakClass));
|
||||||
|
}
|
||||||
|
|
||||||
if(Core.getVersion() > 8){
|
if(Core.getVersion() > 8){
|
||||||
protocolManager.addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.USE_ITEM) {
|
ProtocolAPI.setIncomingHandler(Reflection.getClass("{nms}.PacketPlayInUseItem"), (p, packet) -> p.getGameMode() == GameMode.SPECTATOR ? null : packet);
|
||||||
@Override
|
}
|
||||||
public void onPacketReceiving(PacketEvent e) {
|
ProtocolAPI.setIncomingHandler(Reflection.getClass("{nms}.PacketPlayInUseEntity"), (p, packet) -> p.getGameMode() == GameMode.SPECTATOR ? null : packet);
|
||||||
Player p = e.getPlayer();
|
|
||||||
|
|
||||||
if(p == null || p.getGameMode() == GameMode.SPECTATOR)
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
protocolManager.addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.USE_ENTITY) {
|
|
||||||
@Override
|
|
||||||
public void onPacketReceiving(PacketEvent e) {
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
|
|
||||||
if(p.getGameMode() == GameMode.SPECTATOR)
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
register();
|
register();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void enable() {
|
public void enable() {
|
||||||
protocolManager.addPacketListener(blockHider);
|
techhiders.forEach(ProtocolAPI::setOutgoingHandler);
|
||||||
protocolManager.addPacketListener(multiBlockHider);
|
|
||||||
protocolManager.addPacketListener(blockActionHider);
|
|
||||||
protocolManager.getAsynchronousManager().registerAsyncHandler(chunkHider).start(threadMultiplier * 4);
|
|
||||||
if(Core.getVersion() > 8) {
|
|
||||||
protocolManager.addPacketListener(updateBlockEntity);
|
|
||||||
}
|
|
||||||
if(Core.getVersion() > 12) {
|
|
||||||
protocolManager.addPacketListener(blockBreakHider);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
protocolManager.removePacketListener(blockHider);
|
techhiders.keySet().forEach(ProtocolAPI::removeOutgoingHandler);
|
||||||
protocolManager.removePacketListener(multiBlockHider);
|
}
|
||||||
protocolManager.removePacketListener(blockActionHider);
|
|
||||||
protocolManager.getAsynchronousManager().unregisterAsyncHandler(chunkHider);
|
private static final Class<?> nbtTagCompound = Reflection.getClass("{nms}.NBTTagCompound");
|
||||||
|
private static final Reflection.MethodInvoker nbtTagGetString = Reflection.getTypedMethod(nbtTagCompound, "getString", String.class, String.class);
|
||||||
|
|
||||||
|
private static final Class<?> mapChunkPacket = Reflection.getClass("{nms}.PacketPlayOutMapChunk");
|
||||||
|
private static final UnaryOperator<Object> mapChunkCloner = ProtocolAPI.shallowCloneGenerator(mapChunkPacket);
|
||||||
|
private static final Reflection.FieldAccessor<Integer> mapChunkX = Reflection.getField(mapChunkPacket, int.class, 0);
|
||||||
|
private static final Reflection.FieldAccessor<Integer> mapChunkZ = Reflection.getField(mapChunkPacket, int.class, 1);
|
||||||
|
private static final Reflection.FieldAccessor<Integer> mapChunkBitMask;
|
||||||
|
private static final Reflection.FieldAccessor<List> mapChunkBlockEntities;
|
||||||
|
private static final Reflection.FieldAccessor<byte[]> mapChunkData;
|
||||||
|
static {
|
||||||
if(Core.getVersion() > 8) {
|
if(Core.getVersion() > 8) {
|
||||||
protocolManager.removePacketListener(updateBlockEntity);
|
mapChunkBitMask = Reflection.getField(mapChunkPacket, int.class, 2);
|
||||||
|
mapChunkBlockEntities = Reflection.getField(mapChunkPacket, List.class, 0);
|
||||||
|
mapChunkData = Reflection.getField(mapChunkPacket, byte[].class, 0);
|
||||||
|
}else {
|
||||||
|
mapChunkBitMask = null;
|
||||||
|
mapChunkBlockEntities = null;
|
||||||
|
mapChunkData = null;
|
||||||
}
|
}
|
||||||
if(Core.getVersion() > 12) {
|
|
||||||
protocolManager.removePacketListener(blockBreakHider);
|
|
||||||
}
|
}
|
||||||
|
private Object mapChunkHider(Player p, Object packet) {
|
||||||
|
if(bypass(p, mapChunkX.get(packet), mapChunkZ.get(packet)))
|
||||||
|
return packet;
|
||||||
|
|
||||||
|
packet = mapChunkCloner.apply(packet);
|
||||||
|
mapChunkBlockEntities.set(packet, ((List<?>)mapChunkBlockEntities.get(packet)).stream().filter(
|
||||||
|
nbttag -> Config.HiddenBlockEntities.contains((String) nbtTagGetString.invoke(nbttag, "id"))
|
||||||
|
).collect(Collectors.toList()));
|
||||||
|
|
||||||
|
byte[] data = chunkDataHider.apply(mapChunkData.get(packet), mapChunkBitMask.get(packet));
|
||||||
|
ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100);
|
||||||
|
data = new byte[buffer.readableBytes()];
|
||||||
|
buffer.readBytes(data);
|
||||||
|
mapChunkData.set(packet, data);
|
||||||
|
|
||||||
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private final PacketAdapter multiBlockHider = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.MULTI_BLOCK_CHANGE) {
|
private static final Class<?> multiBlockChangePacket = Reflection.getClass("{nms}.PacketPlayOutMultiBlockChange");
|
||||||
@Override
|
private static final UnaryOperator<Object> multiBlockChangeCloner = ProtocolAPI.shallowCloneGenerator(multiBlockChangePacket);
|
||||||
public void onPacketSending(PacketEvent e) {
|
private static final Class<?> chunkCoordinateIntPair = Reflection.getClass("{nms}.ChunkCoordIntPair");
|
||||||
PacketContainer packet = e.getPacket();
|
private static final Reflection.FieldAccessor<?> multiBlockChangeChunk = Reflection.getField(multiBlockChangePacket, chunkCoordinateIntPair, 0);
|
||||||
|
private static final Reflection.FieldAccessor<Integer> chunkCoordinateX = Reflection.getField(baseBlockPosition, int.class, 0);
|
||||||
|
private static final Reflection.FieldAccessor<Integer> chunkCoordinateZ = Reflection.getField(baseBlockPosition, int.class, 1);
|
||||||
|
private static final Class<?> multiBlockChangeInfo = Reflection.getClass("{nms}.PacketPlayOutMultiBlockChange.MultiBlockChangeInfo");
|
||||||
|
private static final UnaryOperator<Object> multiBlockChangeInfoCloner = ProtocolAPI.shallowCloneGenerator(multiBlockChangeInfo);
|
||||||
|
private static final BiFunction<Object, UnaryOperator<Object>, Object> multiBlockChangeInfoArrayCloner = ProtocolAPI.arrayCloneGenerator(multiBlockChangeInfo);
|
||||||
|
private static final Reflection.FieldAccessor<?> multiBlockChangeInfoBlock = Reflection.getField(multiBlockChangeInfo, iBlockData, 0);
|
||||||
|
private static final Class<?> multiBlockChangeInfoArray = Reflection.getClass("[L{nms}.PacketPlayOutMultiBlockChange.MultiBlockChangeInfo;");
|
||||||
|
private static final Reflection.FieldAccessor<?> multiBlockChangeInfos = Reflection.getField(multiBlockChangePacket, multiBlockChangeInfoArray, 0);
|
||||||
|
private Object multiBlockChangeHider(Player p, Object packet) {
|
||||||
|
Object chunkCoords = multiBlockChangeChunk.get(packet);
|
||||||
|
if(bypass(p, chunkCoordinateX.get(chunkCoords), chunkCoordinateZ.get(chunkCoords)))
|
||||||
|
return packet;
|
||||||
|
|
||||||
Player p = e.getPlayer();
|
packet = multiBlockChangeCloner.apply(packet);
|
||||||
ChunkCoordIntPair pos = packet.getChunkCoordIntPairs().read(0);
|
multiBlockChangeInfos.set(packet, multiBlockChangeInfoArrayCloner.apply(multiBlockChangeInfos.get(packet), mbci -> {
|
||||||
if(bypass(p, pos.getChunkX(), pos.getChunkZ()))
|
if(Config.HiddenBlocks.contains(getMaterialByIBlockData(multiBlockChangeInfoBlock.get(mbci)).name().toLowerCase())) {
|
||||||
return;
|
mbci = multiBlockChangeInfoCloner.apply(mbci);
|
||||||
|
multiBlockChangeInfoBlock.set(mbci, obfuscateIBlockData);
|
||||||
PacketContainer cached = packetCache.get(packet);
|
}
|
||||||
if(cached != null){
|
return mbci;
|
||||||
e.setPacket(cached);
|
}));
|
||||||
return;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
cached = packet.shallowClone();
|
private static final Class<?> blockChangePacket = Reflection.getClass("{nms}.PacketPlayOutBlockChange");
|
||||||
packetCache.put(packet, cached);
|
private static final Function<Object, Object> blockChangeCloner = ProtocolAPI.shallowCloneGenerator(blockChangePacket);
|
||||||
e.setPacket(cached);
|
private static final Reflection.FieldAccessor<?> blockChangePosition = Reflection.getField(blockChangePacket, blockPosition, 0);
|
||||||
StructureModifier<MultiBlockChangeInfo[]> blockStructure = cached.getMultiBlockChangeInfoArrays();
|
private static final Reflection.FieldAccessor<?> blockChangeBlockData = Reflection.getField(blockChangePacket, iBlockData, 0);
|
||||||
MultiBlockChangeInfo[] changes = blockStructure.read(0).clone();
|
private Object blockChangeHider(Player p, Object packet) {
|
||||||
boolean changed = false;
|
Object pos = blockChangePosition.get(packet);
|
||||||
for(MultiBlockChangeInfo mbci : changes){
|
if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos))))
|
||||||
WrappedBlockData block = mbci.getData();
|
return packet;
|
||||||
if(Config.HiddenBlocks.contains(block.getType().name().toLowerCase())){
|
|
||||||
changed = true;
|
if(Config.HiddenBlocks.contains(getMaterialByIBlockData(blockChangeBlockData.get(packet)).name().toLowerCase())){
|
||||||
block.setType(obfuscateMaterial);
|
packet = blockChangeCloner.apply(packet);
|
||||||
mbci.setData(block);
|
blockChangeBlockData.set(packet, obfuscateIBlockData);
|
||||||
}
|
}
|
||||||
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(changed){
|
private static final Class<?> blockActionPacket = Reflection.getClass("{nms}.PacketPlayOutBlockAction");
|
||||||
blockStructure.write(0, changes);
|
private static final Reflection.FieldAccessor<?> blockActionPosition = Reflection.getField(blockActionPacket, blockPosition, 0);
|
||||||
|
private Object blockActionHider(Player p, Object packet) {
|
||||||
|
Object pos = blockActionPosition.get(packet);
|
||||||
|
if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos))))
|
||||||
|
return packet;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket){
|
||||||
|
UnaryOperator<Object> blockBreakCloner = ProtocolAPI.shallowCloneGenerator(blockBreakPacket);
|
||||||
|
Reflection.FieldAccessor<?> blockBreakPosition = Reflection.getField(blockBreakPacket, blockPosition, 0);
|
||||||
|
Reflection.FieldAccessor<?> blockBreakBlockData = Reflection.getField(blockBreakPacket, iBlockData, 0);
|
||||||
|
|
||||||
|
return (p, packet) -> {
|
||||||
|
Object pos = blockBreakPosition.get(packet);
|
||||||
|
if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos))))
|
||||||
|
return packet;
|
||||||
|
|
||||||
|
if(Config.HiddenBlocks.contains(getMaterialByIBlockData(blockBreakBlockData.get(packet)).name().toLowerCase())){
|
||||||
|
packet = blockBreakCloner.apply(packet);
|
||||||
|
blockBreakBlockData.set(packet, obfuscateIBlockData);
|
||||||
}
|
}
|
||||||
|
return packet;
|
||||||
};
|
};
|
||||||
|
|
||||||
private final PacketAdapter blockHider = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_CHANGE) {
|
|
||||||
@Override
|
|
||||||
public void onPacketSending(PacketEvent e) {
|
|
||||||
PacketContainer packet = e.getPacket();
|
|
||||||
BlockPosition pos = packet.getBlockPositionModifier().read(0);
|
|
||||||
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ())))
|
|
||||||
return;
|
|
||||||
|
|
||||||
PacketContainer cached = packetCache.get(packet);
|
|
||||||
if(cached != null){
|
|
||||||
e.setPacket(cached);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cached = packet.deepClone();
|
private static final Class<?> tileEntityDataPacket = Reflection.getClass("{nms}.PacketPlayOutTileEntityData");
|
||||||
packetCache.put(packet, cached);
|
private static final Reflection.FieldAccessor<?> tileEntityDataPosition = Reflection.getField(tileEntityDataPacket, blockPosition, 0);
|
||||||
e.setPacket(cached);
|
private static final Reflection.FieldAccessor<Integer> tileEntityDataAction = Reflection.getField(tileEntityDataPacket, int.class, 0);
|
||||||
StructureModifier<WrappedBlockData> blockStructure = cached.getBlockData();
|
private Object tileEntityDataHider(Player p, Object packet) {
|
||||||
WrappedBlockData block = blockStructure.read(0);
|
Object pos = tileEntityDataPosition.get(packet);
|
||||||
if(Config.HiddenBlocks.contains(block.getType().name().toLowerCase())){
|
if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos))))
|
||||||
block.setType(obfuscateMaterial);
|
return packet;
|
||||||
blockStructure.write(0, block);
|
|
||||||
|
if(tileEntityDataAction.get(packet) != 9)
|
||||||
|
return packet;
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final PacketAdapter blockActionHider = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_ACTION) {
|
|
||||||
@Override
|
|
||||||
public void onPacketSending(PacketEvent e) {
|
|
||||||
PacketContainer packet = e.getPacket();
|
|
||||||
BlockPosition pos = packet.getBlockPositionModifier().read(0);
|
|
||||||
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ())))
|
|
||||||
return;
|
|
||||||
|
|
||||||
e.setCancelled(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final PacketAdapter blockBreakHider = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_BREAK) {
|
|
||||||
@Override
|
|
||||||
public void onPacketSending(PacketEvent e) {
|
|
||||||
PacketContainer packet = e.getPacket();
|
|
||||||
BlockPosition pos = packet.getBlockPositionModifier().read(0);
|
|
||||||
|
|
||||||
Player p = e.getPlayer();
|
|
||||||
if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ())))
|
|
||||||
return;
|
|
||||||
|
|
||||||
|
|
||||||
PacketContainer cached = packetCache.get(packet);
|
|
||||||
if(cached != null){
|
|
||||||
e.setPacket(cached);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cached = packet.deepClone();
|
|
||||||
packetCache.put(packet, cached);
|
|
||||||
e.setPacket(cached);
|
|
||||||
StructureModifier<WrappedBlockData> blockStructure = cached.getBlockData();
|
|
||||||
WrappedBlockData block = blockStructure.read(0);
|
|
||||||
if(Config.HiddenBlocks.contains(block.getType().name().toLowerCase())){
|
|
||||||
block.setType(obfuscateMaterial);
|
|
||||||
blockStructure.write(0, block);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final PacketAdapter updateBlockEntity = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.TILE_ENTITY_DATA) {
|
|
||||||
@Override
|
|
||||||
public void onPacketSending(PacketEvent event) {
|
|
||||||
PacketContainer packet = event.getPacket();
|
|
||||||
BlockPosition pos = packet.getBlockPositionModifier().read(0);
|
|
||||||
|
|
||||||
Player p = event.getPlayer();
|
|
||||||
if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ())))
|
|
||||||
return;
|
|
||||||
|
|
||||||
// 9 == Set sign text
|
|
||||||
if(packet.getIntegers().read(0) != 9)
|
|
||||||
return;
|
|
||||||
|
|
||||||
event.setCancelled(true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public static List<ChunkPos> prepareChunkReload(Player p, boolean hide){
|
public static List<ChunkPos> prepareChunkReload(Player p, boolean hide){
|
||||||
if(!ENABLED)
|
if(!ENABLED)
|
||||||
@ -284,6 +259,10 @@ public class TechHider extends StateDependent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Material getMaterialByIBlockData(Object iBlockData) {
|
||||||
|
return (Material) getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(iBlockData));
|
||||||
|
}
|
||||||
|
|
||||||
private static int posToChunk(int c){
|
private static int posToChunk(int c){
|
||||||
int chunk = c / 16;
|
int chunk = c / 16;
|
||||||
if(c<0)
|
if(c<0)
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren