Start hard-fork from Luminol
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* This file is part of Pufferfish (https://github.com/pufferfish-gg/Pufferfish)
|
||||
*
|
||||
* Pufferfish is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Pufferfish is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Pufferfish. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package gg.pufferfish.pufferfish.sentry;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import org.apache.logging.log4j.ThreadContext;
|
||||
import org.bukkit.command.Command;
|
||||
import org.bukkit.command.CommandSender;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.player.PlayerEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.RegisteredListener;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
public class SentryContext {
|
||||
|
||||
private static final Gson GSON = new Gson();
|
||||
|
||||
public static void setPluginContext(@Nullable Plugin plugin) {
|
||||
if (plugin != null) {
|
||||
ThreadContext.put("pufferfishsentry_pluginname", plugin.getName());
|
||||
ThreadContext.put("pufferfishsentry_pluginversion", plugin.getPluginMeta().getVersion());
|
||||
}
|
||||
}
|
||||
|
||||
public static void removePluginContext() {
|
||||
ThreadContext.remove("pufferfishsentry_pluginname");
|
||||
ThreadContext.remove("pufferfishsentry_pluginversion");
|
||||
}
|
||||
|
||||
public static void setSenderContext(@Nullable CommandSender sender) {
|
||||
if (sender != null) {
|
||||
ThreadContext.put("pufferfishsentry_playername", sender.getName());
|
||||
if (sender instanceof Player player) {
|
||||
ThreadContext.put("pufferfishsentry_playerid", player.getUniqueId().toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void removeSenderContext() {
|
||||
ThreadContext.remove("pufferfishsentry_playername");
|
||||
ThreadContext.remove("pufferfishsentry_playerid");
|
||||
}
|
||||
|
||||
public static void setEventContext(Event event, RegisteredListener registration) {
|
||||
setPluginContext(registration.getPlugin());
|
||||
|
||||
try {
|
||||
// Find the player that was involved with this event
|
||||
Player player = null;
|
||||
if (event instanceof PlayerEvent) {
|
||||
player = ((PlayerEvent) event).getPlayer();
|
||||
} else {
|
||||
Class<? extends Event> eventClass = event.getClass();
|
||||
|
||||
Field playerField = null;
|
||||
|
||||
for (Field field : eventClass.getDeclaredFields()) {
|
||||
if (field.getType().equals(Player.class)) {
|
||||
playerField = field;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerField != null) {
|
||||
playerField.setAccessible(true);
|
||||
player = (Player) playerField.get(event);
|
||||
}
|
||||
}
|
||||
|
||||
if (player != null) {
|
||||
setSenderContext(player);
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
} // We can't really safely log exceptions.
|
||||
|
||||
ThreadContext.put("pufferfishsentry_eventdata", GSON.toJson(serializeFields(event)));
|
||||
}
|
||||
|
||||
public static void removeEventContext() {
|
||||
removePluginContext();
|
||||
removeSenderContext();
|
||||
ThreadContext.remove("pufferfishsentry_eventdata");
|
||||
}
|
||||
|
||||
private static Map<String, String> serializeFields(Object object) {
|
||||
Map<String, String> fields = new TreeMap<>();
|
||||
fields.put("_class", object.getClass().getName());
|
||||
for (Field declaredField : object.getClass().getDeclaredFields()) {
|
||||
try {
|
||||
if (Modifier.isStatic(declaredField.getModifiers())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String fieldName = declaredField.getName();
|
||||
if (fieldName.equals("handlers")) {
|
||||
continue;
|
||||
}
|
||||
declaredField.setAccessible(true);
|
||||
Object value = declaredField.get(object);
|
||||
if (value != null) {
|
||||
fields.put(fieldName, value.toString());
|
||||
} else {
|
||||
fields.put(fieldName, "<null>");
|
||||
}
|
||||
} catch (Exception ignored) {
|
||||
} // We can't really safely log exceptions.
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
public static class State {
|
||||
|
||||
private Plugin plugin;
|
||||
private Command command;
|
||||
private String commandLine;
|
||||
private Event event;
|
||||
private RegisteredListener registeredListener;
|
||||
|
||||
public Plugin getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
public void setPlugin(Plugin plugin) {
|
||||
this.plugin = plugin;
|
||||
}
|
||||
|
||||
public Command getCommand() {
|
||||
return command;
|
||||
}
|
||||
|
||||
public void setCommand(Command command) {
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public String getCommandLine() {
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
public void setCommandLine(String commandLine) {
|
||||
this.commandLine = commandLine;
|
||||
}
|
||||
|
||||
public Event getEvent() {
|
||||
return event;
|
||||
}
|
||||
|
||||
public void setEvent(Event event) {
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
public RegisteredListener getRegisteredListener() {
|
||||
return registeredListener;
|
||||
}
|
||||
|
||||
public void setRegisteredListener(RegisteredListener registeredListener) {
|
||||
this.registeredListener = registeredListener;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Pufferfish (https://github.com/pufferfish-gg/Pufferfish)
|
||||
*
|
||||
* Pufferfish is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Pufferfish is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Pufferfish. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package gg.pufferfish.pufferfish.simd;
|
||||
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.IntVector;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
* Basically, java is annoying, and we have to push this out to its own class.
|
||||
*/
|
||||
@Deprecated
|
||||
public class SIMDChecker {
|
||||
|
||||
@Deprecated
|
||||
public static boolean canEnable(Logger logger) {
|
||||
try {
|
||||
SIMDDetection.testRun = true;
|
||||
|
||||
VectorSpecies<Integer> ISPEC = IntVector.SPECIES_PREFERRED;
|
||||
VectorSpecies<Float> FSPEC = FloatVector.SPECIES_PREFERRED;
|
||||
|
||||
logger.info("Max SIMD vector size on this system is {} bits (int)", ISPEC.vectorBitSize());
|
||||
logger.info("Max SIMD vector size on this system is " + FSPEC.vectorBitSize() + " bits (float)");
|
||||
|
||||
if (ISPEC.elementSize() < 2 || FSPEC.elementSize() < 2) {
|
||||
logger.warn("SIMD is not properly supported on this system!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (NoClassDefFoundError | Exception ignored) {
|
||||
} // Basically, we don't do anything. This lets us detect if it's not functional and disable it.
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Pufferfish (https://github.com/pufferfish-gg/Pufferfish)
|
||||
*
|
||||
* Pufferfish is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Pufferfish is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Pufferfish. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package gg.pufferfish.pufferfish.simd;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
@Deprecated
|
||||
public class SIMDDetection {
|
||||
|
||||
public static boolean isEnabled = false;
|
||||
public static boolean testRun = false;
|
||||
|
||||
@Deprecated
|
||||
public static boolean canEnable(Logger logger) {
|
||||
try {
|
||||
return SIMDChecker.canEnable(logger);
|
||||
} catch (NoClassDefFoundError | Exception ignored) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static int getJavaVersion() {
|
||||
// https://stackoverflow.com/a/2591122
|
||||
String version = System.getProperty("java.version");
|
||||
if (version.startsWith("1.")) {
|
||||
version = version.substring(2, 3);
|
||||
} else {
|
||||
int dot = version.indexOf(".");
|
||||
if (dot != -1) {
|
||||
version = version.substring(0, dot);
|
||||
}
|
||||
}
|
||||
version = version.split("-")[0]; // Azul is stupid
|
||||
return Integer.parseInt(version);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* This file is part of Pufferfish (https://github.com/pufferfish-gg/Pufferfish)
|
||||
*
|
||||
* Pufferfish is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Pufferfish is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Pufferfish. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package gg.pufferfish.pufferfish.simd;
|
||||
|
||||
import jdk.incubator.vector.FloatVector;
|
||||
import jdk.incubator.vector.IntVector;
|
||||
import jdk.incubator.vector.VectorMask;
|
||||
import jdk.incubator.vector.VectorSpecies;
|
||||
import org.bukkit.map.MapPalette;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
@Deprecated
|
||||
public class VectorMapPalette {
|
||||
|
||||
private static final VectorSpecies<Integer> I_SPEC = IntVector.SPECIES_PREFERRED;
|
||||
private static final VectorSpecies<Float> F_SPEC = FloatVector.SPECIES_PREFERRED;
|
||||
|
||||
@Deprecated
|
||||
public static void matchColorVectorized(int[] in, byte[] out) {
|
||||
int speciesLength = I_SPEC.length();
|
||||
int i;
|
||||
for (i = 0; i < in.length - speciesLength; i += speciesLength) {
|
||||
float[] redsArr = new float[speciesLength];
|
||||
float[] bluesArr = new float[speciesLength];
|
||||
float[] greensArr = new float[speciesLength];
|
||||
int[] alphasArr = new int[speciesLength];
|
||||
|
||||
for (int j = 0; j < speciesLength; j++) {
|
||||
alphasArr[j] = (in[i + j] >> 24) & 0xFF;
|
||||
redsArr[j] = (in[i + j] >> 16) & 0xFF;
|
||||
greensArr[j] = (in[i + j] >> 8) & 0xFF;
|
||||
bluesArr[j] = (in[i + j] >> 0) & 0xFF;
|
||||
}
|
||||
|
||||
IntVector alphas = IntVector.fromArray(I_SPEC, alphasArr, 0);
|
||||
FloatVector reds = FloatVector.fromArray(F_SPEC, redsArr, 0);
|
||||
FloatVector greens = FloatVector.fromArray(F_SPEC, greensArr, 0);
|
||||
FloatVector blues = FloatVector.fromArray(F_SPEC, bluesArr, 0);
|
||||
IntVector resultIndex = IntVector.zero(I_SPEC);
|
||||
VectorMask<Integer> modificationMask = VectorMask.fromLong(I_SPEC, 0xffffffff);
|
||||
|
||||
modificationMask = modificationMask.and(alphas.lt(128).not());
|
||||
FloatVector bestDistances = FloatVector.broadcast(F_SPEC, Float.MAX_VALUE);
|
||||
|
||||
for (int c = 4; c < MapPalette.colors.length; c++) {
|
||||
// We're using 32-bit floats here because it's 2x faster and nobody will know the difference.
|
||||
// For correctness, the original algorithm uses 64-bit floats instead. Completely unnecessary.
|
||||
FloatVector compReds = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getRed());
|
||||
FloatVector compGreens = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getGreen());
|
||||
FloatVector compBlues = FloatVector.broadcast(F_SPEC, MapPalette.colors[c].getBlue());
|
||||
|
||||
FloatVector rMean = reds.add(compReds).div(2.0f);
|
||||
FloatVector rDiff = reds.sub(compReds);
|
||||
FloatVector gDiff = greens.sub(compGreens);
|
||||
FloatVector bDiff = blues.sub(compBlues);
|
||||
|
||||
FloatVector weightR = rMean.div(256.0f).add(2);
|
||||
FloatVector weightG = FloatVector.broadcast(F_SPEC, 4.0f);
|
||||
FloatVector weightB = FloatVector.broadcast(F_SPEC, 255.0f).sub(rMean).div(256.0f).add(2.0f);
|
||||
|
||||
FloatVector distance = weightR.mul(rDiff).mul(rDiff).add(weightG.mul(gDiff).mul(gDiff)).add(weightB.mul(bDiff).mul(bDiff));
|
||||
|
||||
// Now we compare to the best distance we've found.
|
||||
// This mask contains a "1" if better, and a "0" otherwise.
|
||||
VectorMask<Float> bestDistanceMask = distance.lt(bestDistances);
|
||||
bestDistances = bestDistances.blend(distance, bestDistanceMask); // Update the best distances
|
||||
|
||||
// Update the result array
|
||||
// We also AND with the modification mask because we don't want to interfere if the alpha value isn't large enough.
|
||||
resultIndex = resultIndex.blend(c, bestDistanceMask.cast(I_SPEC).and(modificationMask)); // Update the results
|
||||
}
|
||||
|
||||
for (int j = 0; j < speciesLength; j++) {
|
||||
int index = resultIndex.lane(j);
|
||||
out[i + j] = (byte) (index < 128 ? index : -129 + (index - 127));
|
||||
}
|
||||
}
|
||||
|
||||
// For the final ones, fall back to the regular method
|
||||
for (; i < in.length; i++) {
|
||||
out[i] = MapPalette.matchColor(new Color(in[i], true));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package me.earthme.luminol.api;
|
||||
|
||||
/**
|
||||
* A simple package of folia's tick region state.It linked to the RegionStats of the nms part so that</br>
|
||||
* You could call these methods to get the status of this tick region</br>
|
||||
*/
|
||||
public interface RegionStats {
|
||||
/**
|
||||
* Get the entity count in this tick region
|
||||
*
|
||||
* @return the entity count
|
||||
*/
|
||||
int getEntityCount();
|
||||
|
||||
/**
|
||||
* Get the player count in this tick region
|
||||
*
|
||||
* @return the player count
|
||||
*/
|
||||
int getPlayerCount();
|
||||
|
||||
/**
|
||||
* Get the chunk count in this tick region
|
||||
*
|
||||
* @return the chunk count
|
||||
*/
|
||||
int getChunkCount();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package me.earthme.luminol.api;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A mirror of folia's ThreadedRegion</br>
|
||||
* Including some handy methods to get the information of the tick region</br>
|
||||
* Note: You should call these methods inside this tick region's thread context
|
||||
*/
|
||||
public interface ThreadedRegion {
|
||||
/**
|
||||
* Get the center chunk pos of this tick region</br>
|
||||
* Note:</br>
|
||||
* 1.Global region will return a null value(But we don't finish the global region yet()</br>
|
||||
* 2.You should call these methods inside this tick region's thread context
|
||||
*
|
||||
* @return The center chunk pos
|
||||
*/
|
||||
@Nullable
|
||||
Location getCenterChunkPos();
|
||||
|
||||
/**
|
||||
* Get the dead section percent of this tick region
|
||||
* Note: </br>
|
||||
* 1.Dead percent is mean the percent of the unloaded chunk count of this tick region, which is also used for determine
|
||||
* that the tick region should or not check for splitting</br>
|
||||
* 2.You should call these methods inside this tick region's thread context
|
||||
*
|
||||
* @return The dead section percent
|
||||
*/
|
||||
double getDeadSectionPercent();
|
||||
|
||||
/**
|
||||
* Get the tick region data of this tick region</br>
|
||||
* Note:</br>
|
||||
* 1.You should call this method inside this tick region's thread context</br>
|
||||
* 2.You should call these methods inside this tick region's thread context
|
||||
*
|
||||
* @return The tick region data
|
||||
*/
|
||||
TickRegionData getTickRegionData();
|
||||
|
||||
/**
|
||||
* Get the world of this tick region</br>
|
||||
* Note: Global region will return a null value too
|
||||
*
|
||||
* @return The world of this tick region
|
||||
*/
|
||||
@Nullable
|
||||
World getWorld();
|
||||
|
||||
/**
|
||||
* Get the id of the tick region</br>
|
||||
*
|
||||
* @return The id of the tick region
|
||||
*/
|
||||
long getId();
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package me.earthme.luminol.api;
|
||||
|
||||
import org.bukkit.Location;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A mirror of folia's ThreadedRegionizer
|
||||
*/
|
||||
public interface ThreadedRegionizer {
|
||||
/**
|
||||
* Get all the tick regions
|
||||
*
|
||||
* @return Temporary copied collection of all tick regions
|
||||
*/
|
||||
Collection<ThreadedRegion> getAllRegions();
|
||||
|
||||
/**
|
||||
* Get the tick region at the given chunk coordinates
|
||||
*
|
||||
* @param chunkX Chunk X
|
||||
* @param chunkZ Chunk Z
|
||||
* @return The tick region at the given chunk coordinates
|
||||
*/
|
||||
@Nullable
|
||||
ThreadedRegion getAtSynchronized(int chunkX, int chunkZ);
|
||||
|
||||
/**
|
||||
* Get the tick region at the given chunk coordinates
|
||||
*
|
||||
* @param chunkX Chunk X
|
||||
* @param chunkZ Chunk Z
|
||||
* @return The tick region at the given chunk coordinates
|
||||
*/
|
||||
@Nullable
|
||||
ThreadedRegion getAtUnSynchronized(int chunkX, int chunkZ);
|
||||
|
||||
/**
|
||||
* Get the tick region at the given location
|
||||
*
|
||||
* @param pos The location
|
||||
* @return The tick region at the given location
|
||||
*/
|
||||
@Nullable
|
||||
default ThreadedRegion getAtSynchronized(@NotNull Location pos) {
|
||||
return this.getAtSynchronized(pos.getBlockX() >> 4, pos.getBlockZ() >> 4);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tick region at the given location
|
||||
*
|
||||
* @param pos The location
|
||||
* @return The tick region at the given location
|
||||
*/
|
||||
@Nullable
|
||||
default ThreadedRegion getAtUnSynchronized(@NotNull Location pos) {
|
||||
return this.getAtUnSynchronized(pos.getBlockX() >> 4, pos.getBlockZ() >> 4);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
package me.earthme.luminol.api;
|
||||
|
||||
import org.bukkit.World;
|
||||
|
||||
/**
|
||||
* A mirror of folia's tick region data
|
||||
*/
|
||||
public interface TickRegionData {
|
||||
/**
|
||||
* Get the world it's currently holding
|
||||
*
|
||||
* @return the world
|
||||
*/
|
||||
World getWorld();
|
||||
|
||||
/**
|
||||
* Get the current tick count
|
||||
*
|
||||
* @return the current tick count
|
||||
*/
|
||||
long getCurrentTickCount();
|
||||
|
||||
/**
|
||||
* Get the region stats
|
||||
*
|
||||
* @return the region stats
|
||||
*/
|
||||
RegionStats getRegionStats();
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package me.earthme.luminol.api.config;
|
||||
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
public record ConfigDataPair(
|
||||
String key,
|
||||
Object value,
|
||||
@Nullable String comment,
|
||||
@Nullable String[] suggestions
|
||||
) {
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package me.earthme.luminol.api.config;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Builder interface for creating {@link LuminolConfigsInstance} instances.
|
||||
* <p>
|
||||
* Provides multiple overloaded factory methods to construct configuration instances
|
||||
* with varying levels of customization, including custom base directories,
|
||||
* file names, and command names.
|
||||
*/
|
||||
public interface LuminolConfigBuilder {
|
||||
/**
|
||||
* Creates a configuration instance using the default base directory and file name.
|
||||
*
|
||||
* @param loader the class loader used to load configuration resources
|
||||
* @param name the configuration name identifier
|
||||
* @param pack the package path where configuration classes are located
|
||||
* @return a new {@link LuminolConfigsInstance}
|
||||
*/
|
||||
LuminolConfigsInstance of(
|
||||
@NotNull ClassLoader loader,
|
||||
@NotNull String name,
|
||||
@NotNull String pack
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates a configuration instance with a custom base directory.
|
||||
*
|
||||
* @param loader the class loader used to load configuration resources
|
||||
* @param base the base directory where the configuration file is stored
|
||||
* @param name the configuration name identifier
|
||||
* @param pack the package path where configuration classes are located
|
||||
* @return a new {@link LuminolConfigsInstance}
|
||||
*/
|
||||
LuminolConfigsInstance of(
|
||||
@NotNull ClassLoader loader,
|
||||
@NotNull File base,
|
||||
@NotNull String name,
|
||||
@NotNull String pack
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates a configuration instance with a custom base directory and file name.
|
||||
*
|
||||
* @param loader the class loader used to load configuration resources
|
||||
* @param base the base directory where the configuration file is stored
|
||||
* @param name the configuration name identifier
|
||||
* @param file_name the configuration file name (without extension)
|
||||
* @param pack the package path where configuration classes are located
|
||||
* @return a new {@link LuminolConfigsInstance}
|
||||
*/
|
||||
LuminolConfigsInstance of(
|
||||
@NotNull ClassLoader loader,
|
||||
@NotNull File base,
|
||||
@NotNull String name,
|
||||
@NotNull String file_name,
|
||||
@NotNull String pack
|
||||
);
|
||||
|
||||
/**
|
||||
* Creates a configuration instance with full customization options.
|
||||
*
|
||||
* @param loader the class loader used to load configuration resources
|
||||
* @param base the base directory where the configuration file is stored
|
||||
* @param name the configuration name identifier
|
||||
* @param file_name the configuration file name (without extension)
|
||||
* @param command_name the command name associated with this configuration
|
||||
* @param pack the package path where configuration classes are located
|
||||
* @return a new {@link LuminolConfigsInstance}
|
||||
*/
|
||||
LuminolConfigsInstance of(
|
||||
@NotNull ClassLoader loader,
|
||||
@NotNull File base,
|
||||
@NotNull String name,
|
||||
@NotNull String file_name,
|
||||
@NotNull String command_name,
|
||||
@NotNull String pack
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
package me.earthme.luminol.api.config;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Interface for managing configuration instances and operations.
|
||||
* Provides methods for loading, saving, modifying, and querying configuration values.
|
||||
*/
|
||||
public interface LuminolConfigsInstance {
|
||||
/**
|
||||
* Initialize the configuration subsystem for this instance.
|
||||
* Implementations should load configuration files, apply defaults and
|
||||
* prepare any internal caches or state needed for subsequent operations.
|
||||
* This method may perform I/O and therefore can throw an {@link IOException}
|
||||
* if initialization fails.
|
||||
*
|
||||
* @throws IOException if an I/O error occurs while initializing
|
||||
*/
|
||||
void initialize() throws IOException;
|
||||
|
||||
/**
|
||||
* Reloads all configurations asynchronously
|
||||
*
|
||||
* @param keepComments whether to preserve existing comments in the config file
|
||||
* @return CompletableFuture that completes when reload is finished
|
||||
*/
|
||||
@NotNull CompletableFuture<Void> reloadAsync(boolean keepComments);
|
||||
|
||||
/**
|
||||
* Sets a configuration value by key
|
||||
*
|
||||
* @param key the configuration key (dot-separated path)
|
||||
* @param value the value to set
|
||||
* @return true if the key exists and value was set, false otherwise
|
||||
*/
|
||||
boolean setConfig(String key, Object value);
|
||||
|
||||
/**
|
||||
* Saves all pending configuration changes to disk
|
||||
*/
|
||||
void saveConfigs();
|
||||
|
||||
/**
|
||||
* Resets a configuration value to its default
|
||||
*
|
||||
* @param key the configuration key to reset
|
||||
*/
|
||||
void resetConfig(String key);
|
||||
|
||||
/**
|
||||
* Gets the default value of a configuration as string
|
||||
*
|
||||
* @param key the configuration key
|
||||
* @return the default value as string
|
||||
*/
|
||||
String getDefaultConfig(String key);
|
||||
|
||||
/**
|
||||
* Gets the current value of a configuration as string
|
||||
*
|
||||
* @param key the configuration key
|
||||
* @return the current value as string
|
||||
*/
|
||||
String getConfig(String key);
|
||||
|
||||
/**
|
||||
* Gets the original (untransformed) value of a configuration
|
||||
*
|
||||
* @param key the configuration key
|
||||
* @param <T> the expected type of the value
|
||||
* @return the original configuration value
|
||||
*/
|
||||
<T> T getConfigOrigin(String key);
|
||||
|
||||
/**
|
||||
* Gets available suggestions for a configuration key
|
||||
*
|
||||
* @param key the configuration key
|
||||
* @return array of suggestion strings, or null if no suggestions available
|
||||
*/
|
||||
String[] getConfigSuggestions(String key);
|
||||
|
||||
/**
|
||||
* Completes a partial configuration path by finding matching keys
|
||||
*
|
||||
* @param partialPath the partial path to complete
|
||||
* @return list of possible completions
|
||||
*/
|
||||
List<String> completeConfigPath(String partialPath);
|
||||
|
||||
/**
|
||||
* Completes a partial configuration path with specific depth
|
||||
*
|
||||
* @param partialPath the partial path to complete
|
||||
* @param dotIndex the maximum number of dots (depth) in the result
|
||||
* @return list of possible completions
|
||||
*/
|
||||
List<String> completeConfigPath(String partialPath, int dotIndex);
|
||||
|
||||
/**
|
||||
* Gets all configuration paths that start with the given prefix
|
||||
*
|
||||
* @param currentPath the prefix to search for
|
||||
* @return list of matching configuration paths
|
||||
*/
|
||||
List<String> getAllConfigPaths(String currentPath);
|
||||
|
||||
/**
|
||||
* Gets all configuration data pairs without prefix filter
|
||||
*
|
||||
* @return set of all configuration data
|
||||
*/
|
||||
Set<ConfigDataPair> getAllData();
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs filtered by prefix
|
||||
*
|
||||
* @param prefix the prefix to filter by
|
||||
* @return set of matching configuration data
|
||||
*/
|
||||
Set<ConfigDataPair> getData(String prefix);
|
||||
|
||||
/**
|
||||
* Gets all configuration data pairs with full information (comments and suggestions)
|
||||
*
|
||||
* @return set of all configuration data with full details
|
||||
*/
|
||||
Set<ConfigDataPair> getAllDataFull();
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs with full information filtered by prefix
|
||||
*
|
||||
* @param prefix the prefix to filter by
|
||||
* @return set of matching configuration data with full details
|
||||
*/
|
||||
Set<ConfigDataPair> getDataFull(String prefix);
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs with optional comments and suggestions
|
||||
*
|
||||
* @param prefix the prefix to filter by
|
||||
* @param _comment whether to include comments
|
||||
* @param _withSuggestions whether to include suggestions
|
||||
* @return set of matching configuration data
|
||||
*/
|
||||
Set<ConfigDataPair> getData(String prefix, boolean _comment, boolean _withSuggestions);
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs for specified keys
|
||||
*
|
||||
* @param list list of configuration keys
|
||||
* @return set of configuration data for the specified keys
|
||||
*/
|
||||
Set<ConfigDataPair> getData(List<String> list);
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs with comments for specified keys
|
||||
*
|
||||
* @param list list of configuration keys
|
||||
* @return set of configuration data with comments
|
||||
*/
|
||||
Set<ConfigDataPair> getDataWithComment(List<String> list);
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs with full information for specified keys
|
||||
*
|
||||
* @param list list of configuration keys
|
||||
* @return set of configuration data with full details
|
||||
*/
|
||||
Set<ConfigDataPair> getDataFull(List<String> list);
|
||||
|
||||
/**
|
||||
* Gets configuration data pairs for specified keys with optional features
|
||||
*
|
||||
* @param list list of configuration keys
|
||||
* @param _comment whether to include comments
|
||||
* @param _withSuggestions whether to include suggestions
|
||||
* @return set of configuration data
|
||||
*/
|
||||
Set<ConfigDataPair> getData(List<String> list, boolean _comment, boolean _withSuggestions);
|
||||
|
||||
/**
|
||||
* Remove a configuration entry by its key.
|
||||
* If the key does not exist this should be a no-op.
|
||||
*
|
||||
* @param key the configuration key to remove
|
||||
*/
|
||||
void removeConfig(String key);
|
||||
|
||||
/**
|
||||
* Remove multiple configuration entries by their keys.
|
||||
* Implementations should attempt to remove each key provided. If some
|
||||
* keys do not exist they may be ignored.
|
||||
*
|
||||
* @param keys an array of configuration keys to remove
|
||||
*/
|
||||
void removeConfig(String[] keys);
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
package me.earthme.luminol.api.entity;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.bukkit.event.player.PlayerTeleportEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A simple event fired when a teleportAsync was called
|
||||
*
|
||||
* @see org.bukkit.entity.Entity#teleportAsync(org.bukkit.Location, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause)
|
||||
* @see org.bukkit.entity.Entity#teleportAsync(org.bukkit.Location)
|
||||
* (Also fired when teleportAsync called from nms)
|
||||
*/
|
||||
public class EntityTeleportAsyncEvent extends Event {
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final Entity entity;
|
||||
private final PlayerTeleportEvent.TeleportCause teleportCause;
|
||||
private final Location destination;
|
||||
|
||||
public EntityTeleportAsyncEvent(Entity entity, PlayerTeleportEvent.TeleportCause teleportCause, Location destination) {
|
||||
Validate.notNull(entity, "entity cannot be a null value!");
|
||||
Validate.notNull(teleportCause, "teleportCause cannot be a null value!");
|
||||
Validate.notNull(destination, "destination cannot be a null value!");
|
||||
|
||||
this.entity = entity;
|
||||
this.teleportCause = teleportCause;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity is about to be teleported
|
||||
*
|
||||
* @return that entity
|
||||
*/
|
||||
public @NotNull Entity getEntity() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cause of the teleport
|
||||
*
|
||||
* @return the cause
|
||||
*/
|
||||
public @NotNull PlayerTeleportEvent.TeleportCause getTeleportCause() {
|
||||
return this.teleportCause;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination of the teleport
|
||||
*
|
||||
* @return the destination
|
||||
*/
|
||||
public @NotNull Location getDestination() {
|
||||
return this.destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
package me.earthme.luminol.api.entity;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A simple event created for missing teleport events api of folia
|
||||
* This event is fired when the entity portal process has been done
|
||||
*/
|
||||
public class PostEntityPortalEvent extends Event {
|
||||
private static final HandlerList HANDLER_LIST = new HandlerList();
|
||||
|
||||
private final Entity teleportedEntity;
|
||||
|
||||
public PostEntityPortalEvent(Entity teleportedEntity) {
|
||||
Validate.notNull(teleportedEntity, "teleportedEntity cannot be null!");
|
||||
|
||||
this.teleportedEntity = teleportedEntity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity which was teleported
|
||||
*
|
||||
* @return the entity which was teleported
|
||||
*/
|
||||
public Entity getTeleportedEntity() {
|
||||
return this.teleportedEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLER_LIST;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package me.earthme.luminol.api.entity;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A simple event created for missing teleport events api of folia
|
||||
* This event will be fired when a portal teleportation is about to happen
|
||||
*/
|
||||
public class PreEntityPortalEvent extends Event implements Cancellable {
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final Entity entity;
|
||||
private final Location portalPos;
|
||||
private final World destination;
|
||||
|
||||
private boolean cancelled = false;
|
||||
|
||||
public PreEntityPortalEvent(Entity entity, Location portalPos, World destination) {
|
||||
Validate.notNull(entity, "entity cannot be null!");
|
||||
Validate.notNull(portalPos, "portalPos cannot be null!");
|
||||
Validate.notNull(destination, "destination cannot be null!");
|
||||
|
||||
this.entity = entity;
|
||||
this.portalPos = portalPos;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the entity that is about to teleport
|
||||
*
|
||||
* @return the entity
|
||||
*/
|
||||
public @NotNull Entity getEntity() {
|
||||
return this.entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the location of the portal
|
||||
*
|
||||
* @return the portal location
|
||||
*/
|
||||
public @NotNull Location getPortalPos() {
|
||||
return this.portalPos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination world
|
||||
*
|
||||
* @return the destination world
|
||||
*/
|
||||
public @NotNull World getDestination() {
|
||||
return this.destination;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
package me.earthme.luminol.api.entity.player;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A simple event fired when the respawn process of player is done
|
||||
*/
|
||||
public class PostPlayerRespawnEvent extends Event {
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final Player player;
|
||||
|
||||
public PostPlayerRespawnEvent(Player player) {
|
||||
Validate.notNull(player, "Player cannot be a null value!");
|
||||
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the respawned player
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public @NotNull Player getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package me.earthme.luminol.api.portal;
|
||||
|
||||
import org.bukkit.event.Cancellable;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A event fired when an end platform is created.
|
||||
*/
|
||||
public class EndPlatformCreateEvent extends Event implements Cancellable {
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private boolean cancelled = false;
|
||||
|
||||
@Override
|
||||
public boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCancelled(boolean cancel) {
|
||||
this.cancelled = cancel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package me.earthme.luminol.api.portal;
|
||||
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.event.Event;
|
||||
import org.bukkit.event.HandlerList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* A event fired when the portal process started locating the destination position
|
||||
* Notice: If you changed the destination to an another position in end teleportation.The end platform won't create under the entity and won't create
|
||||
* if the position is out of current tick region
|
||||
*/
|
||||
public class PortalLocateEvent extends Event {
|
||||
private static final HandlerList HANDLERS = new HandlerList();
|
||||
|
||||
private final Location original;
|
||||
private final Location destination;
|
||||
|
||||
public PortalLocateEvent(Location original, Location destination) {
|
||||
Validate.notNull(original, "original couldn't be null!");
|
||||
Validate.notNull(destination, "destination couldn't be null!");
|
||||
|
||||
this.original = original;
|
||||
this.destination = destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the destination position of this teleportation
|
||||
*
|
||||
* @return the destination position
|
||||
*/
|
||||
public Location getDestination() {
|
||||
return this.destination;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the original portal position of this teleportation
|
||||
*
|
||||
* @return the original portal position
|
||||
*/
|
||||
public Location getOriginal() {
|
||||
return this.original;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull HandlerList getHandlers() {
|
||||
return HANDLERS;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static HandlerList getHandlerList() {
|
||||
return HANDLERS;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* This file is licensed under the MIT license.
|
||||
* Origin : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.plugin;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public interface FeatureManager {
|
||||
Set<String> getAvailableFeatures();
|
||||
|
||||
boolean isFeatureAvailable(String feature);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* This file is licensed under the MIT license.
|
||||
* Origin : Leaves (https://github.com/LeavesMC/Leaves)
|
||||
*/
|
||||
|
||||
package org.leavesmc.leaves.plugin;
|
||||
|
||||
public class Features {
|
||||
public static final String MIXIN = "mixin";
|
||||
public static final String FAKEPLAYER = "fakeplayer";
|
||||
public static final String PHOTOGRAPHER = "photographer";
|
||||
public static final String RECORDER = "recorder";
|
||||
public static final String BYTEBUF = "bytebuf";
|
||||
public static final String UPDATE_SUPPRESSION_EVENT = "update_suppression_event";
|
||||
}
|
||||
Reference in New Issue
Block a user