From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: violetc <58360096+s-yh-china@users.noreply.github.com> Date: Tue, 13 Sep 2022 16:59:31 +0800 Subject: [PATCH] Leaves Server Utils diff --git a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java index 41b9405d6759d865e0d14dd4f95163e9690e967d..67008112e1d1c059938838c544f093fa1f0a4fee 100644 --- a/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java +++ b/src/main/java/com/destroystokyo/paper/util/misc/AreaMap.java @@ -26,7 +26,7 @@ public abstract class AreaMap { // we use linked for better iteration. // map of: coordinate to set of objects in coordinate - protected final Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); + protected Long2ObjectOpenHashMap> areaMap = new Long2ObjectOpenHashMap<>(1024, 0.7f); // Leaves - not final protected final PooledLinkedHashSets pooledHashSets; protected final ChangeCallback addCallback; diff --git a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java index 46954db7ecd35ac4018fdf476df7c8020d7ce6c8..044c51ebb058fc36074fd178929e3279335f6c99 100644 --- a/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java +++ b/src/main/java/com/destroystokyo/paper/util/misc/PlayerAreaMap.java @@ -5,7 +5,7 @@ import net.minecraft.server.level.ServerPlayer; /** * @author Spottedleaf */ -public final class PlayerAreaMap extends AreaMap { +public class PlayerAreaMap extends AreaMap { // Leaves - not final public PlayerAreaMap() { super(); diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index be9976a994dd04cf53048567576dd3484facf625..d582615c0ca9f483f1da31e91e66b22129881d63 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -430,6 +430,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess private UUID originWorld; public boolean freezeLocked = false; // Paper - Freeze Tick Lock API public boolean fixedPose = false; // Paper - Expand Pose API + private CompoundTag leavesData = new CompoundTag(); // Leaves - Leaves ex data public void setOrigin(@javax.annotation.Nonnull Location location) { this.origin = location.toVector(); @@ -2556,6 +2557,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess nbttagcompound.putBoolean("Paper.FreezeLock", true); } // Paper end + nbttagcompound.put("Leaves.Data", leavesData); // Leaves - leaves ex data return nbttagcompound; } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Saving entity NBT"); @@ -2703,6 +2705,11 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess freezeLocked = nbt.getBoolean("Paper.FreezeLock"); } // Paper end + // Leaves start - leaves ex data + if (nbt.contains("Leaves.Data")) { + leavesData = nbt.getCompound("Leaves.Data"); + } + // Leaves end - leaves ex data } catch (Throwable throwable) { CrashReport crashreport = CrashReport.forThrowable(throwable, "Loading entity NBT"); @@ -4988,4 +4995,10 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess return ((net.minecraft.server.level.ServerChunkCache) level.getChunkSource()).isPositionTicking(this); } // Paper end - Expose entity id counter + + // Leaves start - leaves ex data + public CompoundTag getLeavesData() { + return leavesData; + } + // Leaves end - leaves ex data } diff --git a/src/main/java/org/leavesmc/leaves/LeavesLogger.java b/src/main/java/org/leavesmc/leaves/LeavesLogger.java new file mode 100644 index 0000000000000000000000000000000000000000..47347a3bdab2ff9818bf8198291d2dabec7da8c6 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/LeavesLogger.java @@ -0,0 +1,24 @@ +package org.leavesmc.leaves; + +import org.bukkit.Bukkit; + +import java.util.logging.Level; +import java.util.logging.Logger; + +public class LeavesLogger extends Logger { + public static final LeavesLogger LOGGER = new LeavesLogger(); + + private LeavesLogger() { + super("Leaves", null); + setParent(Bukkit.getLogger()); + setLevel(Level.ALL); + } + + public void severe(String msg, Exception exception) { + this.severe(msg + ", " + exception.getCause() + ": " + exception.getMessage()); + } + + public void warning(String msg, Exception exception) { + this.warning(msg + ", " + exception.getCause() + ": " + exception.getMessage()); + } +} diff --git a/src/main/java/org/leavesmc/leaves/util/AsyncExecutor.java b/src/main/java/org/leavesmc/leaves/util/AsyncExecutor.java new file mode 100644 index 0000000000000000000000000000000000000000..067e351f6e96f2ac1a46d78dc952b2e845c1efef --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/util/AsyncExecutor.java @@ -0,0 +1,76 @@ +package org.leavesmc.leaves.util; + +import com.google.common.collect.Queues; +import org.leavesmc.leaves.LeavesLogger; + +import java.util.Queue; +import java.util.concurrent.locks.Condition; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import java.util.logging.Level; + +// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) +public class AsyncExecutor implements Runnable { + + private final Queue jobs = Queues.newArrayDeque(); + private final Lock mutex = new ReentrantLock(); + private final Condition cond = mutex.newCondition(); + private final Thread thread; + private volatile boolean killswitch = false; + + public AsyncExecutor(String threadName) { + this.thread = new Thread(this, threadName); + } + + public void start() { + thread.start(); + } + + public void kill() { + killswitch = true; + cond.signalAll(); + } + + public void submit(Runnable runnable) { + mutex.lock(); + try { + jobs.offer(runnable); + cond.signalAll(); + } finally { + mutex.unlock(); + } + } + + @Override + public void run() { + while (!killswitch) { + try { + Runnable runnable = takeRunnable(); + if (runnable != null) { + runnable.run(); + } + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } catch (Exception e) { + LeavesLogger.LOGGER.log(Level.SEVERE, e, () -> "Failed to execute async job for thread " + thread.getName()); + } + } + } + + private Runnable takeRunnable() throws InterruptedException { + mutex.lock(); + try { + while (jobs.isEmpty() && !killswitch) { + cond.await(); + } + + if (jobs.isEmpty()) { + return null; + } + + return jobs.remove(); + } finally { + mutex.unlock(); + } + } +} diff --git a/src/main/java/org/leavesmc/leaves/util/AsyncPlayerAreaMap.java b/src/main/java/org/leavesmc/leaves/util/AsyncPlayerAreaMap.java new file mode 100644 index 0000000000000000000000000000000000000000..0a2d58901b25fd771701e45aab6239626681ed4f --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/util/AsyncPlayerAreaMap.java @@ -0,0 +1,32 @@ +package org.leavesmc.leaves.util; + +import com.destroystokyo.paper.util.misc.PlayerAreaMap; +import com.destroystokyo.paper.util.misc.PooledLinkedHashSets; +import net.minecraft.server.level.ServerPlayer; + +import java.util.concurrent.ConcurrentHashMap; + +// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) +public class AsyncPlayerAreaMap extends PlayerAreaMap { + + public AsyncPlayerAreaMap() { + super(); + this.areaMap = new Long2ObjectOpenHashMapWrapper<>(new ConcurrentHashMap<>(1024, 0.7f)); + } + + public AsyncPlayerAreaMap(final PooledLinkedHashSets pooledHashSets) { + super(pooledHashSets); + this.areaMap = new Long2ObjectOpenHashMapWrapper<>(new ConcurrentHashMap<>(1024, 0.7f)); + } + + public AsyncPlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, + final ChangeCallback removeCallback) { + this(pooledHashSets, addCallback, removeCallback, null); + } + + public AsyncPlayerAreaMap(final PooledLinkedHashSets pooledHashSets, final ChangeCallback addCallback, + final ChangeCallback removeCallback, final ChangeSourceCallback changeSourceCallback) { + super(pooledHashSets, addCallback, removeCallback, changeSourceCallback); + this.areaMap = new Long2ObjectOpenHashMapWrapper<>(new ConcurrentHashMap<>(1024, 0.7f)); + } +} diff --git a/src/main/java/org/leavesmc/leaves/util/IterableWrapper.java b/src/main/java/org/leavesmc/leaves/util/IterableWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..a07feaf53905df87e45e8414b1dca02d4e8411d5 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/util/IterableWrapper.java @@ -0,0 +1,21 @@ +package org.leavesmc.leaves.util; + +import org.jetbrains.annotations.NotNull; + +import java.util.Iterator; + +// Powered by Pufferfish(https://github.com/pufferfish-gg/Pufferfish) +public class IterableWrapper implements Iterable { + + private final Iterator iterator; + + public IterableWrapper(Iterator iterator) { + this.iterator = iterator; + } + + @NotNull + @Override + public Iterator iterator() { + return iterator; + } +} diff --git a/src/main/java/org/leavesmc/leaves/util/Long2ObjectOpenHashMapWrapper.java b/src/main/java/org/leavesmc/leaves/util/Long2ObjectOpenHashMapWrapper.java new file mode 100644 index 0000000000000000000000000000000000000000..440c4d903e145229bc54eb5b6f3578fdd8bcfb84 --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/util/Long2ObjectOpenHashMapWrapper.java @@ -0,0 +1,41 @@ +package org.leavesmc.leaves.util; + +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import org.jetbrains.annotations.Nullable; + +import java.util.Map; + +public class Long2ObjectOpenHashMapWrapper extends Long2ObjectOpenHashMap { + + private final Map backingMap; + + public Long2ObjectOpenHashMapWrapper(Map map) { + backingMap = map; + } + + @Override + public V put(Long key, V value) { + return backingMap.put(key, value); + } + + @Override + public V get(Object key) { + return backingMap.get(key); + } + + @Override + public V remove(Object key) { + return backingMap.remove(key); + } + + @Nullable + @Override + public V putIfAbsent(Long key, V value) { + return backingMap.putIfAbsent(key, value); + } + + @Override + public int size() { + return backingMap.size(); + } +} diff --git a/src/main/java/org/leavesmc/leaves/util/MathUtils.java b/src/main/java/org/leavesmc/leaves/util/MathUtils.java new file mode 100644 index 0000000000000000000000000000000000000000..a6a4fd61644815a7fb01ab1a5844a34f39e57e6d --- /dev/null +++ b/src/main/java/org/leavesmc/leaves/util/MathUtils.java @@ -0,0 +1,100 @@ +package org.leavesmc.leaves.util; + +import org.bukkit.util.NumberConversions; +import org.bukkit.util.Vector; + +import java.util.regex.Pattern; + +public class MathUtils { + // Lag ? + public static void clean(Vector vector) { + if (!NumberConversions.isFinite(vector.getX())) vector.setX(0); + if (!NumberConversions.isFinite(vector.getY())) vector.setY(0); + if (!NumberConversions.isFinite(vector.getZ())) vector.setZ(0); + } + + private static final Pattern numericPattern = Pattern.compile("^-?[1-9]\\d*$|^0$"); + + public static boolean isNumeric(String str) { + return numericPattern.matcher(str).matches(); + } + + public static float[] fetchYawPitch(Vector dir) { + double x = dir.getX(); + double z = dir.getZ(); + + float[] out = new float[2]; + + if (x == 0.0D && z == 0.0D) { + out[1] = (float) (dir.getY() > 0.0D ? -90 : 90); + } else { + double theta = Math.atan2(-x, z); + out[0] = (float) Math.toDegrees((theta + 6.283185307179586D) % 6.283185307179586D); + + double x2 = NumberConversions.square(x); + double z2 = NumberConversions.square(z); + double xz = Math.sqrt(x2 + z2); + out[1] = (float) Math.toDegrees(Math.atan(-dir.getY() / xz)); + } + + return out; + } + + public static float fetchPitch(Vector dir) { + double x = dir.getX(); + double z = dir.getZ(); + + float result; + + if (x == 0.0D && z == 0.0D) { + result = (float) (dir.getY() > 0.0D ? -90 : 90); + } else { + double x2 = NumberConversions.square(x); + double z2 = NumberConversions.square(z); + double xz = Math.sqrt(x2 + z2); + result = (float) Math.toDegrees(Math.atan(-dir.getY() / xz)); + } + + return result; + } + + public static Vector getDirection(double rotX, double rotY) { + Vector vector = new Vector(); + + rotX = Math.toRadians(rotX); + rotY = Math.toRadians(rotY); + + double xz = Math.abs(Math.cos(rotY)); + + vector.setX(-Math.sin(rotX) * xz); + vector.setZ(Math.cos(rotX) * xz); + vector.setY(-Math.sin(rotY)); + + return vector; + } + + private static final int[] MULTIPLY_DE_BRUIJN_BIT_POSITION = new int[]{0, 1, 28, 2, 29, 14, 24, 3, 30, 22, 20, 15, 25, 17, 4, 8, 31, 27, 13, 23, 21, 19, 16, 7, 26, 12, 18, 6, 11, 5, 10, 9}; + + public static int floorLog2(int value) { + return ceilLog2(value) - (isPowerOfTwo(value) ? 0 : 1); + } + + public static int ceilLog2(int value) { + value = isPowerOfTwo(value) ? value : smallestEncompassingPowerOfTwo(value); + return MULTIPLY_DE_BRUIJN_BIT_POSITION[(int) ((long) value * 125613361L >> 27) & 31]; + } + + public static boolean isPowerOfTwo(int value) { + return value != 0 && (value & value - 1) == 0; + } + + public static int smallestEncompassingPowerOfTwo(int value) { + int i = value - 1; + i |= i >> 1; + i |= i >> 2; + i |= i >> 4; + i |= i >> 8; + i |= i >> 16; + return i + 1; + } +}