forked from SteamWar/SteamWar
Implement basic techhider
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
plugins {
|
||||
steamwar.java
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly(project(":CommonCore", "default"))
|
||||
compileOnly(project(":HiderCore:HiderCore_TechHider", "default"))
|
||||
compileOnly(project(":SpigotCore:SpigotCore_Main", "default"))
|
||||
compileOnly(project(":HiderCore:HiderCore_TechHider_8", "default"))
|
||||
|
||||
compileOnly(libs.nms9)
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
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.techhider;
|
||||
|
||||
import de.steamwar.Reflection;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ChunkHider9 extends ChunkHider8 {
|
||||
|
||||
private static final UnaryOperator<Object> mapChunkCloner = ProtocolUtils.shallowCloneGenerator(mapChunkPacket);
|
||||
|
||||
private static final Reflection.Field<Integer> mapChunkX = Reflection.getField(mapChunkPacket, int.class, 0);
|
||||
private static final Reflection.Field<Integer> mapChunkZ = Reflection.getField(mapChunkPacket, int.class, 1);
|
||||
private static final Reflection.Field<Integer> mapChunkBitMask = Reflection.getField(mapChunkPacket, int.class, 2);
|
||||
private static final Reflection.Field<List> mapChunkBlockEntities = Reflection.getField(mapChunkPacket, List.class, 0);
|
||||
private static final Reflection.Field<byte[]> mapChunkData = Reflection.getField(mapChunkPacket, byte[].class, 0);
|
||||
|
||||
private static final Class<?> nbtTagCompound = Reflection.getClass("net.minecraft.nbt.CompoundTag");
|
||||
private static final Reflection.Method nbtTagGetString = Reflection.getTypedMethod(nbtTagCompound, null, String.class, String.class);
|
||||
|
||||
@Override
|
||||
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
|
||||
return (p, packet) -> {
|
||||
int chunkX = mapChunkX.get(packet);
|
||||
int chunkZ = mapChunkZ.get(packet);
|
||||
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
|
||||
return packet;
|
||||
|
||||
packet = mapChunkCloner.apply(packet);
|
||||
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
|
||||
mapChunkBlockEntities.set(packet, ((List<?>)mapChunkBlockEntities.get(packet)).stream().filter(
|
||||
nbttag -> !hiddenBlockEntities.contains((String) nbtTagGetString.invoke(nbttag, "id"))
|
||||
).collect(Collectors.toList()));
|
||||
|
||||
int primaryBitMask = mapChunkBitMask.get(packet);
|
||||
ByteBuf in = Unpooled.wrappedBuffer(mapChunkData.get(packet));
|
||||
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
|
||||
for(int chunkY = 0; chunkY < p.getWorld().getMaxHeight()/16; chunkY++) {
|
||||
if(((1 << chunkY) & primaryBitMask) == 0)
|
||||
continue;
|
||||
|
||||
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, chunkY, chunkZ);
|
||||
dataHider(section);
|
||||
}
|
||||
byte[] data = new byte[out.readableBytes()];
|
||||
out.readBytes(data);
|
||||
mapChunkData.set(packet, data);
|
||||
|
||||
return packet;
|
||||
};
|
||||
}
|
||||
|
||||
protected void dataHider(SectionHider section) {
|
||||
section.copyBitsPerBlock();
|
||||
section.processPalette();
|
||||
|
||||
if(section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) { //section.getBitsPerBlock() < 9
|
||||
section.skipDataArray();
|
||||
} else {
|
||||
processDataArray(section);
|
||||
}
|
||||
|
||||
section.getOut().writeBytes(section.getIn(), 4096); //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
|
||||
}
|
||||
|
||||
protected void processDataArray(SectionHider section) {
|
||||
VariableValueArray values = new VariableValueArray(section.getBitsPerBlock(), section.readDataArray());
|
||||
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int pos = (((y * 16) + z) * 16) + x;
|
||||
|
||||
switch (section.test(x, y, z)) {
|
||||
case SKIP:
|
||||
break;
|
||||
case CHECK:
|
||||
if(!section.getObfuscate().contains(values.get(pos)))
|
||||
break;
|
||||
case HIDE:
|
||||
values.set(pos, section.getTarget());
|
||||
break;
|
||||
case HIDE_AIR:
|
||||
default:
|
||||
values.set(pos, section.getAir());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
section.writeDataArray(values.backing);
|
||||
}
|
||||
|
||||
private static class VariableValueArray {
|
||||
private final long[] backing;
|
||||
private final int bitsPerValue;
|
||||
private final long valueMask;
|
||||
|
||||
public VariableValueArray(int bitsPerEntry, long[] dataArray) {
|
||||
this.bitsPerValue = bitsPerEntry;
|
||||
this.valueMask = (1L << this.bitsPerValue) - 1;
|
||||
this.backing = dataArray;
|
||||
}
|
||||
|
||||
public int get(int index) {
|
||||
index *= bitsPerValue;
|
||||
int i0 = index >> 6;
|
||||
int i1 = index & 0x3f;
|
||||
|
||||
long value = backing[i0] >>> i1;
|
||||
|
||||
// The value is divided over two long values
|
||||
if (i1 + bitsPerValue > 64)
|
||||
value |= backing[++i0] << 64 - i1;
|
||||
|
||||
return (int) (value & valueMask);
|
||||
}
|
||||
|
||||
public void set(int index, int value) {
|
||||
index *= bitsPerValue;
|
||||
int i0 = index >> 6;
|
||||
int i1 = index & 0x3f;
|
||||
|
||||
backing[i0] = backing[i0] & ~(valueMask << i1) | (value & valueMask) << i1;
|
||||
int i2 = i1 + bitsPerValue;
|
||||
// The value is divided over two long values
|
||||
if (i2 > 64) {
|
||||
i0++;
|
||||
backing[i0] = backing[i0] & -(1L << i2 - 64) | value >> 64 - i1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user