From 927585d92f61ebd43a4ef8a189c67a763dc1b4ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Thu, 27 Apr 2023 17:01:35 +0200 Subject: [PATCH 01/12] feat: add login packet hash obfuscation --- .github/workflows/buildtools.sh | 1 + .../orebfuscator/config/BlockFlags.java | 1 + .../orebfuscator-nms-v1_18_R1/pom.xml | 2 +- orebfuscator-plugin/pom.xml | 2 +- .../obfuscation/ObfuscationListenerSync.java | 8 +- .../obfuscation/ObfuscationSystem.java | 3 + .../seed/SeedObfuscationListener.java | 33 ++++++++ .../seed/SeedObfuscationStrategy.java | 78 +++++++++++++++++++ pom.xml | 6 +- 9 files changed, 122 insertions(+), 12 deletions(-) create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java diff --git a/.github/workflows/buildtools.sh b/.github/workflows/buildtools.sh index e0e4d190..d10f4264 100644 --- a/.github/workflows/buildtools.sh +++ b/.github/workflows/buildtools.sh @@ -13,6 +13,7 @@ build () { curl -o BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar "$JAVA_HOME/bin/java" -jar BuildTools.jar --rev $1 --remapped + rm -rf $1 cd .. } diff --git a/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/BlockFlags.java b/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/BlockFlags.java index 5a90988d..82b8aa4d 100644 --- a/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/BlockFlags.java +++ b/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/BlockFlags.java @@ -6,6 +6,7 @@ public interface BlockFlags { public static final int FLAG_BLOCK_ENTITY = 2; public static final int FLAG_PROXIMITY = 4; public static final int FLAG_USE_BLOCK_BELOW = 8; + public static final int FLAG_ALLOW_FOR_USE_BLOCK_BELOW = 16; public static boolean isEmpty(int mask) { return (mask & 0xFF) == 0; diff --git a/orebfuscator-nms/orebfuscator-nms-v1_18_R1/pom.xml b/orebfuscator-nms/orebfuscator-nms-v1_18_R1/pom.xml index 63999745..4b2d88b5 100644 --- a/orebfuscator-nms/orebfuscator-nms-v1_18_R1/pom.xml +++ b/orebfuscator-nms/orebfuscator-nms-v1_18_R1/pom.xml @@ -28,7 +28,7 @@ com.comphenix.protocol - ProtocolLib-API + ProtocolLib ${dependency.protocollib.version} provided diff --git a/orebfuscator-plugin/pom.xml b/orebfuscator-plugin/pom.xml index 51ec41dd..a160c021 100644 --- a/orebfuscator-plugin/pom.xml +++ b/orebfuscator-plugin/pom.xml @@ -60,7 +60,7 @@ com.comphenix.protocol - ProtocolLib-API + ProtocolLib ${dependency.protocollib.version} provided diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListenerSync.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListenerSync.java index c9781fad..6f21150b 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListenerSync.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListenerSync.java @@ -1,7 +1,5 @@ package net.imprex.orebfuscator.obfuscation; -import java.lang.reflect.InvocationTargetException; - import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.ProtocolManager; import com.comphenix.protocol.events.PacketEvent; @@ -31,11 +29,7 @@ protected void preChunkProcessing(PacketEvent event) { @Override protected void postChunkProcessing(PacketEvent event) { - try { - this.protocolManager.sendServerPacket(event.getPlayer(), event.getPacket(), false); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } + this.protocolManager.sendServerPacket(event.getPlayer(), event.getPacket(), false); } @Override diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java index 0889bedd..795d4dd6 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java @@ -9,6 +9,7 @@ import net.imprex.orebfuscator.cache.ObfuscationCache; import net.imprex.orebfuscator.chunk.ChunkStruct; import net.imprex.orebfuscator.config.OrebfuscatorConfig; +import net.imprex.orebfuscator.obfuscation.seed.SeedObfuscationListener; public class ObfuscationSystem { @@ -32,6 +33,8 @@ public ObfuscationSystem(Orebfuscator orebfuscator) { this.deobfuscationWorker = new DeobfuscationWorker(orebfuscator); DeobfuscationListener.createAndRegister(orebfuscator, this.deobfuscationWorker); + + new SeedObfuscationListener(orebfuscator); } public void registerChunkListener() { diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java new file mode 100644 index 00000000..c41b55e8 --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java @@ -0,0 +1,33 @@ +package net.imprex.orebfuscator.obfuscation.seed; + +import java.nio.ByteBuffer; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; + +import net.imprex.orebfuscator.Orebfuscator; + +public class SeedObfuscationListener extends PacketAdapter { + + private final SeedObfuscationStrategy strategy = SeedObfuscationStrategy.createDynamically(); + private final long hash; + + public SeedObfuscationListener(Orebfuscator orebfuscator) { + super(orebfuscator, PacketType.Play.Server.LOGIN); + + + ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + protocolManager.addPacketListener(this); + + ByteBuffer buffer = ByteBuffer.wrap(orebfuscator.getOrebfuscatorConfig().systemHash()); + this.hash = buffer.getLong(0); + } + + @Override + public void onPacketSending(PacketEvent event) { + event.setPacket(strategy.process(event.getPacket(), this.hash)); + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java new file mode 100644 index 00000000..4b6788ec --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java @@ -0,0 +1,78 @@ +package net.imprex.orebfuscator.obfuscation.seed; + +import java.lang.reflect.RecordComponent; +import java.util.Arrays; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.reflect.accessors.Accessors; +import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; +import com.comphenix.protocol.reflect.accessors.FieldAccessor; + +@FunctionalInterface +public interface SeedObfuscationStrategy { + + static final SeedObfuscationStrategy NOOP = (packet, hash) -> packet; + + static SeedObfuscationStrategy createDynamically() { + final PacketType packetType = PacketType.Play.Server.LOGIN; + final Class packetClass = packetType.getPacketClass(); + + if (packetClass.isRecord()) { + final RecordComponent[] components = packetClass.getRecordComponents(); + final Class[] componentClasses = new Class[components.length]; + + int longIndex = -1; + for (int i = 0; i < components.length; i++) { + Class componentClass = components[i].getType(); + + if (longIndex == -1 && componentClass == long.class) { + longIndex = i; + } + + componentClasses[i] = componentClass; + } + + final int hashIndex = longIndex; + if (hashIndex == -1) { + return NOOP; + } + + final ConstructorAccessor constructorAccessor = Accessors.getConstructorAccessor( + packetClass, componentClasses); + + final FieldAccessor[] fieldAccessors = Arrays.stream(packetClass.getDeclaredFields()) + .map(Accessors::getFieldAccessor) + .toArray(FieldAccessor[]::new); + + return (packet, hash) -> { + Object handle = packet.getHandle(); + Object[] arguments = new Object[components.length]; + + for (int i = 0; i < components.length; i++) { + if (hashIndex == i) { + arguments[i] = hash; + } else { + arguments[i] = fieldAccessors[i].get(handle); + } + } + + handle = constructorAccessor.invoke(arguments); + return new PacketContainer(packetType, handle); + }; + } else { + try { + Accessors.getFieldAccessor(packetClass, long.class, true); + } catch (Exception e) { + return NOOP; + } + + return (packet, hash) -> { + packet.getLongs().write(0, hash); + return packet; + }; + } + } + + PacketContainer process(PacketContainer packet, long hash); +} diff --git a/pom.xml b/pom.xml index 62b3c551..3a2460ff 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 3.0.2 5.9.2 4.1.68.Final - 4.4.0 + 5.0.0-SNAPSHOT 3.11.0 3.4.1 @@ -40,7 +40,7 @@ dmulloy2-repo - https://repo.dmulloy2.net/nexus/repository/public/ + https://repo.dmulloy2.net/repository/public/ @@ -111,7 +111,7 @@ maven-compiler-plugin ${plugin.compile.version} - 8 + 17 From 6d7f4b99331d66bffec8c01fe2ae46c036db4ade Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Mon, 5 Jun 2023 13:07:09 +0200 Subject: [PATCH 02/12] feat: wip - add new proximity system --- .github/workflows/buildtools.sh | 10 +- .../net/imprex/orebfuscator/Orebfuscator.java | 24 ++- .../orebfuscator/OrebfuscatorPlayer.java | 86 +++++++++++ .../orebfuscator/config/WorldMatcher.java | 51 ------- .../obfuscation/DeobfuscationListener.java | 2 +- .../obfuscation/ObfuscationListener.java | 34 +++-- .../ProximityDirectorThread.java | 143 ++++++++++++++++++ .../proximityhider/ProximityHider.java | 85 ----------- .../proximityhider/ProximityListener.java | 56 ------- .../ProximityPacketListener.java | 8 +- .../proximityhider/ProximityPlayer.java | 82 ---------- .../ProximityPlayerManager.java | 102 ------------- .../proximityhider/ProximityQueue.java | 80 ---------- .../proximityhider/ProximityThread.java | 120 --------------- .../proximityhider/ProximityWorker.java | 133 ++++++++++++++++ .../proximityhider/ProximityWorkerThread.java | 46 ++++++ .../orebfuscator/util/PermissionUtil.java | 2 +- .../src/main/resources/config/config-1.19.yml | 12 ++ pom.xml | 2 +- 19 files changed, 466 insertions(+), 612 deletions(-) create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/WorldMatcher.java create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityHider.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityListener.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayer.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayerManager.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityQueue.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityThread.java create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java diff --git a/.github/workflows/buildtools.sh b/.github/workflows/buildtools.sh index d10f4264..2c884041 100644 --- a/.github/workflows/buildtools.sh +++ b/.github/workflows/buildtools.sh @@ -7,14 +7,14 @@ build () { echo "Building v$1 with java-$2 ($JAVA_HOME)" rm -rf $1 - mkdir $1 - cd $1 + mkdir $1 + cd $1 - curl -o BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar - "$JAVA_HOME/bin/java" -jar BuildTools.jar --rev $1 --remapped + curl -o BuildTools.jar https://hub.spigotmc.org/jenkins/job/BuildTools/lastSuccessfulBuild/artifact/target/BuildTools.jar + "$JAVA_HOME/bin/java" -jar BuildTools.jar --rev $1 --remapped rm -rf $1 - cd .. + cd .. } checkVersion () { diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java index 74409f9d..d0b9f25a 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java @@ -15,8 +15,7 @@ import net.imprex.orebfuscator.cache.ObfuscationCache; import net.imprex.orebfuscator.config.OrebfuscatorConfig; import net.imprex.orebfuscator.obfuscation.ObfuscationSystem; -import net.imprex.orebfuscator.proximityhider.ProximityHider; -import net.imprex.orebfuscator.proximityhider.ProximityListener; +import net.imprex.orebfuscator.proximityhider.ProximityDirectorThread; import net.imprex.orebfuscator.proximityhider.ProximityPacketListener; import net.imprex.orebfuscator.util.HeightAccessor; import net.imprex.orebfuscator.util.OFCLogger; @@ -31,7 +30,7 @@ public class Orebfuscator extends JavaPlugin implements Listener { private UpdateSystem updateSystem; private ObfuscationCache obfuscationCache; private ObfuscationSystem obfuscationSystem; - private ProximityHider proximityHider; + private ProximityDirectorThread proximityThread; private ProximityPacketListener proximityPacketListener; @Override @@ -69,15 +68,18 @@ public void onEnable() { this.obfuscationSystem = new ObfuscationSystem(this); // Load proximity hider - this.proximityHider = new ProximityHider(this); + this.proximityThread = new ProximityDirectorThread(this); if (this.config.proximityEnabled()) { - this.proximityHider.start(); + this.proximityThread.start(); this.proximityPacketListener = new ProximityPacketListener(this); - - this.getServer().getPluginManager().registerEvents(new ProximityListener(this), this); } + Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { + System.out.println("OFC_PLAYER: " + OrebfuscatorPlayer.PLAYER_MAP.size()); + System.gc(); + }, 200, 200); + // Load packet listener this.obfuscationSystem.registerChunkListener(); @@ -110,9 +112,9 @@ public void onDisable() { this.obfuscationSystem.shutdown(); } - if (this.config != null && this.config.proximityEnabled() && this.proximityPacketListener != null && this.proximityHider != null) { + if (this.config != null && this.config.proximityEnabled() && this.proximityPacketListener != null && this.proximityThread != null) { this.proximityPacketListener.unregister(); - this.proximityHider.close(); + this.proximityThread.close(); } this.getServer().getScheduler().cancelTasks(this); @@ -150,10 +152,6 @@ public ObfuscationSystem getObfuscationSystem() { return obfuscationSystem; } - public ProximityHider getProximityHider() { - return this.proximityHider; - } - public ProximityPacketListener getProximityPacketListener() { return this.proximityPacketListener; } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java new file mode 100644 index 00000000..361d87f5 --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java @@ -0,0 +1,86 @@ +package net.imprex.orebfuscator; + +import java.lang.ref.WeakReference; +import java.util.Collections; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.BiPredicate; + +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import com.google.common.base.Objects; +import com.google.common.collect.MapMaker; + +import net.imprex.orebfuscator.util.BlockPos; +import net.imprex.orebfuscator.util.ChunkPosition; + +public class OrebfuscatorPlayer { + + public static final ConcurrentMap PLAYER_MAP = new MapMaker().weakKeys().makeMap(); + + public static OrebfuscatorPlayer get(Player player) { + OrebfuscatorPlayer playerData = PLAYER_MAP.computeIfAbsent(player, OrebfuscatorPlayer::new); + playerData.updateWorld(); + return playerData; + } + + private final WeakReference player; + + private final AtomicReference world = new AtomicReference<>(); + private final Map> chunks = new ConcurrentHashMap<>(); + + private volatile Location location = new Location(null, 0, 0, 0); + + public OrebfuscatorPlayer(Player player) { + this.player = new WeakReference(player); + } + + public boolean hasLocationChanged(BiPredicate equals) { + if (this.player.refersTo(null)) { + return false; + } + + Location location = this.player.get().getLocation(); + if (equals.test(this.location, location)) { + return false; + } + + this.location = location; + + return true; + } + + private void updateWorld() { + if (this.player.refersTo(null)) { + return; + } + + World world = this.player.get().getWorld(); + if (!Objects.equal(this.world.getAndSet(world), world)) { + this.chunks.clear(); + } + } + + public void addChunk(int chunkX, int chunkZ, Set blocks) { + long key = ChunkPosition.toLong(chunkX, chunkZ); + System.out.println("add: " + chunkX + " " + chunkZ + " " + blocks.size()); + this.chunks.computeIfAbsent(key, k -> { + return Collections.newSetFromMap(new ConcurrentHashMap<>()); + }).addAll(blocks); + } + + public Set getChunk(int chunkX, int chunkZ) { + long key = ChunkPosition.toLong(chunkX, chunkZ); + return this.chunks.getOrDefault(key, Collections.emptySet()); + } + + public void removeChunk(int chunkX, int chunkZ) { + long key = ChunkPosition.toLong(chunkX, chunkZ); + this.chunks.remove(key); + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/WorldMatcher.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/WorldMatcher.java deleted file mode 100644 index 6680a89a..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/WorldMatcher.java +++ /dev/null @@ -1,51 +0,0 @@ -package net.imprex.orebfuscator.config; - -import java.util.function.Predicate; -import java.util.regex.Pattern; - -public class WorldMatcher implements Predicate { - - public static WorldMatcher parseMatcher(String value) { - if (value.startsWith("regex:")) { - return new WorldMatcher(parseRegexMatcher(value.substring(6)), Type.REGEX); - } else { - return new WorldMatcher(parseWildcardMatcher(value), Type.WILDCARD); - } - } - - private static Pattern parseRegexMatcher(String pattern) { - return Pattern.compile(pattern); - } - - private static Pattern parseWildcardMatcher(String value) { - String pattern = ("\\Q" + value + "\\E").replace("*", "\\E.*\\Q"); - return Pattern.compile(pattern); - } - - private final Pattern pattern; - private final Type type; - - public WorldMatcher(Pattern pattern, Type type) { - this.pattern = pattern; - this.type = type; - } - - @Override - public boolean test(String value) { - return this.pattern.matcher(value).matches(); - } - - public String serialize() { - if (this.type == Type.REGEX) { - return "regex:" + this.pattern.pattern(); - } else { - return this.pattern.pattern() - .replace("\\E.*\\Q", "*") - .replaceAll("\\\\Q|\\\\E", ""); - } - } - - private enum Type { - REGEX, WILDCARD; - } -} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/DeobfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/DeobfuscationListener.java index af1e3308..9d842cea 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/DeobfuscationListener.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/DeobfuscationListener.java @@ -97,7 +97,7 @@ public void onPlayerInteract(PlayerInteractEvent event) { public void onJoin(PlayerJoinEvent event) { Player player = event.getPlayer(); - if (this.config.general().bypassNotification() && PermissionUtil.canDeobfuscate(player)) { + if (this.config.general().bypassNotification() && PermissionUtil.canBypassObfuscate(player)) { player.sendMessage( "[§bOrebfuscator§f]§7 You bypass Orebfuscator because you have the 'orebfuscator.bypass' permission."); } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java index 3e288959..a5f2d1be 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java @@ -2,17 +2,17 @@ import java.util.Set; -import org.bukkit.Bukkit; import org.bukkit.entity.Player; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketEvent; +import com.comphenix.protocol.events.PacketPostAdapter; import net.imprex.orebfuscator.Orebfuscator; +import net.imprex.orebfuscator.OrebfuscatorPlayer; import net.imprex.orebfuscator.chunk.ChunkStruct; import net.imprex.orebfuscator.config.OrebfuscatorConfig; -import net.imprex.orebfuscator.proximityhider.ProximityPlayerManager; import net.imprex.orebfuscator.util.BlockPos; import net.imprex.orebfuscator.util.OFCLogger; import net.imprex.orebfuscator.util.PermissionUtil; @@ -20,14 +20,12 @@ public abstract class ObfuscationListener extends PacketAdapter { private final OrebfuscatorConfig config; - private final ProximityPlayerManager proximityManager; private final ObfuscationSystem obfuscationSystem; public ObfuscationListener(Orebfuscator orebfuscator) { super(orebfuscator, PacketType.Play.Server.MAP_CHUNK); this.config = orebfuscator.getOrebfuscatorConfig(); - this.proximityManager = orebfuscator.getProximityHider().getPlayerManager(); this.obfuscationSystem = orebfuscator.getObfuscationSystem(); } @@ -55,6 +53,15 @@ public void onPacketSending(PacketEvent event) { this.preChunkProcessing(event); + event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { + + @Override + public void onPostEvent(PacketEvent event) { + System.out.println("post-1: " + struct.chunkX + " " + struct.chunkZ); + } + + }); + this.obfuscationSystem.obfuscate(struct).whenComplete((chunk, throwable) -> { if (throwable != null) { this.completeExceptionally(event, struct, throwable); @@ -69,7 +76,7 @@ public void onPacketSending(PacketEvent event) { } private boolean shouldNotObfuscate(Player player) { - return PermissionUtil.canDeobfuscate(player) || !config.world(player.getWorld()).needsObfuscation(); + return PermissionUtil.canBypassObfuscate(player) || !config.world(player.getWorld()).needsObfuscation(); } private void completeExceptionally(PacketEvent event, ChunkStruct struct, Throwable throwable) { @@ -86,12 +93,19 @@ private void complete(PacketEvent event, ChunkStruct struct, ObfuscationResult c struct.removeBlockEntityIf(blockEntities::contains); } - Player player = event.getPlayer(); - this.proximityManager.addAndLockChunk(player, struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); + final OrebfuscatorPlayer player = OrebfuscatorPlayer.get(event.getPlayer()); - Bukkit.getScheduler().runTask(this.plugin, () -> { - this.postChunkProcessing(event); - this.proximityManager.unlockChunk(player, struct.chunkX, struct.chunkZ); + event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { + + @Override + public void onPostEvent(PacketEvent event) { + System.out.println("post-2: " + struct.chunkX + " " + struct.chunkZ); + player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); + } + }); +// player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); + + this.postChunkProcessing(event); } } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java new file mode 100644 index 00000000..cded255e --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -0,0 +1,143 @@ +package net.imprex.orebfuscator.proximityhider; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import net.imprex.orebfuscator.Orebfuscator; + +public class ProximityDirectorThread extends Thread { + + private final CyclicBarrier cyclicBarrier; + private volatile boolean running = true; + + private final int workerCount; + private final Queue> bucketQueue = new LinkedList<>(); + + private final Lock bucketLock = new ReentrantLock(); + private final Condition nextBucket = bucketLock.newCondition(); + + private final ProximityWorker worker; + private final ProximityWorkerThread[] workerThreads; + + public ProximityDirectorThread(Orebfuscator orebfuscator) { + super(Orebfuscator.THREAD_GROUP, "ofc-proximity-director"); + + this.workerCount = 1;//orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); + this.cyclicBarrier = new CyclicBarrier(this.workerCount); + + this.worker = new ProximityWorker(orebfuscator); + this.workerThreads = new ProximityWorkerThread[workerCount - 1]; + } + + @Override + public void start() { + super.start(); + + for (int i = 0; i < workerCount - 1; i++) { + this.workerThreads[i] = new ProximityWorkerThread(this, this.worker); + this.workerThreads[i].start(); + } + } + + public void close() { + this.running = false; + + this.interrupt(); + for (int i = 0; i < workerCount - 1; i++) { + this.workerThreads[i].interrupt(); + } + } + + boolean isRunning() { + return this.running; + } + + List getBucket() throws InterruptedException { + this.bucketLock.lock(); + try { + this.nextBucket.await(); + return bucketQueue.poll(); + } finally { + this.bucketLock.unlock(); + } + } + + void awaitNextExecution() throws InterruptedException, BrokenBarrierException { + this.cyclicBarrier.await(); + } + + @Override + public void run() { + while (this.isRunning()) { + try { + Collection players = Bukkit.getOnlinePlayers(); + Iterator iterator = players.iterator(); + + int playerCount = players.size(); + int bucketCount = Math.min((int) Math.ceil((float) playerCount / 50f), this.workerCount); + int bucketSize = (int) Math.ceil((float) playerCount / (float) bucketCount); + + List localBucket = null; + + this.bucketLock.lock(); + try { + // refill buckets + for (int index = 0; index < bucketCount; index++) { + List bucket = new ArrayList<>(); + + for (int size = 0; size < bucketSize && iterator.hasNext(); size++) { + bucket.add(iterator.next()); + } + + this.bucketQueue.offer(bucket); + } + + System.out.println("buckets: " + this.bucketQueue); + + // get own bucket + localBucket = this.bucketQueue.poll(); + + // wake up enough threads for the amount of created buckets + for (int i = 0; i < bucketCount - 1; i++) { + this.nextBucket.signal(); + } + } finally { + this.bucketLock.unlock(); + } + + // process local bucket + if (localBucket != null) { + for (Player player : localBucket) { + this.worker.process(player); + } + } + + // wait for all threads to finish and reset barrier + this.awaitNextExecution(); + this.cyclicBarrier.reset(); + + // sleep till next execution + Thread.sleep(1000L); + } catch (InterruptedException e) { + continue; + } catch (BrokenBarrierException e) { + e.printStackTrace(); + break; + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityHider.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityHider.java deleted file mode 100644 index 987608b9..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityHider.java +++ /dev/null @@ -1,85 +0,0 @@ -package net.imprex.orebfuscator.proximityhider; - -import java.util.concurrent.atomic.AtomicBoolean; - -import org.bukkit.GameMode; -import org.bukkit.entity.Player; - -import net.imprex.orebfuscator.Orebfuscator; -import net.imprex.orebfuscator.config.OrebfuscatorConfig; -import net.imprex.orebfuscator.config.ProximityConfig; - -public class ProximityHider { - - private final Orebfuscator orebfuscator; - private final OrebfuscatorConfig config; - - private final ProximityPlayerManager dataManager = new ProximityPlayerManager(this); - private final ProximityQueue queue = new ProximityQueue(); - - private final AtomicBoolean running = new AtomicBoolean(); - private final ProximityThread[] queueThreads; - - public ProximityHider(Orebfuscator orebfuscator) { - this.orebfuscator = orebfuscator; - this.config = this.orebfuscator.getOrebfuscatorConfig(); - - this.queueThreads = new ProximityThread[this.config.advanced().proximityHiderThreads()]; - } - - public ProximityPlayerManager getPlayerManager() { - return dataManager; - } - - ProximityQueue getQueue() { - return queue; - } - - public boolean isInProximityWorld(Player player) { - ProximityConfig proximityConfig = this.config.world(player.getWorld()).proximity(); - return proximityConfig != null && proximityConfig.isEnabled(); - } - - public boolean shouldIgnorePlayer(Player player) { - return player.getGameMode() == GameMode.SPECTATOR && this.config.general().ignoreSpectator(); - } - - public void queuePlayerUpdate(Player player) { - if (this.isInProximityWorld(player) && !shouldIgnorePlayer(player)) { - this.queue.offerAndLock(player); - } - } - - public void removePlayer(Player player) { - this.queue.remove(player); - this.dataManager.remove(player); - } - - public void start() { - if (!this.running.compareAndSet(false, true)) { - throw new IllegalStateException("proximity hider already running"); - } - - for (int i = 0; i < this.queueThreads.length; i++) { - ProximityThread thread = new ProximityThread(this, this.orebfuscator); - thread.setDaemon(true); - thread.start(); - this.queueThreads[i] = thread; - } - } - - public void close() { - if (!this.running.compareAndSet(true, false)) { - throw new IllegalStateException("proximity hider isn't running"); - } - - this.queue.clear(); - this.dataManager.clear(); - - for (ProximityThread thread : this.queueThreads) { - if (thread != null) { - thread.close(); - } - } - } -} \ No newline at end of file diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityListener.java deleted file mode 100644 index 0ad753e5..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityListener.java +++ /dev/null @@ -1,56 +0,0 @@ -package net.imprex.orebfuscator.proximityhider; - -import org.bukkit.event.EventHandler; -import org.bukkit.event.Listener; -import org.bukkit.event.block.BlockBreakEvent; -import org.bukkit.event.player.PlayerChangedWorldEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.player.PlayerTeleportEvent; - -import net.imprex.orebfuscator.Orebfuscator; - -public class ProximityListener implements Listener { - - private ProximityHider proximityHider; - - public ProximityListener(Orebfuscator orebfuscator) { - this.proximityHider = orebfuscator.getProximityHider(); - } - - @EventHandler - public void onPlayerJoin(PlayerJoinEvent event) { - this.proximityHider.queuePlayerUpdate(event.getPlayer()); - } - - @EventHandler - public void onPlayerQuit(PlayerQuitEvent event) { - this.proximityHider.removePlayer(event.getPlayer()); - } - - @EventHandler - public void onPlayerChangedWorld(PlayerChangedWorldEvent event) { - this.proximityHider.queuePlayerUpdate(event.getPlayer()); - } - - @EventHandler - public void onPlayerTeleport(PlayerTeleportEvent event) { - // already called in PlayerChangedWorldEvent event - if (!event.getFrom().getWorld().equals(event.getTo().getWorld())) { - return; - } - - this.proximityHider.queuePlayerUpdate(event.getPlayer()); - } - - @EventHandler - public void onPlayerMove(PlayerMoveEvent event) { - this.proximityHider.queuePlayerUpdate(event.getPlayer()); - } - - @EventHandler - public void onBlockBreak(BlockBreakEvent event) { - this.proximityHider.queuePlayerUpdate(event.getPlayer()); - } -} \ No newline at end of file diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java index 21eaa04a..75d8b9c9 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java @@ -11,6 +11,7 @@ import com.comphenix.protocol.reflect.StructureModifier; import net.imprex.orebfuscator.Orebfuscator; +import net.imprex.orebfuscator.OrebfuscatorPlayer; import net.imprex.orebfuscator.config.OrebfuscatorConfig; import net.imprex.orebfuscator.config.ProximityConfig; import net.imprex.orebfuscator.util.PermissionUtil; @@ -21,8 +22,6 @@ public class ProximityPacketListener extends PacketAdapter { private final OrebfuscatorConfig config; - private final ProximityPlayerManager playerManager; - public ProximityPacketListener(Orebfuscator orebfuscator) { super(orebfuscator, PacketType.Play.Server.UNLOAD_CHUNK); @@ -30,7 +29,6 @@ public ProximityPacketListener(Orebfuscator orebfuscator) { this.protocolManager.addPacketListener(this); this.config = orebfuscator.getOrebfuscatorConfig(); - this.playerManager = orebfuscator.getProximityHider().getPlayerManager(); } public void unregister() { @@ -40,7 +38,7 @@ public void unregister() { @Override public void onPacketSending(PacketEvent event) { Player player = event.getPlayer(); - if (PermissionUtil.canDeobfuscate(player)) { + if (PermissionUtil.canBypassObfuscate(player)) { return; } @@ -51,6 +49,6 @@ public void onPacketSending(PacketEvent event) { } StructureModifier ints = event.getPacket().getIntegers(); - this.playerManager.removeChunk(player, ints.read(0), ints.read(1)); + OrebfuscatorPlayer.get(player).removeChunk(ints.read(0), ints.read(1)); } } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayer.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayer.java deleted file mode 100644 index 91dd5d19..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayer.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.imprex.orebfuscator.proximityhider; - -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.bukkit.World; -import org.bukkit.entity.Player; - -import net.imprex.orebfuscator.util.BlockPos; -import net.imprex.orebfuscator.util.ChunkPosition; - -public class ProximityPlayer { - - private final Map> chunks = new ConcurrentHashMap<>(); - private final Set lockedChunks = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - private final Lock lock = new ReentrantLock(); - private World world; - - public ProximityPlayer(Player player) { - this.world = player.getWorld(); - } - - public World getWorld() { - this.lock.lock(); - try { - return this.world; - } finally { - this.lock.unlock(); - } - } - - public void setWorld(World world) { - this.lock.lock(); - try { - if (this.world != world) { - this.world = world; - this.chunks.clear(); - this.lockedChunks.clear(); - } - } finally { - this.lock.unlock(); - } - } - - public void unlockChunk(int chunkX, int chunkZ) { - this.lockedChunks.remove(ChunkPosition.toLong(chunkX, chunkZ)); - } - - public void addAndLockChunk(int chunkX, int chunkZ, Set blocks) { - long key = ChunkPosition.toLong(chunkX, chunkZ); - this.chunks.computeIfAbsent(key, k -> { - return Collections.newSetFromMap(new ConcurrentHashMap<>()); - }).addAll(blocks); - this.lockedChunks.add(key); - } - - public void addChunk(int chunkX, int chunkZ, Set blocks) { - long key = ChunkPosition.toLong(chunkX, chunkZ); - this.chunks.computeIfAbsent(key, k -> { - return Collections.newSetFromMap(new ConcurrentHashMap<>()); - }).addAll(blocks); - } - - public Set getChunk(int chunkX, int chunkZ) { - long key = ChunkPosition.toLong(chunkX, chunkZ); - if (this.lockedChunks.contains(key)) { - return null; - } - return this.chunks.get(key); - } - - public void removeChunk(int chunkX, int chunkZ) { - long key = ChunkPosition.toLong(chunkX, chunkZ); - this.chunks.remove(key); - this.lockedChunks.remove(key); - } -} \ No newline at end of file diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayerManager.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayerManager.java deleted file mode 100644 index 7cab6f4f..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPlayerManager.java +++ /dev/null @@ -1,102 +0,0 @@ -package net.imprex.orebfuscator.proximityhider; - -import java.util.Map; -import java.util.Set; -import java.util.WeakHashMap; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -import org.bukkit.entity.Player; - -import net.imprex.orebfuscator.util.BlockPos; - -public class ProximityPlayerManager { - - private final ReadWriteLock lock = new ReentrantReadWriteLock(true); - private final Map proximityData = new WeakHashMap<>(); - - private final ProximityHider proximityHider; - - public ProximityPlayerManager(ProximityHider proximityHider) { - this.proximityHider = proximityHider; - } - - private ProximityPlayer getOrCreate(Player player) { - this.lock.readLock().lock(); - try { - ProximityPlayer data = this.proximityData.get(player); - if (data != null) { - return data; - } - } finally { - this.lock.readLock().unlock(); - } - - ProximityPlayer data = new ProximityPlayer(player); - this.lock.writeLock().lock(); - try { - this.proximityData.putIfAbsent(player, data); - return this.proximityData.get(player); - } finally { - this.lock.writeLock().unlock(); - } - } - - ProximityPlayer get(Player player) { - ProximityPlayer data = this.getOrCreate(player); - data.setWorld(player.getWorld()); - return data; - } - - public void remove(Player player) { - this.lock.writeLock().lock(); - try { - this.proximityData.remove(player); - } finally { - this.lock.writeLock().unlock(); - } - } - - public void addAndLockChunk(Player player, int chunkX, int chunkZ, Set blocks) { - if (this.proximityHider.isInProximityWorld(player)) { - ProximityPlayer data = this.get(player); - if (blocks.isEmpty()) { - data.removeChunk(chunkX, chunkZ); - } else { - data.addAndLockChunk(chunkX, chunkZ, blocks); - } - } - } - - public void addChunk(Player player, int chunkX, int chunkZ, Set blocks) { - if (this.proximityHider.isInProximityWorld(player)) { - ProximityPlayer data = this.get(player); - if (blocks.isEmpty()) { - data.removeChunk(chunkX, chunkZ); - } else { - data.addChunk(chunkX, chunkZ, blocks); - } - } - } - - public void unlockChunk(Player player, int chunkX, int chunkZ) { - if (this.proximityHider.isInProximityWorld(player)) { - this.get(player).unlockChunk(chunkX, chunkZ); - } - } - - public void removeChunk(Player player, int chunkX, int chunkZ) { - if (this.proximityHider.isInProximityWorld(player)) { - this.get(player).removeChunk(chunkX, chunkZ); - } - } - - public void clear() { - this.lock.writeLock().lock(); - try { - this.proximityData.clear(); - } finally { - this.lock.writeLock().unlock(); - } - } -} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityQueue.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityQueue.java deleted file mode 100644 index 392c280b..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityQueue.java +++ /dev/null @@ -1,80 +0,0 @@ -package net.imprex.orebfuscator.proximityhider; - -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Objects; -import java.util.Queue; -import java.util.Set; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - -import org.bukkit.entity.Player; - -public class ProximityQueue { - - private final Lock lock = new ReentrantLock(); - private final Condition notEmpty = lock.newCondition(); - - private final Queue queue = new LinkedList<>(); - private final Set lockedPlayer = new HashSet<>(); - - public void offerAndLock(Player player) { - Objects.requireNonNull(player); - - lock.lock(); - try { - if (this.lockedPlayer.add(player)) { - boolean empty = this.queue.isEmpty(); - this.queue.offer(player); - if (empty) { - this.notEmpty.signal(); - } - } - } finally { - lock.unlock(); - } - } - - public Player poll() throws InterruptedException { - lock.lock(); - try { - if (this.queue.isEmpty()) { - this.notEmpty.await(); - } - return this.queue.poll(); - } finally { - lock.unlock(); - } - } - - public void unlock(Player player) { - lock.lock(); - try { - this.lockedPlayer.remove(player); - } finally { - lock.unlock(); - } - } - - public void remove(Player player) { - lock.lock(); - try { - if (this.lockedPlayer.remove(player)) { - this.queue.remove(player); - } - } finally { - lock.unlock(); - } - } - - public void clear() { - lock.lock(); - try { - this.lockedPlayer.clear(); - this.queue.clear(); - } finally { - lock.unlock(); - } - } -} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityThread.java deleted file mode 100644 index 72a69abf..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityThread.java +++ /dev/null @@ -1,120 +0,0 @@ -package net.imprex.orebfuscator.proximityhider; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; - -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.entity.Player; - -import net.imprex.orebfuscator.NmsInstance; -import net.imprex.orebfuscator.Orebfuscator; -import net.imprex.orebfuscator.config.OrebfuscatorConfig; -import net.imprex.orebfuscator.config.ProximityConfig; -import net.imprex.orebfuscator.util.BlockPos; -import net.imprex.orebfuscator.util.MathUtil; - -public class ProximityThread extends Thread { - - private static final AtomicInteger NEXT_ID = new AtomicInteger(); - - private final Orebfuscator orebfuscator; - private final OrebfuscatorConfig config; - - private final ProximityQueue proximityQueue; - private final ProximityPlayerManager dataManager; - - private final AtomicBoolean running = new AtomicBoolean(true); - - public ProximityThread(ProximityHider proximityHider, Orebfuscator orebfuscator) { - super(Orebfuscator.THREAD_GROUP, "ofc-proximity-hider-" + NEXT_ID.getAndIncrement()); - this.dataManager = proximityHider.getPlayerManager(); - this.proximityQueue = proximityHider.getQueue(); - this.orebfuscator = orebfuscator; - this.config = orebfuscator.getOrebfuscatorConfig(); - } - - @Override - public void run() { - while (this.running.get()) { - try { - Player player = this.proximityQueue.poll(); - try { - if (player == null || !player.isOnline()) { - continue; - } - - Location location = player.getLocation(); - World world = location.getWorld(); - - ProximityConfig proximityConfig = this.config.world(world).proximity(); - ProximityPlayer proximityPlayer = this.dataManager.get(player); - if (proximityPlayer == null || proximityConfig == null || !proximityConfig.isEnabled() || !proximityPlayer.getWorld().equals(world)) { - continue; - } - - int distance = proximityConfig.distance(); - int distanceSquared = distance * distance; - - List updateBlocks = new ArrayList<>(); - Location eyeLocation = player.getEyeLocation(); - - int minChunkX = (location.getBlockX() - distance) >> 4; - int maxChunkX = (location.getBlockX() + distance) >> 4; - int minChunkZ = (location.getBlockZ() - distance) >> 4; - int maxChunkZ = (location.getBlockZ() + distance) >> 4; - - for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ++) { - for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX++) { - Set blocks = proximityPlayer.getChunk(chunkX, chunkZ); - - if (blocks == null) { - continue; - } - - for (Iterator iterator = blocks.iterator(); iterator.hasNext(); ) { - BlockPos blockCoords = iterator.next(); - Location blockLocation = new Location(world, blockCoords.x, blockCoords.y, blockCoords.z); - - if (location.distanceSquared(blockLocation) < distanceSquared) { - if (!proximityConfig.useFastGazeCheck() || MathUtil.doFastCheck(blockLocation, eyeLocation, world)) { - iterator.remove(); - updateBlocks.add(blockCoords); - } - } - } - - if (blocks.isEmpty()) { - proximityPlayer.removeChunk(chunkX, chunkZ); - } - } - } - - Bukkit.getScheduler().runTask(this.orebfuscator, () -> { - if (player.isOnline()) { - for (BlockPos blockCoords : updateBlocks) { - NmsInstance.sendBlockChange(player, blockCoords); - } - } - }); - } finally { - this.proximityQueue.unlock(player); - } - } catch (InterruptedException e) { - break; - } catch (Exception e) { - e.printStackTrace(); - } - } - } - - public void close() { - this.running.set(false); - this.interrupt(); - } -} \ No newline at end of file diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java new file mode 100644 index 00000000..8481df7b --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java @@ -0,0 +1,133 @@ +package net.imprex.orebfuscator.proximityhider; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.entity.Player; + +import com.google.common.base.Objects; + +import net.imprex.orebfuscator.NmsInstance; +import net.imprex.orebfuscator.Orebfuscator; +import net.imprex.orebfuscator.OrebfuscatorPlayer; +import net.imprex.orebfuscator.config.OrebfuscatorConfig; +import net.imprex.orebfuscator.config.ProximityConfig; +import net.imprex.orebfuscator.util.BlockPos; +import net.imprex.orebfuscator.util.MathUtil; +import net.imprex.orebfuscator.util.PermissionUtil; + +public class ProximityWorker { + + private final Orebfuscator orebfuscator; + private final OrebfuscatorConfig config; + + public ProximityWorker(Orebfuscator orebfuscator) { + this.orebfuscator = orebfuscator; + this.config = orebfuscator.getOrebfuscatorConfig(); + } + + private boolean shouldIgnorePlayer(Player player) { + if (PermissionUtil.canBypassObfuscate(player)) { + return true; + } + + return player.getGameMode() == GameMode.SPECTATOR && this.config.general().ignoreSpectator(); + } + + private boolean isLocationSimilar(boolean rotation, Location a, Location b) { + // check if world changed + if (!Objects.equal(a.getWorld(), b.getWorld())) { + return false; + } + + // check if len(xyz) changed less then 0.5 blocks + if (a.distanceSquared(b) > 0.25) { + return false; + } + + // check if rotation changed less then 10deg yaw or 5deg pitch + if (rotation && (Math.abs(a.getYaw() - b.getYaw()) > 10 || Math.abs(a.getPitch() - b.getPitch()) > 5)) { + return false; + } + + return true; + } + + protected void process(Player player) { + if (this.shouldIgnorePlayer(player)) { + System.out.println("ignored: " + player); + return; + } + + World world = player.getWorld(); + + // check if world has enabled proximity config + ProximityConfig proximityConfig = this.config.world(world).proximity(); + if (proximityConfig == null || !proximityConfig.isEnabled()) { + System.out.println("no_config: " + player); + return; + } + + // check if player changed location since last time + OrebfuscatorPlayer orebfuscatorPlayer = OrebfuscatorPlayer.get(player); + if (!orebfuscatorPlayer.hasLocationChanged((a, b) -> isLocationSimilar(proximityConfig.useFastGazeCheck(), a, b))) { + System.out.println("no_change: " + player); + return; + } + + int distance = proximityConfig.distance(); + int distanceSquared = distance * distance; + + List updateBlocks = new ArrayList<>(); + Location eyeLocation = proximityConfig.useFastGazeCheck() + ? player.getEyeLocation() + : null; + + Location location = player.getLocation(); + int minChunkX = (location.getBlockX() - distance) >> 4; + int maxChunkX = (location.getBlockX() + distance) >> 4; + int minChunkZ = (location.getBlockZ() - distance) >> 4; + int maxChunkZ = (location.getBlockZ() + distance) >> 4; + + for (int chunkZ = minChunkZ; chunkZ <= maxChunkZ; chunkZ++) { + for (int chunkX = minChunkX; chunkX <= maxChunkX; chunkX++) { + + Set blocks = orebfuscatorPlayer.getChunk(chunkX, chunkZ); + if (blocks == null) { + continue; + } + + for (Iterator iterator = blocks.iterator(); iterator.hasNext(); ) { + BlockPos blockCoords = iterator.next(); + Location blockLocation = new Location(world, blockCoords.x, blockCoords.y, blockCoords.z); + + if (location.distanceSquared(blockLocation) < distanceSquared) { + if (!proximityConfig.useFastGazeCheck() || MathUtil.doFastCheck(blockLocation, eyeLocation, world)) { + iterator.remove(); + updateBlocks.add(blockCoords); + } + } + } + + if (blocks.isEmpty()) { + orebfuscatorPlayer.removeChunk(chunkX, chunkZ); + } + } + } + + Bukkit.getScheduler().runTask(this.orebfuscator, () -> { + if (player.isOnline()) { + player.sendMessage("updated: " + updateBlocks.size()); + for (BlockPos blockCoords : updateBlocks) { + NmsInstance.sendBlockChange(player, blockCoords); + } + } + }); + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java new file mode 100644 index 00000000..ff20d72c --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java @@ -0,0 +1,46 @@ +package net.imprex.orebfuscator.proximityhider; + +import java.util.List; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.atomic.AtomicInteger; + +import org.bukkit.entity.Player; + +import net.imprex.orebfuscator.Orebfuscator; + +public class ProximityWorkerThread extends Thread { + + private static final AtomicInteger NEXT_ID = new AtomicInteger(); + + private final ProximityDirectorThread directorThread; + private final ProximityWorker worker; + + public ProximityWorkerThread(ProximityDirectorThread directorThread, ProximityWorker worker) { + super(Orebfuscator.THREAD_GROUP, "ofc-proximity-worker-" + NEXT_ID.getAndIncrement()); + + this.directorThread = directorThread; + this.worker = worker; + } + + @Override + public void run() { + while (this.directorThread.isRunning()) { + try { + List bucket = this.directorThread.getBucket(); + + for (Player player : bucket) { + this.worker.process(player); + } + + this.directorThread.awaitNextExecution(); + } catch (InterruptedException e) { + continue; + } catch (BrokenBarrierException e) { + e.printStackTrace(); + break; + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/PermissionUtil.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/PermissionUtil.java index d3c79674..19e6d296 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/PermissionUtil.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/util/PermissionUtil.java @@ -4,7 +4,7 @@ public class PermissionUtil { - public static boolean canDeobfuscate(Permissible permissible) { + public static boolean canBypassObfuscate(Permissible permissible) { try { return permissible.hasPermission("orebfuscator.bypass"); } catch (UnsupportedOperationException e) { diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.19.yml b/orebfuscator-plugin/src/main/resources/config/config-1.19.yml index 6d98df5d..e015c5a4 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.19.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.19.yml @@ -21,6 +21,18 @@ cache: maximumSize: 16384 expireAfterAccess: 60000 maximumTaskQueueSize: 32768 +seed-obfuscation: + enabled: false + worlds: + world: + enabled: true + hash: -56238923789 + world_nether: + enabled: true + hash: -56238923789 + world_the_end: + enabled: true + hash: -56238923789 obfuscation: obfuscation-overworld: enabled: true diff --git a/pom.xml b/pom.xml index 3a2460ff..83cc7aed 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,7 @@ 3.0.2 5.9.2 4.1.68.Final - 5.0.0-SNAPSHOT + 5.0.0 3.11.0 3.4.1 From 089f15b168657e23ae61f578cbaa6c2c96c7b34a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Mon, 5 Jun 2023 15:42:14 +0200 Subject: [PATCH 03/12] feat: wip - test phaser design --- .../ProximityDirectorThread.java | 108 ++++++++++++++++-- 1 file changed, 100 insertions(+), 8 deletions(-) diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java index cded255e..fa03f28b 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -1,5 +1,6 @@ package net.imprex.orebfuscator.proximityhider; +import java.time.LocalTime; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; @@ -7,10 +8,13 @@ import java.util.List; import java.util.Queue; import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Phaser; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.stream.IntStream; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -19,6 +23,7 @@ public class ProximityDirectorThread extends Thread { + private final Phaser phaser = new Phaser(1); private final CyclicBarrier cyclicBarrier; private volatile boolean running = true; @@ -34,7 +39,7 @@ public class ProximityDirectorThread extends Thread { public ProximityDirectorThread(Orebfuscator orebfuscator) { super(Orebfuscator.THREAD_GROUP, "ofc-proximity-director"); - this.workerCount = 1;//orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); + this.workerCount = 1;// orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); this.cyclicBarrier = new CyclicBarrier(this.workerCount); this.worker = new ProximityWorker(orebfuscator); @@ -64,14 +69,101 @@ boolean isRunning() { return this.running; } + public static void main(String[] args) { + final Phaser phaser = new Phaser(1) { + @Override + protected boolean onAdvance(int phase, int registeredParties) { + System.out.println("onAdvance: " + phase + " " + registeredParties + " " + Thread.currentThread().getName()); + if (registeredParties == 0) { + new Exception().printStackTrace(); + } + return registeredParties == 0; + } + }; + + final Lock bucketLock = new ReentrantLock(); + final Condition nextBucket = bucketLock.newCondition(); + + final Queue queue = new ConcurrentLinkedQueue<>(); + final int workerCount = Runtime.getRuntime().availableProcessors(); + + IntStream.range(0, workerCount).forEach(index -> { + new Thread(() -> { + while (!phaser.isTerminated()) { + try { + String element; + + bucketLock.lock(); + try { + nextBucket.await(); + element = queue.poll(); + } finally { + bucketLock.unlock(); + } + + System.out.println(Thread.currentThread().getName() + ": " + element); + + phaser.arriveAndDeregister(); + } catch (InterruptedException e) { + break; + } + } + }, "wroker-" + index).start(); + }); + + while (!phaser.isTerminated()) { + try { + int bucketCount = (int) Math.round(Math.random() * workerCount); + if (bucketCount == 0) { + continue; + } + + String element; + + bucketLock.lock(); + try { + for (int i = 0; i < bucketCount; i++) { + queue.offer("element " + i + " in phase " + (phaser.getPhase() + 1)); + } + } finally { + bucketLock.unlock(); + } + + phaser.arriveAndAwaitAdvance(); + + Thread.sleep(1L); + + if (bucketCount > 1) { + phaser.bulkRegister(bucketCount - 1); + } + System.out.println(String.format("bucketCount: %s, phase: %s, registed: %s, arrived: %s, queue: %s, time: %s", bucketCount, + phaser.getPhase(), phaser.getRegisteredParties(), phaser.getArrivedParties(), queue.size(), LocalTime.now().toString())); + + bucketLock.lock(); + try { + element = queue.poll(); + for (int i = 0; i < bucketCount - 1; i++) { + nextBucket.signal(); + } + } finally { + bucketLock.unlock(); + } + + System.out.println(Thread.currentThread().getName() + ": " + element); + } catch (Exception e) { + break; + } + } + } + List getBucket() throws InterruptedException { - this.bucketLock.lock(); - try { - this.nextBucket.await(); - return bucketQueue.poll(); - } finally { - this.bucketLock.unlock(); + List bucket; + + while ((bucket = this.bucketQueue.poll()) == null) { + this.phaser.awaitAdvance(this.phaser.arriveAndDeregister()); } + + return bucket; } void awaitNextExecution() throws InterruptedException, BrokenBarrierException { @@ -90,7 +182,7 @@ public void run() { int bucketSize = (int) Math.ceil((float) playerCount / (float) bucketCount); List localBucket = null; - + this.bucketLock.lock(); try { // refill buckets From 282f3843611316beb27dd6c77f7dae12dca1720f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Wed, 7 Jun 2023 20:00:32 +0200 Subject: [PATCH 04/12] feat: wip - proximity rework --- .../obfuscation/SeedObfuscationListener.java | 32 +++++++ .../obfuscation/SeedObfuscationStrategy.java | 92 +++++++++++++++++++ .../ProximityDirectorThread.java | 40 ++++++-- 3 files changed, 155 insertions(+), 9 deletions(-) create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java new file mode 100644 index 00000000..b27ed58f --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java @@ -0,0 +1,32 @@ +package net.imprex.orebfuscator.obfuscation; + +import java.nio.ByteBuffer; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.ProtocolManager; +import com.comphenix.protocol.events.PacketAdapter; +import com.comphenix.protocol.events.PacketEvent; + +import net.imprex.orebfuscator.Orebfuscator; + +public class SeedObfuscationListener extends PacketAdapter { + + private final long hash; + + public SeedObfuscationListener(Orebfuscator orebfuscator) { + super(orebfuscator, PacketType.Play.Server.LOGIN, PacketType.Play.Server.RESPAWN); + + + ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); + protocolManager.addPacketListener(this); + + ByteBuffer buffer = ByteBuffer.wrap(orebfuscator.getOrebfuscatorConfig().systemHash()); + this.hash = buffer.getLong(0); + } + + @Override + public void onPacketSending(PacketEvent event) { + event.setPacket(SeedObfuscationStrategy.obfuscate(event.getPacket(), hash)); + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java new file mode 100644 index 00000000..d161bcbc --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java @@ -0,0 +1,92 @@ +package net.imprex.orebfuscator.obfuscation; + +import java.lang.reflect.RecordComponent; +import java.util.Arrays; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.events.PacketContainer; +import com.comphenix.protocol.reflect.accessors.Accessors; +import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; +import com.comphenix.protocol.reflect.accessors.FieldAccessor; + +@FunctionalInterface +public interface SeedObfuscationStrategy { + + static final SeedObfuscationStrategy NOOP = (packet, hash) -> packet; + static final SeedObfuscationStrategy DYNAMIC_LOGIN = createDynamicFor(PacketType.Play.Server.LOGIN); + static final SeedObfuscationStrategy DYNAMIC_RESPAWN = createDynamicFor(PacketType.Play.Server.RESPAWN); + + static PacketContainer obfuscate(PacketContainer packet, long hash) { + if (packet.getType() == PacketType.Play.Server.LOGIN) { + return DYNAMIC_LOGIN.process(packet, hash); + } else if (packet.getType() == PacketType.Play.Server.RESPAWN) { + return DYNAMIC_RESPAWN.process(packet, hash); + } + return packet; + } + + static SeedObfuscationStrategy createDynamicFor(PacketType packetType) { + if (packetType != PacketType.Play.Server.LOGIN || packetType != PacketType.Play.Server.RESPAWN) { + throw new IllegalArgumentException("unsupported packet type: " + packetType); + } + + final Class packetClass = packetType.getPacketClass(); + + if (packetClass.isRecord()) { + final RecordComponent[] components = packetClass.getRecordComponents(); + final Class[] componentClasses = new Class[components.length]; + + int longIndex = -1; + for (int i = 0; i < components.length; i++) { + Class componentClass = components[i].getType(); + + if (longIndex == -1 && componentClass == long.class) { + longIndex = i; + } + + componentClasses[i] = componentClass; + } + + final int hashIndex = longIndex; + if (hashIndex == -1) { + return NOOP; + } + + final ConstructorAccessor constructorAccessor = Accessors.getConstructorAccessor( + packetClass, componentClasses); + + final FieldAccessor[] fieldAccessors = Arrays.stream(packetClass.getDeclaredFields()) + .map(Accessors::getFieldAccessor) + .toArray(FieldAccessor[]::new); + + return (packet, hash) -> { + Object handle = packet.getHandle(); + Object[] arguments = new Object[components.length]; + + for (int i = 0; i < components.length; i++) { + if (hashIndex == i) { + arguments[i] = hash; + } else { + arguments[i] = fieldAccessors[i].get(handle); + } + } + + handle = constructorAccessor.invoke(arguments); + return new PacketContainer(packetType, handle); + }; + } else { + try { + Accessors.getFieldAccessor(packetClass, long.class, true); + } catch (Exception e) { + return NOOP; + } + + return (packet, hash) -> { + packet.getLongs().write(0, hash); + return packet; + }; + } + } + + PacketContainer process(PacketContainer packet, long hash); +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java index fa03f28b..61cffd1a 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -10,10 +10,12 @@ import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.Executors; import java.util.concurrent.Phaser; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.IntUnaryOperator; import java.util.stream.IntStream; import org.bukkit.Bukkit; @@ -42,6 +44,8 @@ public ProximityDirectorThread(Orebfuscator orebfuscator) { this.workerCount = 1;// orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); this.cyclicBarrier = new CyclicBarrier(this.workerCount); + Executors.newFixedThreadPool(1).execute(null); + this.worker = new ProximityWorker(orebfuscator); this.workerThreads = new ProximityWorkerThread[workerCount - 1]; } @@ -81,12 +85,26 @@ protected boolean onAdvance(int phase, int registeredParties) { } }; - final Lock bucketLock = new ReentrantLock(); + final Lock bucketLock = new ReentrantLock(true); final Condition nextBucket = bucketLock.newCondition(); final Queue queue = new ConcurrentLinkedQueue<>(); final int workerCount = Runtime.getRuntime().availableProcessors(); + final int fibonacciCount = 36; + IntUnaryOperator fibonacci = new IntUnaryOperator() { + + @Override + public int applyAsInt(int operand) { + if(operand == 0) + return 0; + else if(operand == 1) + return 1; + else + return applyAsInt(operand - 1) + applyAsInt(operand - 2); + } + }; + IntStream.range(0, workerCount).forEach(index -> { new Thread(() -> { while (!phaser.isTerminated()) { @@ -95,12 +113,14 @@ protected boolean onAdvance(int phase, int registeredParties) { bucketLock.lock(); try { - nextBucket.await(); - element = queue.poll(); + while ((element = queue.poll()) == null) { + nextBucket.await(); + } } finally { bucketLock.unlock(); } + fibonacci.applyAsInt(fibonacciCount); System.out.println(Thread.currentThread().getName() + ": " + element); phaser.arriveAndDeregister(); @@ -113,7 +133,7 @@ protected boolean onAdvance(int phase, int registeredParties) { while (!phaser.isTerminated()) { try { - int bucketCount = (int) Math.round(Math.random() * workerCount); + int bucketCount = (int) Math.round(Math.random() * workerCount * 4); if (bucketCount == 0) { continue; } @@ -129,10 +149,6 @@ protected boolean onAdvance(int phase, int registeredParties) { bucketLock.unlock(); } - phaser.arriveAndAwaitAdvance(); - - Thread.sleep(1L); - if (bucketCount > 1) { phaser.bulkRegister(bucketCount - 1); } @@ -142,14 +158,20 @@ protected boolean onAdvance(int phase, int registeredParties) { bucketLock.lock(); try { element = queue.poll(); - for (int i = 0; i < bucketCount - 1; i++) { + int currentWorkerCount = Math.min(workerCount, bucketCount); + for (int i = 0; i < currentWorkerCount - 1; i++) { nextBucket.signal(); } } finally { bucketLock.unlock(); } + fibonacci.applyAsInt(fibonacciCount); System.out.println(Thread.currentThread().getName() + ": " + element); + + phaser.arriveAndAwaitAdvance(); + + Thread.sleep(50L); } catch (Exception e) { break; } From f96c6b37700e2bfaf68225824bcfd9c3f7ae799b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Thu, 8 Jun 2023 23:39:41 +0200 Subject: [PATCH 05/12] feat: wip - add new proximity worker/threads --- .../net/imprex/orebfuscator/Orebfuscator.java | 6 +- .../orebfuscator/OrebfuscatorPlayer.java | 29 ++- .../obfuscation/ObfuscationListener.java | 30 +-- .../ProximityDirectorThread.java | 232 +++++------------- .../proximityhider/ProximityWorker.java | 6 +- .../proximityhider/ProximityWorkerThread.java | 9 +- 6 files changed, 106 insertions(+), 206 deletions(-) diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java index d0b9f25a..1ce4b045 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java @@ -76,9 +76,11 @@ public void onEnable() { } Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { - System.out.println("OFC_PLAYER: " + OrebfuscatorPlayer.PLAYER_MAP.size()); System.gc(); - }, 200, 200); + }, 20, 20); + Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { + System.out.println("OFC_PLAYER: " + OrebfuscatorPlayer.PLAYER_MAP.size()); + }, 400, 400); // Load packet listener this.obfuscationSystem.registerChunkListener(); diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java index 361d87f5..259d25c0 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java @@ -21,7 +21,9 @@ public class OrebfuscatorPlayer { - public static final ConcurrentMap PLAYER_MAP = new MapMaker().weakKeys().makeMap(); + private static final long CHECK_INTERVAL = 5000; // TODO add to config + + public static final ConcurrentMap PLAYER_MAP = new MapMaker().weakKeys().makeMap(); // TODO remove on quit event public static OrebfuscatorPlayer get(Player player) { OrebfuscatorPlayer playerData = PLAYER_MAP.computeIfAbsent(player, OrebfuscatorPlayer::new); @@ -34,24 +36,44 @@ public static OrebfuscatorPlayer get(Player player) { private final AtomicReference world = new AtomicReference<>(); private final Map> chunks = new ConcurrentHashMap<>(); + private volatile long latestUpdateTimestamp = System.currentTimeMillis(); private volatile Location location = new Location(null, 0, 0, 0); public OrebfuscatorPlayer(Player player) { this.player = new WeakReference(player); + this.location = player.getLocation(); } - public boolean hasLocationChanged(BiPredicate equals) { + /** + * Returns true if the last proximity update is longer ago then 5s or if the players + * location since the last update change according to the given equals method. + * @param equals the location equals function + * @return true if a proximity update is needed + */ + public boolean needsProximityUpdate(BiPredicate equals) { if (this.player.refersTo(null)) { return false; } + long timestamp = System.currentTimeMillis(); + if (timestamp - this.latestUpdateTimestamp > CHECK_INTERVAL) { + + // always update location + latestUpdateTimestamp on update + this.location = location; + this.latestUpdateTimestamp = timestamp; + + return true; + } + Location location = this.player.get().getLocation(); if (equals.test(this.location, location)) { return false; } + // always update location + latestUpdateTimestamp on update this.location = location; - + this.latestUpdateTimestamp = timestamp; + return true; } @@ -68,7 +90,6 @@ private void updateWorld() { public void addChunk(int chunkX, int chunkZ, Set blocks) { long key = ChunkPosition.toLong(chunkX, chunkZ); - System.out.println("add: " + chunkX + " " + chunkZ + " " + blocks.size()); this.chunks.computeIfAbsent(key, k -> { return Collections.newSetFromMap(new ConcurrentHashMap<>()); }).addAll(blocks); diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java index a5f2d1be..0e87d805 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java @@ -7,7 +7,6 @@ import com.comphenix.protocol.PacketType; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketEvent; -import com.comphenix.protocol.events.PacketPostAdapter; import net.imprex.orebfuscator.Orebfuscator; import net.imprex.orebfuscator.OrebfuscatorPlayer; @@ -53,15 +52,6 @@ public void onPacketSending(PacketEvent event) { this.preChunkProcessing(event); - event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { - - @Override - public void onPostEvent(PacketEvent event) { - System.out.println("post-1: " + struct.chunkX + " " + struct.chunkZ); - } - - }); - this.obfuscationSystem.obfuscate(struct).whenComplete((chunk, throwable) -> { if (throwable != null) { this.completeExceptionally(event, struct, throwable); @@ -95,16 +85,16 @@ private void complete(PacketEvent event, ChunkStruct struct, ObfuscationResult c final OrebfuscatorPlayer player = OrebfuscatorPlayer.get(event.getPlayer()); - event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { - - @Override - public void onPostEvent(PacketEvent event) { - System.out.println("post-2: " + struct.chunkX + " " + struct.chunkZ); - player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); - } - - }); -// player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); +// event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { +// +// @Override +// public void onPostEvent(PacketEvent event) { +// System.out.println("post-2: " + struct.chunkX + " " + struct.chunkZ); +// player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); +// } +// +// }); + player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); this.postChunkProcessing(event); } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java index 61cffd1a..be98ad26 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -1,55 +1,54 @@ package net.imprex.orebfuscator.proximityhider; -import java.time.LocalTime; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; -import java.util.Queue; -import java.util.concurrent.BrokenBarrierException; -import java.util.concurrent.ConcurrentLinkedQueue; -import java.util.concurrent.CyclicBarrier; -import java.util.concurrent.Executors; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.Phaser; -import java.util.concurrent.locks.Condition; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.IntUnaryOperator; -import java.util.stream.IntStream; +import java.util.concurrent.locks.LockSupport; import org.bukkit.Bukkit; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerJoinEvent; import net.imprex.orebfuscator.Orebfuscator; +import net.imprex.orebfuscator.util.OFCLogger; -public class ProximityDirectorThread extends Thread { +public class ProximityDirectorThread extends Thread implements Listener { + + private static final int DEFAULT_BUCKET_SIZE = 50; private final Phaser phaser = new Phaser(1); - private final CyclicBarrier cyclicBarrier; private volatile boolean running = true; private final int workerCount; - private final Queue> bucketQueue = new LinkedList<>(); - - private final Lock bucketLock = new ReentrantLock(); - private final Condition nextBucket = bucketLock.newCondition(); + private final BlockingQueue> bucketQueue = new LinkedBlockingQueue<>(); private final ProximityWorker worker; private final ProximityWorkerThread[] workerThreads; public ProximityDirectorThread(Orebfuscator orebfuscator) { super(Orebfuscator.THREAD_GROUP, "ofc-proximity-director"); + this.setDaemon(true); - this.workerCount = 1;// orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); - this.cyclicBarrier = new CyclicBarrier(this.workerCount); - - Executors.newFixedThreadPool(1).execute(null); + this.workerCount = orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); + Bukkit.getPluginManager().registerEvents(this, orebfuscator); this.worker = new ProximityWorker(orebfuscator); this.workerThreads = new ProximityWorkerThread[workerCount - 1]; } + @EventHandler + public void onJoin(PlayerJoinEvent event) { + if (LockSupport.getBlocker(this) == this) { + LockSupport.unpark(this); + } + } + @Override public void start() { super.start(); @@ -64,132 +63,24 @@ public void close() { this.running = false; this.interrupt(); + for (int i = 0; i < workerCount - 1; i++) { this.workerThreads[i].interrupt(); } - } - boolean isRunning() { - return this.running; + this.phaser.forceTermination(); } - public static void main(String[] args) { - final Phaser phaser = new Phaser(1) { - @Override - protected boolean onAdvance(int phase, int registeredParties) { - System.out.println("onAdvance: " + phase + " " + registeredParties + " " + Thread.currentThread().getName()); - if (registeredParties == 0) { - new Exception().printStackTrace(); - } - return registeredParties == 0; - } - }; - - final Lock bucketLock = new ReentrantLock(true); - final Condition nextBucket = bucketLock.newCondition(); - - final Queue queue = new ConcurrentLinkedQueue<>(); - final int workerCount = Runtime.getRuntime().availableProcessors(); - - final int fibonacciCount = 36; - IntUnaryOperator fibonacci = new IntUnaryOperator() { - - @Override - public int applyAsInt(int operand) { - if(operand == 0) - return 0; - else if(operand == 1) - return 1; - else - return applyAsInt(operand - 1) + applyAsInt(operand - 2); - } - }; - - IntStream.range(0, workerCount).forEach(index -> { - new Thread(() -> { - while (!phaser.isTerminated()) { - try { - String element; - - bucketLock.lock(); - try { - while ((element = queue.poll()) == null) { - nextBucket.await(); - } - } finally { - bucketLock.unlock(); - } - - fibonacci.applyAsInt(fibonacciCount); - System.out.println(Thread.currentThread().getName() + ": " + element); - - phaser.arriveAndDeregister(); - } catch (InterruptedException e) { - break; - } - } - }, "wroker-" + index).start(); - }); - - while (!phaser.isTerminated()) { - try { - int bucketCount = (int) Math.round(Math.random() * workerCount * 4); - if (bucketCount == 0) { - continue; - } - - String element; - - bucketLock.lock(); - try { - for (int i = 0; i < bucketCount; i++) { - queue.offer("element " + i + " in phase " + (phaser.getPhase() + 1)); - } - } finally { - bucketLock.unlock(); - } - - if (bucketCount > 1) { - phaser.bulkRegister(bucketCount - 1); - } - System.out.println(String.format("bucketCount: %s, phase: %s, registed: %s, arrived: %s, queue: %s, time: %s", bucketCount, - phaser.getPhase(), phaser.getRegisteredParties(), phaser.getArrivedParties(), queue.size(), LocalTime.now().toString())); - - bucketLock.lock(); - try { - element = queue.poll(); - int currentWorkerCount = Math.min(workerCount, bucketCount); - for (int i = 0; i < currentWorkerCount - 1; i++) { - nextBucket.signal(); - } - } finally { - bucketLock.unlock(); - } - - fibonacci.applyAsInt(fibonacciCount); - System.out.println(Thread.currentThread().getName() + ": " + element); - - phaser.arriveAndAwaitAdvance(); - - Thread.sleep(50L); - } catch (Exception e) { - break; - } - } + boolean isRunning() { + return this.running && !this.phaser.isTerminated(); } - List getBucket() throws InterruptedException { - List bucket; - - while ((bucket = this.bucketQueue.poll()) == null) { - this.phaser.awaitAdvance(this.phaser.arriveAndDeregister()); - } - - return bucket; + List nextBucket() throws InterruptedException { + return this.bucketQueue.take(); } - void awaitNextExecution() throws InterruptedException, BrokenBarrierException { - this.cyclicBarrier.await(); + void finishBucketProcessing() { + this.phaser.arriveAndDeregister(); } @Override @@ -199,59 +90,62 @@ public void run() { Collection players = Bukkit.getOnlinePlayers(); Iterator iterator = players.iterator(); + // park thread if no players are online + if (players.isEmpty()) { + LockSupport.park(this); + } + int playerCount = players.size(); - int bucketCount = Math.min((int) Math.ceil((float) playerCount / 50f), this.workerCount); + int maxBucketSize = Math.max(DEFAULT_BUCKET_SIZE, (int) Math.ceil((float) playerCount / this.workerCount)); + + int bucketCount = (int) Math.ceil((float) playerCount / maxBucketSize); int bucketSize = (int) Math.ceil((float) playerCount / (float) bucketCount); - List localBucket = null; + // register extra worker threads in phaser + if (bucketCount > 1) { + this.phaser.bulkRegister(bucketCount - 1); + } - this.bucketLock.lock(); - try { - // refill buckets - for (int index = 0; index < bucketCount; index++) { - List bucket = new ArrayList<>(); + // this threads local bucket + List localBucket = null; - for (int size = 0; size < bucketSize && iterator.hasNext(); size++) { - bucket.add(iterator.next()); - } + // create buckets and fill queue + for (int index = 0; index < bucketCount; index++) { + List bucket = new ArrayList<>(); - this.bucketQueue.offer(bucket); + // fill bucket until bucket full or no players remain + for (int size = 0; size < bucketSize && iterator.hasNext(); size++) { + bucket.add(iterator.next()); } - System.out.println("buckets: " + this.bucketQueue); - - // get own bucket - localBucket = this.bucketQueue.poll(); - - // wake up enough threads for the amount of created buckets - for (int i = 0; i < bucketCount - 1; i++) { - this.nextBucket.signal(); + // assign first bucket to current thread + if (index == 0) { + localBucket = bucket; + } else { + this.bucketQueue.offer(bucket); } - } finally { - this.bucketLock.unlock(); } // process local bucket - if (localBucket != null) { - for (Player player : localBucket) { - this.worker.process(player); - } + for (Player player : localBucket) { + this.worker.process(player); } // wait for all threads to finish and reset barrier - this.awaitNextExecution(); - this.cyclicBarrier.reset(); + this.phaser.arriveAndAwaitAdvance(); // sleep till next execution - Thread.sleep(1000L); + Thread.sleep(50L);// TODO add to config } catch (InterruptedException e) { continue; - } catch (BrokenBarrierException e) { - e.printStackTrace(); - break; } catch (Exception e) { e.printStackTrace(); } } + + if (this.phaser.isTerminated()) { + OFCLogger.error("Looks like we encountered an invalid state, please report this:", + new IllegalStateException("Proximity Phaser terminated!")); + } } } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java index 8481df7b..af74e24f 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java @@ -61,7 +61,6 @@ private boolean isLocationSimilar(boolean rotation, Location a, Location b) { protected void process(Player player) { if (this.shouldIgnorePlayer(player)) { - System.out.println("ignored: " + player); return; } @@ -70,14 +69,12 @@ protected void process(Player player) { // check if world has enabled proximity config ProximityConfig proximityConfig = this.config.world(world).proximity(); if (proximityConfig == null || !proximityConfig.isEnabled()) { - System.out.println("no_config: " + player); return; } // check if player changed location since last time OrebfuscatorPlayer orebfuscatorPlayer = OrebfuscatorPlayer.get(player); - if (!orebfuscatorPlayer.hasLocationChanged((a, b) -> isLocationSimilar(proximityConfig.useFastGazeCheck(), a, b))) { - System.out.println("no_change: " + player); + if (!orebfuscatorPlayer.needsProximityUpdate((a, b) -> isLocationSimilar(proximityConfig.useFastGazeCheck(), a, b))) { return; } @@ -123,7 +120,6 @@ protected void process(Player player) { Bukkit.getScheduler().runTask(this.orebfuscator, () -> { if (player.isOnline()) { - player.sendMessage("updated: " + updateBlocks.size()); for (BlockPos blockCoords : updateBlocks) { NmsInstance.sendBlockChange(player, blockCoords); } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java index ff20d72c..4be8f54b 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorkerThread.java @@ -1,7 +1,6 @@ package net.imprex.orebfuscator.proximityhider; import java.util.List; -import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.atomic.AtomicInteger; import org.bukkit.entity.Player; @@ -17,6 +16,7 @@ public class ProximityWorkerThread extends Thread { public ProximityWorkerThread(ProximityDirectorThread directorThread, ProximityWorker worker) { super(Orebfuscator.THREAD_GROUP, "ofc-proximity-worker-" + NEXT_ID.getAndIncrement()); + this.setDaemon(true); this.directorThread = directorThread; this.worker = worker; @@ -26,18 +26,15 @@ public ProximityWorkerThread(ProximityDirectorThread directorThread, ProximityWo public void run() { while (this.directorThread.isRunning()) { try { - List bucket = this.directorThread.getBucket(); + List bucket = this.directorThread.nextBucket(); for (Player player : bucket) { this.worker.process(player); } - this.directorThread.awaitNextExecution(); + this.directorThread.finishBucketProcessing(); } catch (InterruptedException e) { continue; - } catch (BrokenBarrierException e) { - e.printStackTrace(); - break; } catch (Exception e) { e.printStackTrace(); } From 28dc8b358d2c6dd62d7a280e17406e40b9a51c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 15:24:42 +0200 Subject: [PATCH 06/12] feat: more advanced config options --- .../orebfuscator/config/AdvancedConfig.java | 12 +++ .../net/imprex/orebfuscator/Orebfuscator.java | 15 ++-- .../orebfuscator/cache/ObfuscationCache.java | 4 +- .../config/OrebfuscatorAdvancedConfig.java | 63 ++++++++++++++- .../obfuscation/ObfuscationListener.java | 40 ++++++---- .../obfuscation/ObfuscationRequest.java | 7 +- .../obfuscation/ObfuscationSystem.java | 7 +- .../seed/SeedObfuscationListener.java | 33 -------- .../seed/SeedObfuscationStrategy.java | 78 ------------------- .../{ => player}/OrebfuscatorPlayer.java | 69 ++++++++++------ .../player/OrebfuscatorPlayerMap.java | 47 +++++++++++ .../ProximityDirectorThread.java | 30 ++++--- .../ProximityPacketListener.java | 12 ++- .../proximityhider/ProximityWorker.java | 30 ++----- 14 files changed, 246 insertions(+), 201 deletions(-) delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java rename orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/{ => player}/OrebfuscatorPlayer.java (55%) create mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java diff --git a/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/AdvancedConfig.java b/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/AdvancedConfig.java index 608410a9..129468a4 100644 --- a/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/AdvancedConfig.java +++ b/orebfuscator-common/src/main/java/net/imprex/orebfuscator/config/AdvancedConfig.java @@ -10,5 +10,17 @@ public interface AdvancedConfig { int obfuscationWorkerThreads(); + boolean hasObfuscationTimeout(); + + int obfuscationTimeout(); + int proximityHiderThreads(); + + int proximityDefaultBucketSize(); + + int proximityThreadCheckInterval(); + + boolean hasProximityPlayerCheckInterval(); + + int proximityPlayerCheckInterval(); } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java index 1ce4b045..faae23b5 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/Orebfuscator.java @@ -15,6 +15,7 @@ import net.imprex.orebfuscator.cache.ObfuscationCache; import net.imprex.orebfuscator.config.OrebfuscatorConfig; import net.imprex.orebfuscator.obfuscation.ObfuscationSystem; +import net.imprex.orebfuscator.player.OrebfuscatorPlayerMap; import net.imprex.orebfuscator.proximityhider.ProximityDirectorThread; import net.imprex.orebfuscator.proximityhider.ProximityPacketListener; import net.imprex.orebfuscator.util.HeightAccessor; @@ -27,6 +28,7 @@ public class Orebfuscator extends JavaPlugin implements Listener { private final Thread mainThread = Thread.currentThread(); private OrebfuscatorConfig config; + private OrebfuscatorPlayerMap playerMap; private UpdateSystem updateSystem; private ObfuscationCache obfuscationCache; private ObfuscationSystem obfuscationSystem; @@ -52,6 +54,8 @@ public void onEnable() { // Load configurations this.config = new OrebfuscatorConfig(this); + this.playerMap = new OrebfuscatorPlayerMap(this); + // register cleanup listener HeightAccessor.registerListener(this); @@ -75,13 +79,6 @@ public void onEnable() { this.proximityPacketListener = new ProximityPacketListener(this); } - Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { - System.gc(); - }, 20, 20); - Bukkit.getScheduler().scheduleSyncRepeatingTask(this, () -> { - System.out.println("OFC_PLAYER: " + OrebfuscatorPlayer.PLAYER_MAP.size()); - }, 400, 400); - // Load packet listener this.obfuscationSystem.registerChunkListener(); @@ -142,6 +139,10 @@ public OrebfuscatorConfig getOrebfuscatorConfig() { return this.config; } + public OrebfuscatorPlayerMap getPlayerMap() { + return playerMap; + } + public UpdateSystem getUpdateSystem() { return updateSystem; } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/cache/ObfuscationCache.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/cache/ObfuscationCache.java index 396cda02..7964cdc5 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/cache/ObfuscationCache.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/cache/ObfuscationCache.java @@ -1,6 +1,6 @@ package net.imprex.orebfuscator.cache; -import java.util.concurrent.CompletionStage; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.TimeUnit; import org.bukkit.Bukkit; @@ -51,7 +51,7 @@ private void onRemoval(RemovalNotification not } } - public CompletionStage get(ObfuscationRequest request) { + public CompletableFuture get(ObfuscationRequest request) { ChunkPosition key = request.getPosition(); ObfuscationResult cacheChunk = this.cache.getIfPresent(key); diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java index 1f77fbf5..d4a74228 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java @@ -10,12 +10,20 @@ public class OrebfuscatorAdvancedConfig implements AdvancedConfig { private boolean useAsyncPacketListener = true; private int maxMillisecondsPerTick = 10; private int protocolLibThreads = -1; + private int obfuscationWorkerThreads = -1; + private int obfuscationTimeout = -1; + private int proximityHiderThreads = -1; + private int proximityDefaultBucketSize = 50; + private int proximityThreadCheckInterval = 50; + private int proximityPlayerCheckInterval = 5000; private boolean protocolLibThreadsSet = false; private boolean obfuscationWorkerThreadsSet = false; + private boolean hasObfuscationTimeout = false; private boolean proximityHiderThreadsSet = false; + private boolean hasProximityPlayerCheckInterval = true; public void deserialize(ConfigurationSection section) { this.verbose = section.getBoolean("verbose", false); @@ -33,8 +41,26 @@ public void deserialize(ConfigurationSection section) { this.obfuscationWorkerThreads = section.getInt("obfuscationWorkerThreads", -1); this.obfuscationWorkerThreadsSet = (this.obfuscationWorkerThreads > 0); + this.obfuscationTimeout = section.getInt("obfuscationTimeout", -1); + this.hasObfuscationTimeout = (this.obfuscationTimeout > 0); + this.proximityHiderThreads = section.getInt("proximityHiderThreads", -1); this.proximityHiderThreadsSet = (this.proximityHiderThreads > 0); + + this.proximityDefaultBucketSize = section.getInt("proximityDefaultBucketSize", 50); + if (proximityDefaultBucketSize <= 0) { + throw new RuntimeException( + "proximityDefaultBucketSize has to be bigger then 0, value: " + this.proximityDefaultBucketSize); + } + + this.proximityThreadCheckInterval = section.getInt("proximityThreadCheckInterval", 50); + if (this.proximityThreadCheckInterval <= 0) { + throw new RuntimeException( + "proximityThreadCheckInterval has to be bigger then 0, value: " + this.proximityThreadCheckInterval); + } + + this.proximityPlayerCheckInterval = section.getInt("proximityPlayerCheckInterval", 5000); + this.hasProximityPlayerCheckInterval = (this.proximityPlayerCheckInterval > 0); } public void initialize() { @@ -44,7 +70,6 @@ public void initialize() { this.proximityHiderThreads = (int) (proximityHiderThreadsSet ? proximityHiderThreads : Math.ceil(availableThreads / 2f)); OFCLogger.setVerboseLogging(this.verbose); - OFCLogger.debug("advanced.maxMillisecondsPerTick = " + this.maxMillisecondsPerTick); OFCLogger.debug("advanced.protocolLibThreads = " + this.protocolLibThreads); OFCLogger.debug("advanced.obfuscationWorkerThreads = " + this.obfuscationWorkerThreads); OFCLogger.debug("advanced.proximityHiderThreads = " + this.proximityHiderThreads); @@ -55,8 +80,14 @@ public void serialize(ConfigurationSection section) { section.set("useAsyncPacketListener", this.useAsyncPacketListener); section.set("maxMillisecondsPerTick", this.maxMillisecondsPerTick); section.set("protocolLibThreads", this.protocolLibThreadsSet ? this.protocolLibThreads : -1); + section.set("obfuscationWorkerThreads", this.obfuscationWorkerThreadsSet ? this.obfuscationWorkerThreads : -1); + section.set("obfuscationTimeout", this.hasObfuscationTimeout ? this.obfuscationTimeout : -1); + section.set("proximityHiderThreads", this.proximityHiderThreadsSet ? this.proximityHiderThreads : -1); + section.set("proximityDefaultBucketSize", this.proximityDefaultBucketSize); + section.set("proximityThreadCheckInterval", this.proximityThreadCheckInterval); + section.set("proximityPlayerCheckInterval", this.hasProximityPlayerCheckInterval ? this.proximityPlayerCheckInterval : -1); } @Override @@ -79,8 +110,38 @@ public int obfuscationWorkerThreads() { return this.obfuscationWorkerThreads; } + @Override + public boolean hasObfuscationTimeout() { + return this.hasObfuscationTimeout; + } + + @Override + public int obfuscationTimeout() { + return this.obfuscationTimeout; + } + @Override public int proximityHiderThreads() { return this.proximityHiderThreads; } + + @Override + public int proximityDefaultBucketSize() { + return this.proximityDefaultBucketSize; + } + + @Override + public int proximityThreadCheckInterval() { + return this.proximityThreadCheckInterval; + } + + @Override + public boolean hasProximityPlayerCheckInterval() { + return this.hasProximityPlayerCheckInterval; + } + + @Override + public int proximityPlayerCheckInterval() { + return this.proximityPlayerCheckInterval; + } } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java index 0e87d805..6faf89bc 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationListener.java @@ -1,6 +1,8 @@ package net.imprex.orebfuscator.obfuscation; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; import org.bukkit.entity.Player; @@ -9,9 +11,11 @@ import com.comphenix.protocol.events.PacketEvent; import net.imprex.orebfuscator.Orebfuscator; -import net.imprex.orebfuscator.OrebfuscatorPlayer; import net.imprex.orebfuscator.chunk.ChunkStruct; +import net.imprex.orebfuscator.config.AdvancedConfig; import net.imprex.orebfuscator.config.OrebfuscatorConfig; +import net.imprex.orebfuscator.player.OrebfuscatorPlayer; +import net.imprex.orebfuscator.player.OrebfuscatorPlayerMap; import net.imprex.orebfuscator.util.BlockPos; import net.imprex.orebfuscator.util.OFCLogger; import net.imprex.orebfuscator.util.PermissionUtil; @@ -19,12 +23,14 @@ public abstract class ObfuscationListener extends PacketAdapter { private final OrebfuscatorConfig config; + private final OrebfuscatorPlayerMap playerMap; private final ObfuscationSystem obfuscationSystem; public ObfuscationListener(Orebfuscator orebfuscator) { super(orebfuscator, PacketType.Play.Server.MAP_CHUNK); this.config = orebfuscator.getOrebfuscatorConfig(); + this.playerMap = orebfuscator.getPlayerMap(); this.obfuscationSystem = orebfuscator.getObfuscationSystem(); } @@ -52,7 +58,14 @@ public void onPacketSending(PacketEvent event) { this.preChunkProcessing(event); - this.obfuscationSystem.obfuscate(struct).whenComplete((chunk, throwable) -> { + AdvancedConfig advancedConfig = this.config.advanced(); + + CompletableFuture future = this.obfuscationSystem.obfuscate(struct); + if (advancedConfig.hasObfuscationTimeout()) { + future = future.orTimeout(advancedConfig.obfuscationTimeout(), TimeUnit.MILLISECONDS); + } + + future.whenComplete((chunk, throwable) -> { if (throwable != null) { this.completeExceptionally(event, struct, throwable); } else if (chunk != null) { @@ -83,18 +96,19 @@ private void complete(PacketEvent event, ChunkStruct struct, ObfuscationResult c struct.removeBlockEntityIf(blockEntities::contains); } - final OrebfuscatorPlayer player = OrebfuscatorPlayer.get(event.getPlayer()); - -// event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { + final OrebfuscatorPlayer player = this.playerMap.get(event.getPlayer()); + if (player != null) { +// event.getNetworkMarker().addPostListener(new PacketPostAdapter(this.plugin) { +// +// @Override +// public void onPostEvent(PacketEvent event) { +// System.out.println("post-2: " + struct.chunkX + " " + struct.chunkZ); +// player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); +// } // -// @Override -// public void onPostEvent(PacketEvent event) { -// System.out.println("post-2: " + struct.chunkX + " " + struct.chunkZ); -// player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); -// } -// -// }); - player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); +// }); + player.addChunk(struct.chunkX, struct.chunkZ, chunk.getProximityBlocks()); + } this.postChunkProcessing(event); } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationRequest.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationRequest.java index 136d0217..24cdcc25 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationRequest.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationRequest.java @@ -3,7 +3,6 @@ import java.util.Arrays; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CompletionStage; import com.google.common.hash.HashFunction; import com.google.common.hash.Hashing; @@ -60,7 +59,7 @@ public boolean isValid(ObfuscationResult result) { return result != null && Arrays.equals(result.getHash(), this.chunkHash); } - public CompletionStage submitForObfuscation() { + public CompletableFuture submitForObfuscation() { this.dispatcher.submitRequest(this); return this.future; } @@ -69,12 +68,12 @@ public ObfuscationResult createResult(byte[] data, Set blockEntities, return new ObfuscationResult(this.position, this.chunkHash, data, blockEntities, proximityBlocks); } - public CompletionStage complete(ObfuscationResult result) { + public CompletableFuture complete(ObfuscationResult result) { this.future.complete(result); return this.future; } - public CompletionStage completeExceptionally(Throwable throwable) { + public CompletableFuture completeExceptionally(Throwable throwable) { this.future.completeExceptionally(throwable); return this.future; } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java index 795d4dd6..7270a096 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/ObfuscationSystem.java @@ -1,7 +1,7 @@ package net.imprex.orebfuscator.obfuscation; import java.util.Collection; -import java.util.concurrent.CompletionStage; +import java.util.concurrent.CompletableFuture; import org.bukkit.block.Block; @@ -9,7 +9,6 @@ import net.imprex.orebfuscator.cache.ObfuscationCache; import net.imprex.orebfuscator.chunk.ChunkStruct; import net.imprex.orebfuscator.config.OrebfuscatorConfig; -import net.imprex.orebfuscator.obfuscation.seed.SeedObfuscationListener; public class ObfuscationSystem { @@ -33,8 +32,6 @@ public ObfuscationSystem(Orebfuscator orebfuscator) { this.deobfuscationWorker = new DeobfuscationWorker(orebfuscator); DeobfuscationListener.createAndRegister(orebfuscator, this.deobfuscationWorker); - - new SeedObfuscationListener(orebfuscator); } public void registerChunkListener() { @@ -45,7 +42,7 @@ public void registerChunkListener() { } } - public CompletionStage obfuscate(ChunkStruct chunkStruct) { + public CompletableFuture obfuscate(ChunkStruct chunkStruct) { ObfuscationRequest request = ObfuscationRequest.fromChunk(chunkStruct, this.config, this.dispatcher); if (this.config.cache().enabled()) { return this.cache.get(request); diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java deleted file mode 100644 index c41b55e8..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationListener.java +++ /dev/null @@ -1,33 +0,0 @@ -package net.imprex.orebfuscator.obfuscation.seed; - -import java.nio.ByteBuffer; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketEvent; - -import net.imprex.orebfuscator.Orebfuscator; - -public class SeedObfuscationListener extends PacketAdapter { - - private final SeedObfuscationStrategy strategy = SeedObfuscationStrategy.createDynamically(); - private final long hash; - - public SeedObfuscationListener(Orebfuscator orebfuscator) { - super(orebfuscator, PacketType.Play.Server.LOGIN); - - - ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - protocolManager.addPacketListener(this); - - ByteBuffer buffer = ByteBuffer.wrap(orebfuscator.getOrebfuscatorConfig().systemHash()); - this.hash = buffer.getLong(0); - } - - @Override - public void onPacketSending(PacketEvent event) { - event.setPacket(strategy.process(event.getPacket(), this.hash)); - } -} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java deleted file mode 100644 index 4b6788ec..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/seed/SeedObfuscationStrategy.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.imprex.orebfuscator.obfuscation.seed; - -import java.lang.reflect.RecordComponent; -import java.util.Arrays; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.accessors.Accessors; -import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; -import com.comphenix.protocol.reflect.accessors.FieldAccessor; - -@FunctionalInterface -public interface SeedObfuscationStrategy { - - static final SeedObfuscationStrategy NOOP = (packet, hash) -> packet; - - static SeedObfuscationStrategy createDynamically() { - final PacketType packetType = PacketType.Play.Server.LOGIN; - final Class packetClass = packetType.getPacketClass(); - - if (packetClass.isRecord()) { - final RecordComponent[] components = packetClass.getRecordComponents(); - final Class[] componentClasses = new Class[components.length]; - - int longIndex = -1; - for (int i = 0; i < components.length; i++) { - Class componentClass = components[i].getType(); - - if (longIndex == -1 && componentClass == long.class) { - longIndex = i; - } - - componentClasses[i] = componentClass; - } - - final int hashIndex = longIndex; - if (hashIndex == -1) { - return NOOP; - } - - final ConstructorAccessor constructorAccessor = Accessors.getConstructorAccessor( - packetClass, componentClasses); - - final FieldAccessor[] fieldAccessors = Arrays.stream(packetClass.getDeclaredFields()) - .map(Accessors::getFieldAccessor) - .toArray(FieldAccessor[]::new); - - return (packet, hash) -> { - Object handle = packet.getHandle(); - Object[] arguments = new Object[components.length]; - - for (int i = 0; i < components.length; i++) { - if (hashIndex == i) { - arguments[i] = hash; - } else { - arguments[i] = fieldAccessors[i].get(handle); - } - } - - handle = constructorAccessor.invoke(arguments); - return new PacketContainer(packetType, handle); - }; - } else { - try { - Accessors.getFieldAccessor(packetClass, long.class, true); - } catch (Exception e) { - return NOOP; - } - - return (packet, hash) -> { - packet.getLongs().write(0, hash); - return packet; - }; - } - } - - PacketContainer process(PacketContainer packet, long hash); -} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayer.java similarity index 55% rename from orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java rename to orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayer.java index 259d25c0..c56a904a 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/OrebfuscatorPlayer.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayer.java @@ -1,36 +1,26 @@ -package net.imprex.orebfuscator; +package net.imprex.orebfuscator.player; import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiPredicate; import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Player; import com.google.common.base.Objects; -import com.google.common.collect.MapMaker; +import net.imprex.orebfuscator.Orebfuscator; +import net.imprex.orebfuscator.config.AdvancedConfig; import net.imprex.orebfuscator.util.BlockPos; import net.imprex.orebfuscator.util.ChunkPosition; public class OrebfuscatorPlayer { - private static final long CHECK_INTERVAL = 5000; // TODO add to config - - public static final ConcurrentMap PLAYER_MAP = new MapMaker().weakKeys().makeMap(); // TODO remove on quit event - - public static OrebfuscatorPlayer get(Player player) { - OrebfuscatorPlayer playerData = PLAYER_MAP.computeIfAbsent(player, OrebfuscatorPlayer::new); - playerData.updateWorld(); - return playerData; - } - + private final AdvancedConfig config; private final WeakReference player; private final AtomicReference world = new AtomicReference<>(); @@ -39,24 +29,29 @@ public static OrebfuscatorPlayer get(Player player) { private volatile long latestUpdateTimestamp = System.currentTimeMillis(); private volatile Location location = new Location(null, 0, 0, 0); - public OrebfuscatorPlayer(Player player) { + public OrebfuscatorPlayer(Orebfuscator orebfuscator, Player player) { + this.config = orebfuscator.getOrebfuscatorConfig().advanced(); this.player = new WeakReference(player); this.location = player.getLocation(); } /** - * Returns true if the last proximity update is longer ago then 5s or if the players - * location since the last update change according to the given equals method. - * @param equals the location equals function + * Returns true if the last proximity update is longer ago then the configured + * proximity player interval (default 5s) or if the players location since the + * last update change according to the given rotation boolean and the + * {@link OrebfuscatorPlayer#isLocationSimilar isLocationSimilar} method. + * + * @param rotation passed to the isLocationSimilar method * @return true if a proximity update is needed */ - public boolean needsProximityUpdate(BiPredicate equals) { + public boolean needsProximityUpdate(boolean rotation) { if (this.player.refersTo(null)) { return false; } long timestamp = System.currentTimeMillis(); - if (timestamp - this.latestUpdateTimestamp > CHECK_INTERVAL) { + if (this.config.hasProximityPlayerCheckInterval() && + timestamp - this.latestUpdateTimestamp > this.config.proximityPlayerCheckInterval()) { // always update location + latestUpdateTimestamp on update this.location = location; @@ -65,8 +60,9 @@ public boolean needsProximityUpdate(BiPredicate equals) { return true; } + Location location = this.player.get().getLocation(); - if (equals.test(this.location, location)) { + if (isLocationSimilar(rotation, this.location, location)) { return false; } @@ -77,7 +73,36 @@ public boolean needsProximityUpdate(BiPredicate equals) { return true; } - private void updateWorld() { + /** + * Returns true if the worlds are the same and the distance between the locations + * is less then 0.5. If the rotation boolean is set this method also check if the + * yaw changed less then 10deg and the pitch less then 5deg. + * + * @param rotation should rotation be checked + * @param a the first location + * @param b the second location + * @return if the locations are similar + */ + private static boolean isLocationSimilar(boolean rotation, Location a, Location b) { + // check if world changed + if (!Objects.equal(a.getWorld(), b.getWorld())) { + return false; + } + + // check if len(xyz) changed less then 0.5 blocks + if (a.distanceSquared(b) > 0.25) { + return false; + } + + // check if rotation changed less then 10deg yaw or 5deg pitch + if (rotation && (Math.abs(a.getYaw() - b.getYaw()) > 10 || Math.abs(a.getPitch() - b.getPitch()) > 5)) { + return false; + } + + return true; + } + + void updateWorld() { if (this.player.refersTo(null)) { return; } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java new file mode 100644 index 00000000..a49f7169 --- /dev/null +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java @@ -0,0 +1,47 @@ +package net.imprex.orebfuscator.player; + +import java.util.concurrent.ConcurrentMap; + +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.player.PlayerLoginEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import com.google.common.collect.MapMaker; + +import net.imprex.orebfuscator.Orebfuscator; + +public class OrebfuscatorPlayerMap implements Listener { + + private final Orebfuscator orebfuscator; + + private final ConcurrentMap internalMap = new MapMaker().weakKeys().makeMap(); + + public OrebfuscatorPlayerMap(Orebfuscator orebfuscator) { + this.orebfuscator = orebfuscator; + if (orebfuscator.getOrebfuscatorConfig().proximityEnabled()) { + Bukkit.getPluginManager().registerEvents(this, orebfuscator); + } + } + + @EventHandler + public void onLogin(PlayerLoginEvent event) { + Player player = event.getPlayer(); + this.internalMap.put(player, new OrebfuscatorPlayer(orebfuscator, player)); + } + + @EventHandler + public void onQuit(PlayerQuitEvent event) { + this.internalMap.remove(event.getPlayer()); + } + + public OrebfuscatorPlayer get(Player player) { + OrebfuscatorPlayer orebfuscatorPlayer = this.internalMap.get(player); + if (orebfuscatorPlayer != null) { + orebfuscatorPlayer.updateWorld(); + } + return orebfuscatorPlayer; + } +} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java index be98ad26..456ce615 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -16,26 +16,32 @@ import org.bukkit.event.player.PlayerJoinEvent; import net.imprex.orebfuscator.Orebfuscator; +import net.imprex.orebfuscator.config.AdvancedConfig; import net.imprex.orebfuscator.util.OFCLogger; public class ProximityDirectorThread extends Thread implements Listener { - private static final int DEFAULT_BUCKET_SIZE = 50; + private final int workerCount; + private final int defaultBucketSize; + private final int checkInterval; private final Phaser phaser = new Phaser(1); private volatile boolean running = true; - private final int workerCount; - private final BlockingQueue> bucketQueue = new LinkedBlockingQueue<>(); - private final ProximityWorker worker; private final ProximityWorkerThread[] workerThreads; + private final BlockingQueue> bucketQueue = new LinkedBlockingQueue<>(); + public ProximityDirectorThread(Orebfuscator orebfuscator) { super(Orebfuscator.THREAD_GROUP, "ofc-proximity-director"); this.setDaemon(true); - this.workerCount = orebfuscator.getOrebfuscatorConfig().advanced().proximityHiderThreads(); + AdvancedConfig advancedConfig = orebfuscator.getOrebfuscatorConfig().advanced(); + this.workerCount = advancedConfig.proximityHiderThreads(); + this.defaultBucketSize = advancedConfig.proximityDefaultBucketSize(); + this.checkInterval = advancedConfig.proximityThreadCheckInterval(); + Bukkit.getPluginManager().registerEvents(this, orebfuscator); this.worker = new ProximityWorker(orebfuscator); @@ -88,16 +94,20 @@ public void run() { while (this.isRunning()) { try { Collection players = Bukkit.getOnlinePlayers(); - Iterator iterator = players.iterator(); // park thread if no players are online if (players.isEmpty()) { LockSupport.park(this); + // reset interrupt flag + Thread.interrupted(); + continue; } + // get player count and derive max bucket size for each thread int playerCount = players.size(); - int maxBucketSize = Math.max(DEFAULT_BUCKET_SIZE, (int) Math.ceil((float) playerCount / this.workerCount)); + int maxBucketSize = Math.max(this.defaultBucketSize, (int) Math.ceil((float) playerCount / this.workerCount)); + // calculate bucketC int bucketCount = (int) Math.ceil((float) playerCount / maxBucketSize); int bucketSize = (int) Math.ceil((float) playerCount / (float) bucketCount); @@ -109,6 +119,8 @@ public void run() { // this threads local bucket List localBucket = null; + Iterator iterator = players.iterator(); + // create buckets and fill queue for (int index = 0; index < bucketCount; index++) { List bucket = new ArrayList<>(); @@ -131,11 +143,11 @@ public void run() { this.worker.process(player); } - // wait for all threads to finish and reset barrier + // wait for all threads to finish and reset phaser this.phaser.arriveAndAwaitAdvance(); // sleep till next execution - Thread.sleep(50L);// TODO add to config + Thread.sleep(this.checkInterval); } catch (InterruptedException e) { continue; } catch (Exception e) { diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java index 75d8b9c9..d58e28ec 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityPacketListener.java @@ -11,9 +11,10 @@ import com.comphenix.protocol.reflect.StructureModifier; import net.imprex.orebfuscator.Orebfuscator; -import net.imprex.orebfuscator.OrebfuscatorPlayer; import net.imprex.orebfuscator.config.OrebfuscatorConfig; import net.imprex.orebfuscator.config.ProximityConfig; +import net.imprex.orebfuscator.player.OrebfuscatorPlayer; +import net.imprex.orebfuscator.player.OrebfuscatorPlayerMap; import net.imprex.orebfuscator.util.PermissionUtil; public class ProximityPacketListener extends PacketAdapter { @@ -21,6 +22,7 @@ public class ProximityPacketListener extends PacketAdapter { private final ProtocolManager protocolManager; private final OrebfuscatorConfig config; + private final OrebfuscatorPlayerMap playerMap; public ProximityPacketListener(Orebfuscator orebfuscator) { super(orebfuscator, PacketType.Play.Server.UNLOAD_CHUNK); @@ -29,6 +31,7 @@ public ProximityPacketListener(Orebfuscator orebfuscator) { this.protocolManager.addPacketListener(this); this.config = orebfuscator.getOrebfuscatorConfig(); + this.playerMap = orebfuscator.getPlayerMap(); } public void unregister() { @@ -48,7 +51,10 @@ public void onPacketSending(PacketEvent event) { return; } - StructureModifier ints = event.getPacket().getIntegers(); - OrebfuscatorPlayer.get(player).removeChunk(ints.read(0), ints.read(1)); + OrebfuscatorPlayer orebfuscatorPlayer = this.playerMap.get(player); + if (orebfuscatorPlayer != null) { + StructureModifier ints = event.getPacket().getIntegers(); + orebfuscatorPlayer.removeChunk(ints.read(0), ints.read(1)); + } } } diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java index af74e24f..3e54e192 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityWorker.java @@ -11,13 +11,12 @@ import org.bukkit.World; import org.bukkit.entity.Player; -import com.google.common.base.Objects; - import net.imprex.orebfuscator.NmsInstance; import net.imprex.orebfuscator.Orebfuscator; -import net.imprex.orebfuscator.OrebfuscatorPlayer; import net.imprex.orebfuscator.config.OrebfuscatorConfig; import net.imprex.orebfuscator.config.ProximityConfig; +import net.imprex.orebfuscator.player.OrebfuscatorPlayer; +import net.imprex.orebfuscator.player.OrebfuscatorPlayerMap; import net.imprex.orebfuscator.util.BlockPos; import net.imprex.orebfuscator.util.MathUtil; import net.imprex.orebfuscator.util.PermissionUtil; @@ -26,10 +25,12 @@ public class ProximityWorker { private final Orebfuscator orebfuscator; private final OrebfuscatorConfig config; + private final OrebfuscatorPlayerMap playerMap; public ProximityWorker(Orebfuscator orebfuscator) { this.orebfuscator = orebfuscator; this.config = orebfuscator.getOrebfuscatorConfig(); + this.playerMap = orebfuscator.getPlayerMap(); } private boolean shouldIgnorePlayer(Player player) { @@ -40,25 +41,6 @@ private boolean shouldIgnorePlayer(Player player) { return player.getGameMode() == GameMode.SPECTATOR && this.config.general().ignoreSpectator(); } - private boolean isLocationSimilar(boolean rotation, Location a, Location b) { - // check if world changed - if (!Objects.equal(a.getWorld(), b.getWorld())) { - return false; - } - - // check if len(xyz) changed less then 0.5 blocks - if (a.distanceSquared(b) > 0.25) { - return false; - } - - // check if rotation changed less then 10deg yaw or 5deg pitch - if (rotation && (Math.abs(a.getYaw() - b.getYaw()) > 10 || Math.abs(a.getPitch() - b.getPitch()) > 5)) { - return false; - } - - return true; - } - protected void process(Player player) { if (this.shouldIgnorePlayer(player)) { return; @@ -73,8 +55,8 @@ protected void process(Player player) { } // check if player changed location since last time - OrebfuscatorPlayer orebfuscatorPlayer = OrebfuscatorPlayer.get(player); - if (!orebfuscatorPlayer.needsProximityUpdate((a, b) -> isLocationSimilar(proximityConfig.useFastGazeCheck(), a, b))) { + OrebfuscatorPlayer orebfuscatorPlayer = this.playerMap.get(player); + if (orebfuscatorPlayer == null || !orebfuscatorPlayer.needsProximityUpdate(proximityConfig.useFastGazeCheck())) { return; } From 4c8a826da207965a519f28d511f98e99cd4b93ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 15:27:31 +0200 Subject: [PATCH 07/12] chore: update default configs --- orebfuscator-plugin/src/main/resources/config/config-1.10.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.11.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.12.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.13.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.14.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.15.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.16.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.17.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.18.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.19.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.20.yml | 4 ++++ orebfuscator-plugin/src/main/resources/config/config-1.9.yml | 4 ++++ 12 files changed, 48 insertions(+) diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.10.yml b/orebfuscator-plugin/src/main/resources/config/config-1.10.yml index 4cf62016..1d2b2a4f 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.10.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.10.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.11.yml b/orebfuscator-plugin/src/main/resources/config/config-1.11.yml index cd95dd1c..739f8f24 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.11.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.11.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.12.yml b/orebfuscator-plugin/src/main/resources/config/config-1.12.yml index cd95dd1c..739f8f24 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.12.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.12.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.13.yml b/orebfuscator-plugin/src/main/resources/config/config-1.13.yml index d828fc1c..02e83fd0 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.13.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.13.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.14.yml b/orebfuscator-plugin/src/main/resources/config/config-1.14.yml index 6be8ee71..9ff4f2b4 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.14.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.14.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.15.yml b/orebfuscator-plugin/src/main/resources/config/config-1.15.yml index 0de3bda2..28ab1a80 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.15.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.15.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.16.yml b/orebfuscator-plugin/src/main/resources/config/config-1.16.yml index 6bc6d20a..11b5aaea 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.16.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.16.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.17.yml b/orebfuscator-plugin/src/main/resources/config/config-1.17.yml index 9546937c..848314df 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.17.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.17.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.18.yml b/orebfuscator-plugin/src/main/resources/config/config-1.18.yml index 565c671d..8dc44a27 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.18.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.18.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.19.yml b/orebfuscator-plugin/src/main/resources/config/config-1.19.yml index 6415782e..5195c613 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.19.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.19.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.20.yml b/orebfuscator-plugin/src/main/resources/config/config-1.20.yml index ce7f1432..0383762d 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.20.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.20.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.9.yml b/orebfuscator-plugin/src/main/resources/config/config-1.9.yml index 4cf62016..1d2b2a4f 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.9.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.9.yml @@ -11,7 +11,11 @@ advanced: maxMillisecondsPerTick: 10 protocolLibThreads: -1 obfuscationWorkerThreads: -1 + obfuscationTimeout: 10000 proximityHiderThreads: -1 + proximityDefaultBucketSize: 50 + proximityThreadCheckInterval: 50 + proximityPlayerCheckInterval: 5000 cache: enabled: true baseDirectory: orebfuscator_cache From d8108d296f625e3ab1116b15d78c1041f15f06fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 15:37:32 +0200 Subject: [PATCH 08/12] fix: better clean-up for proximity director thread --- .../orebfuscator/proximityhider/ProximityDirectorThread.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java index 456ce615..9b90dfde 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -74,6 +74,7 @@ public void close() { this.workerThreads[i].interrupt(); } + // technically not need but better be safe this.phaser.forceTermination(); } @@ -144,7 +145,7 @@ public void run() { } // wait for all threads to finish and reset phaser - this.phaser.arriveAndAwaitAdvance(); + this.phaser.awaitAdvanceInterruptibly(this.phaser.arrive()); // sleep till next execution Thread.sleep(this.checkInterval); From c1b4c1676812b9315bce59316fb99d4feab61664 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 15:43:09 +0200 Subject: [PATCH 09/12] chore: update default config values in code --- .../imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java index d4a74228..2be16eaa 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/config/OrebfuscatorAdvancedConfig.java @@ -12,7 +12,7 @@ public class OrebfuscatorAdvancedConfig implements AdvancedConfig { private int protocolLibThreads = -1; private int obfuscationWorkerThreads = -1; - private int obfuscationTimeout = -1; + private int obfuscationTimeout = 10_000; private int proximityHiderThreads = -1; private int proximityDefaultBucketSize = 50; From 5b28910e434674b8a4f5a71ea760454e598da2c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 15:53:57 +0200 Subject: [PATCH 10/12] fix: player map broken on reload --- .../orebfuscator/player/OrebfuscatorPlayerMap.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java index a49f7169..3d94ea4c 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/player/OrebfuscatorPlayerMap.java @@ -23,13 +23,20 @@ public OrebfuscatorPlayerMap(Orebfuscator orebfuscator) { this.orebfuscator = orebfuscator; if (orebfuscator.getOrebfuscatorConfig().proximityEnabled()) { Bukkit.getPluginManager().registerEvents(this, orebfuscator); + + for (Player player : Bukkit.getOnlinePlayers()) { + this.addPlayer(player); + } } } + private void addPlayer(Player player) { + this.internalMap.put(player, new OrebfuscatorPlayer(orebfuscator, player)); + } + @EventHandler public void onLogin(PlayerLoginEvent event) { - Player player = event.getPlayer(); - this.internalMap.put(player, new OrebfuscatorPlayer(orebfuscator, player)); + this.addPlayer(event.getPlayer()); } @EventHandler From ea5e0db528cd0624e8b6c00c64e9dfa15fbbad1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 16:04:08 +0200 Subject: [PATCH 11/12] chore: cleanup --- .../obfuscation/SeedObfuscationListener.java | 32 ------- .../obfuscation/SeedObfuscationStrategy.java | 92 ------------------- .../src/main/resources/config/config-1.19.yml | 12 --- 3 files changed, 136 deletions(-) delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java delete mode 100644 orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java deleted file mode 100644 index b27ed58f..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationListener.java +++ /dev/null @@ -1,32 +0,0 @@ -package net.imprex.orebfuscator.obfuscation; - -import java.nio.ByteBuffer; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketEvent; - -import net.imprex.orebfuscator.Orebfuscator; - -public class SeedObfuscationListener extends PacketAdapter { - - private final long hash; - - public SeedObfuscationListener(Orebfuscator orebfuscator) { - super(orebfuscator, PacketType.Play.Server.LOGIN, PacketType.Play.Server.RESPAWN); - - - ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - protocolManager.addPacketListener(this); - - ByteBuffer buffer = ByteBuffer.wrap(orebfuscator.getOrebfuscatorConfig().systemHash()); - this.hash = buffer.getLong(0); - } - - @Override - public void onPacketSending(PacketEvent event) { - event.setPacket(SeedObfuscationStrategy.obfuscate(event.getPacket(), hash)); - } -} diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java deleted file mode 100644 index d161bcbc..00000000 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/obfuscation/SeedObfuscationStrategy.java +++ /dev/null @@ -1,92 +0,0 @@ -package net.imprex.orebfuscator.obfuscation; - -import java.lang.reflect.RecordComponent; -import java.util.Arrays; - -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.accessors.Accessors; -import com.comphenix.protocol.reflect.accessors.ConstructorAccessor; -import com.comphenix.protocol.reflect.accessors.FieldAccessor; - -@FunctionalInterface -public interface SeedObfuscationStrategy { - - static final SeedObfuscationStrategy NOOP = (packet, hash) -> packet; - static final SeedObfuscationStrategy DYNAMIC_LOGIN = createDynamicFor(PacketType.Play.Server.LOGIN); - static final SeedObfuscationStrategy DYNAMIC_RESPAWN = createDynamicFor(PacketType.Play.Server.RESPAWN); - - static PacketContainer obfuscate(PacketContainer packet, long hash) { - if (packet.getType() == PacketType.Play.Server.LOGIN) { - return DYNAMIC_LOGIN.process(packet, hash); - } else if (packet.getType() == PacketType.Play.Server.RESPAWN) { - return DYNAMIC_RESPAWN.process(packet, hash); - } - return packet; - } - - static SeedObfuscationStrategy createDynamicFor(PacketType packetType) { - if (packetType != PacketType.Play.Server.LOGIN || packetType != PacketType.Play.Server.RESPAWN) { - throw new IllegalArgumentException("unsupported packet type: " + packetType); - } - - final Class packetClass = packetType.getPacketClass(); - - if (packetClass.isRecord()) { - final RecordComponent[] components = packetClass.getRecordComponents(); - final Class[] componentClasses = new Class[components.length]; - - int longIndex = -1; - for (int i = 0; i < components.length; i++) { - Class componentClass = components[i].getType(); - - if (longIndex == -1 && componentClass == long.class) { - longIndex = i; - } - - componentClasses[i] = componentClass; - } - - final int hashIndex = longIndex; - if (hashIndex == -1) { - return NOOP; - } - - final ConstructorAccessor constructorAccessor = Accessors.getConstructorAccessor( - packetClass, componentClasses); - - final FieldAccessor[] fieldAccessors = Arrays.stream(packetClass.getDeclaredFields()) - .map(Accessors::getFieldAccessor) - .toArray(FieldAccessor[]::new); - - return (packet, hash) -> { - Object handle = packet.getHandle(); - Object[] arguments = new Object[components.length]; - - for (int i = 0; i < components.length; i++) { - if (hashIndex == i) { - arguments[i] = hash; - } else { - arguments[i] = fieldAccessors[i].get(handle); - } - } - - handle = constructorAccessor.invoke(arguments); - return new PacketContainer(packetType, handle); - }; - } else { - try { - Accessors.getFieldAccessor(packetClass, long.class, true); - } catch (Exception e) { - return NOOP; - } - - return (packet, hash) -> { - packet.getLongs().write(0, hash); - return packet; - }; - } - } - - PacketContainer process(PacketContainer packet, long hash); -} diff --git a/orebfuscator-plugin/src/main/resources/config/config-1.19.yml b/orebfuscator-plugin/src/main/resources/config/config-1.19.yml index 5195c613..0383762d 100644 --- a/orebfuscator-plugin/src/main/resources/config/config-1.19.yml +++ b/orebfuscator-plugin/src/main/resources/config/config-1.19.yml @@ -25,18 +25,6 @@ cache: maximumSize: 16384 expireAfterAccess: 60000 maximumTaskQueueSize: 32768 -seed-obfuscation: - enabled: false - worlds: - world: - enabled: true - hash: -56238923789 - world_nether: - enabled: true - hash: -56238923789 - world_the_end: - enabled: true - hash: -56238923789 obfuscation: obfuscation-overworld: enabled: true From 2f2166482a54ce6c5bd9c2663212b2fbe8d43ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maurice=20Eisenbl=C3=A4tter?= Date: Sun, 11 Jun 2023 16:07:21 +0200 Subject: [PATCH 12/12] fix: only register proximity director listener on start --- .../proximityhider/ProximityDirectorThread.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java index 9b90dfde..214de2ab 100644 --- a/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java +++ b/orebfuscator-plugin/src/main/java/net/imprex/orebfuscator/proximityhider/ProximityDirectorThread.java @@ -21,6 +21,7 @@ public class ProximityDirectorThread extends Thread implements Listener { + private final Orebfuscator orebfuscator; private final int workerCount; private final int defaultBucketSize; private final int checkInterval; @@ -37,13 +38,13 @@ public ProximityDirectorThread(Orebfuscator orebfuscator) { super(Orebfuscator.THREAD_GROUP, "ofc-proximity-director"); this.setDaemon(true); + this.orebfuscator = orebfuscator; + AdvancedConfig advancedConfig = orebfuscator.getOrebfuscatorConfig().advanced(); this.workerCount = advancedConfig.proximityHiderThreads(); this.defaultBucketSize = advancedConfig.proximityDefaultBucketSize(); this.checkInterval = advancedConfig.proximityThreadCheckInterval(); - Bukkit.getPluginManager().registerEvents(this, orebfuscator); - this.worker = new ProximityWorker(orebfuscator); this.workerThreads = new ProximityWorkerThread[workerCount - 1]; } @@ -57,6 +58,8 @@ public void onJoin(PlayerJoinEvent event) { @Override public void start() { + Bukkit.getPluginManager().registerEvents(this, this.orebfuscator); + super.start(); for (int i = 0; i < workerCount - 1; i++) {