Skip to content

Commit

Permalink
[#287] Add Folia support (#319)
Browse files Browse the repository at this point in the history
* feat: wip - add folia support

* chore: fix folia build pipeline

* feat: add folia support

* chore: udpate README

* chore: deduplicate compatibility code

* Cleanup NMS code (#320)

chore: cleanup nms code

* feat: add reload support to compatibility layer

* fix: 1.10+1.11 occluding check

* fix: 1.10 isOccluding flag

* fix: use latest game version per nms revision

* feat: add 1.20.2 support

* feat: add 1.20.2 support

* fix: issue #324

* feat: add 1.20.2 support for mojang mapped nms

* feat: register new chunk bulk packet types

* chore: revert prev commit

* fix: block below using non occluding blocks

* fix: blockBelow return air in rare cases

* fix: NPE in nms

* chore: change old configs random blocks to more closely resemble newer configs

* fix: invalid nms import on paper

* fix: disable paper layer on 1.12 and below

* fix: minor deobfuscation bugs
  • Loading branch information
Ingrim4 authored Sep 27, 2023
1 parent 71815cc commit ddc9bc9
Show file tree
Hide file tree
Showing 142 changed files with 2,210 additions and 1,837 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/buildtools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ checkVersion "1.12.2" "8"
checkVersion "1.13" "8"
checkVersion "1.13.2" "8"
checkVersion "1.14.4" "8"
checkVersion "1.15.1" "8"
checkVersion "1.15.2" "8"
checkVersion "1.16.1" "8"
checkVersion "1.16.3" "8"
checkVersion "1.16.5" "8"
Expand All @@ -42,3 +42,4 @@ checkVersion "1.19.2" "17"
checkVersion "1.19.3" "17"
checkVersion "1.19.4" "17"
checkVersion "1.20.1" "17"
checkVersion "1.20.2" "17"
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Orebfuscator empowers server owners to protect their server from X-Ray Clients a

### Requirements
* Java 11 or higher
* Spigot or compatible forks (1.9.4 or newer)
* Spigot, Paper, Folia or compatible forks (1.9.4 or newer)
* [ProtocolLib](https://www.spigotmc.org/resources/protocollib.1997) 5.0.0 or later

### Installation
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package net.imprex.orebfuscator.util;

public class MathUtil {

public static int ceilToPowerOfTwo(int value) {
value--;
value |= value >> 1;
value |= value >> 2;
value |= value >> 4;
value |= value >> 8;
value |= value >> 16;
value++;
return value;
}

public static int clamp(int value, int min, int max) {
return Math.max(min, Math.min(max, value));
}

public static int ceilLog2(int value) {
int result = 31 - Integer.numberOfLeadingZeros(value);
// add 1 if value is NOT a power of 2 (to do the ceil)
return result + (value != 0 && (value & value - 1) == 0 ? 0 : 1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package net.imprex.orebfuscator.util;

public class ServerVersion {

private static final boolean IS_MOJANG_MAPPED = classExists("net.minecraft.core.BlockPos");
private static final boolean IS_FOLIA = classExists("io.papermc.paper.threadedregions.RegionizedServer");
private static final boolean IS_PAPER = !IS_FOLIA && classExists("com.destroystokyo.paper.PaperConfig");
private static final boolean IS_BUKKIT = !IS_FOLIA && !IS_PAPER;

private static boolean classExists(String className) {
try {
Class.forName(className);
return true;
} catch (ClassNotFoundException e) {
return false;
}
}

public static boolean isMojangMapped() {
return IS_MOJANG_MAPPED;
}

public static boolean isFolia() {
return IS_FOLIA;
}

public static boolean isPaper() {
return IS_PAPER;
}

public static boolean isBukkit() {
return IS_BUKKIT;
}
}
35 changes: 35 additions & 0 deletions orebfuscator-compatibility/orebfuscator-compatibility-api/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-compatibility</artifactId>
<version>${revision}</version>
</parent>

<artifactId>orebfuscator-compatibility-api</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${dependency.bukkit.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-common</artifactId>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-nms-api</artifactId>
<version>${revision}</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package net.imprex.orebfuscator;

import java.lang.reflect.Constructor;
import java.util.concurrent.CompletableFuture;

import org.bukkit.World;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;

import net.imprex.orebfuscator.compatibility.CompatibilityLayer;
import net.imprex.orebfuscator.config.Config;
import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.imprex.orebfuscator.util.ChunkPosition;
import net.imprex.orebfuscator.util.MinecraftVersion;
import net.imprex.orebfuscator.util.OFCLogger;
import net.imprex.orebfuscator.util.ServerVersion;

public class OrebfuscatorCompatibility {

private static CompatibilityLayer instance;

public static void initialize(Plugin plugin, Config config) {
if (OrebfuscatorCompatibility.instance != null) {
throw new IllegalStateException("Compatibility layer is already initialized!");
}

String className = "net.imprex.orebfuscator.compatibility.bukkit.BukkitCompatibilityLayer";
if (ServerVersion.isFolia()) {
className = "net.imprex.orebfuscator.compatibility.folia.FoliaCompatibilityLayer";
} else if (ServerVersion.isPaper() && MinecraftVersion.minorVersion() >= 13) {
className = "net.imprex.orebfuscator.compatibility.paper.PaperCompatibilityLayer";
}

try {
OFCLogger.debug("Loading compatibility layer for: " + className);
Class<? extends CompatibilityLayer> nmsManager = Class.forName(className).asSubclass(CompatibilityLayer.class);
Constructor<? extends CompatibilityLayer> constructor = nmsManager.getConstructor(Plugin.class, Config.class);
OrebfuscatorCompatibility.instance = constructor.newInstance(plugin, config);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Compatibility layer is missing", e);
} catch (Exception e) {
throw new RuntimeException("Couldn't initialize compatibility layer", e);
}

OFCLogger.debug("Compatibility layer successfully loaded");
}

public static void runForPlayer(Player player, Runnable runnable) {
instance.getScheduler().runForPlayer(player, runnable);
}

public static void runAsyncNow(Runnable runnable) {
instance.getScheduler().runAsyncNow(runnable);
}

public static void runAsyncAtFixedRate(Runnable runnable, long delay, long period) {
instance.getScheduler().runAsyncAtFixedRate(runnable, delay, period);
}

public static void cancelTasks() {
instance.getScheduler().cancelTasks();
}

public static CompletableFuture<ReadOnlyChunk[]> getNeighboringChunks(World world, ChunkPosition position) {
return instance.getNeighboringChunks(world, position);
}

public static void close() {
if (instance != null) {
instance.getScheduler().cancelTasks();
instance = null;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package net.imprex.orebfuscator.compatibility;

import java.util.concurrent.CompletableFuture;

import org.bukkit.World;

import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.imprex.orebfuscator.util.ChunkPosition;

public interface CompatibilityLayer {

CompatibilityScheduler getScheduler();

CompletableFuture<ReadOnlyChunk[]> getNeighboringChunks(World world, ChunkPosition position);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package net.imprex.orebfuscator.compatibility;

import org.bukkit.entity.Player;

public interface CompatibilityScheduler {

void runForPlayer(Player player, Runnable runnable);

void runAsyncNow(Runnable runnable);

void runAsyncAtFixedRate(Runnable runnable, long delay, long period);

void cancelTasks();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-compatibility</artifactId>
<version>${revision}</version>
</parent>

<artifactId>orebfuscator-compatibility-bukkit</artifactId>
<packaging>jar</packaging>

<dependencies>
<dependency>
<groupId>net.imprex</groupId>
<artifactId>orebfuscator-compatibility-api</artifactId>
<version>${revision}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>${dependency.bukkit.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package net.imprex.orebfuscator.compatibility.bukkit;

import java.util.Queue;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

import org.bukkit.Bukkit;
import org.bukkit.World;
import org.bukkit.plugin.Plugin;

import net.imprex.orebfuscator.OrebfuscatorNms;
import net.imprex.orebfuscator.config.Config;
import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.imprex.orebfuscator.util.ChunkDirection;
import net.imprex.orebfuscator.util.ChunkPosition;

public class BukkitChunkLoader implements Runnable {

private final Queue<Request> requests = new ConcurrentLinkedQueue<>();

private final long availableNanosPerTick;

public BukkitChunkLoader(Plugin plugin, Config config) {
this.availableNanosPerTick = TimeUnit.MILLISECONDS.toNanos(config.advanced().maxMillisecondsPerTick());

Bukkit.getScheduler().runTaskTimer(plugin, this, 0, 1);
}

public CompletableFuture<ReadOnlyChunk[]> submitRequest(World world, ChunkPosition chunkPosition) {
Request request = new Request(world, chunkPosition);
this.requests.offer(request);
return request.future;
}

@Override
public void run() {
final long time = System.nanoTime();

Request request = null;
while (System.nanoTime() - time < this.availableNanosPerTick && (request = this.requests.poll()) != null) {
request.run();
}
}

private class Request implements Runnable {

private final World world;
private final ChunkPosition position;

private final CompletableFuture<ReadOnlyChunk[]> future = new CompletableFuture<>();

public Request(World world, ChunkPosition position) {
this.world = world;
this.position = position;
}

@Override
public void run() {
final ReadOnlyChunk[] neighboringChunks = new ReadOnlyChunk[4];

for (ChunkDirection direction : ChunkDirection.values()) {
int chunkX = position.x + direction.getOffsetX();
int chunkZ = position.z + direction.getOffsetZ();

neighboringChunks[direction.ordinal()] = OrebfuscatorNms.getReadOnlyChunk(world, chunkX, chunkZ);
}

future.complete(neighboringChunks);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package net.imprex.orebfuscator.compatibility.bukkit;

import java.util.concurrent.CompletableFuture;

import org.bukkit.World;
import org.bukkit.plugin.Plugin;

import net.imprex.orebfuscator.compatibility.CompatibilityLayer;
import net.imprex.orebfuscator.compatibility.CompatibilityScheduler;
import net.imprex.orebfuscator.config.Config;
import net.imprex.orebfuscator.nms.ReadOnlyChunk;
import net.imprex.orebfuscator.util.ChunkPosition;

public class BukkitCompatibilityLayer implements CompatibilityLayer {

private final BukkitScheduler scheduler;
private final BukkitChunkLoader chunkLoader;

public BukkitCompatibilityLayer(Plugin plugin, Config config) {
this.scheduler = new BukkitScheduler(plugin);
this.chunkLoader = new BukkitChunkLoader(plugin, config);
}

@Override
public CompatibilityScheduler getScheduler() {
return this.scheduler;
}

@Override
public CompletableFuture<ReadOnlyChunk[]> getNeighboringChunks(World world, ChunkPosition position) {
return this.chunkLoader.submitRequest(world, position);
}
}
Loading

0 comments on commit ddc9bc9

Please sign in to comment.