forked from SteamWar/SteamWar
Refactored over all functionality
This commit is contained in:
-1
@@ -31,7 +31,6 @@ import de.steamwar.command.TypeMapper;
|
|||||||
import de.steamwar.core.CraftbukkitWrapper;
|
import de.steamwar.core.CraftbukkitWrapper;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.linkage.LinkedInstance;
|
import de.steamwar.linkage.LinkedInstance;
|
||||||
import de.steamwar.techhider.TechHider;
|
|
||||||
import net.md_5.bungee.api.ChatMessageType;
|
import net.md_5.bungee.api.ChatMessageType;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|||||||
-1
@@ -27,7 +27,6 @@ import de.steamwar.inventory.SWItem;
|
|||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.linkage.MinVersion;
|
import de.steamwar.linkage.MinVersion;
|
||||||
import de.steamwar.sql.BauweltMember;
|
import de.steamwar.sql.BauweltMember;
|
||||||
import de.steamwar.techhider.TechHider;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ import de.steamwar.command.SWCommand;
|
|||||||
import de.steamwar.core.CraftbukkitWrapper;
|
import de.steamwar.core.CraftbukkitWrapper;
|
||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.linkage.LinkedInstance;
|
import de.steamwar.linkage.LinkedInstance;
|
||||||
import de.steamwar.techhider.TechHider;
|
|
||||||
import net.md_5.bungee.api.ChatMessageType;
|
import net.md_5.bungee.api.ChatMessageType;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ import de.steamwar.fightsystem.states.FightState;
|
|||||||
import de.steamwar.fightsystem.states.StateDependent;
|
import de.steamwar.fightsystem.states.StateDependent;
|
||||||
import de.steamwar.fightsystem.states.StateDependentListener;
|
import de.steamwar.fightsystem.states.StateDependentListener;
|
||||||
import de.steamwar.fightsystem.states.StateDependentTask;
|
import de.steamwar.fightsystem.states.StateDependentTask;
|
||||||
import de.steamwar.techhider.TechHider;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
@@ -49,7 +48,6 @@ import org.bukkit.event.player.PlayerJoinEvent;
|
|||||||
import org.bukkit.event.player.PlayerQuitEvent;
|
import org.bukkit.event.player.PlayerQuitEvent;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.function.BiFunction;
|
import java.util.function.BiFunction;
|
||||||
|
|||||||
@@ -31,7 +31,6 @@ import de.steamwar.fightsystem.states.FightState;
|
|||||||
import de.steamwar.fightsystem.states.StateDependent;
|
import de.steamwar.fightsystem.states.StateDependent;
|
||||||
import de.steamwar.fightsystem.states.StateDependentListener;
|
import de.steamwar.fightsystem.states.StateDependentListener;
|
||||||
import de.steamwar.sql.SteamwarUser;
|
import de.steamwar.sql.SteamwarUser;
|
||||||
import de.steamwar.techhider.TechHider;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.bukkit.GameMode;
|
import org.bukkit.GameMode;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ public class ChunkHider18 implements ChunkHider {
|
|||||||
boolean singletonPalette = section.getBitsPerBlock() == 0;
|
boolean singletonPalette = section.getBitsPerBlock() == 0;
|
||||||
if(singletonPalette) {
|
if(singletonPalette) {
|
||||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getBlockIdsToObfuscate().contains(value) ? section.getTarget() : value);
|
||||||
}else if(section.getBitsPerBlock() < 15) {
|
}else if(section.getBitsPerBlock() < 15) {
|
||||||
section.processPalette();
|
section.processPalette();
|
||||||
}
|
}
|
||||||
@@ -123,7 +123,7 @@ public class ChunkHider18 implements ChunkHider {
|
|||||||
case SKIP:
|
case SKIP:
|
||||||
break;
|
break;
|
||||||
case CHECK:
|
case CHECK:
|
||||||
if(!section.getObfuscate().contains(values.a(pos)))
|
if(!section.getBlockIdsToObfuscate().contains(values.a(pos)))
|
||||||
break;
|
break;
|
||||||
case HIDE:
|
case HIDE:
|
||||||
values.b(pos, section.getTarget());
|
values.b(pos, section.getTarget());
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public class ChunkHider21 implements ChunkHider {
|
|||||||
boolean singleValued = section.getBitsPerBlock() == 0;
|
boolean singleValued = section.getBitsPerBlock() == 0;
|
||||||
if (singleValued) {
|
if (singleValued) {
|
||||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getBlockIdsToObfuscate().contains(value) ? section.getTarget() : value);
|
||||||
return;
|
return;
|
||||||
} else if (section.getBitsPerBlock() < 9) {
|
} else if (section.getBitsPerBlock() < 9) {
|
||||||
// Indirect (paletted) storage – only present when bitsPerBlock < 9 in 1.21+
|
// Indirect (paletted) storage – only present when bitsPerBlock < 9 in 1.21+
|
||||||
@@ -130,7 +130,7 @@ public class ChunkHider21 implements ChunkHider {
|
|||||||
case SKIP:
|
case SKIP:
|
||||||
break;
|
break;
|
||||||
case CHECK:
|
case CHECK:
|
||||||
if (!section.getObfuscate().contains(values.get(pos)))
|
if (!section.getBlockIdsToObfuscate().contains(values.get(pos)))
|
||||||
break;
|
break;
|
||||||
case HIDE:
|
case HIDE:
|
||||||
values.set(pos, section.getTarget());
|
values.set(pos, section.getTarget());
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ public class ChunkHider9 extends ChunkHider8 {
|
|||||||
case SKIP:
|
case SKIP:
|
||||||
break;
|
break;
|
||||||
case CHECK:
|
case CHECK:
|
||||||
if(!section.getObfuscate().contains(values.get(pos)))
|
if(!section.getBlockIdsToObfuscate().contains(values.get(pos)))
|
||||||
break;
|
break;
|
||||||
case HIDE:
|
case HIDE:
|
||||||
values.set(pos, section.getTarget());
|
values.set(pos, section.getTarget());
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import de.steamwar.core.Core;
|
|||||||
import de.steamwar.linkage.Linked;
|
import de.steamwar.linkage.Linked;
|
||||||
import de.steamwar.sql.SWException;
|
import de.steamwar.sql.SWException;
|
||||||
import de.steamwar.techhider.ProtocolUtils;
|
import de.steamwar.techhider.ProtocolUtils;
|
||||||
import de.steamwar.techhider.TechHider;
|
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
|
|||||||
@@ -19,15 +19,13 @@
|
|||||||
|
|
||||||
package de.steamwar.techhider;
|
package de.steamwar.techhider;
|
||||||
|
|
||||||
import de.steamwar.core.Core;
|
|
||||||
import de.steamwar.core.VersionDependent;
|
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
import net.minecraft.world.level.block.state.BlockState;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This file is a part of the SteamWar software.
|
* This file is a part of the SteamWar software.
|
||||||
@@ -51,17 +49,13 @@ import java.util.function.BiFunction;
|
|||||||
package de.steamwar.techhider;
|
package de.steamwar.techhider;
|
||||||
|
|
||||||
import de.steamwar.Reflection;
|
import de.steamwar.Reflection;
|
||||||
import io.netty.buffer.ByteBuf;
|
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData;
|
||||||
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket;
|
||||||
import net.minecraft.util.SimpleBitStorage;
|
import net.minecraft.util.SimpleBitStorage;
|
||||||
import net.minecraft.world.level.block.entity.BlockEntityType;
|
import net.minecraft.world.level.block.entity.BlockEntityType;
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.UnaryOperator;
|
import java.util.function.UnaryOperator;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@@ -69,33 +63,27 @@ public class ChunkHider {
|
|||||||
private static final UnaryOperator<Object> chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class);
|
private static final UnaryOperator<Object> chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class);
|
||||||
private static final UnaryOperator<Object> chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class);
|
private static final UnaryOperator<Object> chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class);
|
||||||
|
|
||||||
private static final Reflection.Field<Integer> chunkXField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 0);
|
|
||||||
private static final Reflection.Field<Integer> chunkZField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 1);
|
|
||||||
private static final Reflection.Field<ClientboundLevelChunkPacketData> chunkData = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkPacketData.class, 0);
|
private static final Reflection.Field<ClientboundLevelChunkPacketData> chunkData = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkPacketData.class, 0);
|
||||||
|
|
||||||
private static final Reflection.Field<byte[]> dataField = Reflection.getField(ClientboundLevelChunkPacketData.class, byte[].class, 0);
|
private static final Reflection.Field<byte[]> dataField = Reflection.getField(ClientboundLevelChunkPacketData.class, byte[].class, 0);
|
||||||
private static final Reflection.Field<List> tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
|
private static final Reflection.Field<List> tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
|
||||||
|
|
||||||
public BiFunction<Player, Object, Object> processLevelChunkWithLightPacket(TechHider techHider) {
|
public ClientboundLevelChunkWithLightPacket processLevelChunkWithLightPacket(Player recivingPlayer, Set<String> hiddenBlockEntities , QuadFunction<Player, Integer, Integer, Integer, Boolean> isPlayerPrivilegedToAccessBlockPos, BlockState blockToObfuscateTo, Set<Integer> blockIdsToObfuscate, ClientboundLevelChunkWithLightPacket packet) {
|
||||||
return (p, packet) -> {
|
int chunkX = packet.getX();
|
||||||
int chunkX = chunkXField.get(packet);
|
int chunkZ = packet.getZ();
|
||||||
int chunkZ = chunkZField.get(packet);
|
|
||||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
|
||||||
return packet;
|
|
||||||
|
|
||||||
packet = chunkPacketCloner.apply(packet);
|
Object clonedPacket = chunkPacketCloner.apply(packet);
|
||||||
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
|
Object dataWrapper = chunkDataCloner.apply(chunkData.get(clonedPacket));
|
||||||
|
|
||||||
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);
|
||||||
for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
|
for(int yOffset = recivingPlayer.getWorld().getMinHeight(); yOffset < recivingPlayer.getWorld().getMaxHeight(); yOffset += 16) {
|
||||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ);
|
SectionHider section = new SectionHider(recivingPlayer, blockToObfuscateTo, blockIdsToObfuscate, in, out, chunkX, yOffset/16, chunkZ);
|
||||||
section.copyBlockCount();
|
section.copyBlockCount();
|
||||||
|
|
||||||
blocks(section);
|
blocks(section, isPlayerPrivilegedToAccessBlockPos);
|
||||||
biomes(section);
|
biomes(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,7 +97,6 @@ public class ChunkHider {
|
|||||||
|
|
||||||
chunkData.set(packet, dataWrapper);
|
chunkData.set(packet, dataWrapper);
|
||||||
return packet;
|
return packet;
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final Class<?> tileEntity = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo");
|
public static final Class<?> tileEntity = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo");
|
||||||
@@ -124,45 +111,29 @@ public class ChunkHider {
|
|||||||
return !hiddenBlockEntities.contains(getName.invoke(getKey.invoke(nameField.get(null), entityType.get(tile))));
|
return !hiddenBlockEntities.contains(getName.invoke(getKey.invoke(nameField.get(null), entityType.get(tile))));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void blocks(SectionHider section) {
|
private void blocks(SectionHider section, QuadFunction<Player, Integer, Integer, Integer, Boolean> isPlayerPrivilegedToAccessBlockPos) {
|
||||||
section.copyBitsPerBlock();
|
section.copyBitsPerBlock();
|
||||||
|
|
||||||
boolean singleValued = section.getBitsPerBlock() == 0;
|
boolean singleValued = section.getBitsPerBlock() == 0;
|
||||||
if (singleValued) {
|
if (singleValued) {
|
||||||
int value = ProtocolUtils.readVarInt(section.getIn());
|
int value = ProtocolUtils.readVarInt(section.getIn());
|
||||||
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
|
ProtocolUtils.writeVarInt(section.getOut(), section.getBlockIdsToObfuscate().contains(value) ? section.getTarget() : value);
|
||||||
return;
|
return;
|
||||||
} else if (section.getBitsPerBlock() < 9) {
|
} else if (section.getBitsPerBlock() < 9) {
|
||||||
// Indirect (paletted) storage – only present when bitsPerBlock < 9 in 1.21+
|
// Indirect (paletted) storage – only present when bitsPerBlock < 9 in 1.21+
|
||||||
section.processPalette();
|
section.processPalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) {
|
|
||||||
section.skipNewDataArray(4096);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readNewDataArray(4096));
|
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readNewDataArray(4096));
|
||||||
|
|
||||||
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;
|
||||||
|
int blockId = values.get(pos);
|
||||||
|
|
||||||
TechHider.State test = section.test(x, y, z);
|
if(!isPlayerPrivilegedToAccessBlockPos.apply(section.player, section.getOffsetX() * x, section.getOffsetY() * y, section.getOffsetZ() * z) && !section.getBlockIdsToObfuscate().contains(blockId)) {
|
||||||
|
values.set(pos, section.getTarget());
|
||||||
switch (test) {
|
|
||||||
case SKIP:
|
|
||||||
break;
|
|
||||||
case CHECK:
|
|
||||||
if (!section.getObfuscate().contains(values.get(pos)))
|
|
||||||
break;
|
|
||||||
case HIDE:
|
|
||||||
values.set(pos, section.getTarget());
|
|
||||||
break;
|
|
||||||
case HIDE_AIR:
|
|
||||||
default:
|
|
||||||
values.set(pos, section.getAir());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -187,7 +158,6 @@ public class ChunkHider {
|
|||||||
@Getter
|
@Getter
|
||||||
class SectionHider {
|
class SectionHider {
|
||||||
private final Player player;
|
private final Player player;
|
||||||
private final TechHider techHider;
|
|
||||||
private final ByteBuf in;
|
private final ByteBuf in;
|
||||||
private final ByteBuf out;
|
private final ByteBuf out;
|
||||||
|
|
||||||
@@ -198,18 +168,17 @@ public class ChunkHider {
|
|||||||
private final int offsetY;
|
private final int offsetY;
|
||||||
private final int offsetZ;
|
private final int offsetZ;
|
||||||
|
|
||||||
private final boolean skipSection;
|
|
||||||
|
|
||||||
private boolean paletted;
|
private boolean paletted;
|
||||||
private int bitsPerBlock;
|
private int bitsPerBlock;
|
||||||
private int blockCount;
|
private int blockCount;
|
||||||
private int air;
|
private int air;
|
||||||
private int target;
|
private int target;
|
||||||
private Set<Integer> obfuscate;
|
private Set<Integer> blockIdsToObfuscate;
|
||||||
|
private final int blockIdToObfuscateTo;
|
||||||
|
|
||||||
public SectionHider(Player player, TechHider techHider, ByteBuf in, ByteBuf out, int chunkX, int chunkY, int chunkZ) {
|
public SectionHider(Player player, BlockState blockToObfuscateTo, Set<Integer> blockIdsToObfuscate, ByteBuf in, ByteBuf out, int chunkX, int chunkY, int chunkZ) {
|
||||||
this.player = player;
|
this.player = player;
|
||||||
this.techHider = techHider;
|
|
||||||
this.in = in;
|
this.in = in;
|
||||||
this.out = out;
|
this.out = out;
|
||||||
this.chunkX = chunkX;
|
this.chunkX = chunkX;
|
||||||
@@ -218,21 +187,13 @@ public class ChunkHider {
|
|||||||
this.offsetX = 16*chunkX;
|
this.offsetX = 16*chunkX;
|
||||||
this.offsetY = 16*chunkY;
|
this.offsetY = 16*chunkY;
|
||||||
this.offsetZ = 16*chunkZ;
|
this.offsetZ = 16*chunkZ;
|
||||||
this.skipSection = techHider.getLocationEvaluator().skipChunkSection(player, chunkX, chunkY, chunkZ);
|
|
||||||
|
this.blockIdsToObfuscate = blockIdsToObfuscate;
|
||||||
|
this.blockIdToObfuscateTo = BlockIds.impl.getCombinedId(blockToObfuscateTo);
|
||||||
|
|
||||||
|
|
||||||
this.paletted = false;
|
this.paletted = false;
|
||||||
this.bitsPerBlock = 0;
|
this.bitsPerBlock = 0;
|
||||||
this.air = TechHider.AIR_ID;
|
|
||||||
this.target = techHider.getObfuscationTargetId();
|
|
||||||
this.obfuscate = techHider.getObfuscateIds();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean blockPrecise() {
|
|
||||||
return techHider.getLocationEvaluator().blockPrecise(player, chunkX, chunkY, chunkZ);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TechHider.State test(int x, int y, int z) {
|
|
||||||
return techHider.getLocationEvaluator().check(player, offsetX+x, offsetY+y, offsetZ+z);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void copyBlockCount() {
|
public void copyBlockCount() {
|
||||||
@@ -258,11 +219,6 @@ public class ChunkHider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void processPalette() {
|
public void processPalette() {
|
||||||
if(skipSection) {
|
|
||||||
skipPalette();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int paletteLength = copyVarInt();
|
int paletteLength = copyVarInt();
|
||||||
if(paletteLength == 0)
|
if(paletteLength == 0)
|
||||||
return;
|
return;
|
||||||
@@ -273,17 +229,17 @@ public class ChunkHider {
|
|||||||
|
|
||||||
for(int i = 0; i < paletteLength; i++) {
|
for(int i = 0; i < paletteLength; i++) {
|
||||||
int entry = ProtocolUtils.readVarInt(in);
|
int entry = ProtocolUtils.readVarInt(in);
|
||||||
if(obfuscate.contains(entry))
|
if(blockIdsToObfuscate.contains(entry))
|
||||||
entry = techHider.getObfuscationTargetId();
|
entry = blockIdToObfuscateTo;
|
||||||
|
|
||||||
if(entry == TechHider.AIR_ID)
|
if(entry == TechHider.AIR_ID)
|
||||||
air = i;
|
air = i;
|
||||||
else if(entry == techHider.getObfuscationTargetId())
|
else if(entry == blockIdToObfuscateTo)
|
||||||
target = i;
|
target = i;
|
||||||
|
|
||||||
ProtocolUtils.writeVarInt(out, entry);
|
ProtocolUtils.writeVarInt(out, entry);
|
||||||
}
|
}
|
||||||
obfuscate = Collections.emptySet();
|
blockIdsToObfuscate = Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void skipDataArray() {
|
public void skipDataArray() {
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* This file is a part of the SteamWar software.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2026 SteamWar.de-Serverteam
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package de.steamwar.techhider;
|
||||||
|
|
||||||
|
public interface QuadFunction<A, B, C, D, Return> {
|
||||||
|
Return apply(A a, B b, C c, D d);
|
||||||
|
}
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is a part of the SteamWar software.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2025 SteamWar.de-Serverteam
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU Affero General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU Affero General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Affero General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package de.steamwar.techhider;
|
|
||||||
|
|
||||||
import com.comphenix.tinyprotocol.TinyProtocol;
|
|
||||||
import de.steamwar.Reflection;
|
|
||||||
import de.steamwar.core.Core;
|
|
||||||
import lombok.Getter;
|
|
||||||
import org.bukkit.Material;
|
|
||||||
import org.bukkit.entity.Player;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.function.UnaryOperator;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class TechHider {
|
|
||||||
|
|
||||||
public static final Class<?> blockPosition = Reflection.getClass("net.minecraft.core.BlockPos");
|
|
||||||
private static final Class<?> baseBlockPosition = Reflection.getClass("net.minecraft.core.Vec3i");
|
|
||||||
public static final Reflection.Field<Integer> blockPositionX = Reflection.getField(baseBlockPosition, int.class, 0);
|
|
||||||
public static final Reflection.Field<Integer> blockPositionY = Reflection.getField(baseBlockPosition, int.class, 1);
|
|
||||||
public static final Reflection.Field<Integer> blockPositionZ = Reflection.getField(baseBlockPosition, int.class, 2);
|
|
||||||
|
|
||||||
public static final Class<?> iBlockData = Reflection.getClass("net.minecraft.world.level.block.state.BlockState");
|
|
||||||
public static final Class<?> block = Reflection.getClass("net.minecraft.world.level.block.Block");
|
|
||||||
private static final Reflection.Method getBlockDataByBlock = Reflection.getTypedMethod(block, null, iBlockData);
|
|
||||||
|
|
||||||
public static final Class<?> craftMagicNumbers = Reflection.getClass("org.bukkit.craftbukkit.util.CraftMagicNumbers");
|
|
||||||
private static final Reflection.Method getBlockByMaterial = Reflection.getTypedMethod(craftMagicNumbers, "getBlock", block, Material.class);
|
|
||||||
|
|
||||||
public boolean iBlockDataHidden(Object iBlockData) {
|
|
||||||
return obfuscateIds.contains(BlockIds.impl.getCombinedId(iBlockData));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Object AIR = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, Material.AIR));
|
|
||||||
public static final int AIR_ID = BlockIds.impl.materialToId(Material.AIR);
|
|
||||||
|
|
||||||
private final Map<Class<?>, BiFunction<Player, Object, Object>> techhiders = new HashMap<>();
|
|
||||||
@Getter
|
|
||||||
private final LocationEvaluator locationEvaluator;
|
|
||||||
@Getter
|
|
||||||
private final Object obfuscationTarget;
|
|
||||||
@Getter
|
|
||||||
private final int obfuscationTargetId;
|
|
||||||
@Getter
|
|
||||||
private final Set<Integer> obfuscateIds;
|
|
||||||
@Getter
|
|
||||||
private final Set<String> hiddenBlockEntities;
|
|
||||||
|
|
||||||
public TechHider(LocationEvaluator locationEvaluator, Material obfuscationTarget, Set<Material> obfuscate, Set<String> hiddenBlockEntities) {
|
|
||||||
this.locationEvaluator = locationEvaluator;
|
|
||||||
this.obfuscateIds = obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet());
|
|
||||||
this.hiddenBlockEntities = hiddenBlockEntities;
|
|
||||||
this.obfuscationTarget = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, obfuscationTarget));
|
|
||||||
this.obfuscationTargetId = BlockIds.impl.materialToId(obfuscationTarget);
|
|
||||||
|
|
||||||
techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(this));
|
|
||||||
|
|
||||||
if(Core.getVersion() > 12 && Core.getVersion() < 19) {
|
|
||||||
Class<?> blockBreakClass = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket");
|
|
||||||
techhiders.put(blockBreakClass, ProtocolWrapper.impl.blockBreakHiderGenerator(blockBreakClass, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
if(Core.getVersion() > 8){
|
|
||||||
techhiders.put(Reflection.getClass("net.minecraft.network.protocol.game.ServerboundUseItemOnPacket"), (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet);
|
|
||||||
}
|
|
||||||
techhiders.put(Reflection.getClass("net.minecraft.network.protocol.game.ServerboundInteractPacket"), (p, packet) -> locationEvaluator.suppressInteractions(p) ? null : packet);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public void enable() {
|
|
||||||
techhiders.forEach(TinyProtocol.instance::addFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void disable() {
|
|
||||||
techhiders.forEach(TinyProtocol.instance::removeFilter);
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum State {
|
|
||||||
SKIP,
|
|
||||||
CHECK,
|
|
||||||
HIDE,
|
|
||||||
HIDE_AIR
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface LocationEvaluator {
|
|
||||||
default boolean suppressInteractions(Player player) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean skipChunk(Player player, int x, int z);
|
|
||||||
default boolean skipChunkSection(Player player, int x, int y, int z) {
|
|
||||||
return skipChunk(player, x, z);
|
|
||||||
}
|
|
||||||
default State check(Player player, int x, int y, int z) {
|
|
||||||
return skipChunkSection(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(y), ProtocolUtils.posToChunk(z)) ? State.SKIP : State.CHECK;
|
|
||||||
}
|
|
||||||
|
|
||||||
default State checkBlockPos(Player player, Object pos) {
|
|
||||||
return check(player, blockPositionX.get(pos), blockPositionY.get(pos), blockPositionZ.get(pos));
|
|
||||||
}
|
|
||||||
|
|
||||||
default boolean blockPrecise(Player player, int x, int y, int z) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -67,11 +67,13 @@ public class TechHiderUpdated {
|
|||||||
private final Map<Class<? extends Packet<? extends PacketListener>>, BiFunction<Player, Packet<? extends PacketListener>, Packet<? extends PacketListener>>> packetProcessors;
|
private final Map<Class<? extends Packet<? extends PacketListener>>, BiFunction<Player, Packet<? extends PacketListener>, Packet<? extends PacketListener>>> packetProcessors;
|
||||||
private final TinyProtocol interceptor;
|
private final TinyProtocol interceptor;
|
||||||
private final Set<Integer> blockIdsToObfuscate;
|
private final Set<Integer> blockIdsToObfuscate;
|
||||||
|
private final Set<String> blockEntitiesToHide;
|
||||||
private final BlockState blockToObfuscateTo;
|
private final BlockState blockToObfuscateTo;
|
||||||
|
|
||||||
public TechHiderUpdated(Plugin plugin, Set<Integer> blockIdsToObfuscate, BlockState blockToObfuscateTo) {
|
public TechHiderUpdated(Plugin plugin, Set<Integer> blockIdsToObfuscate, BlockState blockToObfuscateTo, Set<String> blockEntitiesToHide) {
|
||||||
this.blockIdsToObfuscate = blockIdsToObfuscate;
|
this.blockIdsToObfuscate = blockIdsToObfuscate;
|
||||||
this.blockToObfuscateTo = blockToObfuscateTo;
|
this.blockToObfuscateTo = blockToObfuscateTo;
|
||||||
|
this.blockEntitiesToHide = blockEntitiesToHide;
|
||||||
this.bypassingPackets = Set.of(
|
this.bypassingPackets = Set.of(
|
||||||
// --- Handshake & Login Protocol ---
|
// --- Handshake & Login Protocol ---
|
||||||
// These must be whitelisted to allow the player to actually reach the 'Play'
|
// These must be whitelisted to allow the player to actually reach the 'Play'
|
||||||
@@ -112,8 +114,7 @@ public class TechHiderUpdated {
|
|||||||
ClientboundCommandsPacket.class // Command tree for tab-complete
|
ClientboundCommandsPacket.class // Command tree for tab-complete
|
||||||
);
|
);
|
||||||
|
|
||||||
BiFunction<Player, Packet<? extends PacketListener>, Packet<? extends PacketListener>> tossPacket = (p,
|
BiFunction<Player, Packet<? extends PacketListener>, Packet<? extends PacketListener>> tossPacket = (p, packet) -> null;
|
||||||
packet) -> null;
|
|
||||||
|
|
||||||
this.packetProcessors = Map.of(
|
this.packetProcessors = Map.of(
|
||||||
ClientboundBlockEventPacket.class,
|
ClientboundBlockEventPacket.class,
|
||||||
@@ -122,8 +123,11 @@ public class TechHiderUpdated {
|
|||||||
(p, packet) -> processBlockUpdatePacket(p, (ClientboundBlockUpdatePacket) packet),
|
(p, packet) -> processBlockUpdatePacket(p, (ClientboundBlockUpdatePacket) packet),
|
||||||
ClientboundBlockEntityDataPacket.class,
|
ClientboundBlockEntityDataPacket.class,
|
||||||
(p, packet) -> processBlockEntityDataPacket(p, (ClientboundBlockEntityDataPacket) packet),
|
(p, packet) -> processBlockEntityDataPacket(p, (ClientboundBlockEntityDataPacket) packet),
|
||||||
ClientboundSectionBlocksUpdatePacket.class, tossPacket,
|
ClientboundSectionBlocksUpdatePacket.class,
|
||||||
ClientboundLevelChunkWithLightPacket.class, tossPacket);
|
(p, packet) -> processSectionUpdate(p, (ClientboundSectionBlocksUpdatePacket) packet),
|
||||||
|
ClientboundLevelChunkWithLightPacket.class,
|
||||||
|
(p, packet) -> processChunkWithLight(p, (ClientboundLevelChunkWithLightPacket) packet)
|
||||||
|
);
|
||||||
|
|
||||||
this.interceptor = new TinyProtocol(plugin) {
|
this.interceptor = new TinyProtocol(plugin) {
|
||||||
@Override
|
@Override
|
||||||
@@ -131,8 +135,7 @@ public class TechHiderUpdated {
|
|||||||
if (bypassingPackets.stream().anyMatch(clazz -> clazz.isInstance(packet))) {
|
if (bypassingPackets.stream().anyMatch(clazz -> clazz.isInstance(packet))) {
|
||||||
return packet;
|
return packet;
|
||||||
} else if (packetProcessors.containsKey(packet.getClass())) {
|
} else if (packetProcessors.containsKey(packet.getClass())) {
|
||||||
return packetProcessors.get(packet.getClass()).apply(receiver,
|
return packetProcessors.get(packet.getClass()).apply(receiver, (Packet<? extends PacketListener>) packet);
|
||||||
(Packet<? extends PacketListener>) packet);
|
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -144,29 +147,32 @@ public class TechHiderUpdated {
|
|||||||
private ClientboundBlockEventPacket processBlockEventPacket(Player player, ClientboundBlockEventPacket packet) {
|
private ClientboundBlockEventPacket processBlockEventPacket(Player player, ClientboundBlockEventPacket packet) {
|
||||||
BlockPos blockPos = packet.getPos();
|
BlockPos blockPos = packet.getPos();
|
||||||
|
|
||||||
if (isPlayerPrivilegedToAccessBlockPos(player, blockPos)) {
|
if (isPlayerPrivilegedToAccessBlockPos(player, blockPos.getX(), blockPos.getY(), blockPos.getZ())) {
|
||||||
return packet;
|
return packet;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientboundBlockUpdatePacket processBlockUpdatePacket(Player p, ClientboundBlockUpdatePacket packet) {
|
private ClientboundBlockUpdatePacket processBlockUpdatePacket(Player player, ClientboundBlockUpdatePacket packet) {
|
||||||
|
BlockPos blockPos = packet.getPos();
|
||||||
int id = BlockIds.impl.getCombinedId(packet.getBlockState());
|
int id = BlockIds.impl.getCombinedId(packet.getBlockState());
|
||||||
|
|
||||||
if (blockIdsToObfuscate.contains(id)) {
|
if(isPlayerPrivilegedToAccessBlockPos(player, blockPos.getX(), blockPos.getY(), blockPos.getZ())) {
|
||||||
// Return a modified copy of the packet with the obfuscated block state
|
return packet;
|
||||||
ClientboundBlockUpdatePacket modifiedPacket = new ClientboundBlockUpdatePacket(packet.getPos(),
|
}
|
||||||
blockToObfuscateTo);
|
else if (blockIdsToObfuscate.contains(id)) {
|
||||||
|
ClientboundBlockUpdatePacket modifiedPacket = new ClientboundBlockUpdatePacket(packet.getPos(), blockToObfuscateTo);
|
||||||
return modifiedPacket;
|
return modifiedPacket;
|
||||||
} else {
|
} else {
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientboundBlockEntityDataPacket processBlockEntityDataPacket(Player p,
|
private ClientboundBlockEntityDataPacket processBlockEntityDataPacket(Player p, ClientboundBlockEntityDataPacket packet) {
|
||||||
ClientboundBlockEntityDataPacket packet) {
|
BlockPos blockPos = packet.getPos();
|
||||||
if (isPlayerPrivilegedToAccessBlockPos(p, packet.getPos())) {
|
|
||||||
|
if (isPlayerPrivilegedToAccessBlockPos(p, blockPos.getX(), blockPos.getY(), blockPos.getZ())) {
|
||||||
return packet;
|
return packet;
|
||||||
} else if (ProtocolWrapper.impl.unfilteredTileEntityDataAction(packet)) {
|
} else if (ProtocolWrapper.impl.unfilteredTileEntityDataAction(packet)) {
|
||||||
return packet;
|
return packet;
|
||||||
@@ -175,8 +181,7 @@ public class TechHiderUpdated {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientboundSectionBlocksUpdatePacket processSectionUpdate(Player p,
|
private ClientboundSectionBlocksUpdatePacket processSectionUpdate(Player p, ClientboundSectionBlocksUpdatePacket packet) {
|
||||||
ClientboundSectionBlocksUpdatePacket packet) {
|
|
||||||
SectionPos sectionPos = packet.sectionPos;
|
SectionPos sectionPos = packet.sectionPos;
|
||||||
short[] oldPos = packet.positions;
|
short[] oldPos = packet.positions;
|
||||||
BlockState[] oldStates = packet.states;
|
BlockState[] oldStates = packet.states;
|
||||||
@@ -195,7 +200,7 @@ public class TechHiderUpdated {
|
|||||||
|
|
||||||
BlockPos pos = new BlockPos(worldX, worldY, worldZ);
|
BlockPos pos = new BlockPos(worldX, worldY, worldZ);
|
||||||
|
|
||||||
if (isPlayerPrivilegedToAccessBlockPos(p, pos)) {
|
if (isPlayerPrivilegedToAccessBlockPos(p, pos.getX(), pos.getY(), pos.getZ())) {
|
||||||
filteredPos.add(posShort);
|
filteredPos.add(posShort);
|
||||||
filteredStates.add(state);
|
filteredStates.add(state);
|
||||||
} else {
|
} else {
|
||||||
@@ -211,14 +216,19 @@ public class TechHiderUpdated {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filteredStates.isEmpty())
|
if (filteredStates.isEmpty()) {
|
||||||
return null;
|
return null;
|
||||||
if (!modified)
|
}
|
||||||
|
if (!modified) {
|
||||||
return packet;
|
return packet;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
short[] newPos = new short[filteredPos.size()];
|
short[] newPos = new short[filteredPos.size()];
|
||||||
for (int i = 0; i < newPos.length; i++)
|
for (int i = 0; i < newPos.length; i++) {
|
||||||
newPos[i] = filteredPos.get(i);
|
newPos[i] = filteredPos.get(i);
|
||||||
|
}
|
||||||
|
|
||||||
BlockState[] newStates = filteredStates.toArray(new BlockState[0]);
|
BlockState[] newStates = filteredStates.toArray(new BlockState[0]);
|
||||||
|
|
||||||
return new ClientboundSectionBlocksUpdatePacket(
|
return new ClientboundSectionBlocksUpdatePacket(
|
||||||
@@ -228,10 +238,12 @@ public class TechHiderUpdated {
|
|||||||
newStates);
|
newStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientboundLevelChunkWithLightPacket processChunkWithLight(Player p, ClientboundLevelChunkWithLightPacket packet) {
|
private final ChunkHider chunkHider = new ChunkHider();
|
||||||
}
|
private ClientboundLevelChunkWithLightPacket processChunkWithLight(Player p, ClientboundLevelChunkWithLightPacket packet) {
|
||||||
|
return chunkHider.processLevelChunkWithLightPacket(p, blockEntitiesToHide, this::isPlayerPrivilegedToAccessBlockPos,blockToObfuscateTo, blockIdsToObfuscate, packet);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isPlayerPrivilegedToAccessBlockPos(Player p, BlockPos pos) {
|
private boolean isPlayerPrivilegedToAccessBlockPos(Player p, int blockX, int blockY, int blockZ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user