FULLCHUNK TECHHIDER + Performanceimprovement + Bugfix #211
@ -25,24 +25,16 @@ import com.comphenix.protocol.events.PacketAdapter;
|
|||||||
import com.comphenix.protocol.events.PacketContainer;
|
import com.comphenix.protocol.events.PacketContainer;
|
||||||
import com.comphenix.protocol.events.PacketEvent;
|
import com.comphenix.protocol.events.PacketEvent;
|
||||||
import com.comphenix.protocol.reflect.StructureModifier;
|
import com.comphenix.protocol.reflect.StructureModifier;
|
||||||
import com.comphenix.protocol.wrappers.ChunkCoordIntPair;
|
|
||||||
import com.comphenix.protocol.wrappers.MultiBlockChangeInfo;
|
|
||||||
import com.comphenix.protocol.wrappers.WrappedBlockData;
|
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
import com.comphenix.protocol.wrappers.nbt.NbtBase;
|
||||||
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
import com.comphenix.protocol.wrappers.nbt.NbtCompound;
|
||||||
import de.steamwar.fightsystem.Config;
|
import de.steamwar.fightsystem.Config;
|
||||||
import de.steamwar.fightsystem.IFightSystem;
|
import de.steamwar.fightsystem.IFightSystem;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.UnpooledByteBufAllocator;
|
import io.netty.buffer.UnpooledByteBufAllocator;
|
||||||
import net.minecraft.server.v1_15_R1.Block;
|
|
||||||
import net.minecraft.server.v1_15_R1.ChunkSection;
|
|
||||||
import org.bukkit.Bukkit;
|
|
||||||
import org.bukkit.World;
|
|
||||||
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
|
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.ArrayList;
|
import java.nio.LongBuffer;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static de.steamwar.fightsystem.utils.ITechHider.bypass;
|
import static de.steamwar.fightsystem.utils.ITechHider.bypass;
|
||||||
@ -50,9 +42,6 @@ import static de.steamwar.fightsystem.utils.ITechHider.bypass;
|
|||||||
public class TechHider_15 {
|
public class TechHider_15 {
|
||||||
private TechHider_15(){}
|
private TechHider_15(){}
|
||||||
|
|
||||||
private static final World WORLD = Bukkit.getWorlds().get(0);
|
|
||||||
private static final WrappedBlockData WRAPPED_BLOCK_DATA = WrappedBlockData.createData(ITechHider.obfuscateMaterial);
|
|
||||||
|
|
||||||
static void start(){
|
static void start(){
|
||||||
chunkHider();
|
chunkHider();
|
||||||
}
|
}
|
||||||
@ -73,16 +62,9 @@ public class TechHider_15 {
|
|||||||
if(bypass(p, chunkX, chunkZ))
|
if(bypass(p, chunkX, chunkZ))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
PacketContainer cached = ITechHider.packetCache.get(packet);
|
packet = packet.shallowClone();
|
||||||
if(cached != null){
|
e.setPacket(packet);
|
||||||
e.setPacket(cached);
|
StructureModifier<List<NbtBase<?>>> list = packet.getListNbtModifier();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
cached = packet.shallowClone();
|
|
||||||
ITechHider.packetCache.put(packet, cached);
|
|
||||||
e.setPacket(cached);
|
|
||||||
StructureModifier<List<NbtBase<?>>> list = cached.getListNbtModifier();
|
|
||||||
List<NbtBase<?>> nmsTags = list.read(0);
|
List<NbtBase<?>> nmsTags = list.read(0);
|
||||||
boolean changed = false;
|
boolean changed = false;
|
||||||
for(int i = nmsTags.size() - 1; i >= 0; i--){
|
for(int i = nmsTags.size() - 1; i >= 0; i--){
|
||||||
@ -99,9 +81,9 @@ public class TechHider_15 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
changed = false;
|
changed = false;
|
||||||
StructureModifier<byte[]> byteArray = cached.getByteArrays();
|
StructureModifier<byte[]> byteArray = packet.getByteArrays();
|
||||||
int primaryBitMask = ints.read(2);
|
int primaryBitMask = ints.read(2);
|
||||||
byte [] data = byteArray.read(0);
|
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;
|
||||||
|
|
||||||
@ -116,13 +98,8 @@ public class TechHider_15 {
|
|||||||
i += 2;
|
i += 2;
|
||||||
byte bitsPerBlock = data[i++];
|
byte bitsPerBlock = data[i++];
|
||||||
buffer.writeByte(bitsPerBlock);
|
buffer.writeByte(bitsPerBlock);
|
||||||
if(bitsPerBlock < 4)
|
|
||||||
bitsPerBlock = 4;
|
|
||||||
else if(bitsPerBlock > 8){
|
|
||||||
bitsPerBlock = 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(bitsPerBlock != 14){
|
if(bitsPerBlock < 9){
|
||||||
int paletteLength = ITechHider.readVarInt(data, i);
|
int paletteLength = ITechHider.readVarInt(data, i);
|
||||||
int paletteLengthLength = ITechHider.readVarIntLength(data, i);
|
int paletteLengthLength = ITechHider.readVarIntLength(data, i);
|
||||||
buffer.writeBytes(data, i, paletteLengthLength);
|
buffer.writeBytes(data, i, paletteLengthLength);
|
||||||
@ -149,65 +126,25 @@ public class TechHider_15 {
|
|||||||
i += dataArrayLength * 8;
|
i += dataArrayLength * 8;
|
||||||
}else{
|
}else{
|
||||||
//Full Chunk/no palette, so the chunk has to be crawled through
|
//Full Chunk/no palette, so the chunk has to be crawled through
|
||||||
//This didn't work, so workaround with MultiBlockChange-Packets was created
|
|
||||||
int dataArrayLength = ITechHider.readVarInt(data, i);
|
int dataArrayLength = ITechHider.readVarInt(data, i);
|
||||||
int dataArrayLengthLength = ITechHider.readVarIntLength(data, i);
|
int dataArrayLengthLength = ITechHider.readVarIntLength(data, i);
|
||||||
buffer.writeBytes(data, i, dataArrayLengthLength + dataArrayLength * 8);
|
buffer.writeBytes(data, i, dataArrayLengthLength);
|
||||||
i += dataArrayLengthLength + dataArrayLength * 8;
|
i += dataArrayLengthLength;
|
||||||
|
|
||||||
/*
|
ByteBuffer source = ByteBuffer.wrap(data, i, dataArrayLength * 8);
|
||||||
ByteBuf chunkData = UnpooledByteBufAllocator.DEFAULT.directBuffer(dataArrayLength * 8);
|
VariableValueArray values = new VariableValueArray(bitsPerBlock, dataArrayLength, source.asLongBuffer());
|
||||||
|
|||||||
chunkData.writeBytes(data, i, dataArrayLength * 8);
|
|
||||||
|
|
||||||
int bitsOver = 0; // Anzahl an Bits, die aus dem letzten Durchlauf noch über sind
|
for(int pos = 0; pos < 4096; pos++){
|
||||||
int lastBits = 0; // Die letzten Bits aus dem vorigen Durchlauf
|
if(Config.HiddenBlocks.contains(values.get(pos))){
|
||||||
while(chunkData.readableBytes() > 0){
|
changed = true;
|
||||||
int currentPos = 70 - bitsOver; // 14 * 5, Die Größe des Bitshifts, der durchgeführt werden muss, um den ersten Block zu lesen
|
values.set(pos, Config.ObfuscateWith);
|
||||||
if(currentPos >= 64)
|
}
|
||||||
currentPos -= 14;
|
|
||||||
|
|
||||||
long values = chunkData.readLong();
|
|
||||||
long result = 0;
|
|
||||||
|
|
||||||
int newLastBits = (int)(values >> currentPos);
|
|
||||||
while(currentPos >= 0){
|
|
||||||
int blockId = (int)(values >> currentPos) & 0x3FFF;
|
|
||||||
|
|
||||||
if(currentPos > 50){ //64 - 14, Prüfen auf Ende des Longs
|
|
||||||
int offset = 14 - (currentPos - 50);
|
|
||||||
blockId |= (data[i+14] << (offset + 8) | data[i+15] << offset) & 0x3FFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(Config.HiddenBlocks.contains(blockId))
|
for(long l : values.backing)
|
||||||
blockId = Config.ObfuscateWith;
|
buffer.writeLong(l);
|
||||||
|
|
||||||
//if(blockId > 11336) Should not occur, but occurs
|
i += dataArrayLength * 8;
|
||||||
|
|
||||||
result <<= 14;
|
|
||||||
result |= blockId;
|
|
||||||
currentPos -= 14;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(currentPos > -14){ // Check the first bits of the chunk
|
|
||||||
int blockId = ((int)values << -currentPos | lastBits) & 0x3FFF;
|
|
||||||
if(Config.HiddenBlocks.contains(blockId))
|
|
||||||
blockId = Config.ObfuscateWith;
|
|
||||||
result <<= (14 + currentPos);
|
|
||||||
result |= blockId >> -currentPos;
|
|
||||||
}
|
|
||||||
|
|
||||||
lastBits = newLastBits;
|
|
||||||
bitsOver += 8;
|
|
||||||
if(bitsOver >= 14)
|
|
||||||
bitsOver -= 14;
|
|
||||||
|
|
||||||
buffer.writeLong(result);
|
|
||||||
i += 8;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
final int cY = chunkY;
|
|
||||||
Bukkit.getScheduler().runTaskLater(IFightSystem.getPlugin(),
|
|
||||||
() -> fullChunkHider(p, chunkX, cY, chunkZ), 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
primaryBitMask >>= 1;
|
primaryBitMask >>= 1;
|
||||||
@ -224,39 +161,45 @@ public class TechHider_15 {
|
|||||||
}).start(ITechHider.threadMultiplier * 4);
|
}).start(ITechHider.threadMultiplier * 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void fullChunkHider(Player player, int chunkX, int chunkY, int chunkZ){
|
private static final class VariableValueArray {
|
||||||
if(!player.isOnline())
|
private final long[] backing;
|
||||||
return;
|
private final int bitsPerValue;
|
||||||
|
private final long valueMask;
|
||||||
|
|
||||||
ArrayList<MultiBlockChangeInfo> blockChangeList = new ArrayList<>();
|
public VariableValueArray(int bitsPerEntry, int dataArrayLength, LongBuffer buffer) {
|
||||||
ChunkCoordIntPair chunkCoords = new ChunkCoordIntPair(chunkX, chunkZ);
|
this.bitsPerValue = bitsPerEntry;
|
||||||
Chaoscaot
hat
Hier sind noch Debug messages Hier sind noch Debug messages
|
|||||||
ChunkSection chunk = ((CraftWorld) WORLD).getHandle().getChunkAt(chunkX, chunkZ).getSections()[chunkY]; //This takes ~70ms async.
|
this.backing = new long[dataArrayLength];
|
||||||
if(ChunkSection.a(chunk))
|
buffer.get(backing);
|
||||||
return;
|
this.valueMask = (1L << this.bitsPerValue) - 1;
|
||||||
|
|
||||||
int minY = chunkY * 16;
|
|
||||||
for(int x = 0; x < 16; x++){
|
|
||||||
for(int y = 0; y < 16; y++){
|
|
||||||
for(int z = 0; z < 16; z++){
|
|
||||||
if(Config.HiddenBlocks.contains(Block.REGISTRY_ID.getId(chunk.getType(x, y, z))))
|
|
||||||
blockChangeList.add(new MultiBlockChangeInfo((short)(x << 12 | z << 8 | (y + minY)), WRAPPED_BLOCK_DATA, chunkCoords));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(blockChangeList.isEmpty())
|
public int get(int index) {
|
||||||
return;
|
index *= bitsPerValue;
|
||||||
|
int i0 = index >> 6;
|
||||||
|
int i1 = index & 0x3f;
|
||||||
|
|
||||||
PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.MULTI_BLOCK_CHANGE);
|
long value = backing[i0] >>> i1;
|
||||||
packet.getChunkCoordIntPairs().write(0, chunkCoords);
|
|
||||||
packet.getMultiBlockChangeInfoArrays().write(0, blockChangeList.toArray(new MultiBlockChangeInfo[0]));
|
|
||||||
|
|
||||||
try {
|
// The value is divided over two long values
|
||||||
ProtocolLibrary.getProtocolManager().sendServerPacket(player, packet, false);
|
if (i1 + bitsPerValue > 64) {
|
||||||
} catch (InvocationTargetException e) {
|
value |= backing[++i0] << 64 - i1;
|
||||||
throw new SecurityException("Something went wrong sending the multiblockchange packet", e);
|
}
|
||||||
} catch (NullPointerException e){
|
|
||||||
//ignored, player offline
|
return (int) (value & valueMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void set(int index, int value) {
|
||||||
|
index *= bitsPerValue;
|
||||||
|
int i0 = index >> 6;
|
||||||
|
int i1 = index & 0x3f;
|
||||||
|
|
||||||
|
backing[i0] = this.backing[i0] & ~(this.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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ public class TechKOCountdown extends Countdown {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
final String countdownCounting() {
|
final String countdownCounting() {
|
||||||
return "bis " + team.getColoredName() + " §7einen Schuss abgegeben haben muss!";
|
return "bis " + team.getColoredName() + " §feinen Schuss abgegeben haben muss!";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -61,7 +61,7 @@ public class FightTeam implements IFightTeam{
|
|||||||
|
|
||||||
private FightPlayer leader;
|
private FightPlayer leader;
|
||||||
private final UUID designatedLeader;
|
private final UUID designatedLeader;
|
||||||
private final Set<FightPlayer> players = new HashSet<>();
|
private final Map<Player, FightPlayer> players = new HashMap<>();
|
||||||
private boolean ready;
|
private boolean ready;
|
||||||
private final Set<Player> invited = new HashSet<>();
|
private final Set<Player> invited = new HashSet<>();
|
||||||
private final String name;
|
private final String name;
|
||||||
@ -123,21 +123,15 @@ public class FightTeam implements IFightTeam{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void teleportToSpawn(){
|
public void teleportToSpawn(){
|
||||||
for(FightPlayer player : players){
|
players.forEach((player, fp) -> player.teleport(spawn));
|
||||||
player.getPlayer().teleport(spawn);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FightPlayer getFightPlayer(Player player) {
|
public FightPlayer getFightPlayer(Player player) {
|
||||||
for(FightPlayer fightPlayer : players) {
|
return players.get(player);
|
||||||
if(fightPlayer.getPlayer().equals(player))
|
|
||||||
return fightPlayer;
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean allPlayersOut() {
|
public boolean allPlayersOut() {
|
||||||
for(FightPlayer fightPlayer : players) {
|
for(FightPlayer fightPlayer : players.values()) {
|
||||||
if(fightPlayer.isLiving())
|
if(fightPlayer.isLiving())
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -146,11 +140,7 @@ public class FightTeam implements IFightTeam{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPlayerInTeam(Player player) {
|
public boolean isPlayerInTeam(Player player) {
|
||||||
for(FightPlayer fightPlayer : players) {
|
return players.containsKey(player);
|
||||||
if(fightPlayer.getPlayer().equals(player))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -166,15 +156,13 @@ public class FightTeam implements IFightTeam{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void broadcast(String message) {
|
public void broadcast(String message) {
|
||||||
for(FightPlayer fightPlayer : players) {
|
players.forEach((player, fp) -> player.sendMessage(message));
|
||||||
fightPlayer.sendMessage(message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FightPlayer addMember(Player player) {
|
public FightPlayer addMember(Player player) {
|
||||||
final List<TechHider.ChunkPos> chunksToReload = TechHider.prepareChunkReload(player);
|
final List<TechHider.ChunkPos> chunksToReload = TechHider.prepareChunkReload(player);
|
||||||
FightPlayer fightPlayer = new FightPlayer(player, this);
|
FightPlayer fightPlayer = new FightPlayer(player, this);
|
||||||
players.add(fightPlayer);
|
players.put(player, fightPlayer);
|
||||||
invited.remove(player);
|
invited.remove(player);
|
||||||
team.addEntry(player.getName());
|
team.addEntry(player.getName());
|
||||||
|
|
||||||
@ -227,7 +215,7 @@ public class FightTeam implements IFightTeam{
|
|||||||
public void setLeader(FightPlayer leader) {
|
public void setLeader(FightPlayer leader) {
|
||||||
if (leader == null){
|
if (leader == null){
|
||||||
if(!players.isEmpty()) {
|
if(!players.isEmpty()) {
|
||||||
setLeader(players.iterator().next());
|
setLeader(players.values().iterator().next());
|
||||||
Bukkit.broadcastMessage(FightSystem.PREFIX + "§aDer Spieler §e" + this.leader.getPlayer().getName() + " §aist nun Leader von Team " + getColoredName() + "§a!");
|
Bukkit.broadcastMessage(FightSystem.PREFIX + "§aDer Spieler §e" + this.leader.getPlayer().getName() + " §aist nun Leader von Team " + getColoredName() + "§a!");
|
||||||
}else if(Config.Ranked){
|
}else if(Config.Ranked){
|
||||||
RankedPlayerLeftWincondition.leaderQuit(this);
|
RankedPlayerLeftWincondition.leaderQuit(this);
|
||||||
@ -263,8 +251,8 @@ public class FightTeam implements IFightTeam{
|
|||||||
inventory.setItem(0, new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).removeAllAttributs().addEnchantment(Enchantment.DURABILITY, 1).setDisplayName("§e" + Config.GameName + " wählen").build());
|
inventory.setItem(0, new ItemBuilder(SWItem.getMaterial("CAULDRON_ITEM")).removeAllAttributs().addEnchantment(Enchantment.DURABILITY, 1).setDisplayName("§e" + Config.GameName + " wählen").build());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<FightPlayer> getPlayers() {
|
public Collection<FightPlayer> getPlayers() {
|
||||||
return players;
|
return players.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isReady() {
|
public boolean isReady() {
|
||||||
@ -398,7 +386,7 @@ public class FightTeam implements IFightTeam{
|
|||||||
public double getHeartRatio(){
|
public double getHeartRatio(){
|
||||||
int maximumHearts = 0;
|
int maximumHearts = 0;
|
||||||
double currentHearts = 0;
|
double currentHearts = 0;
|
||||||
for(FightPlayer fightPlayer : players){
|
for(FightPlayer fightPlayer : players.values()){
|
||||||
maximumHearts += 20;
|
maximumHearts += 20;
|
||||||
if(!fightPlayer.isLiving())
|
if(!fightPlayer.isLiving())
|
||||||
continue;
|
continue;
|
||||||
@ -411,7 +399,7 @@ public class FightTeam implements IFightTeam{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void loadKits(){
|
public void loadKits(){
|
||||||
for(FightPlayer fightPlayer : players) {
|
for(FightPlayer fightPlayer : players.values()) {
|
||||||
if(fightPlayer.getPlayer() == null)
|
if(fightPlayer.getPlayer() == null)
|
||||||
continue;
|
continue;
|
||||||
fightPlayer.getPlayer().getInventory().clear();
|
fightPlayer.getPlayer().getInventory().clear();
|
||||||
|
@ -68,8 +68,14 @@ public class WinconditionTechKO extends ListenerWincondition {
|
|||||||
@Override
|
@Override
|
||||||
public void disable() {
|
public void disable() {
|
||||||
super.disable();
|
super.disable();
|
||||||
|
if(smallerZcountdown != null){
|
||||||
smallerZcountdown.disable();
|
smallerZcountdown.disable();
|
||||||
|
smallerZcountdown = null;
|
||||||
|
}
|
||||||
|
if(biggerZcountdown != null){
|
||||||
biggerZcountdown.disable();
|
biggerZcountdown.disable();
|
||||||
|
biggerZcountdown = null;
|
||||||
|
}
|
||||||
task.cancel();
|
task.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
In neuem Issue referenzieren
Einen Benutzer sperren
Noch eine